@adhdev/daemon-core 0.6.12 → 0.6.15
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 +6688 -6598
- 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 +201 -148
- 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
package/src/daemon/dev-server.ts
CHANGED
|
@@ -307,8 +307,8 @@ export class DevServer {
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
private async handleRunScript(type: string, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
311
|
-
const body = await this.readBody(req);
|
|
310
|
+
private async handleRunScript(type: string, req: http.IncomingMessage, res: http.ServerResponse, parsedBody?: any): Promise<void> {
|
|
311
|
+
const body = parsedBody || await this.readBody(req);
|
|
312
312
|
const { script: scriptName, params, ideType: scriptIdeType } = body;
|
|
313
313
|
|
|
314
314
|
const provider = this.providerLoader.resolve(type);
|
|
@@ -495,7 +495,7 @@ export class DevServer {
|
|
|
495
495
|
return;
|
|
496
496
|
}
|
|
497
497
|
// Delegate to handleRunScript
|
|
498
|
-
await this.handleRunScript(type, req, res);
|
|
498
|
+
await this.handleRunScript(type, req, res, body);
|
|
499
499
|
}
|
|
500
500
|
|
|
501
501
|
private async handleStatus(_req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
@@ -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})...` } });
|
|
@@ -2065,94 +2023,190 @@ export class DevServer {
|
|
|
2065
2023
|
// Strip interactive-only flags for auto-implement (non-interactive mode)
|
|
2066
2024
|
const interactiveFlags = ['--yolo', '--interactive', '-i'];
|
|
2067
2025
|
const baseArgs: string[] = [...(spawn.args || [])].filter((a: string) => !interactiveFlags.includes(a));
|
|
2068
|
-
|
|
2069
|
-
|
|
2026
|
+
|
|
2027
|
+
// 6. Construct the complete shell command per-agent
|
|
2028
|
+
let shellCmd: string;
|
|
2070
2029
|
|
|
2071
2030
|
if (command === 'claude') {
|
|
2072
|
-
// Claude Code: --print mode, skip permissions
|
|
2073
|
-
args = [...baseArgs, '--print', '--dangerously-skip-permissions', '--add-dir', providerDir];
|
|
2074
|
-
|
|
2031
|
+
// Claude Code: --print mode, skip permissions, prompt via -p "$(cat file)"
|
|
2032
|
+
const args = [...baseArgs, '--print', '--dangerously-skip-permissions', '--add-dir', providerDir];
|
|
2033
|
+
const escapedArgs = args.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
|
|
2034
|
+
shellCmd = `${command} ${escapedArgs} -p "$(cat '${promptFile}')"`;
|
|
2075
2035
|
} else if (command === 'gemini') {
|
|
2076
|
-
// Gemini CLI:
|
|
2077
|
-
//
|
|
2078
|
-
// -
|
|
2079
|
-
args = [...baseArgs, '-
|
|
2080
|
-
if (model)
|
|
2081
|
-
|
|
2036
|
+
// Gemini CLI: non-interactive prompt mode
|
|
2037
|
+
// We can't use @file syntax (causes Parts object parsing bug) or $(cat) (arg too long).
|
|
2038
|
+
// Solution: meta-prompt that tells Gemini to read the instructions file itself.
|
|
2039
|
+
const args = [...baseArgs, '-y', '-s', 'false'];
|
|
2040
|
+
if (model) args.push('-m', model);
|
|
2041
|
+
const escapedArgs = args.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
|
|
2042
|
+
shellCmd = `${command} ${escapedArgs} -p "Read the file at ${promptFile} and follow ALL the instructions in it exactly. Do not ask questions, just execute."`;
|
|
2043
|
+
|
|
2044
|
+
} else if (command === 'codex') {
|
|
2045
|
+
const args = ['exec', ...baseArgs];
|
|
2046
|
+
if (!args.includes('--dangerously-bypass-approvals-and-sandbox')) {
|
|
2047
|
+
args.push('--dangerously-bypass-approvals-and-sandbox');
|
|
2082
2048
|
}
|
|
2083
|
-
|
|
2049
|
+
if (!args.includes('--skip-git-repo-check')) {
|
|
2050
|
+
args.push('--skip-git-repo-check');
|
|
2051
|
+
}
|
|
2052
|
+
if (model) args.push('--model', model);
|
|
2053
|
+
const escapedArgs = args.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
|
|
2054
|
+
const metaPrompt = `Read the file at ${promptFile} and follow ALL the instructions. Implement the specific function requested, then test it via CDP curl targeting 127.0.0.1:19280, wait for confirmation of success, and then close. DO NOT start working on other features not listed in the prompt constraint.`;
|
|
2055
|
+
shellCmd = `${command} ${escapedArgs} "${metaPrompt}"`;
|
|
2084
2056
|
} else {
|
|
2085
|
-
//
|
|
2086
|
-
|
|
2057
|
+
// Generic fallback: pipe prompt via stdin
|
|
2058
|
+
const escapedArgs = baseArgs.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
|
|
2059
|
+
shellCmd = `cat '${promptFile}' | ${command} ${escapedArgs}`;
|
|
2087
2060
|
}
|
|
2088
2061
|
|
|
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)
|
|
2100
|
-
this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `에이전트 실행 중: ${command} ${args.join(' ')} (prompt: ${prompt.length} chars)` } });
|
|
2062
|
+
this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `에이전트 실행 중: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
2101
2063
|
|
|
2102
2064
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
2103
2065
|
|
|
2066
|
+
let child: any;
|
|
2067
|
+
let isPty = false;
|
|
2104
2068
|
const { spawn: spawnFn } = await import('child_process');
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
this.log(`
|
|
2120
|
-
|
|
2121
|
-
|
|
2069
|
+
|
|
2070
|
+
try {
|
|
2071
|
+
const pty = require('node-pty');
|
|
2072
|
+
this.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
2073
|
+
const isWin = os.platform() === 'win32';
|
|
2074
|
+
child = pty.spawn(isWin ? 'cmd.exe' : (process.env.SHELL || '/bin/zsh'), [isWin ? '/c' : '-c', shellCmd], {
|
|
2075
|
+
name: 'xterm-256color',
|
|
2076
|
+
cols: 120,
|
|
2077
|
+
rows: 40,
|
|
2078
|
+
cwd: providerDir,
|
|
2079
|
+
env: { ...process.env, ...(spawn.env || {}) },
|
|
2080
|
+
});
|
|
2081
|
+
isPty = true;
|
|
2082
|
+
} catch (err: any) {
|
|
2083
|
+
this.log(`PTY not available, using child_process: ${err.message}`);
|
|
2084
|
+
child = spawnFn('sh', ['-c', shellCmd], {
|
|
2085
|
+
cwd: providerDir,
|
|
2086
|
+
shell: false,
|
|
2087
|
+
timeout: 900000,
|
|
2088
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
2089
|
+
env: {
|
|
2090
|
+
...process.env,
|
|
2091
|
+
...(spawn.env || {}),
|
|
2092
|
+
...(command === 'gemini' ? { SANDBOX: '1', GEMINI_CLI_NO_RELAUNCH: '1' } : {}),
|
|
2093
|
+
},
|
|
2094
|
+
});
|
|
2095
|
+
child.on('error', (err: Error) => {
|
|
2096
|
+
this.log(`Auto-implement spawn error: ${err.message}`);
|
|
2097
|
+
this.sendAutoImplSSE({ event: 'output', data: { chunk: `[Spawn Error] ${err.message}\n`, stream: 'stderr' } });
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2122
2100
|
|
|
2101
|
+
this.autoImplProcess = child;
|
|
2123
2102
|
let stdout = '';
|
|
2124
2103
|
let stderr = '';
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2104
|
+
|
|
2105
|
+
let approvalPatterns: RegExp[] = [];
|
|
2106
|
+
let approvalKeys: Record<number, string> = { 0: 'y\r' };
|
|
2107
|
+
let approvalBuffer = '';
|
|
2108
|
+
let lastApprovalTime = 0;
|
|
2109
|
+
|
|
2110
|
+
try {
|
|
2111
|
+
const { normalizeCliProviderForRuntime } = await import('../cli-adapters/provider-cli-adapter.js');
|
|
2112
|
+
const normalized = normalizeCliProviderForRuntime(agentProvider);
|
|
2113
|
+
approvalPatterns = normalized.patterns.approval;
|
|
2114
|
+
approvalKeys = (agentProvider as any)?.approvalKeys || { 0: 'y\r', 1: 'a\r' };
|
|
2115
|
+
} catch (err: any) {
|
|
2116
|
+
this.log(`Failed to load approval patterns: ${err.message}`);
|
|
2117
|
+
}
|
|
2135
2118
|
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2119
|
+
const checkAutoApproval = (chunk: string, writeFn: (s: string) => void) => {
|
|
2120
|
+
// Strip ANSI
|
|
2121
|
+
const cleanData = chunk.replace(/\x1B\[\d*[A-HJKSTfG]/g, ' ')
|
|
2122
|
+
.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '')
|
|
2123
|
+
.replace(/\x1B\][^\x07]*\x07/g, '')
|
|
2124
|
+
.replace(/\x1B\][^\x1B]*\x1B\\/g, '')
|
|
2125
|
+
.replace(/ +/g, ' ');
|
|
2126
|
+
|
|
2127
|
+
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
2128
|
+
|
|
2129
|
+
// Force exit on completion signal
|
|
2130
|
+
if (approvalBuffer.includes('AUTO_IMPLEMENT_FINISHED')) {
|
|
2131
|
+
this.log('Agent finished task. Terminating interactive CLI session to unblock pipeline.');
|
|
2132
|
+
this.sendAutoImplSSE({ event: 'output', data: { chunk: `\n[🤖 ADHDev Pipeline] Completion token detected. Proceeding...\n`, stream: 'stdout' } });
|
|
2133
|
+
approvalBuffer = '';
|
|
2134
|
+
|
|
2135
|
+
try {
|
|
2136
|
+
(this.autoImplProcess as any).kill('SIGINT');
|
|
2137
|
+
} catch {
|
|
2138
|
+
// ignore
|
|
2139
|
+
}
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
// Use a cooldown to prevent overlapping approval submissions
|
|
2144
|
+
if (Date.now() - lastApprovalTime < 2000) return;
|
|
2145
|
+
|
|
2146
|
+
if (approvalPatterns.some(p => p.test(approvalBuffer))) {
|
|
2147
|
+
// Use 'Always allow' (1) if available, otherwise 'Allow once' (0), otherwise hard fallback to 'a\r' for newer CLIs
|
|
2148
|
+
const key = approvalKeys[1] || approvalKeys[0] || 'a\r';
|
|
2149
|
+
writeFn(key);
|
|
2150
|
+
this.log(`Auto-Implement auto-approved prompt! Sending: ${JSON.stringify(key)}`);
|
|
2151
|
+
this.sendAutoImplSSE({ event: 'output', data: { chunk: `\n[🤖 ADHDev Auto-Approve] CLI Action Approved\n`, stream: 'stdout' } });
|
|
2152
|
+
approvalBuffer = '';
|
|
2153
|
+
lastApprovalTime = Date.now();
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
2155
2156
|
|
|
2157
|
+
if (isPty) {
|
|
2158
|
+
child.onData((data: string) => {
|
|
2159
|
+
stdout += data;
|
|
2160
|
+
if (data.includes('\x1b[6n')) {
|
|
2161
|
+
child.write('\x1b[12;1R');
|
|
2162
|
+
this.log('Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]');
|
|
2163
|
+
}
|
|
2164
|
+
checkAutoApproval(data, (s) => child.write(s));
|
|
2165
|
+
this.sendAutoImplSSE({ event: 'output', data: { chunk: data, stream: 'stdout' } });
|
|
2166
|
+
});
|
|
2167
|
+
child.onExit(({ exitCode: code }: { exitCode: number }) => {
|
|
2168
|
+
this.autoImplProcess = null;
|
|
2169
|
+
this.autoImplStatus.running = false;
|
|
2170
|
+
const success = code === 0;
|
|
2171
|
+
this.sendAutoImplSSE({
|
|
2172
|
+
event: 'complete',
|
|
2173
|
+
data: { success, exitCode: code, functions, message: success ? '✅ Auto-implement 완료' : `❌ 에이전트 종료 (code: ${code})` },
|
|
2174
|
+
});
|
|
2175
|
+
try { this.providerLoader.reload(); } catch { /* ignore */ }
|
|
2176
|
+
try { fs.unlinkSync(promptFile); } catch { /* ignore */ }
|
|
2177
|
+
});
|
|
2178
|
+
} else {
|
|
2179
|
+
child.stdout?.on('data', (d: Buffer) => {
|
|
2180
|
+
const chunk = d.toString();
|
|
2181
|
+
stdout += chunk;
|
|
2182
|
+
if (chunk.includes('\x1b[6n')) child.stdin?.write('\x1b[1;1R');
|
|
2183
|
+
checkAutoApproval(chunk, (s) => child.stdin?.write(s));
|
|
2184
|
+
this.sendAutoImplSSE({ event: 'output', data: { chunk, stream: 'stdout' } });
|
|
2185
|
+
});
|
|
2186
|
+
child.stderr?.on('data', (d: Buffer) => {
|
|
2187
|
+
const chunk = d.toString();
|
|
2188
|
+
stderr += chunk;
|
|
2189
|
+
checkAutoApproval(chunk, (s) => child.stdin?.write(s));
|
|
2190
|
+
this.sendAutoImplSSE({ event: 'output', data: { chunk, stream: 'stderr' } });
|
|
2191
|
+
});
|
|
2192
|
+
child.on('exit', (code: number) => {
|
|
2193
|
+
this.autoImplProcess = null;
|
|
2194
|
+
this.autoImplStatus.running = false;
|
|
2195
|
+
const success = code === 0;
|
|
2196
|
+
this.sendAutoImplSSE({
|
|
2197
|
+
event: 'complete',
|
|
2198
|
+
data: {
|
|
2199
|
+
success,
|
|
2200
|
+
exitCode: code,
|
|
2201
|
+
functions,
|
|
2202
|
+
message: success ? '✅ Auto-implement 완료' : `❌ 에이전트 종료 (code: ${code})`,
|
|
2203
|
+
},
|
|
2204
|
+
});
|
|
2205
|
+
try { this.providerLoader.reload(); } catch { /* ignore */ }
|
|
2206
|
+
try { fs.unlinkSync(promptFile); } catch { /* ignore */ }
|
|
2207
|
+
this.log(`Auto-implement ${success ? 'completed' : 'failed'}: ${type} (exit: ${code})`);
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2156
2210
|
this.json(res, 202, {
|
|
2157
2211
|
started: true,
|
|
2158
2212
|
type,
|
|
@@ -2273,6 +2327,7 @@ export class DevServer {
|
|
|
2273
2327
|
lines.push('4. Always wrap in try-catch, return `JSON.stringify(result)`');
|
|
2274
2328
|
lines.push('5. Do NOT modify `scripts.js` router — only edit individual `*.js` files');
|
|
2275
2329
|
lines.push('6. All scripts run in the browser (CDP evaluate) — use DOM APIs only');
|
|
2330
|
+
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
2331
|
lines.push('');
|
|
2277
2332
|
|
|
2278
2333
|
// ── Output contracts ──
|
|
@@ -2300,42 +2355,40 @@ export class DevServer {
|
|
|
2300
2355
|
lines.push('');
|
|
2301
2356
|
|
|
2302
2357
|
// ── DevConsole API for verification ──
|
|
2303
|
-
lines.push('##
|
|
2304
|
-
lines.push(
|
|
2358
|
+
lines.push('## YOU MUST EXPLORE THE DOM YOURSELF!');
|
|
2359
|
+
lines.push('I have NOT provided you with the DOM snapshot. You MUST use your command-line tools to discover the IDE structure dynamically!');
|
|
2305
2360
|
lines.push('');
|
|
2306
|
-
lines.push('###
|
|
2361
|
+
lines.push('### 1. Evaluate JS to explore IDE DOM');
|
|
2362
|
+
lines.push('Use cURL to run JavaScript inside the IDE:');
|
|
2307
2363
|
lines.push('```bash');
|
|
2308
|
-
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/
|
|
2364
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
|
|
2309
2365
|
lines.push(` -H "Content-Type: application/json" \\`);
|
|
2310
|
-
lines.push(` -d '{"
|
|
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"}}'`);
|
|
2366
|
+
lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${type}"}'`);
|
|
2317
2367
|
lines.push('```');
|
|
2318
2368
|
lines.push('');
|
|
2319
|
-
lines.push('###
|
|
2320
|
-
lines.push('
|
|
2321
|
-
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cdp/evaluate \\`);
|
|
2322
|
-
lines.push(` -H "Content-Type: application/json" \\`);
|
|
2323
|
-
lines.push(` -d '{"expression": "document.title", "ideType": "${type}"}'`);
|
|
2324
|
-
lines.push('```');
|
|
2325
|
-
lines.push('');
|
|
2326
|
-
lines.push('### Reload provider (after editing files)');
|
|
2369
|
+
lines.push('### 2. Test your generated function');
|
|
2370
|
+
lines.push('Once you save the file, test it by running:');
|
|
2327
2371
|
lines.push('```bash');
|
|
2328
2372
|
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
2373
|
+
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
2374
|
lines.push('```');
|
|
2330
|
-
lines.push('**IMPORTANT**: After editing script files, you MUST call reload before running scripts.');
|
|
2331
2375
|
lines.push('');
|
|
2332
|
-
lines.push('### Workflow
|
|
2333
|
-
lines.push('1.
|
|
2334
|
-
lines.push('2.
|
|
2335
|
-
lines.push(
|
|
2336
|
-
lines.push('4.
|
|
2376
|
+
lines.push('### Task Workflow');
|
|
2377
|
+
lines.push('1. Write bash scripts to `curl` the CDP evaluate API above to find exactly where `.chat-message`, etc., are located.');
|
|
2378
|
+
lines.push('2. Iteratively explore until you are confident in your selectors.');
|
|
2379
|
+
lines.push('3. Edit the `.js` files using the selectors you discovered.');
|
|
2380
|
+
lines.push('4. Reload providers and TEST your script via the API.');
|
|
2381
|
+
lines.push('');
|
|
2382
|
+
lines.push('### 🔥 Advanced UI Parsing (CRUCIAL for `readChat`)');
|
|
2383
|
+
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.');
|
|
2384
|
+
lines.push('To achieve this, you MUST generate a live test scenario:');
|
|
2385
|
+
lines.push('1. Early in your process, send a rich prompt to the IDE using the API:');
|
|
2386
|
+
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"}}\'`');
|
|
2387
|
+
lines.push('2. Wait a few seconds for the IDE AI to generate these elements in the UI.');
|
|
2388
|
+
lines.push('3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.');
|
|
2389
|
+
lines.push('4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).');
|
|
2337
2390
|
lines.push('');
|
|
2338
|
-
lines.push('Start NOW.
|
|
2391
|
+
lines.push('Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.');
|
|
2339
2392
|
|
|
2340
2393
|
return lines.join('\n');
|
|
2341
2394
|
}
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|