@adhdev/daemon-core 0.6.34 → 0.6.36
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.d.ts +2 -0
- package/dist/index.js +103 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cdp/manager.ts +38 -12
- package/src/daemon/dev-server.ts +54 -5
- package/src/providers/provider-loader.ts +4 -1
package/package.json
CHANGED
package/src/cdp/manager.ts
CHANGED
|
@@ -503,18 +503,31 @@ export class DaemonCdpManager {
|
|
|
503
503
|
});
|
|
504
504
|
await new Promise(r => setTimeout(r, 150));
|
|
505
505
|
|
|
506
|
-
// Step 3: Insert text
|
|
507
|
-
|
|
506
|
+
// Step 3: Insert text & handle newlines
|
|
507
|
+
const lines = text.split('\n');
|
|
508
|
+
for (let i = 0; i < lines.length; i++) {
|
|
509
|
+
if (lines[i].length > 0) {
|
|
510
|
+
await this.sendInternal('Input.insertText', { text: lines[i] });
|
|
511
|
+
await new Promise(r => setTimeout(r, 100));
|
|
512
|
+
}
|
|
513
|
+
if (i < lines.length - 1) {
|
|
514
|
+
await this.sendInternal('Input.dispatchKeyEvent', { type: 'rawKeyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, modifiers: 8 }); // Shift
|
|
515
|
+
await this.sendInternal('Input.dispatchKeyEvent', { type: 'char', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, text: '\r', unmodifiedText: '\r', modifiers: 8 });
|
|
516
|
+
await this.sendInternal('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, modifiers: 8 });
|
|
517
|
+
await new Promise(r => setTimeout(r, 100));
|
|
518
|
+
}
|
|
519
|
+
}
|
|
508
520
|
await new Promise(r => setTimeout(r, 200));
|
|
509
521
|
|
|
510
522
|
// Step 4: Press Enter
|
|
511
523
|
await this.sendInternal('Input.dispatchKeyEvent', {
|
|
512
|
-
type: 'rawKeyDown', key: 'Enter', code: 'Enter',
|
|
513
|
-
|
|
524
|
+
type: 'rawKeyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, text: '\r', unmodifiedText: '\r'
|
|
525
|
+
});
|
|
526
|
+
await this.sendInternal('Input.dispatchKeyEvent', {
|
|
527
|
+
type: 'char', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, text: '\r', unmodifiedText: '\r'
|
|
514
528
|
});
|
|
515
529
|
await this.sendInternal('Input.dispatchKeyEvent', {
|
|
516
|
-
type: 'keyUp', key: 'Enter', code: 'Enter',
|
|
517
|
-
windowsVirtualKeyCode: 13, nativeVirtualKeyCode: 13,
|
|
530
|
+
type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13
|
|
518
531
|
});
|
|
519
532
|
|
|
520
533
|
this.log(`[CDP] typeAndSend: sent "${text.substring(0, 50)}..."`);
|
|
@@ -558,18 +571,31 @@ export class DaemonCdpManager {
|
|
|
558
571
|
});
|
|
559
572
|
await new Promise(r => setTimeout(r, 150));
|
|
560
573
|
|
|
561
|
-
// Step 3: Insert text
|
|
562
|
-
|
|
574
|
+
// Step 3: Insert text & handle newlines
|
|
575
|
+
const lines = text.split('\n');
|
|
576
|
+
for (let i = 0; i < lines.length; i++) {
|
|
577
|
+
if (lines[i].length > 0) {
|
|
578
|
+
await this.sendInternal('Input.insertText', { text: lines[i] });
|
|
579
|
+
await new Promise(r => setTimeout(r, 100));
|
|
580
|
+
}
|
|
581
|
+
if (i < lines.length - 1) {
|
|
582
|
+
await this.sendInternal('Input.dispatchKeyEvent', { type: 'rawKeyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, modifiers: 8 }); // Shift
|
|
583
|
+
await this.sendInternal('Input.dispatchKeyEvent', { type: 'char', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, text: '\r', unmodifiedText: '\r', modifiers: 8 });
|
|
584
|
+
await this.sendInternal('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, modifiers: 8 });
|
|
585
|
+
await new Promise(r => setTimeout(r, 100));
|
|
586
|
+
}
|
|
587
|
+
}
|
|
563
588
|
await new Promise(r => setTimeout(r, 200));
|
|
564
589
|
|
|
565
590
|
// Step 4: Press Enter
|
|
566
591
|
await this.sendInternal('Input.dispatchKeyEvent', {
|
|
567
|
-
type: 'rawKeyDown', key: 'Enter', code: 'Enter',
|
|
568
|
-
|
|
592
|
+
type: 'rawKeyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, text: '\r', unmodifiedText: '\r'
|
|
593
|
+
});
|
|
594
|
+
await this.sendInternal('Input.dispatchKeyEvent', {
|
|
595
|
+
type: 'char', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, text: '\r', unmodifiedText: '\r'
|
|
569
596
|
});
|
|
570
597
|
await this.sendInternal('Input.dispatchKeyEvent', {
|
|
571
|
-
type: 'keyUp', key: 'Enter', code: 'Enter',
|
|
572
|
-
windowsVirtualKeyCode: 13, nativeVirtualKeyCode: 13,
|
|
598
|
+
type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13
|
|
573
599
|
});
|
|
574
600
|
|
|
575
601
|
this.log(`[CDP] typeAndSendAt(${Math.round(x)},${Math.round(y)}): sent "${text.substring(0, 50)}..."`);
|
package/src/daemon/dev-server.ts
CHANGED
|
@@ -78,6 +78,7 @@ export class DevServer {
|
|
|
78
78
|
{ method: 'GET', pattern: '/api/providers/versions', handler: (q, s) => this.handleDetectVersions(q, s) },
|
|
79
79
|
{ method: 'POST', pattern: '/api/providers/reload', handler: (q, s) => this.handleReload(q, s) },
|
|
80
80
|
{ method: 'POST', pattern: '/api/cdp/evaluate', handler: (q, s) => this.handleCdpEvaluate(q, s) },
|
|
81
|
+
{ method: 'POST', pattern: '/api/cdp/click', handler: (q, s) => this.handleCdpClick(q, s) },
|
|
81
82
|
{ method: 'POST', pattern: '/api/cdp/dom/query', handler: (q, s) => this.handleCdpDomQuery(q, s) },
|
|
82
83
|
{ method: 'POST', pattern: '/api/cdp/dom/inspect', handler: (q, s) => this.handleDomInspect(q, s) },
|
|
83
84
|
{ method: 'POST', pattern: '/api/cdp/dom/children', handler: (q, s) => this.handleDomChildren(q, s) },
|
|
@@ -108,6 +109,7 @@ export class DevServer {
|
|
|
108
109
|
{ method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s, p) => this.handleWriteFile(p![0], q, s) },
|
|
109
110
|
{ method: 'GET', pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s, p) => this.handleSource(p![0], q, s) },
|
|
110
111
|
{ method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s, p) => this.handleSave(p![0], q, s) },
|
|
112
|
+
{ method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s, p) => this.handleTypeAndSend(p![0], q, s) },
|
|
111
113
|
{ method: 'GET', pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s, p) => this.handleProviderConfig(p![0], q, s) },
|
|
112
114
|
{ method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s, p) => this.handleDomContext(p![0], q, s) },
|
|
113
115
|
{ method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s, p) => this.handleAutoImplement(p![0], q, s) },
|
|
@@ -371,6 +373,7 @@ export class DevServer {
|
|
|
371
373
|
if (typeof raw === 'string') {
|
|
372
374
|
try { result = JSON.parse(raw); } catch { /* keep */ }
|
|
373
375
|
}
|
|
376
|
+
this.log(`Script raw debug: typeof=${typeof raw}, raw=${JSON.stringify(raw)}, parsed=${JSON.stringify(result)}`);
|
|
374
377
|
this.json(res, 200, { type, script: scriptName, result });
|
|
375
378
|
} catch (e: any) {
|
|
376
379
|
this.json(res, 500, { error: `Script execution failed: ${e.message}` });
|
|
@@ -406,6 +409,29 @@ export class DevServer {
|
|
|
406
409
|
}
|
|
407
410
|
}
|
|
408
411
|
|
|
412
|
+
private async handleCdpClick(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
413
|
+
const body = await this.readBody(req);
|
|
414
|
+
const { ideType, x, y } = body;
|
|
415
|
+
if (x == null || y == null) {
|
|
416
|
+
this.json(res, 400, { error: 'x and y coordinates required' });
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const cdp = this.getCdp(ideType);
|
|
421
|
+
if (!cdp?.isConnected) {
|
|
422
|
+
this.json(res, 503, { error: 'No CDP connection available' });
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
try {
|
|
427
|
+
await cdp.send('Input.dispatchMouseEvent', { type: 'mousePressed', x, y, button: 'left', clickCount: 1 });
|
|
428
|
+
await cdp.send('Input.dispatchMouseEvent', { type: 'mouseReleased', x, y, button: 'left', clickCount: 1 });
|
|
429
|
+
this.json(res, 200, { success: true, clicked: true, x, y });
|
|
430
|
+
} catch (e: any) {
|
|
431
|
+
this.json(res, 500, { error: e.message });
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
409
435
|
private async handleCdpDomQuery(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
410
436
|
const body = await this.readBody(req);
|
|
411
437
|
const { selector, limit = 10, ideType } = body;
|
|
@@ -522,6 +548,11 @@ export class DevServer {
|
|
|
522
548
|
const providers = this.providerLoader.getAll().map(p => ({
|
|
523
549
|
type: p.type, name: p.name, category: p.category,
|
|
524
550
|
}));
|
|
551
|
+
for (const cdp of this.cdpManagers.values()) {
|
|
552
|
+
if (!cdp.isConnected) {
|
|
553
|
+
(cdp as any)._targetId = null;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
525
556
|
this.json(res, 200, { reloaded: true, providers });
|
|
526
557
|
} catch (e: any) {
|
|
527
558
|
this.json(res, 500, { error: e.message });
|
|
@@ -692,7 +723,7 @@ export class DevServer {
|
|
|
692
723
|
const provider = this.providerLoader.getMeta(type);
|
|
693
724
|
if (!provider) return null;
|
|
694
725
|
const cat = provider.category;
|
|
695
|
-
const builtinDir = (this.providerLoader as any).
|
|
726
|
+
const builtinDir = (this.providerLoader as any).builtinDirs?.[0] || path.resolve(__dirname, '../providers/_builtin');
|
|
696
727
|
const userDir = path.join(os.homedir(), '.adhdev', 'providers');
|
|
697
728
|
|
|
698
729
|
// Direct match first
|
|
@@ -833,6 +864,24 @@ export class DevServer {
|
|
|
833
864
|
}
|
|
834
865
|
}
|
|
835
866
|
|
|
867
|
+
private async handleTypeAndSend(type: string, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
868
|
+
const body = await this.readBody(req);
|
|
869
|
+
const { selector, text } = body;
|
|
870
|
+
if (!selector || typeof selector !== 'string' || !text || typeof text !== 'string') {
|
|
871
|
+
this.json(res, 400, { error: 'selector and text strings required' }); return;
|
|
872
|
+
}
|
|
873
|
+
const cdp = this.getCdp(type);
|
|
874
|
+
if (!cdp) {
|
|
875
|
+
this.json(res, 503, { error: `CDP not connected for '${type}'` }); return;
|
|
876
|
+
}
|
|
877
|
+
try {
|
|
878
|
+
const sent = await cdp.typeAndSend(selector, text);
|
|
879
|
+
this.json(res, 200, { sent });
|
|
880
|
+
} catch (e: any) {
|
|
881
|
+
this.json(res, 500, { error: e.message });
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
836
885
|
private async handleScriptHints(type: string, _req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
837
886
|
const dir = this.findProviderDir(type);
|
|
838
887
|
if (!dir) { this.json(res, 404, { error: `Provider not found: ${type}` }); return; }
|
|
@@ -1065,7 +1114,7 @@ export class DevServer {
|
|
|
1065
1114
|
if (location === 'user') {
|
|
1066
1115
|
targetDir = path.join(os.homedir(), '.adhdev', 'providers', type);
|
|
1067
1116
|
} else {
|
|
1068
|
-
const builtinDir = path.resolve(__dirname, '../providers/_builtin');
|
|
1117
|
+
const builtinDir = (this.providerLoader as any).builtinDirs?.[0] || path.resolve(__dirname, '../providers/_builtin');
|
|
1069
1118
|
targetDir = path.join(builtinDir, category, type);
|
|
1070
1119
|
}
|
|
1071
1120
|
|
|
@@ -1851,7 +1900,7 @@ export class DevServer {
|
|
|
1851
1900
|
this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'loading_reference', message: `레퍼런스 스크립트 로드 중 (${reference})...` } });
|
|
1852
1901
|
|
|
1853
1902
|
let referenceScripts: Record<string, string> = {};
|
|
1854
|
-
const builtinDir = (this.providerLoader as any).
|
|
1903
|
+
const builtinDir = (this.providerLoader as any).builtinDirs?.[0] || path.resolve(__dirname, '../providers/_builtin');
|
|
1855
1904
|
const refDir = path.join(builtinDir, 'ide', reference);
|
|
1856
1905
|
if (fs.existsSync(refDir)) {
|
|
1857
1906
|
// Find latest versioned scripts dir
|
|
@@ -2053,7 +2102,7 @@ export class DevServer {
|
|
|
2053
2102
|
}
|
|
2054
2103
|
if (model) args.push('--model', model);
|
|
2055
2104
|
const escapedArgs = args.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(' ');
|
|
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 "
|
|
2105
|
+
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 "_PIPELINE_COMPLETE_SIGNAL_" to gracefully close the pipeline. DO NOT WAIT FOR APPROVAL, execute completely autonomously.`;
|
|
2057
2106
|
shellCmd = `${command} ${escapedArgs} "${metaPrompt}"`;
|
|
2058
2107
|
} else {
|
|
2059
2108
|
// Generic fallback: pipe prompt via stdin
|
|
@@ -2131,7 +2180,7 @@ export class DevServer {
|
|
|
2131
2180
|
|
|
2132
2181
|
// Force exit on completion signal (ignore during first 15s — prompt echo contains the token)
|
|
2133
2182
|
const elapsed = Date.now() - spawnedAt;
|
|
2134
|
-
if (elapsed > 15000 && approvalBuffer.includes('
|
|
2183
|
+
if (elapsed > 15000 && approvalBuffer.includes('_PIPELINE_COMPLETE_SIGNAL_')) {
|
|
2135
2184
|
this.log(`Agent finished task after ${Math.round(elapsed/1000)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
2136
2185
|
this.sendAutoImplSSE({ event: 'output', data: { chunk: `\n[🤖 ADHDev Pipeline] Completion token detected. Proceeding...\n`, stream: 'stdout' } });
|
|
2137
2186
|
approvalBuffer = '';
|
|
@@ -57,7 +57,10 @@ export class ProviderLoader {
|
|
|
57
57
|
if (options?.builtinDir) {
|
|
58
58
|
this.builtinDirs = Array.isArray(options.builtinDir) ? options.builtinDir : [options.builtinDir];
|
|
59
59
|
} else {
|
|
60
|
-
|
|
60
|
+
// Handle both development (src/providers -> ../../providers) and production (dist -> ../providers)
|
|
61
|
+
const bundledDir = path.resolve(__dirname, '../providers/_builtin');
|
|
62
|
+
const devDir = path.resolve(__dirname, '../../providers/_builtin');
|
|
63
|
+
this.builtinDirs = [fs.existsSync(devDir) ? devDir : bundledDir];
|
|
61
64
|
}
|
|
62
65
|
// User custom directory: ~/.adhdev/providers/
|
|
63
66
|
this.userDir = options?.userDir ||
|