@adhdev/daemon-core 0.6.18 → 0.6.21

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.18",
3
+ "version": "0.6.21",
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",
@@ -369,6 +369,12 @@ export class DaemonCommandHandler implements CommandHelpers {
369
369
  case 'list_extension_modes': return Stream.handleExtensionScript(this, args, 'listModes');
370
370
  case 'set_extension_mode': return Stream.handleExtensionScript(this, args, 'setMode');
371
371
 
372
+ // ─── Provider Auto-Fix / Clone (DevServer proxy) ──────────
373
+ case 'provider_auto_fix': return this.proxyDevServerPost(args, 'auto-implement');
374
+ case 'provider_auto_fix_cancel': return this.proxyDevServerPost(args, 'auto-implement/cancel');
375
+ case 'provider_auto_fix_status': return this.proxyDevServerGet(args, 'auto-implement/status');
376
+ case 'provider_clone': return this.proxyDevServerScaffold(args);
377
+
372
378
  default:
373
379
  return { success: false, error: `Unknown command: ${cmd}` };
374
380
  }
@@ -398,4 +404,83 @@ export class DaemonCommandHandler implements CommandHelpers {
398
404
  }
399
405
  return { success: false, error: 'ProviderLoader not initialized' };
400
406
  }
407
+
408
+ // ─── DevServer HTTP proxy helpers ─────────────────
409
+ // These bridge WS commands to the DevServer REST API (localhost:19280)
410
+
411
+ private async proxyDevServerPost(args: any, endpoint: string): Promise<CommandResult> {
412
+ const { providerType, ...body } = args || {};
413
+ if (!providerType) return { success: false, error: 'providerType required' };
414
+ try {
415
+ const http = await import('http');
416
+ const postData = JSON.stringify(body);
417
+ const result = await new Promise<any>((resolve, reject) => {
418
+ const req = http.request({
419
+ hostname: '127.0.0.1', port: 19280,
420
+ path: `/api/providers/${providerType}/${endpoint}`,
421
+ method: 'POST',
422
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
423
+ }, (res) => {
424
+ let data = '';
425
+ res.on('data', (chunk: Buffer) => data += chunk);
426
+ res.on('end', () => {
427
+ try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); }
428
+ });
429
+ });
430
+ req.on('error', reject);
431
+ req.write(postData);
432
+ req.end();
433
+ });
434
+ return { success: true, ...result };
435
+ } catch (e: any) {
436
+ return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
437
+ }
438
+ }
439
+
440
+ private async proxyDevServerGet(args: any, endpoint: string): Promise<CommandResult> {
441
+ const { providerType } = args || {};
442
+ if (!providerType) return { success: false, error: 'providerType required' };
443
+ try {
444
+ const http = await import('http');
445
+ const result = await new Promise<any>((resolve, reject) => {
446
+ http.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
447
+ let data = '';
448
+ res.on('data', (chunk: Buffer) => data += chunk);
449
+ res.on('end', () => {
450
+ try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); }
451
+ });
452
+ }).on('error', reject);
453
+ });
454
+ return { success: true, ...result };
455
+ } catch (e: any) {
456
+ return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
457
+ }
458
+ }
459
+
460
+ private async proxyDevServerScaffold(args: any): Promise<CommandResult> {
461
+ try {
462
+ const http = await import('http');
463
+ const postData = JSON.stringify(args || {});
464
+ const result = await new Promise<any>((resolve, reject) => {
465
+ const req = http.request({
466
+ hostname: '127.0.0.1', port: 19280,
467
+ path: '/api/scaffold',
468
+ method: 'POST',
469
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
470
+ }, (res) => {
471
+ let data = '';
472
+ res.on('data', (chunk: Buffer) => data += chunk);
473
+ res.on('end', () => {
474
+ try { resolve(JSON.parse(data)); } catch { resolve({ raw: data }); }
475
+ });
476
+ });
477
+ req.on('error', reject);
478
+ req.write(postData);
479
+ req.end();
480
+ });
481
+ return { success: true, ...result };
482
+ } catch (e: any) {
483
+ return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
484
+ }
485
+ }
401
486
  }
@@ -323,7 +323,7 @@ export class DevServer {
323
323
  return;
324
324
  }
325
325
 
