@adhdev/daemon-core 0.5.24 → 0.5.26
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.js +122 -105
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/providers/_builtin/COMPATIBILITY.md +1 -1
- package/providers/_builtin/README.md +1 -1
- package/providers/_builtin/cli/claude-cli/provider.json +2 -1
- package/providers/_builtin/docs/PROVIDER_GUIDE.md +3 -3
- package/providers/_builtin/extension/cline/provider.json +4 -2
- package/providers/_builtin/extension/codex/provider.json +4 -2
- package/providers/_builtin/extension/codex/scripts/{list_models.js → 1.0/list_models.js} +1 -0
- package/providers/_builtin/extension/codex/scripts/{read_chat.js → 1.0/read_chat.js} +36 -11
- package/providers/_builtin/extension/codex/scripts/list_modes.js +138 -0
- package/providers/_builtin/extension/codex/scripts/set_mode.js +165 -0
- package/providers/_builtin/extension/roo-code/provider.json +4 -2
- package/providers/_builtin/ide/cursor/provider.json +1 -70
- package/providers/_builtin/ide/cursor/provider.json.bak +70 -0
- package/providers/_builtin/ide/kiro/provider.json +4 -2
- package/providers/_builtin/ide/pearai/provider.json +4 -2
- package/providers/_builtin/ide/trae/provider.json +4 -2
- package/providers/_builtin/ide/windsurf/provider.json +4 -2
- package/providers/_builtin/registry.json +1 -1
- package/src/agent-stream/poller.ts +15 -0
- package/src/cli-adapters/provider-cli-adapter.ts +45 -36
- package/providers/_builtin/extension/cline/scripts.js +0 -73
- package/providers/_builtin/extension/codex/scripts.js +0 -94
- package/providers/_builtin/ide/kiro/scripts.js +0 -62
- package/providers/_builtin/ide/pearai/scripts.js +0 -74
- package/providers/_builtin/ide/trae/scripts.js +0 -57
- package/providers/_builtin/ide/windsurf/scripts.js +0 -57
- /package/providers/_builtin/extension/cline/scripts/{focus_editor.js → 1.0/focus_editor.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{list_chats.js → 1.0/list_chats.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{list_models.js → 1.0/list_models.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{list_modes.js → 1.0/list_modes.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{new_session.js → 1.0/new_session.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{open_panel.js → 1.0/open_panel.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{read_chat.js → 1.0/read_chat.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{resolve_action.js → 1.0/resolve_action.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{send_message.js → 1.0/send_message.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{set_mode.js → 1.0/set_mode.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{set_model.js → 1.0/set_model.js} +0 -0
- /package/providers/_builtin/extension/cline/scripts/{switch_session.js → 1.0/switch_session.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{click_conversation_webview.js → 1.0/click_conversation_webview.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{explore_chat_webview.js → 1.0/explore_chat_webview.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{explore_controls_webview.js → 1.0/explore_controls_webview.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{explore_dom.js → 1.0/explore_dom.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{explore_dropdown_webview.js → 1.0/explore_dropdown_webview.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{inspect_code_webview.js → 1.0/inspect_code_webview.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{message_structure_webview.js → 1.0/message_structure_webview.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{new_session.js → 1.0/new_session.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{resolve_action.js → 1.0/resolve_action.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{send_message.js → 1.0/send_message.js} +0 -0
- /package/providers/_builtin/extension/codex/scripts/{set_model.js → 1.0/set_model.js} +0 -0
- /package/providers/_builtin/extension/roo-code/{scripts.js → scripts/1.0/scripts.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{focus_editor.js → 1.0/focus_editor.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{open_panel.js → 1.0/open_panel.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{resolve_action.js → 1.0/resolve_action.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{send_message.js → 1.0/send_message.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_list_models.js → 1.0/webview_list_models.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_list_modes.js → 1.0/webview_list_modes.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_list_sessions.js → 1.0/webview_list_sessions.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_new_session.js → 1.0/webview_new_session.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_read_chat.js → 1.0/webview_read_chat.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_send_message.js → 1.0/webview_send_message.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_set_mode.js → 1.0/webview_set_mode.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_set_model.js → 1.0/webview_set_model.js} +0 -0
- /package/providers/_builtin/ide/kiro/scripts/{webview_switch_session.js → 1.0/webview_switch_session.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{focus_editor.js → 1.0/focus_editor.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{list_sessions.js → 1.0/list_sessions.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{new_session.js → 1.0/new_session.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{open_panel.js → 1.0/open_panel.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{resolve_action.js → 1.0/resolve_action.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{send_message.js → 1.0/send_message.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_list_models.js → 1.0/webview_list_models.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_list_modes.js → 1.0/webview_list_modes.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_list_sessions.js → 1.0/webview_list_sessions.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_new_session.js → 1.0/webview_new_session.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_read_chat.js → 1.0/webview_read_chat.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_resolve_action.js → 1.0/webview_resolve_action.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_send_message.js → 1.0/webview_send_message.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_set_mode.js → 1.0/webview_set_mode.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_set_model.js → 1.0/webview_set_model.js} +0 -0
- /package/providers/_builtin/ide/pearai/scripts/{webview_switch_session.js → 1.0/webview_switch_session.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{focus_editor.js → 1.0/focus_editor.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{list_chats.js → 1.0/list_chats.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{list_models.js → 1.0/list_models.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{list_modes.js → 1.0/list_modes.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{new_session.js → 1.0/new_session.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{open_panel.js → 1.0/open_panel.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{read_chat.js → 1.0/read_chat.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{resolve_action.js → 1.0/resolve_action.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{send_message.js → 1.0/send_message.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{set_mode.js → 1.0/set_mode.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{set_model.js → 1.0/set_model.js} +0 -0
- /package/providers/_builtin/ide/trae/scripts/{switch_session.js → 1.0/switch_session.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{focus_editor.js → 1.0/focus_editor.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{list_chats.js → 1.0/list_chats.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{list_models.js → 1.0/list_models.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{list_modes.js → 1.0/list_modes.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{new_session.js → 1.0/new_session.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{open_panel.js → 1.0/open_panel.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{read_chat.js → 1.0/read_chat.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{resolve_action.js → 1.0/resolve_action.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{send_message.js → 1.0/send_message.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{set_mode.js → 1.0/set_mode.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{set_model.js → 1.0/set_model.js} +0 -0
- /package/providers/_builtin/ide/windsurf/scripts/{switch_session.js → 1.0/switch_session.js} +0 -0
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
├── ide/ — IDE providers (Cursor, Antigravity, Windsurf, Kiro, etc.)
|
|
9
9
|
├── cli/ — CLI agent providers (Gemini CLI, Claude Code, Codex CLI)
|
|
10
10
|
├── extension/ — VS Code extension providers (Cline, Roo Code)
|
|
11
|
-
├── acp/ — ACP agent providers (
|
|
11
|
+
├── acp/ — ACP agent providers (35 agents)
|
|
12
12
|
├── registry.json — Auto-generated provider index (used by daemon)
|
|
13
13
|
├── validate.js — Provider schema validator
|
|
14
14
|
├── CONTRIBUTING.md — How to add a new provider
|
|
@@ -90,7 +90,8 @@
|
|
|
90
90
|
{ "source": "Allow\\s*tool", "flags": "i" },
|
|
91
91
|
{ "source": "Yes,?\\s*don'?t\\s*ask", "flags": "i" },
|
|
92
92
|
{ "source": "Deny", "flags": "i" },
|
|
93
|
-
{ "source": "Do you want to proceed", "flags": "i" }
|
|
93
|
+
{ "source": "Do you want to proceed", "flags": "i" },
|
|
94
|
+
{ "source": "Esc to cancel", "flags": "i" }
|
|
94
95
|
],
|
|
95
96
|
"ready": [
|
|
96
97
|
{ "source": "for\\s*shortcuts", "flags": "i" },
|
|
@@ -28,7 +28,7 @@ ProviderLoader.loadAll() ← 3-tier priority loading
|
|
|
28
28
|
|
|
29
29
|
| Priority | Directory | Auto-update | Purpose |
|
|
30
30
|
|----------|-----------|-------------|---------|
|
|
31
|
-
| 1 (lowest) | `packages/
|
|
31
|
+
| 1 (lowest) | `packages/daemon-core/providers/_builtin/` | npm update only | Offline fallback |
|
|
32
32
|
| 2 | `~/.adhdev/providers/.upstream/` | ✅ On daemon start | Latest GitHub providers |
|
|
33
33
|
| 3 (highest) | `~/.adhdev/providers/` (excl. _upstream) | ❌ **Never** | User custom |
|
|
34
34
|
|
|
@@ -219,7 +219,7 @@ scripts: {
|
|
|
219
219
|
## 3️⃣ Script Output Contract
|
|
220
220
|
|
|
221
221
|
All scripts **must return a JSON string**.
|
|
222
|
-
See [contracts.ts](file:///Users/vilmire/Work/remote_vs/packages/
|
|
222
|
+
See [contracts.ts](file:///Users/vilmire/Work/remote_vs/packages/daemon-core/src/providers/contracts.ts) for reference.
|
|
223
223
|
|
|
224
224
|
### Core Scripts
|
|
225
225
|
|
|
@@ -464,7 +464,7 @@ adhdev daemon --dev
|
|
|
464
464
|
|
|
465
465
|
## 5️⃣ Using _helpers (Optional)
|
|
466
466
|
|
|
467
|
-
[_helpers/index.js](file:///Users/vilmire/Work/remote_vs/packages/
|
|
467
|
+
[_helpers/index.js](file:///Users/vilmire/Work/remote_vs/packages/daemon-core/providers/_helpers/index.js) provides common utilities you can use.
|
|
468
468
|
|
|
469
469
|
| Helper | Purpose |
|
|
470
470
|
|--------|---------|
|
|
@@ -22,12 +22,34 @@
|
|
|
22
22
|
*/
|
|
23
23
|
(() => {
|
|
24
24
|
try {
|
|
25
|
-
|
|
25
|
+
// When executed via evaluateInSession, we're in the outer vscode-webview
|
|
26
|
+
// iframe. The Codex React app lives in a child iframe. Try to access it.
|
|
27
|
+
let doc = document;
|
|
28
|
+
let root = doc.getElementById('root');
|
|
29
|
+
|
|
30
|
+
if (!root) {
|
|
31
|
+
// Traverse into inner iframe(s)
|
|
32
|
+
const iframes = doc.querySelectorAll('iframe');
|
|
33
|
+
for (const iframe of iframes) {
|
|
34
|
+
try {
|
|
35
|
+
const innerDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
36
|
+
if (innerDoc) {
|
|
37
|
+
const innerRoot = innerDoc.getElementById('root');
|
|
38
|
+
if (innerRoot) {
|
|
39
|
+
doc = innerDoc;
|
|
40
|
+
root = innerRoot;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} catch (e) { /* cross-origin, skip */ }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
26
48
|
if (!root) return JSON.stringify({ error: 'no root element' });
|
|
27
49
|
|
|
28
50
|
const isVisible = root.offsetHeight > 0;
|
|
29
51
|
|
|
30
|
-
const headerEl =
|
|
52
|
+
const headerEl = doc.querySelector('[style*="view-transition-name: header-title"]');
|
|
31
53
|
const headerText = (headerEl?.textContent || '').trim();
|
|
32
54
|
const isTaskList = headerText === '작업' || headerText === 'Tasks';
|
|
33
55
|
|
|
@@ -216,7 +238,7 @@
|
|
|
216
238
|
|
|
217
239
|
// ─── 1. Messages ───
|
|
218
240
|
const messages = [];
|
|
219
|
-
const turnEls =
|
|
241
|
+
const turnEls = doc.querySelectorAll('[data-content-search-turn-key]');
|
|
220
242
|
|
|
221
243
|
for (const turnEl of turnEls) {
|
|
222
244
|
const turnKey = turnEl.getAttribute('data-content-search-turn-key');
|
|
@@ -243,7 +265,7 @@
|
|
|
243
265
|
|
|
244
266
|
// Fallback
|
|
245
267
|
if (messages.length === 0 && !isTaskList) {
|
|
246
|
-
const threadArea =
|
|
268
|
+
const threadArea = doc.querySelector('[data-thread-find-target="conversation"]');
|
|
247
269
|
if (threadArea) {
|
|
248
270
|
const text = extractRichContent(threadArea);
|
|
249
271
|
if (text.length > 0) {
|
|
@@ -258,7 +280,7 @@
|
|
|
258
280
|
|
|
259
281
|
// ─── 2. Input field ───
|
|
260
282
|
let inputContent = '';
|
|
261
|
-
const proseMirror =
|
|
283
|
+
const proseMirror = doc.querySelector('.ProseMirror');
|
|
262
284
|
if (proseMirror) {
|
|
263
285
|
const placeholder = proseMirror.querySelector('.placeholder');
|
|
264
286
|
const text = (proseMirror.textContent || '').trim();
|
|
@@ -269,7 +291,7 @@
|
|
|
269
291
|
|
|
270
292
|
// ─── 3. Status ───
|
|
271
293
|
let status = 'idle';
|
|
272
|
-
const buttons = Array.from(
|
|
294
|
+
const buttons = Array.from(doc.querySelectorAll('button'))
|
|
273
295
|
.filter(b => b.offsetWidth > 0);
|
|
274
296
|
const buttonTexts = buttons.map(b => (b.textContent || '').trim().toLowerCase());
|
|
275
297
|
const buttonLabels = buttons.map(b => (b.getAttribute('aria-label') || '').toLowerCase());
|
|
@@ -279,9 +301,12 @@
|
|
|
279
301
|
status = 'generating';
|
|
280
302
|
}
|
|
281
303
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
304
|
+
// Codex approval buttons appear as distinct action buttons (e.g. "Approve", "Always approve", "Deny")
|
|
305
|
+
// They typically appear at the bottom of a tool-call/action block
|
|
306
|
+
const approvalSpecificPatterns = /^(approve|always approve|deny|reject|승인|항상 승인|거부)/i;
|
|
307
|
+
const hasApprovalButton = buttonTexts.some(b => approvalSpecificPatterns.test(b)) ||
|
|
308
|
+
buttonLabels.some(l => approvalSpecificPatterns.test(l));
|
|
309
|
+
if (hasApprovalButton) {
|
|
285
310
|
status = 'waiting_approval';
|
|
286
311
|
}
|
|
287
312
|
|
|
@@ -293,7 +318,7 @@
|
|
|
293
318
|
// ─── 4. Model / Mode ───
|
|
294
319
|
let model = '';
|
|
295
320
|
let mode = '';
|
|
296
|
-
const footerButtons =
|
|
321
|
+
const footerButtons = doc.querySelectorAll(
|
|
297
322
|
'[class*="thread-composer-max-width"] button, [class*="pb-2"] button'
|
|
298
323
|
);
|
|
299
324
|
for (const btn of footerButtons) {
|
|
@@ -318,7 +343,7 @@
|
|
|
318
343
|
}
|
|
319
344
|
|
|
320
345
|
// ─── 6. Task info ───
|
|
321
|
-
const taskBtn =
|
|
346
|
+
const taskBtn = doc.querySelector('[aria-label*="작업"], [aria-label*="task" i]');
|
|
322
347
|
const taskInfo = taskBtn ? (taskBtn.textContent || '').trim() : '';
|
|
323
348
|
|
|
324
349
|
return JSON.stringify({
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Extension — list_modes
|
|
3
|
+
*
|
|
4
|
+
* Finds the mode / autonomy dropdown next to the model chip in the composer footer,
|
|
5
|
+
* opens it (Radix), reads options, closes. UI expects `modes` + `current` (see ModelModeBar).
|
|
6
|
+
*/
|
|
7
|
+
(() => {
|
|
8
|
+
try {
|
|
9
|
+
function resolveDoc() {
|
|
10
|
+
let doc = document;
|
|
11
|
+
let root = doc.getElementById('root');
|
|
12
|
+
if (!root) {
|
|
13
|
+
const iframes = doc.querySelectorAll('iframe');
|
|
14
|
+
for (const iframe of iframes) {
|
|
15
|
+
try {
|
|
16
|
+
const innerDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
17
|
+
if (innerDoc?.getElementById('root')) {
|
|
18
|
+
doc = innerDoc;
|
|
19
|
+
root = innerDoc.getElementById('root');
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
} catch (e) { /* cross-origin */ }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { doc, root };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isModelMenuButton(b) {
|
|
29
|
+
const text = (b.textContent || '').trim();
|
|
30
|
+
if (b.getAttribute('aria-haspopup') !== 'menu') return false;
|
|
31
|
+
return /^(GPT-|gpt-|o\d|claude-|sonnet|opus)/i.test(text);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Mode chip: menu trigger in composer that is not the model selector. */
|
|
35
|
+
function findModeMenuButton(doc) {
|
|
36
|
+
const composer =
|
|
37
|
+
doc.querySelector('[class*="thread-composer-max-width"]') ||
|
|
38
|
+
doc.querySelector('[class*="thread-composer"]') ||
|
|
39
|
+
doc.getElementById('root') ||
|
|
40
|
+
doc.body;
|
|
41
|
+
|
|
42
|
+
const buttons = Array.from(composer.querySelectorAll('button')).filter(
|
|
43
|
+
(b) => b.offsetWidth > 0 && b.offsetHeight > 0,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const menuTriggers = buttons.filter(
|
|
47
|
+
(b) => b.getAttribute('aria-haspopup') === 'menu' && !isModelMenuButton(b),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (menuTriggers.length === 0) return null;
|
|
51
|
+
|
|
52
|
+
const byAria = menuTriggers.find((b) => {
|
|
53
|
+
const al = (b.getAttribute('aria-label') || '').toLowerCase();
|
|
54
|
+
return /mode|agent|ask|plan|autonomy|codex|모드|에이전트|플랜/i.test(al);
|
|
55
|
+
});
|
|
56
|
+
if (byAria) return byAria;
|
|
57
|
+
|
|
58
|
+
return menuTriggers[0];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function openMenu(btn) {
|
|
62
|
+
const rect = btn.getBoundingClientRect();
|
|
63
|
+
const cx = rect.left + rect.width / 2;
|
|
64
|
+
const cy = rect.top + rect.height / 2;
|
|
65
|
+
btn.dispatchEvent(
|
|
66
|
+
new PointerEvent('pointerdown', { bubbles: true, clientX: cx, clientY: cy, pointerId: 1 }),
|
|
67
|
+
);
|
|
68
|
+
btn.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: cx, clientY: cy }));
|
|
69
|
+
btn.dispatchEvent(
|
|
70
|
+
new PointerEvent('pointerup', { bubbles: true, clientX: cx, clientY: cy, pointerId: 1 }),
|
|
71
|
+
);
|
|
72
|
+
btn.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: cx, clientY: cy }));
|
|
73
|
+
btn.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: cx, clientY: cy }));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { doc, root } = resolveDoc();
|
|
77
|
+
if (!root) return JSON.stringify({ modes: [], current: '', currentMode: '', error: 'no root' });
|
|
78
|
+
|
|
79
|
+
const modeBtn = findModeMenuButton(doc);
|
|
80
|
+
if (!modeBtn) {
|
|
81
|
+
return JSON.stringify({
|
|
82
|
+
modes: [],
|
|
83
|
+
current: '',
|
|
84
|
+
currentMode: '',
|
|
85
|
+
error: 'mode menu button not found',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const currentLabel = (modeBtn.textContent || '').trim();
|
|
90
|
+
openMenu(modeBtn);
|
|
91
|
+
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
setTimeout(() => {
|
|
94
|
+
let menu = doc.querySelector('[role="menu"][data-state="open"]');
|
|
95
|
+
if (!menu) {
|
|
96
|
+
menu = doc.querySelector('[role="menu"]');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const collected = [];
|
|
100
|
+
if (menu) {
|
|
101
|
+
const items = menu.querySelectorAll(
|
|
102
|
+
'[role="menuitem"], [role="menuitemradio"], [role="option"], div[class*="cursor-interaction"]',
|
|
103
|
+
);
|
|
104
|
+
for (const item of items) {
|
|
105
|
+
const text = (item.textContent || '').trim();
|
|
106
|
+
if (
|
|
107
|
+
text &&
|
|
108
|
+
text.length > 0 &&
|
|
109
|
+
text.length < 80 &&
|
|
110
|
+
!/^모델|^model\b|^select\b/i.test(text)
|
|
111
|
+
) {
|
|
112
|
+
collected.push(text);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
doc.dispatchEvent(
|
|
118
|
+
new KeyboardEvent('keydown', {
|
|
119
|
+
key: 'Escape',
|
|
120
|
+
code: 'Escape',
|
|
121
|
+
keyCode: 27,
|
|
122
|
+
bubbles: true,
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const modes = [...new Set(collected)];
|
|
127
|
+
const out = {
|
|
128
|
+
modes: modes.length > 0 ? modes : currentLabel ? [currentLabel] : [],
|
|
129
|
+
current: currentLabel,
|
|
130
|
+
currentMode: currentLabel,
|
|
131
|
+
};
|
|
132
|
+
resolve(JSON.stringify(out));
|
|
133
|
+
}, 550);
|
|
134
|
+
});
|
|
135
|
+
} catch (e) {
|
|
136
|
+
return JSON.stringify({ error: e.message || String(e), modes: [], current: '', currentMode: '' });
|
|
137
|
+
}
|
|
138
|
+
})();
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Extension — set_mode
|
|
3
|
+
*
|
|
4
|
+
* Opens the mode dropdown (same discovery as list_modes), selects an item matching ${MODE}.
|
|
5
|
+
*
|
|
6
|
+
* Placeholder: ${MODE}
|
|
7
|
+
*/
|
|
8
|
+
(() => {
|
|
9
|
+
try {
|
|
10
|
+
const targetMode = ${MODE};
|
|
11
|
+
|
|
12
|
+
function resolveDoc() {
|
|
13
|
+
let doc = document;
|
|
14
|
+
let root = doc.getElementById('root');
|
|
15
|
+
if (!root) {
|
|
16
|
+
const iframes = doc.querySelectorAll('iframe');
|
|
17
|
+
for (const iframe of iframes) {
|
|
18
|
+
try {
|
|
19
|
+
const innerDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
20
|
+
if (innerDoc?.getElementById('root')) {
|
|
21
|
+
doc = innerDoc;
|
|
22
|
+
root = innerDoc.getElementById('root');
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
} catch (e) { /* cross-origin */ }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return { doc, root };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isModelMenuButton(b) {
|
|
32
|
+
const text = (b.textContent || '').trim();
|
|
33
|
+
if (b.getAttribute('aria-haspopup') !== 'menu') return false;
|
|
34
|
+
return /^(GPT-|gpt-|o\d|claude-|sonnet|opus)/i.test(text);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function findModeMenuButton(doc) {
|
|
38
|
+
const composer =
|
|
39
|
+
doc.querySelector('[class*="thread-composer-max-width"]') ||
|
|
40
|
+
doc.querySelector('[class*="thread-composer"]') ||
|
|
41
|
+
doc.getElementById('root') ||
|
|
42
|
+
doc.body;
|
|
43
|
+
|
|
44
|
+
const buttons = Array.from(composer.querySelectorAll('button')).filter(
|
|
45
|
+
(b) => b.offsetWidth > 0 && b.offsetHeight > 0,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const menuTriggers = buttons.filter(
|
|
49
|
+
(b) => b.getAttribute('aria-haspopup') === 'menu' && !isModelMenuButton(b),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
if (menuTriggers.length === 0) return null;
|
|
53
|
+
|
|
54
|
+
const byAria = menuTriggers.find((b) => {
|
|
55
|
+
const al = (b.getAttribute('aria-label') || '').toLowerCase();
|
|
56
|
+
return /mode|agent|ask|plan|autonomy|codex|모드|에이전트|플랜/i.test(al);
|
|
57
|
+
});
|
|
58
|
+
if (byAria) return byAria;
|
|
59
|
+
|
|
60
|
+
return menuTriggers[0];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function openMenu(btn) {
|
|
64
|
+
const rect = btn.getBoundingClientRect();
|
|
65
|
+
const cx = rect.left + rect.width / 2;
|
|
66
|
+
const cy = rect.top + rect.height / 2;
|
|
67
|
+
btn.dispatchEvent(
|
|
68
|
+
new PointerEvent('pointerdown', { bubbles: true, clientX: cx, clientY: cy, pointerId: 1 }),
|
|
69
|
+
);
|
|
70
|
+
btn.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: cx, clientY: cy }));
|
|
71
|
+
btn.dispatchEvent(
|
|
72
|
+
new PointerEvent('pointerup', { bubbles: true, clientX: cx, clientY: cy, pointerId: 1 }),
|
|
73
|
+
);
|
|
74
|
+
btn.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: cx, clientY: cy }));
|
|
75
|
+
btn.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: cx, clientY: cy }));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function clickItem(el) {
|
|
79
|
+
const ir = el.getBoundingClientRect();
|
|
80
|
+
const ix = ir.left + ir.width / 2;
|
|
81
|
+
const iy = ir.top + ir.height / 2;
|
|
82
|
+
el.dispatchEvent(
|
|
83
|
+
new PointerEvent('pointerdown', { bubbles: true, clientX: ix, clientY: iy }),
|
|
84
|
+
);
|
|
85
|
+
el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: ix, clientY: iy }));
|
|
86
|
+
el.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, clientX: ix, clientY: iy }));
|
|
87
|
+
el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: ix, clientY: iy }));
|
|
88
|
+
el.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: ix, clientY: iy }));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const { doc, root } = resolveDoc();
|
|
92
|
+
if (!root) return JSON.stringify({ success: false, error: 'no root' });
|
|
93
|
+
|
|
94
|
+
const want =
|
|
95
|
+
typeof targetMode === 'string'
|
|
96
|
+
? targetMode.trim()
|
|
97
|
+
: targetMode != null
|
|
98
|
+
? String(targetMode).trim()
|
|
99
|
+
: '';
|
|
100
|
+
if (!want) return JSON.stringify({ success: false, error: 'empty mode' });
|
|
101
|
+
|
|
102
|
+
const modeBtn = findModeMenuButton(doc);
|
|
103
|
+
if (!modeBtn) return JSON.stringify({ success: false, error: 'mode menu button not found' });
|
|
104
|
+
|
|
105
|
+
const currentLabel = (modeBtn.textContent || '').trim();
|
|
106
|
+
if (currentLabel.toLowerCase() === want.toLowerCase()) {
|
|
107
|
+
return JSON.stringify({ success: true, mode: currentLabel, changed: false });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
openMenu(modeBtn);
|
|
111
|
+
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
let menu = doc.querySelector('[role="menu"][data-state="open"]');
|
|
115
|
+
if (!menu) menu = doc.querySelector('[role="menu"]');
|
|
116
|
+
|
|
117
|
+
if (!menu) {
|
|
118
|
+
doc.dispatchEvent(
|
|
119
|
+
new KeyboardEvent('keydown', { key: 'Escape', code: 'Escape', keyCode: 27, bubbles: true }),
|
|
120
|
+
);
|
|
121
|
+
return resolve(JSON.stringify({ success: false, error: 'mode menu did not open' }));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const items = Array.from(
|
|
125
|
+
menu.querySelectorAll(
|
|
126
|
+
'[role="menuitem"], [role="menuitemradio"], [role="option"], div[class*="cursor-interaction"]',
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const norm = (s) => (s || '').trim().toLowerCase();
|
|
131
|
+
const wantN = norm(want);
|
|
132
|
+
|
|
133
|
+
let match = items.find((el) => norm(el.textContent) === wantN);
|
|
134
|
+
if (!match) {
|
|
135
|
+
match = items.find((el) => norm(el.textContent).includes(wantN) || wantN.includes(norm(el.textContent)));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!match) {
|
|
139
|
+
doc.dispatchEvent(
|
|
140
|
+
new KeyboardEvent('keydown', { key: 'Escape', code: 'Escape', keyCode: 27, bubbles: true }),
|
|
141
|
+
);
|
|
142
|
+
const available = items
|
|
143
|
+
.map((el) => (el.textContent || '').trim())
|
|
144
|
+
.filter((t) => t.length > 0 && t.length < 80);
|
|
145
|
+
return resolve(
|
|
146
|
+
JSON.stringify({
|
|
147
|
+
success: false,
|
|
148
|
+
error: `mode "${want}" not found`,
|
|
149
|
+
available,
|
|
150
|
+
}),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const picked = (match.textContent || '').trim();
|
|
155
|
+
clickItem(match);
|
|
156
|
+
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
resolve(JSON.stringify({ success: true, mode: picked, changed: true }));
|
|
159
|
+
}, 350);
|
|
160
|
+
}, 550);
|
|
161
|
+
});
|
|
162
|
+
} catch (e) {
|
|
163
|
+
return JSON.stringify({ success: false, error: e.message || String(e) });
|
|
164
|
+
}
|
|
165
|
+
})();
|
|
@@ -1,70 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"type": "cursor",
|
|
3
|
-
"name": "Cursor",
|
|
4
|
-
"category": "ide",
|
|
5
|
-
"displayName": "Cursor",
|
|
6
|
-
"icon": "⚡",
|
|
7
|
-
"cli": "cursor",
|
|
8
|
-
"cdpPorts": [
|
|
9
|
-
9333,
|
|
10
|
-
9334
|
|
11
|
-
],
|
|
12
|
-
"targetFilter": {
|
|
13
|
-
"urlIncludes": "workbench.html",
|
|
14
|
-
"urlExcludes": ["agent"],
|
|
15
|
-
"titleExcludes": "extension-output|ADHDev CDP|Debug Console|Output\\s*$|Launchpad"
|
|
16
|
-
},
|
|
17
|
-
"processNames": {
|
|
18
|
-
"darwin": "Cursor",
|
|
19
|
-
"win32": [
|
|
20
|
-
"Cursor.exe"
|
|
21
|
-
]
|
|
22
|
-
},
|
|
23
|
-
"paths": {
|
|
24
|
-
"darwin": [
|
|
25
|
-
"/Applications/Cursor.app"
|
|
26
|
-
],
|
|
27
|
-
"win32": [
|
|
28
|
-
"C:\\Users\\*\\AppData\\Local\\Programs\\cursor\\Cursor.exe"
|
|
29
|
-
],
|
|
30
|
-
"linux": [
|
|
31
|
-
"/opt/Cursor",
|
|
32
|
-
"/usr/share/cursor"
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
|
-
"inputMethod": "cdp-type-and-send",
|
|
36
|
-
"inputSelector": ".aislash-editor-input[contenteditable=\"true\"]",
|
|
37
|
-
"versionCommand": "cursor --version",
|
|
38
|
-
"providerVersion": "1.0.0",
|
|
39
|
-
"compatibility": [
|
|
40
|
-
{ "ideVersion": ">=0.49.0", "scriptDir": "scripts/0.49" }
|
|
41
|
-
],
|
|
42
|
-
"defaultScriptDir": "scripts/0.49",
|
|
43
|
-
"vscodeCommands": {
|
|
44
|
-
"changeModel": "cursor.model"
|
|
45
|
-
},
|
|
46
|
-
"settings": {
|
|
47
|
-
"approvalAlert": {
|
|
48
|
-
"type": "boolean",
|
|
49
|
-
"default": true,
|
|
50
|
-
"public": true,
|
|
51
|
-
"label": "Approval Notifications",
|
|
52
|
-
"description": "Show notification when approval is needed"
|
|
53
|
-
},
|
|
54
|
-
"longGeneratingAlert": {
|
|
55
|
-
"type": "boolean",
|
|
56
|
-
"default": true,
|
|
57
|
-
"public": true,
|
|
58
|
-
"label": "Long Generation Alert",
|
|
59
|
-
"description": "Alert when generation takes too long"
|
|
60
|
-
},
|
|
61
|
-
"longGeneratingThresholdSec": {
|
|
62
|
-
"type": "number",
|
|
63
|
-
"default": 180,
|
|
64
|
-
"public": true,
|
|
65
|
-
"label": "Long Generation Threshold (sec)",
|
|
66
|
-
"min": 30,
|
|
67
|
-
"max": 600
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
1
|
+
JSON.stringify((() => { const frames = document.querySelectorAll('iframe.webview'); const results = []; frames.forEach((f, i) => { try { results.push({ index: i, src: f.src?.substring(0, 200), id: f.id?.substring(0, 100), class: f.className?.substring(0, 100) }); } catch(e) { results.push({ index: i, error: e.message }); } }); return { total: frames.length, frames: results }; })())
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "cursor",
|
|
3
|
+
"name": "Cursor",
|
|
4
|
+
"category": "ide",
|
|
5
|
+
"displayName": "Cursor",
|
|
6
|
+
"icon": "⚡",
|
|
7
|
+
"cli": "cursor",
|
|
8
|
+
"cdpPorts": [
|
|
9
|
+
9333,
|
|
10
|
+
9334
|
|
11
|
+
],
|
|
12
|
+
"targetFilter": {
|
|
13
|
+
"urlIncludes": "workbench.html",
|
|
14
|
+
"urlExcludes": ["agent"],
|
|
15
|
+
"titleExcludes": "extension-output|ADHDev CDP|Debug Console|Output\\s*$|Launchpad"
|
|
16
|
+
},
|
|
17
|
+
"processNames": {
|
|
18
|
+
"darwin": "Cursor",
|
|
19
|
+
"win32": [
|
|
20
|
+
"Cursor.exe"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"paths": {
|
|
24
|
+
"darwin": [
|
|
25
|
+
"/Applications/Cursor.app"
|
|
26
|
+
],
|
|
27
|
+
"win32": [
|
|
28
|
+
"C:\\Users\\*\\AppData\\Local\\Programs\\cursor\\Cursor.exe"
|
|
29
|
+
],
|
|
30
|
+
"linux": [
|
|
31
|
+
"/opt/Cursor",
|
|
32
|
+
"/usr/share/cursor"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"inputMethod": "cdp-type-and-send",
|
|
36
|
+
"inputSelector": ".aislash-editor-input[contenteditable=\"true\"]",
|
|
37
|
+
"versionCommand": "cursor --version",
|
|
38
|
+
"providerVersion": "1.0.0",
|
|
39
|
+
"compatibility": [
|
|
40
|
+
{ "ideVersion": ">=0.49.0", "scriptDir": "scripts/0.49" }
|
|
41
|
+
],
|
|
42
|
+
"defaultScriptDir": "scripts/0.49",
|
|
43
|
+
"vscodeCommands": {
|
|
44
|
+
"changeModel": "cursor.model"
|
|
45
|
+
},
|
|
46
|
+
"settings": {
|
|
47
|
+
"approvalAlert": {
|
|
48
|
+
"type": "boolean",
|
|
49
|
+
"default": true,
|
|
50
|
+
"public": true,
|
|
51
|
+
"label": "Approval Notifications",
|
|
52
|
+
"description": "Show notification when approval is needed"
|
|
53
|
+
},
|
|
54
|
+
"longGeneratingAlert": {
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"default": true,
|
|
57
|
+
"public": true,
|
|
58
|
+
"label": "Long Generation Alert",
|
|
59
|
+
"description": "Alert when generation takes too long"
|
|
60
|
+
},
|
|
61
|
+
"longGeneratingThresholdSec": {
|
|
62
|
+
"type": "number",
|
|
63
|
+
"default": 180,
|
|
64
|
+
"public": true,
|
|
65
|
+
"label": "Long Generation Threshold (sec)",
|
|
66
|
+
"min": 30,
|
|
67
|
+
"max": 600
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|