@adhdev/daemon-core 0.5.3
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.
- package/dist/index.d.ts +2662 -0
- package/dist/index.js +11341 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
- package/providers/_builtin/.github/workflows/generate-registry.yml +57 -0
- package/providers/_builtin/COMPATIBILITY.md +217 -0
- package/providers/_builtin/CONTRIBUTING.md +200 -0
- package/providers/_builtin/README.md +119 -0
- package/providers/_builtin/_helpers/index.js +188 -0
- package/providers/_builtin/acp/agentpool/provider.json +54 -0
- package/providers/_builtin/acp/amp/provider.json +52 -0
- package/providers/_builtin/acp/auggie/provider.json +57 -0
- package/providers/_builtin/acp/autodev/provider.json +54 -0
- package/providers/_builtin/acp/autohand/provider.json +52 -0
- package/providers/_builtin/acp/blackbox-ai/provider.json +54 -0
- package/providers/_builtin/acp/claude-agent/provider.json +57 -0
- package/providers/_builtin/acp/cline-acp/provider.json +54 -0
- package/providers/_builtin/acp/codebuddy/provider.json +54 -0
- package/providers/_builtin/acp/codex-cli/provider.json +57 -0
- package/providers/_builtin/acp/corust-agent/provider.json +52 -0
- package/providers/_builtin/acp/crow-cli/provider.json +54 -0
- package/providers/_builtin/acp/cursor-acp/provider.json +54 -0
- package/providers/_builtin/acp/deepagents/provider.json +52 -0
- package/providers/_builtin/acp/dimcode/provider.json +54 -0
- package/providers/_builtin/acp/docker-cagent/provider.json +57 -0
- package/providers/_builtin/acp/factory-droid/provider.json +60 -0
- package/providers/_builtin/acp/fast-agent/provider.json +52 -0
- package/providers/_builtin/acp/gemini-cli/provider.json +114 -0
- package/providers/_builtin/acp/github-copilot/provider.json +54 -0
- package/providers/_builtin/acp/goose/provider.json +57 -0
- package/providers/_builtin/acp/junie/provider.json +52 -0
- package/providers/_builtin/acp/kilo/provider.json +54 -0
- package/providers/_builtin/acp/kimi-cli/provider.json +57 -0
- package/providers/_builtin/acp/minion-code/provider.json +52 -0
- package/providers/_builtin/acp/mistral-vibe/provider.json +57 -0
- package/providers/_builtin/acp/nova/provider.json +54 -0
- package/providers/_builtin/acp/openclaw/provider.json +54 -0
- package/providers/_builtin/acp/opencode/provider.json +52 -0
- package/providers/_builtin/acp/openhands/provider.json +54 -0
- package/providers/_builtin/acp/pi-acp/provider.json +52 -0
- package/providers/_builtin/acp/qoder/provider.json +54 -0
- package/providers/_builtin/acp/qwen-code/provider.json +60 -0
- package/providers/_builtin/acp/stakpak/provider.json +54 -0
- package/providers/_builtin/acp/vtcode/provider.json +54 -0
- package/providers/_builtin/cli/claude-cli/provider.json +100 -0
- package/providers/_builtin/cli/codex-cli/provider.json +89 -0
- package/providers/_builtin/cli/gemini-cli/provider.json +93 -0
- package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +370 -0
- package/providers/_builtin/docs/PROVIDER_GUIDE.md +916 -0
- package/providers/_builtin/extension/cline/provider.json +35 -0
- package/providers/_builtin/extension/cline/scripts/focus_editor.js +48 -0
- package/providers/_builtin/extension/cline/scripts/list_chats.js +100 -0
- package/providers/_builtin/extension/cline/scripts/list_models.js +43 -0
- package/providers/_builtin/extension/cline/scripts/list_modes.js +35 -0
- package/providers/_builtin/extension/cline/scripts/new_session.js +85 -0
- package/providers/_builtin/extension/cline/scripts/open_panel.js +25 -0
- package/providers/_builtin/extension/cline/scripts/read_chat.js +257 -0
- package/providers/_builtin/extension/cline/scripts/resolve_action.js +83 -0
- package/providers/_builtin/extension/cline/scripts/send_message.js +95 -0
- package/providers/_builtin/extension/cline/scripts/set_mode.js +36 -0
- package/providers/_builtin/extension/cline/scripts/set_model.js +36 -0
- package/providers/_builtin/extension/cline/scripts/switch_session.js +206 -0
- package/providers/_builtin/extension/cline/scripts.js +73 -0
- package/providers/_builtin/extension/roo-code/provider.json +35 -0
- package/providers/_builtin/extension/roo-code/scripts.js +659 -0
- package/providers/_builtin/ide/antigravity/provider.json +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/focus_editor.js +20 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_chats.js +137 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_models.js +38 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_modes.js +48 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/read_chat.js +262 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/resolve_action.js +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/scripts.js +57 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/set_mode.js +34 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/set_model.js +47 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/switch_session.js +114 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/focus_editor.js +20 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_chats.js +137 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_models.js +61 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_modes.js +72 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/read_chat.js +262 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/resolve_action.js +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/scripts.js +67 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/set_mode.js +67 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/set_model.js +72 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/switch_session.js +114 -0
- package/providers/_builtin/ide/cursor/provider.json +70 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/dismiss_notification.js +30 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/focus_editor.js +13 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_models.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_modes.js +40 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_notifications.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_sessions.js +42 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/new_session.js +20 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/open_panel.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/read_chat.js +75 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/resolve_action.js +19 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/scripts.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/send_message.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/set_mode.js +38 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/set_model.js +81 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/switch_session.js +28 -0
- package/providers/_builtin/ide/kiro/provider.json +67 -0
- package/providers/_builtin/ide/kiro/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/kiro/scripts/open_panel.js +47 -0
- package/providers/_builtin/ide/kiro/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/kiro/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_models.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_modes.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_sessions.js +21 -0
- package/providers/_builtin/ide/kiro/scripts/webview_new_session.js +34 -0
- package/providers/_builtin/ide/kiro/scripts/webview_read_chat.js +68 -0
- package/providers/_builtin/ide/kiro/scripts/webview_send_message.js +72 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_mode.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_model.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_switch_session.js +26 -0
- package/providers/_builtin/ide/kiro/scripts.js +62 -0
- package/providers/_builtin/ide/pearai/provider.json +67 -0
- package/providers/_builtin/ide/pearai/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/pearai/scripts/list_sessions.js +38 -0
- package/providers/_builtin/ide/pearai/scripts/new_session.js +55 -0
- package/providers/_builtin/ide/pearai/scripts/open_panel.js +46 -0
- package/providers/_builtin/ide/pearai/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/pearai/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_models.js +43 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_modes.js +35 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_sessions.js +62 -0
- package/providers/_builtin/ide/pearai/scripts/webview_new_session.js +49 -0
- package/providers/_builtin/ide/pearai/scripts/webview_read_chat.js +92 -0
- package/providers/_builtin/ide/pearai/scripts/webview_resolve_action.js +59 -0
- package/providers/_builtin/ide/pearai/scripts/webview_send_message.js +72 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_mode.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_model.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_switch_session.js +34 -0
- package/providers/_builtin/ide/pearai/scripts.js +74 -0
- package/providers/_builtin/ide/trae/provider.json +66 -0
- package/providers/_builtin/ide/trae/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/trae/scripts/list_chats.js +24 -0
- package/providers/_builtin/ide/trae/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/trae/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/trae/scripts/new_session.js +30 -0
- package/providers/_builtin/ide/trae/scripts/open_panel.js +44 -0
- package/providers/_builtin/ide/trae/scripts/read_chat.js +113 -0
- package/providers/_builtin/ide/trae/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/trae/scripts/send_message.js +69 -0
- package/providers/_builtin/ide/trae/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/trae/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/trae/scripts/switch_session.js +23 -0
- package/providers/_builtin/ide/trae/scripts.js +57 -0
- package/providers/_builtin/ide/vscode/provider.json +64 -0
- package/providers/_builtin/ide/vscode-insiders/provider.json +62 -0
- package/providers/_builtin/ide/vscodium/provider.json +63 -0
- package/providers/_builtin/ide/windsurf/provider.json +53 -0
- package/providers/_builtin/ide/windsurf/scripts/focus_editor.js +30 -0
- package/providers/_builtin/ide/windsurf/scripts/list_chats.js +117 -0
- package/providers/_builtin/ide/windsurf/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/new_session.js +69 -0
- package/providers/_builtin/ide/windsurf/scripts/open_panel.js +58 -0
- package/providers/_builtin/ide/windsurf/scripts/read_chat.js +297 -0
- package/providers/_builtin/ide/windsurf/scripts/resolve_action.js +68 -0
- package/providers/_builtin/ide/windsurf/scripts/send_message.js +87 -0
- package/providers/_builtin/ide/windsurf/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/switch_session.js +58 -0
- package/providers/_builtin/ide/windsurf/scripts.js +57 -0
- package/providers/_builtin/registry.json +266 -0
- package/providers/_builtin/validate.js +156 -0
- package/src/agent-stream/index.ts +6 -0
- package/src/agent-stream/manager.ts +286 -0
- package/src/agent-stream/poller.ts +154 -0
- package/src/agent-stream/provider-adapter.ts +138 -0
- package/src/agent-stream/types.ts +61 -0
- package/src/boot/daemon-lifecycle.ts +252 -0
- package/src/cdp/devtools.ts +335 -0
- package/src/cdp/initializer.ts +191 -0
- package/src/cdp/manager.ts +897 -0
- package/src/cdp/scanner.ts +185 -0
- package/src/cdp/setup.ts +150 -0
- package/src/cli-adapter-types.ts +25 -0
- package/src/cli-adapters/provider-cli-adapter.ts +448 -0
- package/src/commands/cdp-commands.ts +208 -0
- package/src/commands/chat-commands.ts +675 -0
- package/src/commands/cli-manager.ts +353 -0
- package/src/commands/handler.ts +328 -0
- package/src/commands/router.ts +258 -0
- package/src/commands/stream-commands.ts +325 -0
- package/src/config/chat-history.ts +211 -0
- package/src/config/config.ts +219 -0
- package/src/daemon/dev-server.ts +2378 -0
- package/src/daemon/scaffold-template.ts +394 -0
- package/src/daemon-core.ts +50 -0
- package/src/detection/cli-detector.ts +89 -0
- package/src/detection/ide-detector.ts +157 -0
- package/src/index.ts +103 -0
- package/src/installer.ts +263 -0
- package/src/ipc-protocol.ts +133 -0
- package/src/launch.ts +433 -0
- package/src/logging/command-log.ts +180 -0
- package/src/logging/logger.ts +316 -0
- package/src/providers/acp-provider-instance.ts +1140 -0
- package/src/providers/cli-provider-instance.ts +207 -0
- package/src/providers/contracts.ts +524 -0
- package/src/providers/extension-provider-instance.ts +156 -0
- package/src/providers/ide-provider-instance.ts +377 -0
- package/src/providers/index.ts +18 -0
- package/src/providers/provider-instance-manager.ts +182 -0
- package/src/providers/provider-instance.ts +112 -0
- package/src/providers/provider-loader.ts +1031 -0
- package/src/providers/status-monitor.ts +125 -0
- package/src/providers/version-archive.ts +266 -0
- package/src/status/reporter.ts +294 -0
- package/src/types.ts +206 -0
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
# ADHDev Provider Creation Guide
|
|
2
|
+
|
|
3
|
+
> Complete guide for adding new IDE, Extension, CLI, and ACP providers to ADHDev.
|
|
4
|
+
> **Just create `provider.json` + `scripts.js` — no TypeScript modifications needed.**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🏗️ Provider Architecture
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
provider.js created (ide/cli/extension/acp)
|
|
12
|
+
│
|
|
13
|
+
▼
|
|
14
|
+
ProviderLoader.loadAll() ← 3-tier priority loading
|
|
15
|
+
│
|
|
16
|
+
├─ 1. _builtin/ (npm bundle — offline fallback)
|
|
17
|
+
├─ 2. .upstream/ (GitHub auto-download — checked every 30min)
|
|
18
|
+
└─ 3. ~/.adhdev/providers/ (user custom — highest priority, never auto-updated)
|
|
19
|
+
│
|
|
20
|
+
├─ registerToDetector() ← IDE: installation detection (paths, cli)
|
|
21
|
+
├─ getCdpPortMap() ← IDE: CDP port auto-assignment
|
|
22
|
+
├─ getCliDetectionList() ← CLI/ACP: installation detection (spawn.command)
|
|
23
|
+
├─ resolveAlias() ← alias resolution ('claude' → 'claude-cli')
|
|
24
|
+
└─ fetchLatest() ← GitHub tarball auto-download
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Loading Priority (later overrides earlier)
|
|
28
|
+
|
|
29
|
+
| Priority | Directory | Auto-update | Purpose |
|
|
30
|
+
|----------|-----------|-------------|---------|
|
|
31
|
+
| 1 (lowest) | `packages/launcher/providers/_builtin/` | npm update only | Offline fallback |
|
|
32
|
+
| 2 | `~/.adhdev/providers/.upstream/` | ✅ On daemon start | Latest GitHub providers |
|
|
33
|
+
| 3 (highest) | `~/.adhdev/providers/` (excl. _upstream) | ❌ **Never** | User custom |
|
|
34
|
+
|
|
35
|
+
### Auto-update Flow
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
adhdev daemon start
|
|
39
|
+
├─ loadAll() → builtin + .upstream + user custom loaded immediately
|
|
40
|
+
└─ background: fetchLatest()
|
|
41
|
+
├─ HEAD request → ETag comparison
|
|
42
|
+
├─ no change → skip (zero network cost)
|
|
43
|
+
└─ changed → download tarball → replace .upstream/ → reload()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
> [!IMPORTANT]
|
|
47
|
+
> **User custom protection**: provider.js files you create directly in `~/.adhdev/providers/`
|
|
48
|
+
> are never auto-updated under any circumstances. Only `.upstream/` is auto-replaced,
|
|
49
|
+
> and user custom always takes priority.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 📁 Directory Structure
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
providers/_builtin/ide/
|
|
57
|
+
├── cursor/ ← reference implementation
|
|
58
|
+
│ ├── provider.json ← metadata (type, name, cdpPorts, etc.)
|
|
59
|
+
│ └── scripts.js ← CDP scripts (readChat, sendMessage, etc.)
|
|
60
|
+
├── windsurf/ ← file-split script pattern
|
|
61
|
+
│ ├── provider.json
|
|
62
|
+
│ ├── scripts.js ← loads from scripts/ folder
|
|
63
|
+
│ └── scripts/
|
|
64
|
+
│ ├── read_chat.js
|
|
65
|
+
│ ├── send_message.js
|
|
66
|
+
│ └── ...
|
|
67
|
+
├── antigravity/
|
|
68
|
+
│ ├── provider.json
|
|
69
|
+
│ └── scripts.js
|
|
70
|
+
├── vscode/
|
|
71
|
+
│ └── provider.json ← infrastructure only (scripts not yet implemented)
|
|
72
|
+
└── [your-ide]/ ← new provider location
|
|
73
|
+
├── provider.json ← required
|
|
74
|
+
└── scripts.js ← required for IDE/Extension, not needed for CLI/ACP
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 1️⃣ provider.js Basic Structure
|
|
80
|
+
|
|
81
|
+
> [!IMPORTANT]
|
|
82
|
+
> `provider.json` contains static metadata. `scripts.js` exports CDP script functions.
|
|
83
|
+
> Type definitions: [contracts.ts](file:///Users/vilmire/Work/remote_vs/packages/daemon-core/src/providers/contracts.ts)
|
|
84
|
+
|
|
85
|
+
**provider.json:**
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"type": "my-ide",
|
|
89
|
+
"name": "My IDE",
|
|
90
|
+
"category": "ide",
|
|
91
|
+
"displayName": "My IDE",
|
|
92
|
+
"icon": "🔧",
|
|
93
|
+
"cli": "my-ide",
|
|
94
|
+
"cdpPorts": [9357, 9358],
|
|
95
|
+
"processNames": { "darwin": "My IDE" },
|
|
96
|
+
"paths": { "darwin": ["/Applications/My IDE.app"] },
|
|
97
|
+
"inputMethod": "cdp-type-and-send",
|
|
98
|
+
"inputSelector": "[contenteditable=\"true\"][role=\"textbox\"]",
|
|
99
|
+
"versionCommand": "my-ide --version",
|
|
100
|
+
"testedVersions": ["1.0.0", "1.1.0"]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**scripts.js:**
|
|
105
|
+
```javascript
|
|
106
|
+
module.exports.readChat = function readChat(params) {
|
|
107
|
+
return `(() => {
|
|
108
|
+
// CDP JS code to extract chat messages
|
|
109
|
+
return JSON.stringify({ id: 'active', status: 'idle', messages: [], inputContent: '' });
|
|
110
|
+
})()`;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
module.exports.sendMessage = function sendMessage(params) {
|
|
114
|
+
const text = typeof params === 'string' ? params : params?.text;
|
|
115
|
+
return `(() => {
|
|
116
|
+
return JSON.stringify({ sent: false, needsTypeAndSend: true, selector: '[contenteditable]' });
|
|
117
|
+
})()`;
|
|
118
|
+
};
|
|
119
|
+
// ... more scripts
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### CDP Ports Already In Use
|
|
123
|
+
|
|
124
|
+
| Port | Provider |
|
|
125
|
+
|------|----------|
|
|
126
|
+
| 9333-9334 | Cursor |
|
|
127
|
+
| 9335-9336 | Antigravity |
|
|
128
|
+
| 9337-9338 | Windsurf |
|
|
129
|
+
| 9339-9340 | VS Code |
|
|
130
|
+
| 9341-9342 | VS Code Insiders |
|
|
131
|
+
| 9343-9344 | VSCodium |
|
|
132
|
+
| 9351-9352 | Kiro |
|
|
133
|
+
| 9353-9354 | Trae |
|
|
134
|
+
| 9355-9356 | PearAI |
|
|
135
|
+
|
|
136
|
+
> [!WARNING]
|
|
137
|
+
> When adding a new provider, **avoid overlapping with existing ports** — use 9357 and above.
|
|
138
|
+
|
|
139
|
+
### aliases Field
|
|
140
|
+
|
|
141
|
+
Defining `aliases` enables usage in `adhdev launch <alias>` etc.
|
|
142
|
+
No need to add alias maps in TypeScript code — just declare in provider.js.
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// CLI example
|
|
146
|
+
module.exports = {
|
|
147
|
+
type: 'claude-cli',
|
|
148
|
+
aliases: ['claude', 'claude-code'], // adhdev launch claude → resolves to claude-cli
|
|
149
|
+
// ...
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// IDE example (optional)
|
|
153
|
+
module.exports = {
|
|
154
|
+
type: 'vscode',
|
|
155
|
+
aliases: ['code', 'vs'], // adhdev launch code → resolves to vscode
|
|
156
|
+
// ...
|
|
157
|
+
};
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 2️⃣ Script Implementation — Two Patterns
|
|
163
|
+
|
|
164
|
+
### Pattern A: Inline (Cursor style)
|
|
165
|
+
|
|
166
|
+
Write directly inside `provider.js` using template literals.
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
scripts: {
|
|
170
|
+
readChat(params) {
|
|
171
|
+
return `(() => {
|
|
172
|
+
try {
|
|
173
|
+
// ... CDP JS code ...
|
|
174
|
+
return JSON.stringify({ id, status, messages, inputContent, activeModal });
|
|
175
|
+
} catch(e) {
|
|
176
|
+
return JSON.stringify({ id: '', status: 'error', messages: [] });
|
|
177
|
+
}
|
|
178
|
+
})()`;
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Pros:** Self-contained in one file, natural parameter substitution (`${JSON.stringify(text)}`)
|
|
184
|
+
**Cons:** Hard to manage when code grows long, no syntax highlighting
|
|
185
|
+
|
|
186
|
+
### Pattern B: File Separation (Windsurf style)
|
|
187
|
+
|
|
188
|
+
Place individual `.js` files in `scripts/` folder and load with `loadScript()`.
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
const fs = require('fs');
|
|
192
|
+
const path = require('path');
|
|
193
|
+
const SCRIPTS_DIR = path.join(__dirname, 'scripts');
|
|
194
|
+
|
|
195
|
+
function loadScript(name) {
|
|
196
|
+
try { return fs.readFileSync(path.join(SCRIPTS_DIR, name), 'utf8'); }
|
|
197
|
+
catch { return null; }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// scripts object
|
|
201
|
+
scripts: {
|
|
202
|
+
readChat() { return loadScript('read_chat.js'); },
|
|
203
|
+
sendMessage(params) {
|
|
204
|
+
const text = typeof params === 'string' ? params : params?.text;
|
|
205
|
+
const s = loadScript('send_message.js');
|
|
206
|
+
return s ? s.replace(/\$\{\s*MESSAGE\s*\}/g, JSON.stringify(text)) : null;
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Pros:** Syntax highlighting, easy to edit/test individually in DevConsole
|
|
212
|
+
**Cons:** Requires file management, needs `${MESSAGE}` placeholder for parameter substitution
|
|
213
|
+
|
|
214
|
+
> [!TIP]
|
|
215
|
+
> For scripts under 30 lines, use **inline**; for longer scripts, use **file separation**.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 3️⃣ Script Output Contract
|
|
220
|
+
|
|
221
|
+
All scripts **must return a JSON string**.
|
|
222
|
+
See [contracts.ts](file:///Users/vilmire/Work/remote_vs/packages/launcher/src/providers/contracts.ts) for reference.
|
|
223
|
+
|
|
224
|
+
### Core Scripts
|
|
225
|
+
|
|
226
|
+
#### readChat(params?) → `ReadChatResult`
|
|
227
|
+
```typescript
|
|
228
|
+
{
|
|
229
|
+
id: string; // session ID
|
|
230
|
+
status: AgentStatus; // 'idle' | 'generating' | 'waiting_approval' | 'error'
|
|
231
|
+
messages: ChatMessage[]; // { role, content, index }
|
|
232
|
+
title?: string;
|
|
233
|
+
inputContent?: string; // current input field text
|
|
234
|
+
activeModal?: { // pending approval modal
|
|
235
|
+
message: string;
|
|
236
|
+
buttons: string[];
|
|
237
|
+
} | null;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### sendMessage(params) → `SendMessageResult`
|
|
242
|
+
```typescript
|
|
243
|
+
{
|
|
244
|
+
sent: boolean;
|
|
245
|
+
error?: string;
|
|
246
|
+
needsTypeAndSend?: boolean; // true → daemon types via CDP Input API
|
|
247
|
+
selector?: string; // target selector when needsTypeAndSend
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### listSessions(params?) → `ListSessionsResult`
|
|
252
|
+
```typescript
|
|
253
|
+
{ sessions: [{ id: string, title: string, active?: boolean, index?: number }] }
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
#### switchSession(params) → `SwitchSessionResult`
|
|
257
|
+
```typescript
|
|
258
|
+
{ switched: boolean, error?: string, title?: string }
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### newSession(params?) → `{ created: boolean, error?: string }`
|
|
262
|
+
|
|
263
|
+
### UI Control Scripts
|
|
264
|
+
|
|
265
|
+
#### focusEditor(params?) → `string` (e.g., `'focused'`, `'not_found'`)
|
|
266
|
+
#### openPanel(params?) → `string` (e.g., `'visible'`, `'opened'`, `'not_found'`)
|
|
267
|
+
|
|
268
|
+
### Modal/Approval Scripts
|
|
269
|
+
|
|
270
|
+
#### resolveAction(params) — Two return methods
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// params: { action: 'approve'|'reject'|'custom', button?: string, buttonText?: string }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Method 1: Script-Click** — script calls `el.click()` directly (Cursor etc.)
|
|
277
|
+
|
|
278
|
+
```js
|
|
279
|
+
// Cursor uses div.cursor-pointer elements, so direct click works
|
|
280
|
+
return JSON.stringify({ resolved: true, clicked: "Run⏎" });
|
|
281
|
+
return JSON.stringify({ resolved: false, available: ["Send", "Cancel"] });
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Method 2: Coordinate-Click** — return coordinates → daemon performs CDP mouse click (Antigravity etc.)
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
// When el.click() doesn't propagate events properly, return coordinates
|
|
288
|
+
return JSON.stringify({ found: true, text: "Accept", x: 800, y: 450, w: 120, h: 32 });
|
|
289
|
+
return JSON.stringify({ found: false });
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
> [!IMPORTANT]
|
|
293
|
+
> Daemon processing order: `resolved: true` → success / `found: true` + `x,y` → CDP click / neither → fail
|
|
294
|
+
|
|
295
|
+
#### Approval Detection (waiting_approval in readChat)
|
|
296
|
+
|
|
297
|
+
Each IDE has different approval UI, so each provider's readChat must detect appropriately:
|
|
298
|
+
|
|
299
|
+
| IDE | Detection method |
|
|
300
|
+
|-----|-----------------|
|
|
301
|
+
| Cursor | `.run-command-review-active` CSS class + `div.cursor-pointer` buttons (`Run⏎`, `SkipEsc`) |
|
|
302
|
+
| Antigravity | `<button>` text matching (`Allow This Conversation`, `Deny` etc.) |
|
|
303
|
+
| Windsurf | Fiber props or button text |
|
|
304
|
+
|
|
305
|
+
> [!TIP]
|
|
306
|
+
> In Cursor 2.6.19+, approval buttons are `<div class="cursor-pointer">` not `<button>`,
|
|
307
|
+
> and button text includes keyboard shortcuts (e.g., `"Run⏎"`, `"SkipEsc"`).
|
|
308
|
+
|
|
309
|
+
#### listNotifications(params?) → `Array<{ index, message, severity, buttons }>`
|
|
310
|
+
#### dismissNotification(params) → `{ dismissed: boolean, error?: string }`
|
|
311
|
+
|
|
312
|
+
### Model / Mode Scripts
|
|
313
|
+
|
|
314
|
+
#### listModels(params?) → `{ models: string[], current: string }`
|
|
315
|
+
#### setModel(params) → `{ success: boolean, model?: string, error?: string }`
|
|
316
|
+
#### listModes(params?) → `{ modes: string[], current: string }`
|
|
317
|
+
#### setMode(params) → `{ success: boolean, mode?: string, error?: string }`
|
|
318
|
+
|
|
319
|
+
> [!NOTE]
|
|
320
|
+
> Webview-based IDEs (Kiro, PearAI) use `webviewListModels`, `webviewSetModel` etc. with webview prefix scripts.
|
|
321
|
+
> `handleExtensionScript` automatically prioritizes webview variants when they exist.
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## 3½. Daemon Routing Logic — What provider.js Controls
|
|
327
|
+
|
|
328
|
+
> [!IMPORTANT]
|
|
329
|
+
> The daemon (daemon-commands.ts) **does not branch by IDE name.**
|
|
330
|
+
> All routing is determined by **properties and script return values** defined in provider.js.
|
|
331
|
+
|
|
332
|
+
### Automatic Routing by IDE Type
|
|
333
|
+
|
|
334
|
+
```
|
|
335
|
+
daemon receives command (readChat, sendMessage, etc.)
|
|
336
|
+
│
|
|
337
|
+
├─ provider.category === 'cli' or 'acp'?
|
|
338
|
+
│ └─ CLI/ACP adapter (stdin/stdout JSON-RPC)
|
|
339
|
+
│
|
|
340
|
+
├─ provider.category === 'extension'?
|
|
341
|
+
│ └─ AgentStream → webview iframe execution
|
|
342
|
+
│
|
|
343
|
+
└─ provider.category === 'ide'?
|
|
344
|
+
│
|
|
345
|
+
├─ scripts.webviewReadChat exists? (★ webview IDE)
|
|
346
|
+
│ └─ evaluateInWebviewFrame() → JS runs inside webview iframe
|
|
347
|
+
│ └─ provider.webviewMatchText matches correct iframe
|
|
348
|
+
│
|
|
349
|
+
└─ scripts.readChat only? (★ mainframe IDE)
|
|
350
|
+
└─ cdp.evaluate() → JS runs in mainframe
|
|
351
|
+
└─ provider.inputMethod determines input method
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Mainframe IDE vs Webview IDE Differences
|
|
355
|
+
|
|
356
|
+
| Property | Mainframe (Cursor, Windsurf, Trae) | Webview (Kiro, PearAI) |
|
|
357
|
+
|----------|-------------------------------------|------------------------|
|
|
358
|
+
| `inputMethod` | `'cdp-type-and-send'` | none (handled in webview script) |
|
|
359
|
+
| `inputSelector` | `'[contenteditable="true"]...'` | none |
|
|
360
|
+
| `webviewMatchText` | none | `'Kiro'` etc. (iframe body match text) |
|
|
361
|
+
| Script names | `readChat`, `sendMessage` | `webviewReadChat`, `webviewSendMessage` |
|
|
362
|
+
| Execution context | IDE main frame DOM | webview iframe internal DOM |
|
|
363
|
+
|
|
364
|
+
### Creating a Mainframe IDE
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
module.exports = {
|
|
368
|
+
type: 'my-ide',
|
|
369
|
+
category: 'ide',
|
|
370
|
+
inputMethod: 'cdp-type-and-send', // ← this determines mainframe mode
|
|
371
|
+
inputSelector: '[contenteditable="true"][role="textbox"]',
|
|
372
|
+
scripts: {
|
|
373
|
+
readChat() { return `(() => { ... })()`; },
|
|
374
|
+
sendMessage(text) {
|
|
375
|
+
// needsTypeAndSend: true → daemon types via CDP into inputSelector
|
|
376
|
+
return `(() => JSON.stringify({ sent: false, needsTypeAndSend: true }))()`;
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Creating a Webview IDE
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
module.exports = {
|
|
386
|
+
type: 'my-webview-ide',
|
|
387
|
+
category: 'ide',
|
|
388
|
+
webviewMatchText: 'MyWebviewApp', // ← matches if iframe body contains this text
|
|
389
|
+
// no inputMethod! handled directly inside webview
|
|
390
|
+
scripts: {
|
|
391
|
+
// webview prefix → auto-routed to evaluateInWebviewFrame()
|
|
392
|
+
webviewReadChat() { return `(() => { ... })()`; },
|
|
393
|
+
webviewSendMessage(text) { return `(() => { ... })()`; },
|
|
394
|
+
webviewListSessions() { return `(() => { ... })()`; },
|
|
395
|
+
|
|
396
|
+
// scripts to run in mainframe (open panel etc.)
|
|
397
|
+
openPanel() { return `(() => { ... })()`; },
|
|
398
|
+
focusEditor() { return `(() => { ... })()`; },
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Daemon Behavior Based on sendMessage Return Values
|
|
404
|
+
|
|
405
|
+
| Return value | Daemon action |
|
|
406
|
+
|-------------|---------------|
|
|
407
|
+
| `{ sent: true }` | Done (script sent directly) |
|
|
408
|
+
| `{ sent: false, needsTypeAndSend: true }` | CDP type + Enter into `inputSelector` |
|
|
409
|
+
| `{ sent: false, needsTypeAndSend: true, selector: '...' }` | Type into specified selector |
|
|
410
|
+
| `{ sent: false, needsTypeAndSend: true, clickCoords: {x,y} }` | Click coordinates then type |
|
|
411
|
+
|
|
412
|
+
### Daemon Behavior Based on resolveAction Return Values
|
|
413
|
+
|
|
414
|
+
| Return value | Daemon action |
|
|
415
|
+
|-------------|---------------|
|
|
416
|
+
| `{ resolved: true }` | Done (script clicked directly) |
|
|
417
|
+
| `{ found: true, x, y, w, h }` | CDP mouse click (coordinate-based) |
|
|
418
|
+
| `{ resolved: false }` / `{ found: false }` | Failed |
|
|
419
|
+
|
|
420
|
+
> [!TIP]
|
|
421
|
+
> When adding a new IDE, **you don't need to read TS code.**
|
|
422
|
+
> Just set the correct properties in provider.js and the daemon automatically picks the right path.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## 4️⃣ Development Workflow (Using DevConsole)
|
|
427
|
+
|
|
428
|
+
### Step 1: Launch IDE in CDP Mode
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
# Example: Cursor
|
|
432
|
+
adhdev launch cursor --cdp
|
|
433
|
+
|
|
434
|
+
# Or re-launch existing IDE with CDP port
|
|
435
|
+
/Applications/MyIDE.app/Contents/MacOS/MyIDE --remote-debugging-port=9350
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Step 2: Open DevConsole
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
adhdev daemon --dev
|
|
442
|
+
# Open http://127.0.0.1:19280 in browser
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Step 3: DOM Exploration and Script Writing
|
|
446
|
+
|
|
447
|
+
1. **📸 Screenshot** button to capture current IDE screen
|
|
448
|
+
2. **CSS selector** input field to explore elements (`Query` button)
|
|
449
|
+
3. **🖥 Editor** tab to write CDP JS code → **▶ Run** for immediate testing
|
|
450
|
+
4. Copy tested code to `provider.js`
|
|
451
|
+
|
|
452
|
+
### Step 4: Using Script Edit Mode
|
|
453
|
+
|
|
454
|
+
1. **📜 Scripts ▾** dropdown → click script name → enter edit mode
|
|
455
|
+
2. Modify code → **▶ Run** to test directly and check Output
|
|
456
|
+
3. When satisfied → **💾 Save Script** button to save to `provider.js`
|
|
457
|
+
|
|
458
|
+
### Step 5: Scripts Requiring Parameters
|
|
459
|
+
|
|
460
|
+
- **⚙ params** button → enter JSON parameters → run
|
|
461
|
+
- Example: `sendMessage` with `{"text": "Hello"}`
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## 5️⃣ Using _helpers (Optional)
|
|
466
|
+
|
|
467
|
+
[_helpers/index.js](file:///Users/vilmire/Work/remote_vs/packages/launcher/providers/_helpers/index.js) provides common utilities you can use.
|
|
468
|
+
|
|
469
|
+
| Helper | Purpose |
|
|
470
|
+
|--------|---------|
|
|
471
|
+
| `getWebviewDoc(selector)` | Access Extension webview iframe document |
|
|
472
|
+
| `getFiber(selectors)` | Extract React Fiber data |
|
|
473
|
+
| `typeAndSubmit(varName, selectorExpr)` | Text input + Enter send |
|
|
474
|
+
| `waitFor(selector, timeout)` | Wait for element appearance |
|
|
475
|
+
| `htmlToMdCode()` | HTML → Markdown converter function declaration |
|
|
476
|
+
| `isNoiseText(text)` | Noise text filtering |
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
const { htmlToMdCode, waitFor } = require('../../_helpers/index.js');
|
|
480
|
+
|
|
481
|
+
scripts: {
|
|
482
|
+
readChat() {
|
|
483
|
+
return `(async () => {
|
|
484
|
+
${htmlToMdCode()}
|
|
485
|
+
${waitFor('.chat-container')}
|
|
486
|
+
// ...
|
|
487
|
+
})()`;
|
|
488
|
+
},
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
> [!NOTE]
|
|
493
|
+
> Using helpers is **completely optional**. Each `provider.js` can be fully independent.
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## 6️⃣ DOM Exploration Tips
|
|
498
|
+
|
|
499
|
+
### Common Patterns Across IDEs
|
|
500
|
+
|
|
501
|
+
Most VS Code-based IDEs share the following structure:
|
|
502
|
+
|
|
503
|
+
| Element | Selector pattern |
|
|
504
|
+
|---------|-----------------|
|
|
505
|
+
| Sidebar | `#workbench.parts.auxiliarybar` |
|
|
506
|
+
| Editor input | `[contenteditable="true"][role="textbox"]` |
|
|
507
|
+
| Notification toast | `.notifications-toasts .notification-toast` |
|
|
508
|
+
| Dialog | `.monaco-dialog-box, [role="dialog"]` |
|
|
509
|
+
| Action button | `a.action-label.codicon-*` |
|
|
510
|
+
|
|
511
|
+
### Status Detection Strategy
|
|
512
|
+
|
|
513
|
+
```
|
|
514
|
+
1. data-* attribute check (most stable)
|
|
515
|
+
→ Cursor: data-composer-status="streaming"
|
|
516
|
+
|
|
517
|
+
2. Fiber props exploration (React-based UI)
|
|
518
|
+
→ Windsurf: fiber.memoizedProps.isRunning
|
|
519
|
+
|
|
520
|
+
3. Stop button presence (universal)
|
|
521
|
+
→ button[aria-label*="stop"], text="Stop"
|
|
522
|
+
|
|
523
|
+
4. Placeholder text (fallback)
|
|
524
|
+
→ input placeholder contains "wait" / "generating"
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## 7️⃣ Verification Checklist
|
|
530
|
+
|
|
531
|
+
After completing a new provider, verify all items below:
|
|
532
|
+
|
|
533
|
+
- [ ] `readChat` — returns message list correctly in idle state
|
|
534
|
+
- [ ] `readChat` — correctly detects generating status
|
|
535
|
+
- [ ] `readChat` — detects waiting_approval status (including modal button list)
|
|
536
|
+
- [ ] `sendMessage` — `needsTypeAndSend: true` return triggers normal daemon typing
|
|
537
|
+
- [ ] `listSessions` — session list (including title, active status)
|
|
538
|
+
- [ ] `switchSession` — switching based on index/title
|
|
539
|
+
- [ ] `newSession` — new chat creation
|
|
540
|
+
- [ ] `focusEditor` — focuses input field
|
|
541
|
+
- [ ] `openPanel` — chat panel toggle
|
|
542
|
+
- [ ] `resolveAction` — approve/reject button click
|
|
543
|
+
- [ ] `listNotifications` — notification list output
|
|
544
|
+
- [ ] `dismissNotification` — dismiss notification
|
|
545
|
+
- [ ] All scripts pass ▶ Run tests in DevConsole
|
|
546
|
+
- [ ] `node -c provider.js` — no syntax errors
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## 8️⃣ Reference Implementations
|
|
551
|
+
|
|
552
|
+
| Pattern | Provider | Features |
|
|
553
|
+
|---------|----------|----------|
|
|
554
|
+
| **Inline** | [cursor/provider.js] | Most complete, concise implementation |
|
|
555
|
+
| **File separation** | [windsurf/provider.js] | Fiber usage, HTML→Markdown conversion |
|
|
556
|
+
| **File separation** | [antigravity/provider.js] | CDP mouse click coordinate return pattern |
|
|
557
|
+
| **Webview** | [kiro/provider.js] | webviewMatchText + webview* script pattern |
|
|
558
|
+
| **Webview** | [pearai/provider.js] | webview iframe-based chat UI |
|
|
559
|
+
| **File separation** | [trae/provider.js] | webviewMatchText + mainframe script hybrid |
|
|
560
|
+
| **ACP** | [gemini-cli/provider.js] | ACP + env_var auth + agent auth |
|
|
561
|
+
| **ACP** | [goose/provider.js] | ACP + terminal auth |
|
|
562
|
+
|
|
563
|
+
> [!TIP]
|
|
564
|
+
> When writing a new provider, **copy Cursor's `provider.json` + `scripts.js`** and modify selectors — it's the fastest approach.
|
|
565
|
+
> For VS Code-based IDEs, the DOM structure is similar, so just change a few selectors.
|
|
566
|
+
> For webview-based IDEs, refer to **Kiro's provider.json**.
|
|
567
|
+
> For ACP agents, refer to **gemini-cli's provider.json**.
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## 📊 Version Detection & Compatibility Tracking
|
|
572
|
+
|
|
573
|
+
ADHDev automatically detects installed versions of all providers and archives the history
|
|
574
|
+
for future compatibility tracking.
|
|
575
|
+
|
|
576
|
+
### How It Works
|
|
577
|
+
|
|
578
|
+
```
|
|
579
|
+
adhdev daemon --dev
|
|
580
|
+
└─ GET /api/providers/versions
|
|
581
|
+
├─ IDE: cli --version → Info.plist fallback (macOS)
|
|
582
|
+
├─ CLI: binary --version → -V → -v (auto-fallback)
|
|
583
|
+
├─ ACP: binary --version → -V → -v (auto-fallback)
|
|
584
|
+
└─ Extensions: detected at runtime via CDP (future)
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### Version Archive
|
|
588
|
+
|
|
589
|
+
Detected versions are archived to `~/.adhdev/version-history.json`:
|
|
590
|
+
|
|
591
|
+
```json
|
|
592
|
+
{
|
|
593
|
+
"cursor": [
|
|
594
|
+
{ "version": "2.5.0", "detectedAt": "2026-02-01T...", "os": "darwin" },
|
|
595
|
+
{ "version": "2.6.19", "detectedAt": "2026-03-18T...", "os": "darwin" }
|
|
596
|
+
],
|
|
597
|
+
"claude-cli": [
|
|
598
|
+
{ "version": "2.1.76", "detectedAt": "2026-03-18T...", "os": "darwin" }
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
- **Deduplication**: Same version is not recorded twice consecutively
|
|
604
|
+
- **Entry limit**: Max 20 entries per provider (oldest trimmed)
|
|
605
|
+
- **OS tracking**: Records which OS the version was detected on
|
|
606
|
+
|
|
607
|
+
### provider.json Version Fields
|
|
608
|
+
|
|
609
|
+
| Field | Type | Purpose |
|
|
610
|
+
|-------|------|---------|
|
|
611
|
+
| `versionCommand` | `string` | Custom version detection command (default: `"<binary> --version"`) |
|
|
612
|
+
| `testedVersions` | `string[]` | Versions tested by the provider maintainer |
|
|
613
|
+
|
|
614
|
+
```json
|
|
615
|
+
{
|
|
616
|
+
"type": "cursor",
|
|
617
|
+
"versionCommand": "cursor --version",
|
|
618
|
+
"testedVersions": ["2.5.0", "2.6.19"]
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Use Cases
|
|
623
|
+
|
|
624
|
+
1. **Compatibility alerts**: When a user's installed version doesn't match `testedVersions`,
|
|
625
|
+
the dashboard can warn that scripts may not work correctly.
|
|
626
|
+
2. **Regression tracking**: When selectors break after an IDE update, the version history
|
|
627
|
+
shows exactly when the change occurred.
|
|
628
|
+
3. **Per-version script overrides**: Use the existing `versions` field in provider config
|
|
629
|
+
to provide different scripts for different IDE versions:
|
|
630
|
+
|
|
631
|
+
```json
|
|
632
|
+
{
|
|
633
|
+
"versions": {
|
|
634
|
+
">=2.7.0": {
|
|
635
|
+
"scripts": {
|
|
636
|
+
"readChat": "... updated selectors for 2.7+ ..."
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### DevServer API
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
# Detect all provider versions (runs installation checks)
|
|
647
|
+
curl http://127.0.0.1:19280/api/providers/versions
|
|
648
|
+
|
|
649
|
+
# Response:
|
|
650
|
+
{
|
|
651
|
+
"total": 52,
|
|
652
|
+
"installed": 13,
|
|
653
|
+
"providers": [
|
|
654
|
+
{
|
|
655
|
+
"type": "cursor",
|
|
656
|
+
"name": "Cursor",
|
|
657
|
+
"category": "ide",
|
|
658
|
+
"installed": true,
|
|
659
|
+
"version": "2.6.19",
|
|
660
|
+
"path": "/Applications/Cursor.app",
|
|
661
|
+
"binary": "/Applications/Cursor.app/Contents/Resources/app/bin/cursor"
|
|
662
|
+
}
|
|
663
|
+
],
|
|
664
|
+
"history": { ... }
|
|
665
|
+
}
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
> [!TIP]
|
|
669
|
+
> Run version detection periodically (or on daemon start) to keep the archive up-to-date.
|
|
670
|
+
> When a provider update breaks selectors, check the archive to identify the version change.
|
|
671
|
+
|
|
672
|
+
---
|
|
673
|
+
|
|
674
|
+
## 9️⃣ ACP Provider Guide
|
|
675
|
+
|
|
676
|
+
> Guide for adding ACP (Agent Client Protocol) agents.
|
|
677
|
+
> ACP agents communicate via stdin/stdout JSON-RPC 2.0.
|
|
678
|
+
|
|
679
|
+
### Directory Structure
|
|
680
|
+
|
|
681
|
+
```
|
|
682
|
+
providers/_builtin/acp/
|
|
683
|
+
├── gemini-cli/ ← env_var auth (reference)
|
|
684
|
+
│ └── provider.js
|
|
685
|
+
├── goose/ ← terminal auth (reference)
|
|
686
|
+
│ └── provider.js
|
|
687
|
+
├── [your-agent]/ ← new ACP provider
|
|
688
|
+
│ └── provider.js
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### provider.js Basic Structure
|
|
692
|
+
|
|
693
|
+
```javascript
|
|
694
|
+
module.exports = {
|
|
695
|
+
type: 'my-agent-acp', // unique identifier
|
|
696
|
+
name: 'My Agent (ACP)', // display name
|
|
697
|
+
category: 'acp', // must be 'acp'
|
|
698
|
+
aliases: ['my-agent'], // aliases (adhdev launch my-agent etc.)
|
|
699
|
+
|
|
700
|
+
displayName: 'My Agent',
|
|
701
|
+
icon: '🤖',
|
|
702
|
+
install: 'npm install -g my-agent', // install command (shown in error messages)
|
|
703
|
+
|
|
704
|
+
spawn: {
|
|
705
|
+
command: 'my-agent', // used for which install check + CLI detection
|
|
706
|
+
args: ['--acp'], // ACP mode activation argument
|
|
707
|
+
shell: false,
|
|
708
|
+
},
|
|
709
|
+
|
|
710
|
+
// ─── Authentication Config ───
|
|
711
|
+
auth: [
|
|
712
|
+
// 1. API key based (env_var)
|
|
713
|
+
{
|
|
714
|
+
type: 'env_var',
|
|
715
|
+
id: 'api-key',
|
|
716
|
+
name: 'API Key',
|
|
717
|
+
link: 'https://my-agent.dev/keys', // key issuance URL
|
|
718
|
+
vars: [
|
|
719
|
+
{ name: 'MY_AGENT_API_KEY', label: 'API Key', secret: true },
|
|
720
|
+
{ name: 'MY_AGENT_ORG', label: 'Organization', optional: true },
|
|
721
|
+
],
|
|
722
|
+
},
|
|
723
|
+
// 2. Self auth (agent)
|
|
724
|
+
// { type: 'agent', id: 'oauth', name: 'OAuth', description: 'First run will open browser' },
|
|
725
|
+
// 3. Terminal command (terminal)
|
|
726
|
+
// { type: 'terminal', id: 'config', name: 'Configure', args: ['configure'] },
|
|
727
|
+
],
|
|
728
|
+
|
|
729
|
+
settings: {
|
|
730
|
+
approvalAlert: {
|
|
731
|
+
type: 'boolean', default: true, public: true,
|
|
732
|
+
label: 'Approval Alerts',
|
|
733
|
+
},
|
|
734
|
+
longGeneratingAlert: {
|
|
735
|
+
type: 'boolean', default: true, public: true,
|
|
736
|
+
label: 'Long Generation Alert',
|
|
737
|
+
},
|
|
738
|
+
longGeneratingThresholdSec: {
|
|
739
|
+
type: 'number', default: 180, public: true,
|
|
740
|
+
label: 'Long Generation Threshold (sec)',
|
|
741
|
+
min: 30, max: 600,
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
};
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
### Authentication Types (auth[]) — Documentation Only
|
|
748
|
+
|
|
749
|
+
> **Note**: ADHDev does not store or inject API keys (v0.7.1+).
|
|
750
|
+
> The `auth[]` field is used for documentation purposes only; each tool handles authentication independently.
|
|
751
|
+
> On auth failure, stderr error messages are displayed directly on the dashboard.
|
|
752
|
+
|
|
753
|
+
| type | Purpose | Note |
|
|
754
|
+
|------|---------|------|
|
|
755
|
+
| `env_var` | API key-based auth | User sets environment variables manually |
|
|
756
|
+
| `agent` | Agent self OAuth/browser auth | Auto-handled on first run |
|
|
757
|
+
| `terminal` | Auth setup via CLI command | User runs manually |
|
|
758
|
+
|
|
759
|
+
### Behavior Flow
|
|
760
|
+
|
|
761
|
+
```
|
|
762
|
+
1. Dashboard CLIs tab → select Launch
|
|
763
|
+
2. daemon-cli.ts → which check → AcpProviderInstance created
|
|
764
|
+
3. spawn(command, args) → JSON-RPC initialize → session/new
|
|
765
|
+
4. Chat available on Dashboard
|
|
766
|
+
5. On auth failure → stderr error messages displayed on dashboard
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### Error Handling (Automatic)
|
|
770
|
+
|
|
771
|
+
- **Not installed**: `which` failure → "Not installed" error + install guide
|
|
772
|
+
- **Auth failure**: stderr detects `unauthorized`, `api_key missing` etc. → `errorReason: 'auth_failed'`
|
|
773
|
+
- **Quick exit**: exit within 3 seconds → `errorReason: 'crash'` + last 3 stderr lines
|
|
774
|
+
- **Handshake failure**: initialize timeout → `errorReason: 'init_failed'`
|
|
775
|
+
|
|
776
|
+
> [!TIP]
|
|
777
|
+
> Adding a new ACP agent only requires creating a single provider.js.
|
|
778
|
+
> Copying `providers/_builtin/acp/gemini-cli/provider.js` is the fastest approach.
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
782
|
+
## 🔟 ProviderLoader API
|
|
783
|
+
|
|
784
|
+
```typescript
|
|
785
|
+
class ProviderLoader {
|
|
786
|
+
loadAll(): void // load _builtin + .upstream + ~/.adhdev/providers
|
|
787
|
+
resolve(type, context?): ResolvedProvider // apply OS/version overrides
|
|
788
|
+
get(type): ProviderModule | undefined
|
|
789
|
+
getAll(): ProviderModule[]
|
|
790
|
+
getByCategory(cat): ProviderModule[]
|
|
791
|
+
|
|
792
|
+
// ─── Helpers (used by other modules) ───
|
|
793
|
+
getCdpPortMap(): Record<string, number[]> // CDP ports per IDE
|
|
794
|
+
getMacAppIdentifiers(): Record<string, string> // IDE → macOS app name
|
|
795
|
+
getWinProcessNames(): Record<string, string[]> // IDE → Windows process names
|
|
796
|
+
getAvailableIdeTypes(): string[] // IDE category only
|
|
797
|
+
registerToDetector(): void // register IDE to core detector
|
|
798
|
+
resolveAlias(alias): string // alias → type resolution
|
|
799
|
+
fetchLatest(): Promise<void> // download GitHub tarball (.upstream/)
|
|
800
|
+
|
|
801
|
+
watch(): void // hot-reload
|
|
802
|
+
stopWatch(): void
|
|
803
|
+
}
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
---
|
|
807
|
+
|
|
808
|
+
## 1️⃣1️⃣ End-to-End Flow When Adding a New IDE
|
|
809
|
+
|
|
810
|
+
```
|
|
811
|
+
① provider.js created
|
|
812
|
+
providers/_builtin/ide/zed/provider.js
|
|
813
|
+
│
|
|
814
|
+
② ProviderLoader.loadAll()
|
|
815
|
+
→ auto-discovered (recursive scan)
|
|
816
|
+
│
|
|
817
|
+
③ registerToDetector()
|
|
818
|
+
→ IDE definition registered to core detector (paths, processNames)
|
|
819
|
+
│
|
|
820
|
+
④ daemon initCdp()
|
|
821
|
+
→ getCdpPortMap() → CDP connection starts
|
|
822
|
+
│
|
|
823
|
+
⑤ daemon statusReport
|
|
824
|
+
→ auto-included in managedIdes (from cdpManagers.keys())
|
|
825
|
+
→ included in availableProviders (delivered to frontend)
|
|
826
|
+
│
|
|
827
|
+
⑥ Dashboard display
|
|
828
|
+
→ DaemonContext auto-creates IDE tab from ':ide:' pattern
|
|
829
|
+
→ formatIdeType('zed') → 'Zed' (fallback capitalize)
|
|
830
|
+
│
|
|
831
|
+
⑦ User interaction — zero TS code changes
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
> [!IMPORTANT]
|
|
835
|
+
> Adding just one `provider.json` + `scripts.js` enables **detection → CDP connection → dashboard display → command execution**
|
|
836
|
+
> to work automatically. No TypeScript code changes are required.
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
## ⚡ Scaffold — Quick Provider Creation
|
|
841
|
+
|
|
842
|
+
Use the scaffold API or DevConsole to generate a new provider skeleton:
|
|
843
|
+
|
|
844
|
+
### Via DevConsole
|
|
845
|
+
|
|
846
|
+
1. Open http://127.0.0.1:19280
|
|
847
|
+
2. Click **+ New** in the toolbar
|
|
848
|
+
3. Fill in Type ID, Display Name, Category
|
|
849
|
+
4. Category-specific fields appear automatically:
|
|
850
|
+
- **IDE**: CDP Port, CLI Command, Process Name, Install Path
|
|
851
|
+
- **Extension**: Extension ID
|
|
852
|
+
- **CLI/ACP**: Binary / Command
|
|
853
|
+
5. Click **Create** → generates `~/.adhdev/providers/{type}/provider.json` + `scripts.js`
|
|
854
|
+
|
|
855
|
+
### Via API
|
|
856
|
+
|
|
857
|
+
```bash
|
|
858
|
+
curl -X POST http://127.0.0.1:19280/api/scaffold \
|
|
859
|
+
-H 'Content-Type: application/json' \
|
|
860
|
+
-d '{
|
|
861
|
+
"type": "zed",
|
|
862
|
+
"name": "Zed",
|
|
863
|
+
"category": "ide",
|
|
864
|
+
"cdpPorts": [9450, 9451],
|
|
865
|
+
"cli": "zed",
|
|
866
|
+
"processName": "Zed",
|
|
867
|
+
"installPath": "/Applications/Zed.app"
|
|
868
|
+
}'
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
### Generated Files
|
|
872
|
+
|
|
873
|
+
| Category | Files Generated |
|
|
874
|
+
|----------|----------------|
|
|
875
|
+
| IDE | `provider.json` + `scripts.js` (with readChat, sendMessage, etc.) |
|
|
876
|
+
| Extension | `provider.json` + `scripts.js` |
|
|
877
|
+
| CLI | `provider.json` only |
|
|
878
|
+
| ACP | `provider.json` only |
|
|
879
|
+
|
|
880
|
+
> [!TIP]
|
|
881
|
+
> After scaffold, open the provider in DevConsole → use the Wizard to discover
|
|
882
|
+
> DOM selectors → implement the TODO stubs in scripts.js.
|
|
883
|
+
|
|
884
|
+
---
|
|
885
|
+
|
|
886
|
+
## 1️⃣2️⃣ Scope Limitations
|
|
887
|
+
|
|
888
|
+
1. **Electron-based IDEs only** — requires `--remote-debugging-port`. Zed, IntelliJ and other non-Electron IDEs not supported.
|
|
889
|
+
2. **Common launch logic** — all IDEs use identical Electron launch arguments. Per-provider custom launch not implemented.
|
|
890
|
+
3. **CLI adapter TypeScript maintained** — PTY lifecycle (spawn, handleOutput) is TS runtime code. provider.js provides config/patterns only.
|
|
891
|
+
4. **P2P-first** — all data (chat, commands, screenshots) transmitted directly via P2P. Server WS for signaling + lightweight meta only.
|
|
892
|
+
|
|
893
|
+
---
|
|
894
|
+
|
|
895
|
+
## 1️⃣3️⃣ Hardcoding Removal Status
|
|
896
|
+
|
|
897
|
+
### ✅ Fully Removed
|
|
898
|
+
|
|
899
|
+
| Location | Before | After |
|
|
900
|
+
|----------|--------|-------|
|
|
901
|
+
| `launch.ts` getCdpPorts | Hardcoded port map | `providerLoader.getCdpPortMap()` |
|
|
902
|
+
| `launch.ts` getMacAppIdentifiers | Hardcoded app names | `providerLoader.getMacAppIdentifiers()` |
|
|
903
|
+
| `launch.ts` getWinProcessNames | Hardcoded process names | `providerLoader.getWinProcessNames()` |
|
|
904
|
+
| `launch.ts` getAvailableIdeIds | Hardcoded IDE list | `providerLoader.getAvailableIdeTypes()` |
|
|
905
|
+
| `Dashboard.tsx` CLI_IDES | Hardcoded | `isCliConv()` — id pattern `:cli:` |
|
|
906
|
+
| `MachineDetail.tsx` CLI_TYPES | Hardcoded | `isCliEntry()` — id pattern |
|
|
907
|
+
| `detector.ts` IDE_DEFINITIONS | Hardcoded | `registerIDEDefinition()` runtime registration |
|
|
908
|
+
|
|
909
|
+
### ⚠️ Intentionally Kept (fallback)
|
|
910
|
+
|
|
911
|
+
| Location | Content | Reason |
|
|
912
|
+
|----------|---------|--------|
|
|
913
|
+
| `adhdev-daemon.ts` | `fallbackType = 'cursor'` | Default on detection failure |
|
|
914
|
+
| `adhdev-daemon.ts` | fallback port map | On ProviderLoader load failure |
|
|
915
|
+
| `Dashboard.tsx` | `IDE_TYPE_LABELS` | Display name override (fallback) |
|
|
916
|
+
| `detector.ts` | `BUILTIN_IDE_DEFINITIONS` | Default before runtime registration |
|