326
- const cdp = this.getCdp(scriptIdeType);
326
+ const cdp = this.getCdp(scriptIdeType || type);
327
327
  if (!cdp) {
328
328
  this.json(res, 503, { error: 'No CDP connection available' });
329
329
  return;
@@ -1824,7 +1824,7 @@ export class DevServer {
1824
1824
 
1825
1825
  private async handleAutoImplement(type: string, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
1826
1826
  const body = await this.readBody(req);
1827
- const { agent = 'claude-cli', functions, reference = 'antigravity', model } = body;
1827
+ const { agent = 'claude-cli', functions, reference = 'antigravity', model, comment } = body;
1828
1828
  if (!functions || !Array.isArray(functions) || functions.length === 0) {
1829
1829
  this.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
1830
1830
  return;
@@ -1874,7 +1874,7 @@ export class DevServer {
1874
1874
  }
1875
1875
 
1876
1876
  // 3. Build the prompt
1877
- const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts);
1877
+ const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment);
1878
1878
 
1879
1879
  // 4. Write prompt to temp file (avoids shell escaping issues with special chars)
1880
1880
  const tmpDir = path.join(os.tmpdir(), 'adhdev-autoimpl');
@@ -2028,10 +2028,12 @@ export class DevServer {
2028
2028
  let shellCmd: string;
2029
2029
 
2030
2030
  if (command === 'claude') {
2031
- // Claude Code: --print mode, skip permissions, prompt via -p "$(cat file)"
2032
- const args = [...baseArgs, '--print', '--dangerously-skip-permissions', '--add-dir', providerDir];
2031
+ // Claude Code: autonomous agent mode (no --print), skip permissions, prompt via meta-prompt
2032
+ const args = [...baseArgs, '--dangerously-skip-permissions'];
2033
+ if (model) args.push('--model', model);
2033
2034
  const escapedArgs = args.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
2034
- shellCmd = `${command} ${escapedArgs} -p "$(cat '${promptFile}')"`;
2035
+ 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.`;
2036
+ shellCmd = `${command} ${escapedArgs} -p "${metaPrompt}"`;
2035
2037
  } else if (command === 'gemini') {
2036
2038
  // Gemini CLI: non-interactive prompt mode
2037
2039
  // We can't use @file syntax (causes Parts object parsing bug) or $(cat) (arg too long).
@@ -2051,7 +2053,7 @@ export class DevServer {
2051
2053
  }
2052
2054
  if (model) args.push('--model', model);
2053
2055
  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.`;
2056
+ const metaPrompt = `Read the file at ${promptFile} and follow ALL instructions recursively. You have full authority to implement ALL required script files, update provider.json configurations based on the reference patterns, and independently test them against 127.0.0.1:19280 via CDP CURL. Upon complete validation of ALL assigned files, print exactly "AUTO_IMPLEMENT_FINISHED" to gracefully close the pipeline. DO NOT WAIT FOR APPROVAL, execute completely autonomously.`;
2055
2057
  shellCmd = `${command} ${escapedArgs} "${metaPrompt}"`;
2056
2058
  } else {
2057
2059
  // Generic fallback: pipe prompt via stdin
@@ -2062,6 +2064,7 @@ export class DevServer {
2062
2064
  this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `에이전트 실행 중: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
2063
2065
 
2064
2066
  this.autoImplStatus = { running: true, type, progress: [] };
2067
+ const spawnedAt = Date.now();
2065
2068
 
2066
2069
  let child: any;
2067
2070
  let isPty = false;
@@ -2126,9 +2129,10 @@ export class DevServer {
2126
2129
 
2127
2130
  approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
2128
2131
 
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
+ // Force exit on completion signal (ignore during first 15s — prompt echo contains the token)
2133
+ const elapsed = Date.now() - spawnedAt;
2134
+ if (elapsed > 15000 && approvalBuffer.includes('AUTO_IMPLEMENT_FINISHED')) {
2135
+ this.log(`Agent finished task after ${Math.round(elapsed/1000)}s. Terminating interactive CLI session to unblock pipeline.`);
2132
2136
  this.sendAutoImplSSE({ event: 'output', data: { chunk: `\n[🤖 ADHDev Pipeline] Completion token detected. Proceeding...\n`, stream: 'stdout' } });
2133
2137
  approvalBuffer = '';
2134
2138
 
@@ -2229,6 +2233,7 @@ export class DevServer {
2229
2233
  functions: string[],
2230
2234
  domContext: any,
2231
2235
  referenceScripts: Record<string, string>,
2236
+ userComment?: string,
2232
2237
  ): string {
2233
2238
  const lines: string[] = [];
2234
2239
 
@@ -2352,6 +2357,10 @@ export class DevServer {
2352
2357
  lines.push('1. Edit the script files to implement working code');
2353
2358
  lines.push('2. After editing, TEST each function using the DevConsole API (see below)');
2354
2359
  lines.push('3. If a test fails, fix the implementation and re-test');
2360
+ lines.push('4. **IMPORTANT VERIFICATION LOGIC**: When verifying your implementation, beware of state contamination! You MUST perform strict Integration Testing:');
2361
+ lines.push(' - `openPanel`: Toggle buttons are usually located in the top header, sidebar, or activity bar. Prefer finding and clicking these native UI buttons over extreme CSS injection hacks if possible.');
2362
+ lines.push(' - `listSessions`: If sessions are unmounted when the panel is closed, try to explicitly interact with the UI to open the history/sessions view (e.g., clicking a history icon usually found near the chat header) BEFORE scraping.');
2363
+ lines.push(' - `switchSession`: Prove your switch was successful by subsequently calling `readChat` and explicitly checking that the chat context has actually changed.');
2355
2364
  lines.push('');
2356
2365
 
2357
2366
  // ── DevConsole API for verification ──
@@ -2388,6 +2397,15 @@ export class DevServer {
2388
2397
  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
2398
  lines.push('4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).');
2390
2399
  lines.push('');
2400
+ // ── User-provided additional instructions ──
2401
+ if (userComment) {
2402
+ lines.push('## ⚠️ User Instructions (HIGH PRIORITY)');
2403
+ lines.push('The user has provided the following additional instructions. Follow them strictly:');
2404
+ lines.push('');
2405
+ lines.push(userComment);
2406
+ lines.push('');
2407
+ }
2408
+
2391
2409
  lines.push('Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.');
2392
2410
 
2393
2411
  return lines.join('\n');