adhdev 0.1.46 → 0.1.48
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 +1178 -459
- package/package.json +1 -1
- package/providers/_builtin/extension/cline/provider.js +22 -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/set_mode.js +36 -0
- package/providers/_builtin/extension/cline/scripts/set_model.js +36 -0
- package/providers/_builtin/extension/roo-code/provider.js +151 -0
- package/providers/_builtin/ide/antigravity/provider.js +22 -0
- package/providers/_builtin/ide/antigravity/scripts/list_models.js +38 -0
- package/providers/_builtin/ide/antigravity/scripts/list_modes.js +48 -0
- package/providers/_builtin/ide/antigravity/scripts/resolve_action.js +55 -51
- package/providers/_builtin/ide/antigravity/scripts/set_mode.js +34 -0
- package/providers/_builtin/ide/antigravity/scripts/set_model.js +47 -0
- package/providers/_builtin/ide/cursor/provider.js +259 -11
- package/providers/_builtin/ide/kiro/provider.js +62 -0
- package/providers/_builtin/ide/pearai/provider.js +62 -0
- package/providers/_builtin/ide/trae/provider.js +62 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity — set_model
|
|
3
|
+
* antigravity-agent-side-panel 모델 드롭다운에서 모델 선택
|
|
4
|
+
* ${MODEL} → JSON.stringify(modelName)
|
|
5
|
+
* → { success: boolean, model?: string }
|
|
6
|
+
*/
|
|
7
|
+
(async () => {
|
|
8
|
+
try {
|
|
9
|
+
const target = ${MODEL};
|
|
10
|
+
|
|
11
|
+
// 1. 모델 드롭다운이 열려 있는 경우 → 직접 선택
|
|
12
|
+
const items = document.querySelectorAll('.px-2.py-1.flex.items-center.justify-between.cursor-pointer');
|
|
13
|
+
for (const item of items) {
|
|
14
|
+
const label = item.querySelector('.text-xs.font-medium');
|
|
15
|
+
const text = (label || item).textContent?.trim();
|
|
16
|
+
if (text && (text === target || text.toLowerCase().includes(target.toLowerCase()))) {
|
|
17
|
+
item.click();
|
|
18
|
+
await new Promise(r => setTimeout(r, 200));
|
|
19
|
+
return JSON.stringify({ success: true, model: text });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 2. 드롭다운이 닫혀 있으면 → 트리거 버튼 클릭해서 열기
|
|
24
|
+
const trigger = document.querySelector('.flex.min-w-0.max-w-full.cursor-pointer.items-center');
|
|
25
|
+
if (trigger) {
|
|
26
|
+
trigger.click();
|
|
27
|
+
await new Promise(r => setTimeout(r, 400));
|
|
28
|
+
|
|
29
|
+
// 다시 항목 탐색
|
|
30
|
+
const newItems = document.querySelectorAll('.px-2.py-1.flex.items-center.justify-between.cursor-pointer');
|
|
31
|
+
for (const item of newItems) {
|
|
32
|
+
const label = item.querySelector('.text-xs.font-medium');
|
|
33
|
+
const text = (label || item).textContent?.trim();
|
|
34
|
+
if (text && (text === target || text.toLowerCase().includes(target.toLowerCase()))) {
|
|
35
|
+
item.click();
|
|
36
|
+
return JSON.stringify({ success: true, model: text });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 못 찾으면 드롭다운 닫기
|
|
40
|
+
trigger.click();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return JSON.stringify({ success: false, error: 'model not found: ' + target });
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
46
|
+
}
|
|
47
|
+
})()
|
|
@@ -35,30 +35,48 @@ module.exports = {
|
|
|
35
35
|
|
|
36
36
|
// Detect approval dialogs
|
|
37
37
|
let activeModal = null;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
// Primary signal: Cursor uses .run-command-review-active on conversations container
|
|
40
|
+
const reviewActive = !!document.querySelector('.run-command-review-active');
|
|
41
|
+
|
|
42
|
+
// Also check clickable elements (Cursor uses divs with cursor-pointer, not buttons)
|
|
43
|
+
// Note: Cursor concatenates button text with shortcut key labels (e.g. "SkipEsc", "Run⏎")
|
|
44
|
+
const clickableEls = [...document.querySelectorAll('button, [role="button"], .cursor-pointer')].filter(b =>
|
|
45
|
+
b.offsetWidth > 0 && /^(accept|reject|approve|deny|run|skip|allow|cancel)/i.test((b.textContent || b.getAttribute('aria-label') || '').trim())
|
|
40
46
|
);
|
|
41
|
-
|
|
47
|
+
|
|
48
|
+
if (reviewActive || clickableEls.length > 0) {
|
|
42
49
|
status = 'waiting_approval';
|
|
50
|
+
const reviewContainer = document.querySelector('.run-command-review-active');
|
|
51
|
+
// Find the tool call context — last rendered message has the command being reviewed
|
|
52
|
+
const renderedMsgs = reviewContainer?.querySelectorAll('.composer-rendered-message');
|
|
53
|
+
const lastRendered = renderedMsgs?.length ? renderedMsgs[renderedMsgs.length - 1] : null;
|
|
54
|
+
const toolMsg = lastRendered || reviewContainer?.querySelector('.composer-tool-former-message:last-of-type');
|
|
43
55
|
activeModal = {
|
|
44
|
-
message:
|
|
45
|
-
buttons:
|
|
56
|
+
message: toolMsg?.textContent?.trim()?.substring(0, 200) || 'Command approval required',
|
|
57
|
+
buttons: clickableEls.map(b => b.textContent.trim().replace(/[⏎↵]/g, '').trim()).filter(Boolean),
|
|
46
58
|
};
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
const msgs = [];
|
|
50
62
|
document.querySelectorAll('.composer-human-ai-pair-container').forEach((p, i) => {
|
|
51
63
|
const h = p.querySelector('.composer-human-message');
|
|
52
|
-
|
|
64
|
+
const userText = h ? h.textContent.trim().substring(0, 6000) : '';
|
|
65
|
+
if (h) msgs.push({ role: 'user', content: userText, index: msgs.length });
|
|
66
|
+
// pair의 첫 번째 자식은 사용자 메시지 블록 — 그 안의 rendered는 건너뜀
|
|
67
|
+
const firstChild = p.children[0];
|
|
53
68
|
p.querySelectorAll('.composer-rendered-message').forEach(a => {
|
|
69
|
+
if (firstChild && firstChild.contains(a)) return;
|
|
54
70
|
if (a.closest('.composer-human-message')) return;
|
|
55
71
|
const t = a.textContent.trim();
|
|
56
|
-
if (t) msgs.push({ role: 'assistant', content: t.substring(0, 6000), index: msgs.length });
|
|
72
|
+
if (t && t !== userText) msgs.push({ role: 'assistant', content: t.substring(0, 6000), index: msgs.length });
|
|
57
73
|
});
|
|
58
74
|
});
|
|
59
75
|
const inputEl = document.querySelector('.aislash-editor-input[contenteditable="true"]');
|
|
60
76
|
const inputContent = inputEl?.textContent?.trim() || '';
|
|
61
|
-
|
|
77
|
+
const titleParts = document.title.split(' — ');
|
|
78
|
+
const projectTitle = (titleParts.length >= 2 ? titleParts[titleParts.length - 2] : titleParts[0] || '').trim();
|
|
79
|
+
return JSON.stringify({ id, status, title: projectTitle, messages: msgs, inputContent, activeModal });
|
|
62
80
|
} catch(e) {
|
|
63
81
|
return JSON.stringify({ id: '', status: 'error', messages: [] });
|
|
64
82
|
}
|
|
@@ -185,11 +203,12 @@ module.exports = {
|
|
|
185
203
|
resolveAction(params) {
|
|
186
204
|
const action = typeof params === 'string' ? params : params?.action || 'approve';
|
|
187
205
|
const buttonText = params?.button || params?.buttonText
|
|
188
|
-
|| (action === 'approve' ? '
|
|
206
|
+
|| (action === 'approve' ? 'Run' : action === 'reject' ? 'Skip' : action);
|
|
189
207
|
return `(() => {
|
|
190
208
|
try {
|
|
191
|
-
const btns = [...document.querySelectorAll('button, [role="button"]')].filter(b => b.offsetWidth > 0);
|
|
192
|
-
const
|
|
209
|
+
const btns = [...document.querySelectorAll('button, [role="button"], .cursor-pointer')].filter(b => b.offsetWidth > 0);
|
|
210
|
+
const searchText = ${JSON.stringify((buttonText||'').toLowerCase())};
|
|
211
|
+
const target = btns.find(b => (b.textContent||'').trim().replace(/[⏎↵]/g, '').trim().toLowerCase().includes(searchText));
|
|
193
212
|
if (target) { target.click(); return JSON.stringify({ resolved: true, clicked: target.textContent.trim() }); }
|
|
194
213
|
return JSON.stringify({ resolved: false, available: btns.map(b => b.textContent.trim()).filter(Boolean).slice(0, 15) });
|
|
195
214
|
} catch(e) { return JSON.stringify({ resolved: false, error: e.message }); }
|
|
@@ -236,6 +255,235 @@ module.exports = {
|
|
|
236
255
|
if (closeBtn) { closeBtn.click(); return JSON.stringify({ dismissed: true }); }
|
|
237
256
|
return JSON.stringify({ dismissed: false, error: 'Close button not found' });
|
|
238
257
|
} catch(e) { return JSON.stringify({ dismissed: false, error: e.message }); }
|
|
258
|
+
})()`;
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* listModels → { models: string[], current: string }
|
|
263
|
+
* .composer-unified-dropdown-model 클릭 → Auto 토글 끄기 → 전체 모델 목록
|
|
264
|
+
*/
|
|
265
|
+
listModels(params) {
|
|
266
|
+
return `(async () => {
|
|
267
|
+
try {
|
|
268
|
+
let current = '';
|
|
269
|
+
const models = [];
|
|
270
|
+
|
|
271
|
+
// 현재 모델: .composer-unified-dropdown-model 텍스트
|
|
272
|
+
const modelBtn = document.querySelector('.composer-unified-dropdown-model');
|
|
273
|
+
if (modelBtn) {
|
|
274
|
+
current = modelBtn.textContent?.trim() || '';
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 드롭다운 열기
|
|
278
|
+
if (modelBtn) {
|
|
279
|
+
modelBtn.click();
|
|
280
|
+
await new Promise(r => setTimeout(r, 500));
|
|
281
|
+
|
|
282
|
+
const menu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
283
|
+
if (menu) {
|
|
284
|
+
// Auto 토글 확인 및 끄기
|
|
285
|
+
const autoItem = menu.querySelector('.composer-unified-context-menu-item[data-is-selected="true"]');
|
|
286
|
+
const autoToggle = autoItem ? [...autoItem.querySelectorAll('[class*="rounded-full"]')].find(el => el.offsetWidth === 24 && el.offsetHeight === 14) : null;
|
|
287
|
+
let wasAutoOn = false;
|
|
288
|
+
if (autoToggle) {
|
|
289
|
+
const bgStyle = autoToggle.getAttribute('style') || '';
|
|
290
|
+
wasAutoOn = bgStyle.includes('green');
|
|
291
|
+
if (wasAutoOn) {
|
|
292
|
+
autoToggle.click();
|
|
293
|
+
await new Promise(r => setTimeout(r, 500));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// 모델 목록 수집 (Auto 끈 상태)
|
|
298
|
+
const refreshedMenu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
299
|
+
if (refreshedMenu) {
|
|
300
|
+
const items = refreshedMenu.querySelectorAll('.composer-unified-context-menu-item');
|
|
301
|
+
for (const item of items) {
|
|
302
|
+
const nameEl = item.querySelector('.monaco-highlighted-label');
|
|
303
|
+
const name = nameEl?.textContent?.trim() || '';
|
|
304
|
+
if (name && name !== 'Add Models') {
|
|
305
|
+
// Think 모드 감지: codicon-br (brain) 아이콘
|
|
306
|
+
const hasBrain = !!item.querySelector('[class*="codicon-br"]');
|
|
307
|
+
const displayName = hasBrain ? name + ' 🧠' : name;
|
|
308
|
+
models.push(displayName);
|
|
309
|
+
if (item.getAttribute('data-is-selected') === 'true') current = displayName;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Auto 다시 켜기 (원래 상태 복원)
|
|
315
|
+
if (wasAutoOn) {
|
|
316
|
+
const newMenu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
317
|
+
const newAutoItem = newMenu?.querySelector('.composer-unified-context-menu-item');
|
|
318
|
+
const newToggle = newAutoItem ? [...newAutoItem.querySelectorAll('[class*="rounded-full"]')].find(el => el.offsetWidth === 24) : null;
|
|
319
|
+
if (newToggle) {
|
|
320
|
+
newToggle.click();
|
|
321
|
+
await new Promise(r => setTimeout(r, 200));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// 닫기 (Escape)
|
|
327
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return JSON.stringify({ models, current });
|
|
331
|
+
} catch(e) { return JSON.stringify({ models: [], current: '', error: e.message }); }
|
|
332
|
+
})()`;
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* setModel → { success: boolean }
|
|
337
|
+
* .composer-unified-dropdown-model 클릭 → 검색 → 선택
|
|
338
|
+
*/
|
|
339
|
+
setModel(params) {
|
|
340
|
+
const model = typeof params === 'string' ? params : params?.model;
|
|
341
|
+
const escaped = JSON.stringify(model);
|
|
342
|
+
return `(async () => {
|
|
343
|
+
try {
|
|
344
|
+
const target = ${escaped};
|
|
345
|
+
|
|
346
|
+
// 모델 드롭다운 열기
|
|
347
|
+
const modelBtn = document.querySelector('.composer-unified-dropdown-model');
|
|
348
|
+
if (!modelBtn) return JSON.stringify({ success: false, error: 'Model button not found' });
|
|
349
|
+
|
|
350
|
+
modelBtn.click();
|
|
351
|
+
await new Promise(r => setTimeout(r, 500));
|
|
352
|
+
|
|
353
|
+
const menu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
354
|
+
if (!menu) return JSON.stringify({ success: false, error: 'Model picker menu not found' });
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
// 🧠 접미사 처리
|
|
358
|
+
const wantBrain = target.includes('🧠');
|
|
359
|
+
const searchName = target.replace(/\\s*🧠\\s*$/, '').trim();
|
|
360
|
+
|
|
361
|
+
// Auto 토글 끄기 (모델 목록 노출)
|
|
362
|
+
const autoItem = menu.querySelector('.composer-unified-context-menu-item[data-is-selected="true"]');
|
|
363
|
+
const autoToggle = autoItem ? [...autoItem.querySelectorAll('[class*="rounded-full"]')].find(el => el.offsetWidth === 24 && el.offsetHeight === 14) : null;
|
|
364
|
+
let wasAutoOn = false;
|
|
365
|
+
if (autoToggle) {
|
|
366
|
+
const bgStyle = autoToggle.getAttribute('style') || '';
|
|
367
|
+
wasAutoOn = bgStyle.includes('green');
|
|
368
|
+
if (wasAutoOn) {
|
|
369
|
+
autoToggle.click();
|
|
370
|
+
await new Promise(r => setTimeout(r, 500));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// 검색 입력으로 필터링
|
|
375
|
+
const refreshedMenu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
376
|
+
const searchInput = refreshedMenu?.querySelector('input[placeholder="Search models"]');
|
|
377
|
+
if (searchInput) {
|
|
378
|
+
searchInput.focus();
|
|
379
|
+
searchInput.value = searchName;
|
|
380
|
+
searchInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
381
|
+
await new Promise(r => setTimeout(r, 300));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// 아이템에서 찾기 (brain 아이콘 매칭)
|
|
385
|
+
const items = (refreshedMenu || menu).querySelectorAll('.composer-unified-context-menu-item');
|
|
386
|
+
for (const item of items) {
|
|
387
|
+
const nameEl = item.querySelector('.monaco-highlighted-label');
|
|
388
|
+
const name = nameEl?.textContent?.trim() || '';
|
|
389
|
+
if (!name || name === 'Add Models') continue;
|
|
390
|
+
const hasBrain = !!item.querySelector('[class*="codicon-br"]');
|
|
391
|
+
|
|
392
|
+
if (name.toLowerCase().includes(searchName.toLowerCase()) && hasBrain === wantBrain) {
|
|
393
|
+
item.click();
|
|
394
|
+
await new Promise(r => setTimeout(r, 200));
|
|
395
|
+
const displayName = hasBrain ? name + ' 🧠' : name;
|
|
396
|
+
return JSON.stringify({ success: true, model: displayName });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Auto 복원 + 닫기
|
|
401
|
+
if (wasAutoOn) {
|
|
402
|
+
const nm = document.querySelector('[data-testid="model-picker-menu"]');
|
|
403
|
+
const nai = nm?.querySelector('.composer-unified-context-menu-item');
|
|
404
|
+
const nt = nai ? [...nai.querySelectorAll('[class*="rounded-full"]')].find(el => el.offsetWidth === 24) : null;
|
|
405
|
+
if (nt) nt.click();
|
|
406
|
+
await new Promise(r => setTimeout(r, 200));
|
|
407
|
+
}
|
|
408
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
409
|
+
return JSON.stringify({ success: false, error: 'model not found: ' + target });
|
|
410
|
+
} catch(e) { return JSON.stringify({ success: false, error: e.message }); }
|
|
411
|
+
})()`;
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* listModes → { modes: string[], current: string }
|
|
416
|
+
* .composer-unified-dropdown (모드 아이콘) 클릭 → Agent/Plan/Debug/Ask
|
|
417
|
+
*/
|
|
418
|
+
listModes(params) {
|
|
419
|
+
return `(async () => {
|
|
420
|
+
try {
|
|
421
|
+
const modes = [];
|
|
422
|
+
let current = '';
|
|
423
|
+
|
|
424
|
+
// 모드 드롭다운 버튼 (아이콘, model이 아닌 unified-dropdown)
|
|
425
|
+
const modeBtn = document.querySelector('.composer-unified-dropdown:not(.composer-unified-dropdown-model)');
|
|
426
|
+
if (!modeBtn) return JSON.stringify({ modes: [], current: '', error: 'Mode button not found' });
|
|
427
|
+
|
|
428
|
+
modeBtn.click();
|
|
429
|
+
await new Promise(r => setTimeout(r, 500));
|
|
430
|
+
|
|
431
|
+
// 팝오버에서 아이템 수집
|
|
432
|
+
const menu = document.querySelector('[data-testid="model-picker-menu"]') || document.querySelector('.typeahead-popover');
|
|
433
|
+
if (menu) {
|
|
434
|
+
const items = menu.querySelectorAll('.composer-unified-context-menu-item');
|
|
435
|
+
for (const item of items) {
|
|
436
|
+
const nameEl = item.querySelector('.monaco-highlighted-label');
|
|
437
|
+
const name = nameEl?.textContent?.trim() || '';
|
|
438
|
+
if (name) {
|
|
439
|
+
modes.push(name);
|
|
440
|
+
if (item.getAttribute('data-is-selected') === 'true') current = name;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// 닫기
|
|
446
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
447
|
+
|
|
448
|
+
return JSON.stringify({ modes, current });
|
|
449
|
+
} catch(e) { return JSON.stringify({ modes: [], current: '', error: e.message }); }
|
|
450
|
+
})()`;
|
|
451
|
+
},
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* setMode → { success: boolean }
|
|
455
|
+
* 모드 드롭다운 열기 → 항목 클릭
|
|
456
|
+
*/
|
|
457
|
+
setMode(params) {
|
|
458
|
+
const mode = typeof params === 'string' ? params : params?.mode;
|
|
459
|
+
const escaped = JSON.stringify(mode);
|
|
460
|
+
return `(async () => {
|
|
461
|
+
try {
|
|
462
|
+
const target = ${escaped};
|
|
463
|
+
|
|
464
|
+
const modeBtn = document.querySelector('.composer-unified-dropdown:not(.composer-unified-dropdown-model)');
|
|
465
|
+
if (!modeBtn) return JSON.stringify({ success: false, error: 'Mode button not found' });
|
|
466
|
+
|
|
467
|
+
modeBtn.click();
|
|
468
|
+
await new Promise(r => setTimeout(r, 500));
|
|
469
|
+
|
|
470
|
+
const menu = document.querySelector('[data-testid="model-picker-menu"]') || document.querySelector('.typeahead-popover');
|
|
471
|
+
if (!menu) return JSON.stringify({ success: false, error: 'Mode menu not found' });
|
|
472
|
+
|
|
473
|
+
const items = menu.querySelectorAll('.composer-unified-context-menu-item');
|
|
474
|
+
for (const item of items) {
|
|
475
|
+
const nameEl = item.querySelector('.monaco-highlighted-label');
|
|
476
|
+
const name = nameEl?.textContent?.trim() || '';
|
|
477
|
+
if (name && (name === target || name.toLowerCase() === target.toLowerCase())) {
|
|
478
|
+
item.click();
|
|
479
|
+
await new Promise(r => setTimeout(r, 200));
|
|
480
|
+
return JSON.stringify({ success: true, mode: name });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
485
|
+
return JSON.stringify({ success: false, error: 'mode not found: ' + target });
|
|
486
|
+
} catch(e) { return JSON.stringify({ success: false, error: e.message }); }
|
|
239
487
|
})()`;
|
|
240
488
|
},
|
|
241
489
|
},
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kiro (AWS) — IDE Provider
|
|
3
|
+
*
|
|
4
|
+
* Category: ide (VS Code fork, Code-OSS based)
|
|
5
|
+
* AWS의 AI-native spec-driven IDE
|
|
6
|
+
*
|
|
7
|
+
* @type {import('../../../src/providers/contracts').ProviderModule}
|
|
8
|
+
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const SCRIPTS_DIR = path.join(__dirname, 'scripts');
|
|
13
|
+
|
|
14
|
+
function loadScript(name) {
|
|
15
|
+
try {
|
|
16
|
+
return fs.readFileSync(path.join(SCRIPTS_DIR, name), 'utf8');
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
type: 'kiro',
|
|
24
|
+
name: 'Kiro',
|
|
25
|
+
category: 'ide',
|
|
26
|
+
|
|
27
|
+
// ─── IDE 인프라 ───
|
|
28
|
+
displayName: 'Kiro',
|
|
29
|
+
icon: '🪁',
|
|
30
|
+
cli: 'kiro',
|
|
31
|
+
cdpPorts: [9351, 9352],
|
|
32
|
+
processNames: {
|
|
33
|
+
darwin: 'Kiro',
|
|
34
|
+
win32: ['Kiro.exe'],
|
|
35
|
+
linux: ['kiro'],
|
|
36
|
+
},
|
|
37
|
+
paths: {
|
|
38
|
+
darwin: ['/Applications/Kiro.app'],
|
|
39
|
+
win32: [
|
|
40
|
+
'C:\\Users\\*\\AppData\\Local\\Programs\\kiro\\Kiro.exe',
|
|
41
|
+
],
|
|
42
|
+
linux: ['/opt/kiro', '/usr/share/kiro'],
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
inputMethod: 'cdp-type-and-send',
|
|
46
|
+
inputSelector: '[contenteditable="true"][role="textbox"]',
|
|
47
|
+
|
|
48
|
+
scripts: {
|
|
49
|
+
readChat() { return loadScript('read_chat.js'); },
|
|
50
|
+
sendMessage(text) {
|
|
51
|
+
const s = loadScript('send_message.js');
|
|
52
|
+
return s ? s.replace(/\$\{\s*MESSAGE\s*\}/g, JSON.stringify(text)) : null;
|
|
53
|
+
},
|
|
54
|
+
resolveAction(params) {
|
|
55
|
+
const action = typeof params === 'string' ? params : params?.action || 'approve';
|
|
56
|
+
const buttonText = params?.button || params?.buttonText
|
|
57
|
+
|| (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : action);
|
|
58
|
+
const s = loadScript('resolve_action.js');
|
|
59
|
+
return s ? s.replace(/\$\{\s*BUTTON_TEXT\s*\}/g, JSON.stringify(buttonText)) : null;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PearAI — IDE Provider
|
|
3
|
+
*
|
|
4
|
+
* Category: ide (VS Code + Continue fork)
|
|
5
|
+
* AI-powered open-source code editor
|
|
6
|
+
*
|
|
7
|
+
* @type {import('../../../src/providers/contracts').ProviderModule}
|
|
8
|
+
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const SCRIPTS_DIR = path.join(__dirname, 'scripts');
|
|
13
|
+
|
|
14
|
+
function loadScript(name) {
|
|
15
|
+
try {
|
|
16
|
+
return fs.readFileSync(path.join(SCRIPTS_DIR, name), 'utf8');
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
type: 'pearai',
|
|
24
|
+
name: 'PearAI',
|
|
25
|
+
category: 'ide',
|
|
26
|
+
|
|
27
|
+
// ─── IDE 인프라 ───
|
|
28
|
+
displayName: 'PearAI',
|
|
29
|
+
icon: '🍐',
|
|
30
|
+
cli: 'pearai',
|
|
31
|
+
cdpPorts: [9355, 9356],
|
|
32
|
+
processNames: {
|
|
33
|
+
darwin: 'PearAI',
|
|
34
|
+
win32: ['PearAI.exe'],
|
|
35
|
+
linux: ['pearai'],
|
|
36
|
+
},
|
|
37
|
+
paths: {
|
|
38
|
+
darwin: ['/Applications/PearAI.app'],
|
|
39
|
+
win32: [
|
|
40
|
+
'C:\\Users\\*\\AppData\\Local\\Programs\\pearai\\PearAI.exe',
|
|
41
|
+
],
|
|
42
|
+
linux: ['/opt/pearai', '/usr/share/pearai'],
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
inputMethod: 'cdp-type-and-send',
|
|
46
|
+
inputSelector: '[contenteditable="true"][role="textbox"]',
|
|
47
|
+
|
|
48
|
+
scripts: {
|
|
49
|
+
readChat() { return loadScript('read_chat.js'); },
|
|
50
|
+
sendMessage(text) {
|
|
51
|
+
const s = loadScript('send_message.js');
|
|
52
|
+
return s ? s.replace(/\$\{\s*MESSAGE\s*\}/g, JSON.stringify(text)) : null;
|
|
53
|
+
},
|
|
54
|
+
resolveAction(params) {
|
|
55
|
+
const action = typeof params === 'string' ? params : params?.action || 'approve';
|
|
56
|
+
const buttonText = params?.button || params?.buttonText
|
|
57
|
+
|| (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : action);
|
|
58
|
+
const s = loadScript('resolve_action.js');
|
|
59
|
+
return s ? s.replace(/\$\{\s*BUTTON_TEXT\s*\}/g, JSON.stringify(buttonText)) : null;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trae — IDE Provider
|
|
3
|
+
*
|
|
4
|
+
* Category: ide (VS Code fork by ByteDance)
|
|
5
|
+
* AI-powered code editor
|
|
6
|
+
*
|
|
7
|
+
* @type {import('../../../src/providers/contracts').ProviderModule}
|
|
8
|
+
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const SCRIPTS_DIR = path.join(__dirname, 'scripts');
|
|
13
|
+
|
|
14
|
+
function loadScript(name) {
|
|
15
|
+
try {
|
|
16
|
+
return fs.readFileSync(path.join(SCRIPTS_DIR, name), 'utf8');
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
type: 'trae',
|
|
24
|
+
name: 'Trae',
|
|
25
|
+
category: 'ide',
|
|
26
|
+
|
|
27
|
+
// ─── IDE 인프라 ───
|
|
28
|
+
displayName: 'Trae',
|
|
29
|
+
icon: '🔮',
|
|
30
|
+
cli: 'trae',
|
|
31
|
+
cdpPorts: [9353, 9354],
|
|
32
|
+
processNames: {
|
|
33
|
+
darwin: 'Trae',
|
|
34
|
+
win32: ['Trae.exe'],
|
|
35
|
+
linux: ['trae'],
|
|
36
|
+
},
|
|
37
|
+
paths: {
|
|
38
|
+
darwin: ['/Applications/Trae.app'],
|
|
39
|
+
win32: [
|
|
40
|
+
'C:\\Users\\*\\AppData\\Local\\Programs\\trae\\Trae.exe',
|
|
41
|
+
],
|
|
42
|
+
linux: ['/opt/trae', '/usr/share/trae'],
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
inputMethod: 'cdp-type-and-send',
|
|
46
|
+
inputSelector: '[contenteditable="true"][role="textbox"]',
|
|
47
|
+
|
|
48
|
+
scripts: {
|
|
49
|
+
readChat() { return loadScript('read_chat.js'); },
|
|
50
|
+
sendMessage(text) {
|
|
51
|
+
const s = loadScript('send_message.js');
|
|
52
|
+
return s ? s.replace(/\$\{\s*MESSAGE\s*\}/g, JSON.stringify(text)) : null;
|
|
53
|
+
},
|
|
54
|
+
resolveAction(params) {
|
|
55
|
+
const action = typeof params === 'string' ? params : params?.action || 'approve';
|
|
56
|
+
const buttonText = params?.button || params?.buttonText
|
|
57
|
+
|| (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : action);
|
|
58
|
+
const s = loadScript('resolve_action.js');
|
|
59
|
+
return s ? s.replace(/\$\{\s*BUTTON_TEXT\s*\}/g, JSON.stringify(buttonText)) : null;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|