@adhdev/daemon-core 0.6.11 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.6.11",
3
+ "version": "0.6.13",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -111,21 +111,23 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
111
111
  providerLoader.loadAll();
112
112
  providerLoader.registerToDetector();
113
113
 
114
- // 2.5 Provider version detection & archive
115
- LOG.info('Init', 'Detecting provider versions...');
114
+ // 2.5 Provider version detection & archive (non-blocking — don't delay startup)
116
115
  const versionArchive = new VersionArchive();
117
116
  providerLoader.setVersionArchive(versionArchive);
118
- const versionResults = await detectAllVersions(providerLoader, versionArchive);
119
- const installedProviders = versionResults.filter(v => v.installed);
120
- const withVersion = installedProviders.filter(v => v.version);
121
- LOG.info('Init', `Provider versions: ${installedProviders.length} installed, ${withVersion.length} versioned`);
122
- for (const v of withVersion) {
123
- LOG.info('Init', ` ${v.type} (${v.category}): v${v.version}${v.warning ? ' ⚠ ' + v.warning : ''}`);
124
- }
125
- const noVersion = installedProviders.filter(v => !v.version);
126
- if (noVersion.length > 0) {
127
- LOG.warn('Init', ` ${noVersion.length} installed but version unknown: ${noVersion.map(v => v.type).join(', ')}`);
128
- }
117
+ detectAllVersions(providerLoader, versionArchive)
118
+ .then((versionResults) => {
119
+ const installedProviders = versionResults.filter(v => v.installed);
120
+ const withVersion = installedProviders.filter(v => v.version);
121
+ LOG.info('Init', `Provider versions: ${installedProviders.length} installed, ${withVersion.length} versioned`);
122
+ for (const v of withVersion) {
123
+ LOG.info('Init', ` ${v.type} (${v.category}): v${v.version}${v.warning ? ' ⚠ ' + v.warning : ''}`);
124
+ }
125
+ const noVersion = installedProviders.filter(v => !v.version);
126
+ if (noVersion.length > 0) {
127
+ LOG.warn('Init', ` ${noVersion.length} installed but version unknown: ${noVersion.map(v => v.type).join(', ')}`);
128
+ }
129
+ })
130
+ .catch(() => {});
129
131
 
130
132
  // 3. Shared state
131
133
  const instanceManager = new ProviderInstanceManager();
@@ -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: 60000,
274
+ timeout: 120000,
275
275
  stdio: ['pipe', 'pipe', 'pipe'],
276
276
  });
277
277
  LOG.info('Upgrade', `✅ Upgraded to v${latest}`);
@@ -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
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'analyzing', message: 'DOM 구조 수집 중...' } });
1847
-
1848
- let domContext: any = null;
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
- // 5.5. Check agent binary exists
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
- // Shell pipe: cat promptFile | command args...
2106
- // This avoids Node.js stdin buffer deadlock and ensures proper EOF signaling
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 = `cat '${promptFile}' | ${command} ${escapedArgs}`;
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('## DevConsole API (for testing)');
2304
- lines.push(`The DevConsole is running at \`http://127.0.0.1:${DEV_SERVER_PORT}\`. Use these HTTP APIs to test your implementations.`);
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 raw JS in the IDE (CDP)');
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.title", "ideType": "${type}"}'`);
2261
+ lines.push(` -d '{"expression": "document.body.innerHTML.substring(0, 1000)", "ideType": "${type}"}'`);
2324
2262
  lines.push('```');
2325
2263
  lines.push('');
2326
- lines.push('### Reload provider (after editing files)');
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: Edit → Reload → Test → Fix');
2333
- lines.push('1. Edit the `.js` file');
2334
- lines.push('2. `curl POST /api/providers/reload`');
2335
- lines.push(`3. \`curl POST /api/providers/${type}/scripts/run -d '{"script":"readChat"}'\``);
2336
- lines.push('4. Check the response if error, fix and repeat from step 1');
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. Edit files, then test each one.');
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
- if (processName) meta.processNames = { darwin: processName };
79
- if (installPath) meta.paths = { darwin: [installPath] };
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}`;