@adhdev/daemon-core 0.6.12 → 0.6.13
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 +38 -88
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/providers/_builtin/ide/antigravity/provider.json +3 -2
- 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/read_chat.js +290 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/scripts.js +57 -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.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/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/resolve_action.js +63 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/switch_session.js +114 -0
- package/providers/_builtin/ide/cursor/provider.json +2 -2
- 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/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/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/cursor/scripts/0.49.bak/list_sessions.js +42 -0
- package/providers/_builtin/ide/cursor/scripts/0.49.bak/read_chat.js +79 -0
- package/src/commands/router.ts +3 -3
- package/src/daemon/dev-server.ts +35 -87
- package/src/daemon/scaffold-template.ts +9 -2
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.106}/focus_editor.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.106}/list_chats.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.106}/new_session.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.106}/resolve_action.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.106}/send_message.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.106}/switch_session.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.107}/list_models.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.107}/list_modes.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.107}/read_chat.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.107}/scripts.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.107}/set_mode.js +0 -0
- /package/providers/_builtin/ide/antigravity/scripts/{1.0 → 1.107}/set_model.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49}/list_sessions.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49}/read_chat.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/dismiss_notification.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/focus_editor.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/list_models.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/list_modes.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/list_notifications.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/new_session.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/open_panel.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/resolve_action.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/scripts.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/send_message.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/set_mode.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/set_model.js +0 -0
- /package/providers/_builtin/ide/cursor/scripts/{1.0 → 0.49.bak}/switch_session.js +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — open_panel
|
|
3
|
+
*
|
|
4
|
+
* 채팅/컴포저 패널 열기:
|
|
5
|
+
* 1. 이미 보이면 'visible' 반환
|
|
6
|
+
* 2. Agent/Chat/Composer 탭 찾아서 클릭
|
|
7
|
+
*/
|
|
8
|
+
(() => {
|
|
9
|
+
try {
|
|
10
|
+
const sidebar = document.getElementById('workbench.parts.auxiliarybar');
|
|
11
|
+
if (sidebar && sidebar.offsetWidth > 0) {
|
|
12
|
+
const chatView = document.querySelector('[data-composer-id]');
|
|
13
|
+
if (chatView) return JSON.stringify({ opened: true });
|
|
14
|
+
}
|
|
15
|
+
const btns = [...document.querySelectorAll('li.action-item a, button, [role="tab"]')];
|
|
16
|
+
const toggle = btns.find(b => {
|
|
17
|
+
const label = (b.textContent || b.getAttribute('aria-label') || '').toLowerCase();
|
|
18
|
+
return /agent|chat|composer|cursor tab/i.test(label);
|
|
19
|
+
});
|
|
20
|
+
if (toggle) { toggle.click(); return JSON.stringify({ opened: true }); }
|
|
21
|
+
return JSON.stringify({ opened: false, error: 'Panel toggle not found' });
|
|
22
|
+
} catch (e) { return JSON.stringify({ opened: false, error: e.message }); }
|
|
23
|
+
})()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — resolve_action
|
|
3
|
+
*
|
|
4
|
+
* 승인/거부 버튼 찾기 + 클릭:
|
|
5
|
+
* button, [role="button"], .cursor-pointer 중 텍스트 매칭
|
|
6
|
+
* Cursor는 단축키 라벨을 붙임 (e.g. "Run⏎", "SkipEsc") → ⏎↵ 제거 후 비교
|
|
7
|
+
*
|
|
8
|
+
* params.buttonText: string — 찾을 버튼 텍스트
|
|
9
|
+
* → { resolved: true/false, clicked?, available? }
|
|
10
|
+
*/
|
|
11
|
+
(params) => {
|
|
12
|
+
try {
|
|
13
|
+
const btns = [...document.querySelectorAll('button, [role="button"], .cursor-pointer')].filter(b => b.offsetWidth > 0);
|
|
14
|
+
const searchText = (params.buttonText || '').toLowerCase();
|
|
15
|
+
const target = btns.find(b => (b.textContent||'').trim().replace(/[⏎↵]/g, '').trim().toLowerCase().includes(searchText));
|
|
16
|
+
if (target) { target.click(); return JSON.stringify({ resolved: true, clicked: target.textContent.trim() }); }
|
|
17
|
+
return JSON.stringify({ resolved: false, available: btns.map(b => b.textContent.trim()).filter(Boolean).slice(0, 15) });
|
|
18
|
+
} catch(e) { return JSON.stringify({ resolved: false, error: e.message }); }
|
|
19
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor CDP Scripts — Router
|
|
3
|
+
*
|
|
4
|
+
* Version routing is handled by ProviderLoader:
|
|
5
|
+
* - provider.json "compatibility" field declares script directory overrides
|
|
6
|
+
* - VersionArchive detects installed Cursor version at daemon startup
|
|
7
|
+
* - resolve() picks the appropriate scripts/ directory
|
|
8
|
+
*
|
|
9
|
+
* Pattern:
|
|
10
|
+
* - Scripts WITHOUT params: loaded as-is (self-invoking IIFE)
|
|
11
|
+
* - Scripts WITH params: loaded as function expression, invoked with params JSON
|
|
12
|
+
* e.g. `(${script})(${JSON.stringify(params)})`
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
function load(name) {
|
|
21
|
+
try { return fs.readFileSync(path.join(__dirname, name), 'utf-8'); }
|
|
22
|
+
catch { return null; }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Wrap a function-expression script with params invocation */
|
|
26
|
+
function withParams(name, params) {
|
|
27
|
+
const script = load(name);
|
|
28
|
+
if (!script) return null;
|
|
29
|
+
return `(${script})(${JSON.stringify(params)})`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ─── Core (no params — IIFE) ───
|
|
33
|
+
|
|
34
|
+
module.exports.readChat = () => load('read_chat.js');
|
|
35
|
+
module.exports.sendMessage = () => load('send_message.js');
|
|
36
|
+
module.exports.listSessions = () => load('list_sessions.js');
|
|
37
|
+
module.exports.newSession = () => load('new_session.js');
|
|
38
|
+
module.exports.focusEditor = () => load('focus_editor.js');
|
|
39
|
+
module.exports.openPanel = () => load('open_panel.js');
|
|
40
|
+
module.exports.listModels = () => load('list_models.js');
|
|
41
|
+
module.exports.listModes = () => load('list_modes.js');
|
|
42
|
+
|
|
43
|
+
// ─── With params (function expression) ───
|
|
44
|
+
|
|
45
|
+
module.exports.switchSession = (params) => {
|
|
46
|
+
const index = typeof params === 'number' ? params : params?.index ?? 0;
|
|
47
|
+
const title = typeof params === 'string' ? params : params?.title || null;
|
|
48
|
+
return withParams('switch_session.js', { index, title });
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
module.exports.resolveAction = (params) => {
|
|
52
|
+
const action = typeof params === 'string' ? params : params?.action || 'approve';
|
|
53
|
+
const buttonText = params?.button || params?.buttonText
|
|
54
|
+
|| (action === 'approve' ? 'Run' : action === 'reject' ? 'Skip' : action);
|
|
55
|
+
return withParams('resolve_action.js', { buttonText });
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports.listNotifications = (params) => {
|
|
59
|
+
const filter = typeof params === 'string' ? params : params?.message || null;
|
|
60
|
+
return withParams('list_notifications.js', { filter });
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
module.exports.dismissNotification = (params) => {
|
|
64
|
+
const index = typeof params === 'number' ? params : params?.index ?? 0;
|
|
65
|
+
const button = typeof params === 'string' ? params : params?.button || null;
|
|
66
|
+
const message = params?.message || null;
|
|
67
|
+
return withParams('dismiss_notification.js', { index, button, message });
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
module.exports.setModel = (params) => {
|
|
71
|
+
const model = typeof params === 'string' ? params : params?.model;
|
|
72
|
+
return withParams('set_model.js', { model });
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
module.exports.setMode = (params) => {
|
|
76
|
+
const mode = typeof params === 'string' ? params : params?.mode;
|
|
77
|
+
return withParams('set_mode.js', { mode });
|
|
78
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — send_message
|
|
3
|
+
*
|
|
4
|
+
* Cursor는 cdp-type-and-send 방식:
|
|
5
|
+
* 1. 입력 필드 존재 확인
|
|
6
|
+
* 2. needsTypeAndSend: true 반환 → daemon이 CDP로 타이핑 + Enter 처리
|
|
7
|
+
*
|
|
8
|
+
* 입력 셀렉터: .aislash-editor-input[contenteditable="true"]
|
|
9
|
+
* 파라미터: ${ MESSAGE } (사용되지 않음 — daemon이 직접 타이핑)
|
|
10
|
+
*/
|
|
11
|
+
(() => {
|
|
12
|
+
try {
|
|
13
|
+
const input = document.querySelector('.aislash-editor-input[contenteditable="true"]');
|
|
14
|
+
if (!input) return JSON.stringify({ sent: false, error: 'Input box not found' });
|
|
15
|
+
return JSON.stringify({
|
|
16
|
+
sent: false,
|
|
17
|
+
needsTypeAndSend: true,
|
|
18
|
+
selector: '.aislash-editor-input[contenteditable="true"]',
|
|
19
|
+
});
|
|
20
|
+
} catch(e) {
|
|
21
|
+
return JSON.stringify({ sent: false, error: e.message });
|
|
22
|
+
}
|
|
23
|
+
})()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — set_mode
|
|
3
|
+
*
|
|
4
|
+
* 모드 드롭다운에서 대상 모드 선택:
|
|
5
|
+
* 1. 드롭다운 열기
|
|
6
|
+
* 2. 매칭 아이템 클릭
|
|
7
|
+
*
|
|
8
|
+
* params.mode: string — 모드 이름
|
|
9
|
+
* → { success: true/false, mode? }
|
|
10
|
+
*/
|
|
11
|
+
async (params) => {
|
|
12
|
+
try {
|
|
13
|
+
const target = params.mode;
|
|
14
|
+
|
|
15
|
+
const modeBtn = document.querySelector('.composer-unified-dropdown:not(.composer-unified-dropdown-model)');
|
|
16
|
+
if (!modeBtn) return JSON.stringify({ success: false, error: 'Mode button not found' });
|
|
17
|
+
|
|
18
|
+
modeBtn.click();
|
|
19
|
+
await new Promise(r => setTimeout(r, 500));
|
|
20
|
+
|
|
21
|
+
const menu = document.querySelector('[data-testid="model-picker-menu"]') || document.querySelector('.typeahead-popover');
|
|
22
|
+
if (!menu) return JSON.stringify({ success: false, error: 'Mode menu not found' });
|
|
23
|
+
|
|
24
|
+
const items = menu.querySelectorAll('.composer-unified-context-menu-item');
|
|
25
|
+
for (const item of items) {
|
|
26
|
+
const nameEl = item.querySelector('.monaco-highlighted-label');
|
|
27
|
+
const name = nameEl?.textContent?.trim() || '';
|
|
28
|
+
if (name && (name === target || name.toLowerCase() === target.toLowerCase())) {
|
|
29
|
+
item.click();
|
|
30
|
+
await new Promise(r => setTimeout(r, 200));
|
|
31
|
+
return JSON.stringify({ success: true, mode: name });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
36
|
+
return JSON.stringify({ success: false, error: 'mode not found: ' + target });
|
|
37
|
+
} catch(e) { return JSON.stringify({ success: false, error: e.message }); }
|
|
38
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — set_model
|
|
3
|
+
*
|
|
4
|
+
* 모델 드롭다운에서 대상 모델 선택:
|
|
5
|
+
* 1. 드롭다운 열기
|
|
6
|
+
* 2. Auto 토글 끄기 (필요 시)
|
|
7
|
+
* 3. 검색 입력으로 필터
|
|
8
|
+
* 4. 매칭 아이템 클릭
|
|
9
|
+
* 5. 원래 Auto 상태 복원
|
|
10
|
+
*
|
|
11
|
+
* params.model: string — 모델 이름 (🧠 접미사 가능)
|
|
12
|
+
* → { success: true/false, model? }
|
|
13
|
+
*/
|
|
14
|
+
async (params) => {
|
|
15
|
+
try {
|
|
16
|
+
const target = params.model;
|
|
17
|
+
|
|
18
|
+
const modelBtn = document.querySelector('.composer-unified-dropdown-model');
|
|
19
|
+
if (!modelBtn) return JSON.stringify({ success: false, error: 'Model button not found' });
|
|
20
|
+
|
|
21
|
+
modelBtn.click();
|
|
22
|
+
await new Promise(r => setTimeout(r, 500));
|
|
23
|
+
|
|
24
|
+
const menu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
25
|
+
if (!menu) return JSON.stringify({ success: false, error: 'Model picker menu not found' });
|
|
26
|
+
|
|
27
|
+
// 🧠 접미사 처리
|
|
28
|
+
const wantBrain = target.includes('🧠');
|
|
29
|
+
const searchName = target.replace(/\s*🧠\s*$/, '').trim();
|
|
30
|
+
|
|
31
|
+
// Auto 토글 끄기
|
|
32
|
+
const autoItem = menu.querySelector('.composer-unified-context-menu-item[data-is-selected="true"]');
|
|
33
|
+
const autoToggle = autoItem ? [...autoItem.querySelectorAll('[class*="rounded-full"]')].find(el => el.offsetWidth === 24 && el.offsetHeight === 14) : null;
|
|
34
|
+
let wasAutoOn = false;
|
|
35
|
+
if (autoToggle) {
|
|
36
|
+
const bgStyle = autoToggle.getAttribute('style') || '';
|
|
37
|
+
wasAutoOn = bgStyle.includes('green');
|
|
38
|
+
if (wasAutoOn) {
|
|
39
|
+
autoToggle.click();
|
|
40
|
+
await new Promise(r => setTimeout(r, 500));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 검색 입력으로 필터링
|
|
45
|
+
const refreshedMenu = document.querySelector('[data-testid="model-picker-menu"]');
|
|
46
|
+
const searchInput = refreshedMenu?.querySelector('input[placeholder="Search models"]');
|
|
47
|
+
if (searchInput) {
|
|
48
|
+
searchInput.focus();
|
|
49
|
+
searchInput.value = searchName;
|
|
50
|
+
searchInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
51
|
+
await new Promise(r => setTimeout(r, 300));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 아이템에서 찾기
|
|
55
|
+
const items = (refreshedMenu || menu).querySelectorAll('.composer-unified-context-menu-item');
|
|
56
|
+
for (const item of items) {
|
|
57
|
+
const nameEl = item.querySelector('.monaco-highlighted-label');
|
|
58
|
+
const name = nameEl?.textContent?.trim() || '';
|
|
59
|
+
if (!name || name === 'Add Models') continue;
|
|
60
|
+
const hasBrain = !!item.querySelector('[class*="codicon-br"]');
|
|
61
|
+
|
|
62
|
+
if (name.toLowerCase().includes(searchName.toLowerCase()) && hasBrain === wantBrain) {
|
|
63
|
+
item.click();
|
|
64
|
+
await new Promise(r => setTimeout(r, 200));
|
|
65
|
+
const displayName = hasBrain ? name + ' 🧠' : name;
|
|
66
|
+
return JSON.stringify({ success: true, model: displayName });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Auto 복원 + 닫기
|
|
71
|
+
if (wasAutoOn) {
|
|
72
|
+
const nm = document.querySelector('[data-testid="model-picker-menu"]');
|
|
73
|
+
const nai = nm?.querySelector('.composer-unified-context-menu-item');
|
|
74
|
+
const nt = nai ? [...nai.querySelectorAll('[class*="rounded-full"]')].find(el => el.offsetWidth === 24) : null;
|
|
75
|
+
if (nt) nt.click();
|
|
76
|
+
await new Promise(r => setTimeout(r, 200));
|
|
77
|
+
}
|
|
78
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
|
|
79
|
+
return JSON.stringify({ success: false, error: 'model not found: ' + target });
|
|
80
|
+
} catch(e) { return JSON.stringify({ success: false, error: e.message }); }
|
|
81
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — switch_session
|
|
3
|
+
*
|
|
4
|
+
* 사이드바 셀 클릭으로 세션 전환:
|
|
5
|
+
* 제목 매칭 (params.title) 또는 인덱스 (params.index)
|
|
6
|
+
*
|
|
7
|
+
* params.index: number, params.title: string|null
|
|
8
|
+
* → { switched: true/false, title?, error? }
|
|
9
|
+
*/
|
|
10
|
+
(params) => {
|
|
11
|
+
try {
|
|
12
|
+
const cells = [...document.querySelectorAll('.agent-sidebar-cell')];
|
|
13
|
+
let target;
|
|
14
|
+
if (params.title) {
|
|
15
|
+
target = cells.find(c => {
|
|
16
|
+
const t = c.querySelector('.agent-sidebar-cell-text')?.textContent?.trim() || '';
|
|
17
|
+
return t.toLowerCase().includes(params.title.toLowerCase());
|
|
18
|
+
});
|
|
19
|
+
} else {
|
|
20
|
+
target = cells[params.index || 0];
|
|
21
|
+
}
|
|
22
|
+
if (!target) return JSON.stringify({ switched: false, error: 'Session not found', available: cells.length });
|
|
23
|
+
target.click();
|
|
24
|
+
return JSON.stringify({ switched: true, title: target.querySelector('.agent-sidebar-cell-text')?.textContent?.trim() });
|
|
25
|
+
} catch(e) {
|
|
26
|
+
return JSON.stringify({ switched: false, error: e.message });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — list_sessions
|
|
3
|
+
*
|
|
4
|
+
* 사이드바 셀 목록에서 세션 파싱:
|
|
5
|
+
* 셀: .agent-sidebar-cell
|
|
6
|
+
* 제목: .agent-sidebar-cell-text
|
|
7
|
+
* 선택 상태: data-selected="true"
|
|
8
|
+
* 활성 ID: [data-composer-id]에서 추출
|
|
9
|
+
*
|
|
10
|
+
* → { sessions: [{ id, title, active, index }] }
|
|
11
|
+
*/
|
|
12
|
+
(() => {
|
|
13
|
+
try {
|
|
14
|
+
const sessions = [];
|
|
15
|
+
const cells = [...document.querySelectorAll('.agent-sidebar-cell')];
|
|
16
|
+
const activeComposer = document.querySelector('[data-composer-id]');
|
|
17
|
+
const activeId = activeComposer?.getAttribute('data-composer-id') || null;
|
|
18
|
+
cells.forEach((cell, i) => {
|
|
19
|
+
const titleEl = cell.querySelector('.agent-sidebar-cell-text');
|
|
20
|
+
const title = titleEl?.textContent?.trim() || 'Untitled';
|
|
21
|
+
const isSelected = cell.getAttribute('data-selected') === 'true';
|
|
22
|
+
sessions.push({
|
|
23
|
+
id: isSelected && activeId ? activeId : 'sidebar-' + i,
|
|
24
|
+
title,
|
|
25
|
+
active: isSelected,
|
|
26
|
+
index: i,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
// If no sidebar cells, fallback to current composer
|
|
30
|
+
if (sessions.length === 0 && activeComposer) {
|
|
31
|
+
sessions.push({
|
|
32
|
+
id: activeId,
|
|
33
|
+
title: document.title.split(' — ')[0],
|
|
34
|
+
active: true,
|
|
35
|
+
index: 0,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return JSON.stringify({ sessions });
|
|
39
|
+
} catch(e) {
|
|
40
|
+
return JSON.stringify({ sessions: [], error: e.message });
|
|
41
|
+
}
|
|
42
|
+
})()
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor — read_chat
|
|
3
|
+
*
|
|
4
|
+
* DOM 구조 (v0.49):
|
|
5
|
+
* 컴포저: [data-composer-id] + [data-composer-status]
|
|
6
|
+
* 메시지 쌍: .composer-human-ai-pair-container
|
|
7
|
+
* 사용자: .composer-human-message
|
|
8
|
+
* AI: direct children after first (tool/assistant)
|
|
9
|
+
* 입력: .aislash-editor-input[contenteditable="true"]
|
|
10
|
+
* 승인: .run-command-review-active + button/cursor-pointer 요소
|
|
11
|
+
*
|
|
12
|
+
* → { id, status, title, messages[], inputContent, activeModal }
|
|
13
|
+
*/
|
|
14
|
+
(() => {
|
|
15
|
+
try {
|
|
16
|
+
const c = document.querySelector('[data-composer-id]');
|
|
17
|
+
const id = c?.getAttribute('data-composer-id') || 'active';
|
|
18
|
+
const rawStatus = c?.getAttribute('data-composer-status') || 'idle';
|
|
19
|
+
let status = rawStatus;
|
|
20
|
+
if (rawStatus === 'thinking' || rawStatus === 'streaming') status = 'generating';
|
|
21
|
+
else if (rawStatus === 'completed' || rawStatus === 'idle' || !rawStatus) status = 'idle';
|
|
22
|
+
|
|
23
|
+
// Detect approval dialogs
|
|
24
|
+
let activeModal = null;
|
|
25
|
+
|
|
26
|
+
// Primary signal: Cursor uses .run-command-review-active on conversations container
|
|
27
|
+
const reviewActive = !!document.querySelector('.run-command-review-active');
|
|
28
|
+
|
|
29
|
+
// Also check clickable elements (Cursor uses divs with cursor-pointer, not buttons)
|
|
30
|
+
// Note: Cursor concatenates button text with shortcut key labels (e.g. "SkipEsc", "Run⏎")
|
|
31
|
+
const clickableEls = [...document.querySelectorAll('button, [role="button"], .cursor-pointer')].filter(b =>
|
|
32
|
+
b.offsetWidth > 0 && /^(accept|reject|approve|deny|run|skip|allow|cancel)/i.test((b.textContent || b.getAttribute('aria-label') || '').trim())
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (reviewActive || clickableEls.length > 0) {
|
|
36
|
+
status = 'waiting_approval';
|
|
37
|
+
const reviewContainer = document.querySelector('.run-command-review-active');
|
|
38
|
+
const renderedMsgs = reviewContainer?.querySelectorAll('.composer-rendered-message');
|
|
39
|
+
const lastRendered = renderedMsgs?.length ? renderedMsgs[renderedMsgs.length - 1] : null;
|
|
40
|
+
const toolMsg = lastRendered || reviewContainer?.querySelector('.composer-tool-former-message:last-of-type');
|
|
41
|
+
activeModal = {
|
|
42
|
+
message: toolMsg?.textContent?.trim()?.substring(0, 200) || 'Command approval required',
|
|
43
|
+
buttons: clickableEls.map(b => b.textContent.trim().replace(/[⏎↵]/g, '').trim()).filter(Boolean),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const msgs = [];
|
|
48
|
+
document.querySelectorAll('.composer-human-ai-pair-container').forEach((p, i) => {
|
|
49
|
+
if (p.children.length === 0) return; // skip virtual-scroll placeholders
|
|
50
|
+
const h = p.querySelector('.composer-human-message');
|
|
51
|
+
if (h) {
|
|
52
|
+
const userText = (h.innerText || '').trim().substring(0, 6000);
|
|
53
|
+
if (userText) msgs.push({ role: 'user', content: userText, index: msgs.length });
|
|
54
|
+
}
|
|
55
|
+
// Iterate direct children after the first (user message block)
|
|
56
|
+
for (let ci = 1; ci < p.children.length; ci++) {
|
|
57
|
+
const b = p.children[ci];
|
|
58
|
+
if ((b.className || '').includes('opacity-50')) continue;
|
|
59
|
+
const t = (b.innerText || '').trim();
|
|
60
|
+
if (t.length < 2) continue;
|
|
61
|
+
// Filter noise: "Thought for Xs", "Explored N files", step group timing headers (e.g. "Crafting a minimal response\n1s")
|
|
62
|
+
if (/^Thought\nfor \d+s?$/i.test(t) || /^Explored\n/i.test(t)) continue;
|
|
63
|
+
if (/^.{1,80}\n\d+s$/.test(t) && !t.includes('\n\n')) continue; // step-group collapsible header with timing
|
|
64
|
+
// Skip step-group collapsible headers (e.g. "Crafting a minimal response\n1s")
|
|
65
|
+
if (b.querySelector('.ui-step-group-collapsible, .ui-collapsible-header') &&
|
|
66
|
+
!b.querySelector('.composer-rendered-message, .composer-tool-former-message, .composer-diff-block')) continue;
|
|
67
|
+
const hasTool = b.querySelector('.composer-tool-former-message, .composer-diff-block, .composer-code-block-container');
|
|
68
|
+
msgs.push({ role: hasTool ? 'tool' : 'assistant', content: t.substring(0, 6000), index: msgs.length });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
const inputEl = document.querySelector('.aislash-editor-input[contenteditable="true"]');
|
|
72
|
+
const inputContent = inputEl?.textContent?.trim() || '';
|
|
73
|
+
const titleParts = document.title.split(' — ');
|
|
74
|
+
const projectTitle = (titleParts.length >= 2 ? titleParts[titleParts.length - 2] : titleParts[0] || '').trim();
|
|
75
|
+
return JSON.stringify({ id, status, title: projectTitle, messages: msgs, inputContent, activeModal });
|
|
76
|
+
} catch(e) {
|
|
77
|
+
return JSON.stringify({ id: '', status: 'error', messages: [] });
|
|
78
|
+
}
|
|
79
|
+
})()
|
package/src/commands/router.ts
CHANGED
|
@@ -268,10 +268,10 @@ export class DaemonCommandRouter {
|
|
|
268
268
|
const latest = execSync(`npm view ${pkgName} version`, { encoding: 'utf-8', timeout: 10000 }).trim();
|
|
269
269
|
LOG.info('Upgrade', `Latest ${pkgName}: v${latest}`);
|
|
270
270
|
|
|
271
|
-
// Install latest
|
|
272
|
-
execSync(`npm install -g ${pkgName}@latest`, {
|
|
271
|
+
// Install latest (--force ensures native addons are rebuilt cleanly)
|
|
272
|
+
execSync(`npm install -g ${pkgName}@latest --force`, {
|
|
273
273
|
encoding: 'utf-8',
|
|
274
|
-
timeout:
|
|
274
|
+
timeout: 120000,
|
|
275
275
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
276
276
|
});
|
|
277
277
|
LOG.info('Upgrade', `✅ Upgraded to v${latest}`);
|
package/src/daemon/dev-server.ts
CHANGED
|
@@ -1055,7 +1055,7 @@ export class DevServer {
|
|
|
1055
1055
|
private async handleScaffold(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
1056
1056
|
const body = await this.readBody(req);
|
|
1057
1057
|
const { type, name, category = 'ide', location = 'user',
|
|
1058
|
-
cdpPorts, cli, processName, installPath, binary, extensionId, version } = body;
|
|
1058
|
+
cdpPorts, cli, processName, installPath, binary, extensionId, version, osPaths, processNames } = body;
|
|
1059
1059
|
if (!type || !name) {
|
|
1060
1060
|
this.json(res, 400, { error: 'type and name required' });
|
|
1061
1061
|
return;
|
|
@@ -1076,7 +1076,7 @@ export class DevServer {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
|
|
1078
1078
|
try {
|
|
1079
|
-
const result = genScaffoldFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version });
|
|
1079
|
+
const result = genScaffoldFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version, osPaths, processNames });
|
|
1080
1080
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
1081
1081
|
fs.writeFileSync(jsonPath, result['provider.json'], 'utf-8');
|
|
1082
1082
|
const createdFiles = ['provider.json'];
|
|
@@ -1843,51 +1843,9 @@ export class DevServer {
|
|
|
1843
1843
|
|
|
1844
1844
|
try {
|
|
1845
1845
|
// 1. Collect DOM context
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
const cdp = this.getCdp(type);
|
|
1850
|
-
if (cdp) {
|
|
1851
|
-
try {
|
|
1852
|
-
const domScript = `(() => {
|
|
1853
|
-
function fp(el) {
|
|
1854
|
-
if (!el || el === document.body) return 'body';
|
|
1855
|
-
const parts = [];
|
|
1856
|
-
let c = el;
|
|
1857
|
-
while (c && c !== document.documentElement) {
|
|
1858
|
-
let s = c.tagName.toLowerCase();
|
|
1859
|
-
if (c.id) s = '#' + c.id;
|
|
1860
|
-
else if (c.className && typeof c.className === 'string') {
|
|
1861
|
-
const cls = c.className.trim().split(/\\s+/).filter(x => x && !x.startsWith('_')).slice(0, 2);
|
|
1862
|
-
if (cls.length) s += '.' + cls.join('.');
|
|
1863
|
-
}
|
|
1864
|
-
parts.unshift(s);
|
|
1865
|
-
c = c.parentElement;
|
|
1866
|
-
}
|
|
1867
|
-
return parts.join(' > ');
|
|
1868
|
-
}
|
|
1869
|
-
const r = {};
|
|
1870
|
-
// Content editables
|
|
1871
|
-
r.editables = [...document.querySelectorAll('[contenteditable], textarea, input')].filter(e => e.offsetWidth > 0).slice(0, 10).map(e => ({
|
|
1872
|
-
selector: fp(e), tag: e.tagName.toLowerCase(), ce: e.getAttribute('contenteditable'), role: e.getAttribute('role'), ph: e.getAttribute('placeholder')
|
|
1873
|
-
}));
|
|
1874
|
-
// Scroll containers
|
|
1875
|
-
r.scrollContainers = [...document.querySelectorAll('div, section')].filter(e => {
|
|
1876
|
-
const s = getComputedStyle(e); const b = e.getBoundingClientRect();
|
|
1877
|
-
return (s.overflowY === 'auto' || s.overflowY === 'scroll') && b.height > 200 && e.children.length > 2;
|
|
1878
|
-
}).slice(0, 5).map(e => ({ selector: fp(e), children: e.children.length, h: Math.round(e.getBoundingClientRect().height) }));
|
|
1879
|
-
// Buttons
|
|
1880
|
-
r.buttons = [...document.querySelectorAll('button, [role="button"]')].filter(e => e.offsetWidth > 0).slice(0, 20).map(e => ({
|
|
1881
|
-
text: (e.textContent||'').trim().substring(0, 60), selector: fp(e), label: e.getAttribute('aria-label')
|
|
1882
|
-
}));
|
|
1883
|
-
return JSON.stringify(r);
|
|
1884
|
-
})()`;
|
|
1885
|
-
const raw = await cdp.evaluate(domScript, 10000);
|
|
1886
|
-
domContext = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
1887
|
-
} catch (e: any) {
|
|
1888
|
-
this.log(`DOM context collection failed (non-fatal): ${e.message}`);
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1846
|
+
// 1. Skip heavy DOM pre-parsing (Agent will use cURL to explore via CDP!)
|
|
1847
|
+
this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'analyzing', message: '에이전트 초기화 (DOM 탐색 권한 부여)...' } });
|
|
1848
|
+
const domContext = null;
|
|
1891
1849
|
|
|
1892
1850
|
// 2. Load reference scripts
|
|
1893
1851
|
this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'loading_reference', message: `레퍼런스 스크립트 로드 중 (${reference})...` } });
|
|
@@ -2086,26 +2044,17 @@ export class DevServer {
|
|
|
2086
2044
|
args = [...baseArgs];
|
|
2087
2045
|
}
|
|
2088
2046
|
|
|
2089
|
-
//
|
|
2090
|
-
const { execSync } = await import('child_process');
|
|
2091
|
-
try {
|
|
2092
|
-
execSync(`which ${command}`, { stdio: 'pipe' });
|
|
2093
|
-
} catch {
|
|
2094
|
-
try { fs.unlinkSync(promptFile); } catch { /* ignore */ }
|
|
2095
|
-
this.json(res, 400, { error: `Agent binary '${command}' not found on PATH. Install it first: ${(agentProvider as any)?.install || 'check provider docs'}` });
|
|
2096
|
-
return;
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
// 6. Spawn CLI agent via shell pipe (avoids Node.js stdin deadlock on large prompts)
|
|
2047
|
+
// 6. Spawn CLI agent natively passing prompt via -p (avoids pipe deadlock)
|
|
2100
2048
|
this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `에이전트 실행 중: ${command} ${args.join(' ')} (prompt: ${prompt.length} chars)` } });
|
|
2101
2049
|
|
|
2102
2050
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
2103
2051
|
|
|
2104
2052
|
const { spawn: spawnFn } = await import('child_process');
|
|
2105
|
-
|
|
2106
|
-
//
|
|
2053
|
+
|
|
2054
|
+
// Add prompt file text directly as an argument using cat evaluation in shell
|
|
2055
|
+
// This completely bypasses massive stdin pipe blocking while retaining CLI formatting
|
|
2107
2056
|
const escapedArgs = args.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
|
|
2108
|
-
const shellCmd =
|
|
2057
|
+
const shellCmd = `${command} ${escapedArgs} -p "$(cat '${promptFile}')"`;
|
|
2109
2058
|
this.log(`Auto-implement spawn: ${shellCmd}`);
|
|
2110
2059
|
const child = spawnFn('sh', ['-c', shellCmd], {
|
|
2111
2060
|
cwd: providerDir,
|
|
@@ -2273,6 +2222,7 @@ export class DevServer {
|
|
|
2273
2222
|
lines.push('4. Always wrap in try-catch, return `JSON.stringify(result)`');
|
|
2274
2223
|
lines.push('5. Do NOT modify `scripts.js` router — only edit individual `*.js` files');
|
|
2275
2224
|
lines.push('6. All scripts run in the browser (CDP evaluate) — use DOM APIs only');
|
|
2225
|
+
lines.push('7. **Cross-Platform Compatibility**: If you use ARIA labels that contain keyboard shortcuts (e.g., `Cascade (⌘L)`), you MUST use substring matches (`aria-label*="Cascade"`) or handle both macOS (`⌘`, `Cmd`) and Windows (`Ctrl`) so the script does not break on other operating systems.');
|
|
2276
2226
|
lines.push('');
|
|
2277
2227
|
|
|
2278
2228
|
// ── Output contracts ──
|
|
@@ -2300,42 +2250,40 @@ export class DevServer {
|
|
|
2300
2250
|
lines.push('');
|
|
2301
2251
|
|
|
2302
2252
|
// ── DevConsole API for verification ──
|
|
2303
|
-
lines.push('##
|
|
2304
|
-
lines.push(
|
|
2305
|
-
lines.push('');
|
|
2306
|
-
lines.push('### Run a script against the live IDE');
|
|
2307
|
-
lines.push('```bash');
|
|
2308
|
-
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/${type}/scripts/run \\`);
|
|
2309
|
-
lines.push(` -H "Content-Type: application/json" \\`);
|
|
2310
|
-
lines.push(` -d '{"script": "readChat"}'`);
|
|
2311
|
-
lines.push('```');
|
|
2312
|
-
lines.push('Replace `"readChat"` with any function name. For functions with params:');
|
|
2313
|
-
lines.push('```bash');
|
|
2314
|
-
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/${type}/scripts/run \\`);
|
|
2315
|
-
lines.push(` -H "Content-Type: application/json" \\`);
|
|
2316
|
-
lines.push(` -d '{"script": "sendMessage", "params": {"text": "hello"}}'`);
|
|
2317
|
-
lines.push('```');
|
|
2253
|
+
lines.push('## YOU MUST EXPLORE THE DOM YOURSELF!');
|
|
2254
|
+
lines.push('I have NOT provided you with the DOM snapshot. You MUST use your command-line tools to discover the IDE structure dynamically!');
|
|
2318
2255
|
lines.push('');
|
|
2319
|
-
lines.push('### Evaluate
|
|
2256
|
+
lines.push('### 1. Evaluate JS to explore IDE DOM');
|
|
2257
|
+
lines.push('Use cURL to run JavaScript inside the IDE:');
|
|
2320
2258
|
lines.push('```bash');
|
|
2321
|
-
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
|
|
2259
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
|
|
2322
2260
|
lines.push(` -H "Content-Type: application/json" \\`);
|
|
2323
|
-
lines.push(` -d '{"expression": "document.
|
|
2261
|
+
lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${type}"}'`);
|
|
2324
2262
|
lines.push('```');
|
|
2325
2263
|
lines.push('');
|
|
2326
|
-
lines.push('###
|
|
2264
|
+
lines.push('### 2. Test your generated function');
|
|
2265
|
+
lines.push('Once you save the file, test it by running:');
|
|
2327
2266
|
lines.push('```bash');
|
|
2328
2267
|
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
2268
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/${type}/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat"}'`);
|
|
2329
2269
|
lines.push('```');
|
|
2330
|
-
lines.push('**IMPORTANT**: After editing script files, you MUST call reload before running scripts.');
|
|
2331
2270
|
lines.push('');
|
|
2332
|
-
lines.push('### Workflow
|
|
2333
|
-
lines.push('1.
|
|
2334
|
-
lines.push('2.
|
|
2335
|
-
lines.push(
|
|
2336
|
-
lines.push('4.
|
|
2271
|
+
lines.push('### Task Workflow');
|
|
2272
|
+
lines.push('1. Write bash scripts to `curl` the CDP evaluate API above to find exactly where `.chat-message`, etc., are located.');
|
|
2273
|
+
lines.push('2. Iteratively explore until you are confident in your selectors.');
|
|
2274
|
+
lines.push('3. Edit the `.js` files using the selectors you discovered.');
|
|
2275
|
+
lines.push('4. Reload providers and TEST your script via the API.');
|
|
2276
|
+
lines.push('');
|
|
2277
|
+
lines.push('### 🔥 Advanced UI Parsing (CRUCIAL for `readChat`)');
|
|
2278
|
+
lines.push('Your `readChat` must flawlessly parse complex UI elements (tables, code blocks, tool calls, and AI thoughts). The quality must match the `antigravity` reference.');
|
|
2279
|
+
lines.push('To achieve this, you MUST generate a live test scenario:');
|
|
2280
|
+
lines.push('1. Early in your process, send a rich prompt to the IDE using the API:');
|
|
2281
|
+
lines.push(' `curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/${type}/scripts/run -H "Content-Type: application/json" -d \'{"script": "sendMessage", "params": {"text": "Write a python script, draw a markdown table, use a tool, and show your reasoning/thought process"}}\'`');
|
|
2282
|
+
lines.push('2. Wait a few seconds for the IDE AI to generate these elements in the UI.');
|
|
2283
|
+
lines.push('3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.');
|
|
2284
|
+
lines.push('4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).');
|
|
2337
2285
|
lines.push('');
|
|
2338
|
-
lines.push('Start NOW.
|
|
2286
|
+
lines.push('Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.');
|
|
2339
2287
|
|
|
2340
2288
|
return lines.join('\n');
|
|
2341
2289
|
}
|
|
@@ -18,6 +18,8 @@ export interface ScaffoldOptions {
|
|
|
18
18
|
binary?: string;
|
|
19
19
|
extensionId?: string;
|
|
20
20
|
version?: string;
|
|
21
|
+
osPaths?: Record<string, string[]>;
|
|
22
|
+
processNames?: Record<string, string>;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export interface ScaffoldResult {
|
|
@@ -75,8 +77,13 @@ export function generateFiles(type: string, name: string, category: string, opts
|
|
|
75
77
|
if (cli) meta.cli = cli;
|
|
76
78
|
if (cdpPorts) meta.cdpPorts = cdpPorts;
|
|
77
79
|
else if (!isExtension) meta.cdpPorts = [9222, 9223];
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
+
|
|
81
|
+
if (opts.processNames) meta.processNames = opts.processNames;
|
|
82
|
+
else if (processName) meta.processNames = { darwin: processName };
|
|
83
|
+
|
|
84
|
+
if (opts.osPaths) meta.paths = opts.osPaths;
|
|
85
|
+
else if (installPath) meta.paths = { darwin: [installPath] };
|
|
86
|
+
|
|
80
87
|
if (isExtension) {
|
|
81
88
|
meta.extensionId = extensionId || `publisher.${type}`;
|
|
82
89
|
meta.extensionIdPattern = `${extensionId || type}`;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|