adhdev 0.1.21 → 0.1.23
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 +826 -323
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -325,11 +325,61 @@ var init_config = __esm({
|
|
|
325
325
|
userName: null,
|
|
326
326
|
setupCompleted: false,
|
|
327
327
|
setupDate: null,
|
|
328
|
-
configuredCLIs: []
|
|
328
|
+
configuredCLIs: [],
|
|
329
|
+
enabledIdes: []
|
|
329
330
|
};
|
|
330
331
|
}
|
|
331
332
|
});
|
|
332
333
|
|
|
334
|
+
// src/cli-detector.ts
|
|
335
|
+
async function detectCLIs() {
|
|
336
|
+
const platform9 = os.platform();
|
|
337
|
+
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
338
|
+
const results = [];
|
|
339
|
+
for (const cli of KNOWN_CLIS) {
|
|
340
|
+
try {
|
|
341
|
+
const pathResult = (0, import_child_process3.execSync)(`${whichCmd} ${cli.command} 2>/dev/null`, {
|
|
342
|
+
encoding: "utf-8",
|
|
343
|
+
timeout: 5e3,
|
|
344
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
345
|
+
}).trim().split("\n")[0];
|
|
346
|
+
if (!pathResult) throw new Error("Not found");
|
|
347
|
+
let version;
|
|
348
|
+
try {
|
|
349
|
+
const versionResult = (0, import_child_process3.execSync)(`${cli.command} --version 2>/dev/null`, {
|
|
350
|
+
encoding: "utf-8",
|
|
351
|
+
timeout: 5e3,
|
|
352
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
353
|
+
}).trim();
|
|
354
|
+
const match = versionResult.match(/(\d+\.\d+[\.\d]*)/);
|
|
355
|
+
version = match ? match[1] : versionResult.split("\n")[0].slice(0, 30);
|
|
356
|
+
} catch {
|
|
357
|
+
}
|
|
358
|
+
results.push({ ...cli, installed: true, version, path: pathResult });
|
|
359
|
+
} catch {
|
|
360
|
+
results.push({ ...cli, installed: false });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return results;
|
|
364
|
+
}
|
|
365
|
+
async function detectCLI(cliId) {
|
|
366
|
+
const all = await detectCLIs();
|
|
367
|
+
return all.find((c) => c.id === cliId && c.installed) || null;
|
|
368
|
+
}
|
|
369
|
+
var import_child_process3, os, KNOWN_CLIS;
|
|
370
|
+
var init_cli_detector = __esm({
|
|
371
|
+
"src/cli-detector.ts"() {
|
|
372
|
+
"use strict";
|
|
373
|
+
import_child_process3 = require("child_process");
|
|
374
|
+
os = __toESM(require("os"));
|
|
375
|
+
KNOWN_CLIS = [
|
|
376
|
+
{ id: "gemini-cli", displayName: "Gemini CLI", icon: "\u264A", command: "gemini" },
|
|
377
|
+
{ id: "claude-code", displayName: "Claude Code", icon: "\u{1F916}", command: "claude" },
|
|
378
|
+
{ id: "codex-cli", displayName: "Codex CLI", icon: "\u{1F9E0}", command: "codex" }
|
|
379
|
+
];
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
|
|
333
383
|
// src/launch.ts
|
|
334
384
|
async function findFreePort(ports) {
|
|
335
385
|
for (const port2 of ports) {
|
|
@@ -377,38 +427,38 @@ async function isCdpActive(port) {
|
|
|
377
427
|
});
|
|
378
428
|
}
|
|
379
429
|
async function killIdeProcess(ideId) {
|
|
380
|
-
const plat =
|
|
430
|
+
const plat = os2.platform();
|
|
381
431
|
const appName = MAC_APP_IDENTIFIERS[ideId];
|
|
382
432
|
const winProcesses = WIN_PROCESS_NAMES[ideId];
|
|
383
433
|
try {
|
|
384
434
|
if (plat === "darwin" && appName) {
|
|
385
435
|
try {
|
|
386
|
-
(0,
|
|
436
|
+
(0, import_child_process4.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
|
|
387
437
|
timeout: 5e3
|
|
388
438
|
});
|
|
389
439
|
} catch {
|
|
390
440
|
try {
|
|
391
|
-
(0,
|
|
441
|
+
(0, import_child_process4.execSync)(`pkill -f "${appName}" 2>/dev/null`);
|
|
392
442
|
} catch {
|
|
393
443
|
}
|
|
394
444
|
}
|
|
395
445
|
} else if (plat === "win32" && winProcesses) {
|
|
396
446
|
for (const proc of winProcesses) {
|
|
397
447
|
try {
|
|
398
|
-
(0,
|
|
448
|
+
(0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`, { timeout: 5e3 });
|
|
399
449
|
} catch {
|
|
400
450
|
}
|
|
401
451
|
}
|
|
402
452
|
try {
|
|
403
453
|
const exeName = winProcesses[0].replace(".exe", "");
|
|
404
|
-
(0,
|
|
454
|
+
(0, import_child_process4.execSync)(`powershell -Command "Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue | Stop-Process -Force"`, {
|
|
405
455
|
timeout: 1e4
|
|
406
456
|
});
|
|
407
457
|
} catch {
|
|
408
458
|
}
|
|
409
459
|
} else {
|
|
410
460
|
try {
|
|
411
|
-
(0,
|
|
461
|
+
(0, import_child_process4.execSync)(`pkill -f "${ideId}" 2>/dev/null`);
|
|
412
462
|
} catch {
|
|
413
463
|
}
|
|
414
464
|
}
|
|
@@ -418,13 +468,13 @@ async function killIdeProcess(ideId) {
|
|
|
418
468
|
}
|
|
419
469
|
if (plat === "darwin" && appName) {
|
|
420
470
|
try {
|
|
421
|
-
(0,
|
|
471
|
+
(0, import_child_process4.execSync)(`pkill -9 -f "${appName}" 2>/dev/null`);
|
|
422
472
|
} catch {
|
|
423
473
|
}
|
|
424
474
|
} else if (plat === "win32" && winProcesses) {
|
|
425
475
|
for (const proc of winProcesses) {
|
|
426
476
|
try {
|
|
427
|
-
(0,
|
|
477
|
+
(0, import_child_process4.execSync)(`taskkill /IM "${proc}" /F 2>nul`);
|
|
428
478
|
} catch {
|
|
429
479
|
}
|
|
430
480
|
}
|
|
@@ -436,26 +486,26 @@ async function killIdeProcess(ideId) {
|
|
|
436
486
|
}
|
|
437
487
|
}
|
|
438
488
|
function isIdeRunning(ideId) {
|
|
439
|
-
const plat =
|
|
489
|
+
const plat = os2.platform();
|
|
440
490
|
try {
|
|
441
491
|
if (plat === "darwin") {
|
|
442
492
|
const appName = MAC_APP_IDENTIFIERS[ideId];
|
|
443
493
|
if (!appName) return false;
|
|
444
|
-
const result = (0,
|
|
494
|
+
const result = (0, import_child_process4.execSync)(`pgrep -f "${appName}" 2>/dev/null`, { encoding: "utf-8" });
|
|
445
495
|
return result.trim().length > 0;
|
|
446
496
|
} else if (plat === "win32") {
|
|
447
497
|
const winProcesses = WIN_PROCESS_NAMES[ideId];
|
|
448
498
|
if (!winProcesses) return false;
|
|
449
499
|
for (const proc of winProcesses) {
|
|
450
500
|
try {
|
|
451
|
-
const result = (0,
|
|
501
|
+
const result = (0, import_child_process4.execSync)(`tasklist /FI "IMAGENAME eq ${proc}" /NH 2>nul`, { encoding: "utf-8" });
|
|
452
502
|
if (result.includes(proc)) return true;
|
|
453
503
|
} catch {
|
|
454
504
|
}
|
|
455
505
|
}
|
|
456
506
|
try {
|
|
457
507
|
const exeName = winProcesses[0].replace(".exe", "");
|
|
458
|
-
const result = (0,
|
|
508
|
+
const result = (0, import_child_process4.execSync)(
|
|
459
509
|
`powershell -Command "(Get-Process -Name '${exeName}' -ErrorAction SilentlyContinue).Count"`,
|
|
460
510
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
461
511
|
);
|
|
@@ -464,7 +514,7 @@ function isIdeRunning(ideId) {
|
|
|
464
514
|
}
|
|
465
515
|
return false;
|
|
466
516
|
} else {
|
|
467
|
-
const result = (0,
|
|
517
|
+
const result = (0, import_child_process4.execSync)(`pgrep -f "${ideId}" 2>/dev/null`, { encoding: "utf-8" });
|
|
468
518
|
return result.trim().length > 0;
|
|
469
519
|
}
|
|
470
520
|
} catch {
|
|
@@ -472,12 +522,12 @@ function isIdeRunning(ideId) {
|
|
|
472
522
|
}
|
|
473
523
|
}
|
|
474
524
|
function detectCurrentWorkspace(ideId) {
|
|
475
|
-
const plat =
|
|
525
|
+
const plat = os2.platform();
|
|
476
526
|
if (plat === "darwin") {
|
|
477
527
|
try {
|
|
478
528
|
const appName = MAC_APP_IDENTIFIERS[ideId];
|
|
479
529
|
if (!appName) return void 0;
|
|
480
|
-
const result = (0,
|
|
530
|
+
const result = (0, import_child_process4.execSync)(
|
|
481
531
|
`lsof -c "${appName}" 2>/dev/null | grep cwd | head -1 | awk '{print $NF}'`,
|
|
482
532
|
{ encoding: "utf-8", timeout: 3e3 }
|
|
483
533
|
);
|
|
@@ -498,7 +548,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
498
548
|
const appName = appNameMap[ideId];
|
|
499
549
|
if (appName) {
|
|
500
550
|
const storagePath = path.join(
|
|
501
|
-
process.env.APPDATA || path.join(
|
|
551
|
+
process.env.APPDATA || path.join(os2.homedir(), "AppData", "Roaming"),
|
|
502
552
|
appName,
|
|
503
553
|
"storage.json"
|
|
504
554
|
);
|
|
@@ -520,7 +570,7 @@ function detectCurrentWorkspace(ideId) {
|
|
|
520
570
|
return void 0;
|
|
521
571
|
}
|
|
522
572
|
async function launchWithCdp(options = {}) {
|
|
523
|
-
const platform9 =
|
|
573
|
+
const platform9 = os2.platform();
|
|
524
574
|
let targetIde;
|
|
525
575
|
const ides = await detectIDEs();
|
|
526
576
|
if (options.ideId) {
|
|
@@ -630,9 +680,9 @@ async function launchMacOS(ide, port, workspace, newWindow) {
|
|
|
630
680
|
if (workspace) args.push(workspace);
|
|
631
681
|
if (appName) {
|
|
632
682
|
const openArgs = ["-a", appName, "--args", ...args];
|
|
633
|
-
(0,
|
|
683
|
+
(0, import_child_process4.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
|
|
634
684
|
} else if (ide.cliCommand) {
|
|
635
|
-
(0,
|
|
685
|
+
(0, import_child_process4.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
636
686
|
} else {
|
|
637
687
|
throw new Error(`No app identifier or CLI for ${ide.displayName}`);
|
|
638
688
|
}
|
|
@@ -658,15 +708,15 @@ async function launchLinux(ide, port, workspace, newWindow) {
|
|
|
658
708
|
const args = ["--remote-debugging-port=" + port];
|
|
659
709
|
if (newWindow) args.push("--new-window");
|
|
660
710
|
if (workspace) args.push(workspace);
|
|
661
|
-
(0,
|
|
711
|
+
(0, import_child_process4.spawn)(cli, args, { detached: true, stdio: "ignore" }).unref();
|
|
662
712
|
}
|
|
663
|
-
var
|
|
713
|
+
var import_child_process4, net, os2, path, CDP_PORTS, MAC_APP_IDENTIFIERS, WIN_PROCESS_NAMES;
|
|
664
714
|
var init_launch = __esm({
|
|
665
715
|
"src/launch.ts"() {
|
|
666
716
|
"use strict";
|
|
667
|
-
|
|
717
|
+
import_child_process4 = require("child_process");
|
|
668
718
|
net = __toESM(require("net"));
|
|
669
|
-
|
|
719
|
+
os2 = __toESM(require("os"));
|
|
670
720
|
path = __toESM(require("path"));
|
|
671
721
|
init_detector();
|
|
672
722
|
init_config();
|
|
@@ -821,6 +871,8 @@ var init_cli_bridge = __esm({
|
|
|
821
871
|
const handlers = this.messageHandlers.get(message.type);
|
|
822
872
|
if (handlers) {
|
|
823
873
|
handlers.forEach((h) => h(message));
|
|
874
|
+
} else if (message.type !== "auth_ok") {
|
|
875
|
+
console.log(`[CliBridge] Unhandled message type: ${message.type}`);
|
|
824
876
|
}
|
|
825
877
|
} catch (error) {
|
|
826
878
|
console.error("[CliBridge] Failed to parse message:", error);
|
|
@@ -881,21 +933,21 @@ function stripAnsi(str) {
|
|
|
881
933
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
882
934
|
}
|
|
883
935
|
function findGeminiBinary() {
|
|
884
|
-
const isWin =
|
|
936
|
+
const isWin = os3.platform() === "win32";
|
|
885
937
|
const cmd = isWin ? "where gemini" : "which gemini";
|
|
886
938
|
try {
|
|
887
|
-
const result = (0,
|
|
939
|
+
const result = (0, import_child_process5.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
888
940
|
return result.split("\n")[0].trim();
|
|
889
941
|
} catch {
|
|
890
942
|
return isWin ? "gemini.cmd" : "gemini";
|
|
891
943
|
}
|
|
892
944
|
}
|
|
893
|
-
var
|
|
945
|
+
var os3, import_child_process5, pty, PROMPT_PATTERNS, STARTUP_DIALOG_PATTERNS, GeminiCliAdapter;
|
|
894
946
|
var init_gemini_cli = __esm({
|
|
895
947
|
"src/cli-adapters/gemini-cli.ts"() {
|
|
896
948
|
"use strict";
|
|
897
|
-
|
|
898
|
-
|
|
949
|
+
os3 = __toESM(require("os"));
|
|
950
|
+
import_child_process5 = require("child_process");
|
|
899
951
|
try {
|
|
900
952
|
pty = require("node-pty");
|
|
901
953
|
} catch {
|
|
@@ -1147,21 +1199,21 @@ function stripAnsi2(str) {
|
|
|
1147
1199
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
1148
1200
|
}
|
|
1149
1201
|
function findClaudeBinary() {
|
|
1150
|
-
const isWin =
|
|
1202
|
+
const isWin = os4.platform() === "win32";
|
|
1151
1203
|
const cmd = isWin ? "where claude" : "which claude";
|
|
1152
1204
|
try {
|
|
1153
|
-
const result = (0,
|
|
1205
|
+
const result = (0, import_child_process6.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1154
1206
|
return result.split("\n")[0].trim();
|
|
1155
1207
|
} catch {
|
|
1156
1208
|
return isWin ? "claude.cmd" : "claude";
|
|
1157
1209
|
}
|
|
1158
1210
|
}
|
|
1159
|
-
var
|
|
1211
|
+
var os4, import_child_process6, pty2, ClaudeCliAdapter;
|
|
1160
1212
|
var init_claude_cli = __esm({
|
|
1161
1213
|
"src/cli-adapters/claude-cli.ts"() {
|
|
1162
1214
|
"use strict";
|
|
1163
|
-
|
|
1164
|
-
|
|
1215
|
+
os4 = __toESM(require("os"));
|
|
1216
|
+
import_child_process6 = require("child_process");
|
|
1165
1217
|
try {
|
|
1166
1218
|
pty2 = require("node-pty");
|
|
1167
1219
|
} catch {
|
|
@@ -1359,21 +1411,21 @@ function stripAnsi3(str) {
|
|
|
1359
1411
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
1360
1412
|
}
|
|
1361
1413
|
function findCodexBinary() {
|
|
1362
|
-
const isWin =
|
|
1414
|
+
const isWin = os5.platform() === "win32";
|
|
1363
1415
|
const cmd = isWin ? "where codex" : "which codex";
|
|
1364
1416
|
try {
|
|
1365
|
-
const result = (0,
|
|
1417
|
+
const result = (0, import_child_process7.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1366
1418
|
return result.split("\n")[0].trim();
|
|
1367
1419
|
} catch {
|
|
1368
1420
|
return isWin ? "codex.cmd" : "codex";
|
|
1369
1421
|
}
|
|
1370
1422
|
}
|
|
1371
|
-
var
|
|
1423
|
+
var os5, import_child_process7, pty3, CodexCliAdapter;
|
|
1372
1424
|
var init_codex_cli = __esm({
|
|
1373
1425
|
"src/cli-adapters/codex-cli.ts"() {
|
|
1374
1426
|
"use strict";
|
|
1375
|
-
|
|
1376
|
-
|
|
1427
|
+
os5 = __toESM(require("os"));
|
|
1428
|
+
import_child_process7 = require("child_process");
|
|
1377
1429
|
try {
|
|
1378
1430
|
pty3 = require("node-pty");
|
|
1379
1431
|
} catch {
|
|
@@ -1826,13 +1878,16 @@ var init_local_server = __esm({
|
|
|
1826
1878
|
/**
|
|
1827
1879
|
* 가장 최근 Extension 상태 데이터 (통합)
|
|
1828
1880
|
*/
|
|
1829
|
-
getLatestExtensionData() {
|
|
1881
|
+
getLatestExtensionData(enabledIdes) {
|
|
1830
1882
|
let activeFile = null;
|
|
1831
1883
|
const allWorkspaceFolders = [];
|
|
1832
1884
|
let totalTerminals = 0;
|
|
1833
1885
|
const allAgents = [];
|
|
1834
1886
|
const connectedIdes = [];
|
|
1835
1887
|
for (const ext of this.extensions.values()) {
|
|
1888
|
+
if (enabledIdes && enabledIdes.length > 0 && !enabledIdes.includes(ext.ideType.toLowerCase())) {
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1836
1891
|
connectedIdes.push({ ideType: ext.ideType, instanceId: ext.instanceId });
|
|
1837
1892
|
if (ext.lastStatus) {
|
|
1838
1893
|
if (!activeFile && ext.lastStatus.activeFile) {
|
|
@@ -1855,55 +1910,6 @@ var init_local_server = __esm({
|
|
|
1855
1910
|
}
|
|
1856
1911
|
});
|
|
1857
1912
|
|
|
1858
|
-
// src/cli-detector.ts
|
|
1859
|
-
async function detectCLIs() {
|
|
1860
|
-
const platform9 = os5.platform();
|
|
1861
|
-
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
1862
|
-
const results = [];
|
|
1863
|
-
for (const cli of KNOWN_CLIS) {
|
|
1864
|
-
try {
|
|
1865
|
-
const pathResult = (0, import_child_process7.execSync)(`${whichCmd} ${cli.command} 2>/dev/null`, {
|
|
1866
|
-
encoding: "utf-8",
|
|
1867
|
-
timeout: 5e3,
|
|
1868
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1869
|
-
}).trim().split("\n")[0];
|
|
1870
|
-
if (!pathResult) throw new Error("Not found");
|
|
1871
|
-
let version;
|
|
1872
|
-
try {
|
|
1873
|
-
const versionResult = (0, import_child_process7.execSync)(`${cli.command} --version 2>/dev/null`, {
|
|
1874
|
-
encoding: "utf-8",
|
|
1875
|
-
timeout: 5e3,
|
|
1876
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1877
|
-
}).trim();
|
|
1878
|
-
const match = versionResult.match(/(\d+\.\d+[\.\d]*)/);
|
|
1879
|
-
version = match ? match[1] : versionResult.split("\n")[0].slice(0, 30);
|
|
1880
|
-
} catch {
|
|
1881
|
-
}
|
|
1882
|
-
results.push({ ...cli, installed: true, version, path: pathResult });
|
|
1883
|
-
} catch {
|
|
1884
|
-
results.push({ ...cli, installed: false });
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
return results;
|
|
1888
|
-
}
|
|
1889
|
-
async function detectCLI(cliId) {
|
|
1890
|
-
const all = await detectCLIs();
|
|
1891
|
-
return all.find((c) => c.id === cliId && c.installed) || null;
|
|
1892
|
-
}
|
|
1893
|
-
var import_child_process7, os5, KNOWN_CLIS;
|
|
1894
|
-
var init_cli_detector = __esm({
|
|
1895
|
-
"src/cli-detector.ts"() {
|
|
1896
|
-
"use strict";
|
|
1897
|
-
import_child_process7 = require("child_process");
|
|
1898
|
-
os5 = __toESM(require("os"));
|
|
1899
|
-
KNOWN_CLIS = [
|
|
1900
|
-
{ id: "gemini-cli", displayName: "Gemini CLI", icon: "\u264A", command: "gemini" },
|
|
1901
|
-
{ id: "claude-code", displayName: "Claude Code", icon: "\u{1F916}", command: "claude" },
|
|
1902
|
-
{ id: "codex-cli", displayName: "Codex CLI", icon: "\u{1F9E0}", command: "codex" }
|
|
1903
|
-
];
|
|
1904
|
-
}
|
|
1905
|
-
});
|
|
1906
|
-
|
|
1907
1913
|
// src/daemon-cdp.ts
|
|
1908
1914
|
var import_ws3, http, fs, KNOWN_AGENTS, DaemonCdpManager;
|
|
1909
1915
|
var init_daemon_cdp = __esm({
|
|
@@ -1919,10 +1925,15 @@ var init_daemon_cdp = __esm({
|
|
|
1919
1925
|
];
|
|
1920
1926
|
DaemonCdpManager = class {
|
|
1921
1927
|
ws = null;
|
|
1928
|
+
browserWs = null;
|
|
1929
|
+
// browser-level WS for Target discovery
|
|
1930
|
+
browserMsgId = 1e4;
|
|
1931
|
+
browserPending = /* @__PURE__ */ new Map();
|
|
1922
1932
|
msgId = 1;
|
|
1923
1933
|
pending = /* @__PURE__ */ new Map();
|
|
1924
1934
|
port;
|
|
1925
1935
|
_connected = false;
|
|
1936
|
+
_browserConnected = false;
|
|
1926
1937
|
targetUrl = "";
|
|
1927
1938
|
reconnectTimer = null;
|
|
1928
1939
|
contexts = /* @__PURE__ */ new Set();
|
|
@@ -1931,8 +1942,10 @@ var init_daemon_cdp = __esm({
|
|
|
1931
1942
|
MAX_FAILURES = 5;
|
|
1932
1943
|
agentSessions = /* @__PURE__ */ new Map();
|
|
1933
1944
|
logFn;
|
|
1934
|
-
|
|
1945
|
+
disableFallback;
|
|
1946
|
+
constructor(port = 9333, logFn, disableFallback = false) {
|
|
1935
1947
|
this.port = port;
|
|
1948
|
+
this.disableFallback = disableFallback;
|
|
1936
1949
|
this.logFn = logFn || ((msg) => {
|
|
1937
1950
|
console.log(msg);
|
|
1938
1951
|
try {
|
|
@@ -2011,6 +2024,7 @@ var init_daemon_cdp = __esm({
|
|
|
2011
2024
|
async findTarget() {
|
|
2012
2025
|
let target = await this.findTargetOnPort(this.port);
|
|
2013
2026
|
if (target) return target;
|
|
2027
|
+
if (this.disableFallback) return null;
|
|
2014
2028
|
const fallbackPorts = [9222, 9333, 9335, 9337, 9339].filter((p) => p !== this.port);
|
|
2015
2029
|
for (const port of fallbackPorts) {
|
|
2016
2030
|
target = await this.findTargetOnPort(port);
|
|
@@ -2031,6 +2045,8 @@ var init_daemon_cdp = __esm({
|
|
|
2031
2045
|
await this.sendInternal("Runtime.enable");
|
|
2032
2046
|
} catch {
|
|
2033
2047
|
}
|
|
2048
|
+
this.connectBrowserWs().catch(() => {
|
|
2049
|
+
});
|
|
2034
2050
|
resolve3(true);
|
|
2035
2051
|
});
|
|
2036
2052
|
this.ws.on("message", (data) => {
|
|
@@ -2055,6 +2071,9 @@ var init_daemon_cdp = __esm({
|
|
|
2055
2071
|
this.ws.on("close", () => {
|
|
2056
2072
|
this.log("[CDP] WebSocket closed \u2014 scheduling reconnect");
|
|
2057
2073
|
this._connected = false;
|
|
2074
|
+
this._browserConnected = false;
|
|
2075
|
+
this.browserWs?.close();
|
|
2076
|
+
this.browserWs = null;
|
|
2058
2077
|
this.connectPromise = null;
|
|
2059
2078
|
this.scheduleReconnect();
|
|
2060
2079
|
});
|
|
@@ -2065,12 +2084,98 @@ var init_daemon_cdp = __esm({
|
|
|
2065
2084
|
});
|
|
2066
2085
|
});
|
|
2067
2086
|
}
|
|
2087
|
+
/** Browser-level CDP 연결 — Target discovery에 필요 */
|
|
2088
|
+
async connectBrowserWs() {
|
|
2089
|
+
if (this._browserConnected && this.browserWs?.readyState === import_ws3.default.OPEN) return;
|
|
2090
|
+
try {
|
|
2091
|
+
const browserWsUrl = await this.getBrowserWsUrl();
|
|
2092
|
+
if (!browserWsUrl) {
|
|
2093
|
+
this.log("[CDP] No browser WS URL found");
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
2097
|
+
await new Promise((resolve3, reject) => {
|
|
2098
|
+
this.browserWs = new import_ws3.default(browserWsUrl);
|
|
2099
|
+
this.browserWs.on("open", async () => {
|
|
2100
|
+
this._browserConnected = true;
|
|
2101
|
+
this.log("[CDP] \u2705 Browser WS connected \u2014 enabling target discovery");
|
|
2102
|
+
try {
|
|
2103
|
+
await this.sendBrowser("Target.setDiscoverTargets", { discover: true });
|
|
2104
|
+
} catch (e) {
|
|
2105
|
+
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
2106
|
+
}
|
|
2107
|
+
resolve3();
|
|
2108
|
+
});
|
|
2109
|
+
this.browserWs.on("message", (data) => {
|
|
2110
|
+
try {
|
|
2111
|
+
const msg = JSON.parse(data.toString());
|
|
2112
|
+
if (msg.id && this.browserPending.has(msg.id)) {
|
|
2113
|
+
const { resolve: resolve4, reject: reject2 } = this.browserPending.get(msg.id);
|
|
2114
|
+
this.browserPending.delete(msg.id);
|
|
2115
|
+
if (msg.error) reject2(new Error(msg.error.message));
|
|
2116
|
+
else resolve4(msg.result);
|
|
2117
|
+
}
|
|
2118
|
+
} catch {
|
|
2119
|
+
}
|
|
2120
|
+
});
|
|
2121
|
+
this.browserWs.on("close", () => {
|
|
2122
|
+
this._browserConnected = false;
|
|
2123
|
+
this.browserWs = null;
|
|
2124
|
+
});
|
|
2125
|
+
this.browserWs.on("error", (err) => {
|
|
2126
|
+
this.log(`[CDP] Browser WS error: ${err.message}`);
|
|
2127
|
+
this._browserConnected = false;
|
|
2128
|
+
reject(err);
|
|
2129
|
+
});
|
|
2130
|
+
});
|
|
2131
|
+
} catch (e) {
|
|
2132
|
+
this.log(`[CDP] Browser WS connect failed: ${e.message}`);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
getBrowserWsUrl() {
|
|
2136
|
+
return new Promise((resolve3) => {
|
|
2137
|
+
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
2138
|
+
let data = "";
|
|
2139
|
+
res.on("data", (chunk) => data += chunk.toString());
|
|
2140
|
+
res.on("end", () => {
|
|
2141
|
+
try {
|
|
2142
|
+
const info = JSON.parse(data);
|
|
2143
|
+
resolve3(info.webSocketDebuggerUrl || null);
|
|
2144
|
+
} catch {
|
|
2145
|
+
resolve3(null);
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
});
|
|
2149
|
+
req.on("error", () => resolve3(null));
|
|
2150
|
+
req.setTimeout(3e3, () => {
|
|
2151
|
+
req.destroy();
|
|
2152
|
+
resolve3(null);
|
|
2153
|
+
});
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
2157
|
+
return new Promise((resolve3, reject) => {
|
|
2158
|
+
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
2159
|
+
const id = this.browserMsgId++;
|
|
2160
|
+
this.browserPending.set(id, { resolve: resolve3, reject });
|
|
2161
|
+
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
2162
|
+
setTimeout(() => {
|
|
2163
|
+
if (this.browserPending.has(id)) {
|
|
2164
|
+
this.browserPending.delete(id);
|
|
2165
|
+
reject(new Error(`Browser CDP timeout: ${method}`));
|
|
2166
|
+
}
|
|
2167
|
+
}, timeoutMs);
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2068
2170
|
scheduleReconnect() {
|
|
2069
2171
|
if (this.reconnectTimer) return;
|
|
2070
2172
|
this.reconnectTimer = setTimeout(async () => {
|
|
2071
2173
|
this.reconnectTimer = null;
|
|
2072
2174
|
if (!this._connected) {
|
|
2073
|
-
await this.connect();
|
|
2175
|
+
const ok = await this.connect();
|
|
2176
|
+
if (!ok && !this._connected) {
|
|
2177
|
+
this.scheduleReconnect();
|
|
2178
|
+
}
|
|
2074
2179
|
}
|
|
2075
2180
|
}, 5e3);
|
|
2076
2181
|
}
|
|
@@ -2082,6 +2187,9 @@ var init_daemon_cdp = __esm({
|
|
|
2082
2187
|
this.ws?.close();
|
|
2083
2188
|
this.ws = null;
|
|
2084
2189
|
this._connected = false;
|
|
2190
|
+
this.browserWs?.close();
|
|
2191
|
+
this.browserWs = null;
|
|
2192
|
+
this._browserConnected = false;
|
|
2085
2193
|
this.failureCount = 0;
|
|
2086
2194
|
}
|
|
2087
2195
|
get isConnected() {
|
|
@@ -2155,23 +2263,47 @@ var init_daemon_cdp = __esm({
|
|
|
2155
2263
|
// ─── Agent Webview Multi-Session ─────────────────────────
|
|
2156
2264
|
async discoverAgentWebviews() {
|
|
2157
2265
|
if (!this.isConnected) return [];
|
|
2266
|
+
if (!this._browserConnected) {
|
|
2267
|
+
await this.connectBrowserWs().catch(() => {
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2158
2270
|
try {
|
|
2159
|
-
|
|
2160
|
-
|
|
2271
|
+
let allTargets = [];
|
|
2272
|
+
if (this._browserConnected) {
|
|
2273
|
+
const result = await this.sendBrowser("Target.getTargets");
|
|
2274
|
+
allTargets = result?.targetInfos || [];
|
|
2275
|
+
} else {
|
|
2276
|
+
const result = await this.sendInternal("Target.getTargets");
|
|
2277
|
+
allTargets = result?.targetInfos || [];
|
|
2278
|
+
}
|
|
2161
2279
|
const iframes = allTargets.filter((t) => t.type === "iframe");
|
|
2162
|
-
|
|
2280
|
+
const typeMap = /* @__PURE__ */ new Map();
|
|
2281
|
+
for (const t of allTargets) {
|
|
2282
|
+
typeMap.set(t.type, (typeMap.get(t.type) || 0) + 1);
|
|
2283
|
+
}
|
|
2284
|
+
const typeSummary = [...typeMap.entries()].map(([k, v]) => `${k}:${v}`).join(",");
|
|
2285
|
+
this.log(`[CDP] discoverAgentWebviews: ${allTargets.length} total [${typeSummary}], ${iframes.length} iframes (browser=${this._browserConnected})`);
|
|
2286
|
+
for (const t of allTargets) {
|
|
2287
|
+
if (t.type !== "page" && t.type !== "worker" && t.type !== "service_worker") {
|
|
2288
|
+
this.log(`[CDP] target: type=${t.type} url=${(t.url || "").substring(0, 120)}`);
|
|
2289
|
+
}
|
|
2290
|
+
if ((t.url || "").includes("vscode-webview")) {
|
|
2291
|
+
this.log(`[CDP] webview: type=${t.type} url=${(t.url || "").substring(0, 150)}`);
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2163
2294
|
const agents = [];
|
|
2164
2295
|
for (const target of allTargets) {
|
|
2165
2296
|
if (target.type !== "iframe") continue;
|
|
2166
|
-
const
|
|
2297
|
+
const url = target.url || "";
|
|
2298
|
+
const hasWebview = url.includes("vscode-webview");
|
|
2167
2299
|
if (!hasWebview) continue;
|
|
2168
2300
|
for (const known of KNOWN_AGENTS) {
|
|
2169
|
-
if (known.extensionIdPattern.test(
|
|
2301
|
+
if (known.extensionIdPattern.test(url)) {
|
|
2170
2302
|
agents.push({
|
|
2171
2303
|
targetId: target.targetId,
|
|
2172
2304
|
extensionId: known.extensionId,
|
|
2173
2305
|
agentType: known.agentType,
|
|
2174
|
-
url
|
|
2306
|
+
url
|
|
2175
2307
|
});
|
|
2176
2308
|
this.log(`[CDP] Found agent: ${known.agentType} (${target.targetId})`);
|
|
2177
2309
|
break;
|
|
@@ -2190,7 +2322,8 @@ var init_daemon_cdp = __esm({
|
|
|
2190
2322
|
if (t.agentType === target.agentType) return sid;
|
|
2191
2323
|
}
|
|
2192
2324
|
try {
|
|
2193
|
-
const
|
|
2325
|
+
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
2326
|
+
const result = await sendFn("Target.attachToTarget", {
|
|
2194
2327
|
targetId: target.targetId,
|
|
2195
2328
|
flatten: true
|
|
2196
2329
|
});
|
|
@@ -2206,12 +2339,15 @@ var init_daemon_cdp = __esm({
|
|
|
2206
2339
|
}
|
|
2207
2340
|
}
|
|
2208
2341
|
async evaluateInSession(sessionId, expression, timeoutMs = 15e3) {
|
|
2209
|
-
|
|
2342
|
+
const ws = this._browserConnected ? this.browserWs : this.ws;
|
|
2343
|
+
const pendingMap = this._browserConnected ? this.browserPending : this.pending;
|
|
2344
|
+
const getNextId = () => this._browserConnected ? this.browserMsgId++ : this.msgId++;
|
|
2345
|
+
if (!ws || ws.readyState !== import_ws3.default.OPEN) {
|
|
2210
2346
|
throw new Error("CDP not connected");
|
|
2211
2347
|
}
|
|
2212
2348
|
return new Promise((resolve3, reject) => {
|
|
2213
|
-
const id =
|
|
2214
|
-
|
|
2349
|
+
const id = getNextId();
|
|
2350
|
+
pendingMap.set(id, {
|
|
2215
2351
|
resolve: (result) => {
|
|
2216
2352
|
if (result?.result?.subtype === "error") {
|
|
2217
2353
|
reject(new Error(result.result.description));
|
|
@@ -2221,15 +2357,15 @@ var init_daemon_cdp = __esm({
|
|
|
2221
2357
|
},
|
|
2222
2358
|
reject
|
|
2223
2359
|
});
|
|
2224
|
-
|
|
2360
|
+
ws.send(JSON.stringify({
|
|
2225
2361
|
id,
|
|
2226
2362
|
sessionId,
|
|
2227
2363
|
method: "Runtime.evaluate",
|
|
2228
2364
|
params: { expression, returnByValue: true, awaitPromise: true }
|
|
2229
2365
|
}));
|
|
2230
2366
|
setTimeout(() => {
|
|
2231
|
-
if (
|
|
2232
|
-
|
|
2367
|
+
if (pendingMap.has(id)) {
|
|
2368
|
+
pendingMap.delete(id);
|
|
2233
2369
|
reject(new Error(`CDP agent timeout: ${sessionId.substring(0, 12)}...`));
|
|
2234
2370
|
}
|
|
2235
2371
|
}, timeoutMs);
|
|
@@ -2237,7 +2373,8 @@ var init_daemon_cdp = __esm({
|
|
|
2237
2373
|
}
|
|
2238
2374
|
async detachAgent(sessionId) {
|
|
2239
2375
|
try {
|
|
2240
|
-
|
|
2376
|
+
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
2377
|
+
await sendFn("Target.detachFromTarget", { sessionId });
|
|
2241
2378
|
} catch {
|
|
2242
2379
|
}
|
|
2243
2380
|
this.agentSessions.delete(sessionId);
|
|
@@ -2256,7 +2393,9 @@ var init_daemon_cdp = __esm({
|
|
|
2256
2393
|
try {
|
|
2257
2394
|
const result = await this.sendInternal("Page.captureScreenshot", {
|
|
2258
2395
|
format: "jpeg",
|
|
2259
|
-
quality:
|
|
2396
|
+
quality: 25,
|
|
2397
|
+
clip: void 0
|
|
2398
|
+
// full viewport
|
|
2260
2399
|
}, 1e4);
|
|
2261
2400
|
if (result?.data) {
|
|
2262
2401
|
return Buffer.from(result.data, "base64");
|
|
@@ -2577,12 +2716,22 @@ var init_daemon_p2p = __esm({
|
|
|
2577
2716
|
fileRequestHandler = null;
|
|
2578
2717
|
inputHandler = null;
|
|
2579
2718
|
commandHandler = null;
|
|
2719
|
+
_ssDebugDone = false;
|
|
2580
2720
|
get screenshotActive() {
|
|
2581
2721
|
for (const peer of this.peers.values()) {
|
|
2582
2722
|
if (peer.screenshotActive && peer.state === "connected") return true;
|
|
2583
2723
|
}
|
|
2584
2724
|
return false;
|
|
2585
2725
|
}
|
|
2726
|
+
/** Get the ideType for the currently active screenshot request */
|
|
2727
|
+
get screenshotIdeType() {
|
|
2728
|
+
for (const peer of this.peers.values()) {
|
|
2729
|
+
if (peer.screenshotActive && peer.state === "connected" && peer.screenshotIdeType) {
|
|
2730
|
+
return peer.screenshotIdeType;
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
return void 0;
|
|
2734
|
+
}
|
|
2586
2735
|
constructor(bridge) {
|
|
2587
2736
|
this.bridge = bridge;
|
|
2588
2737
|
this.tryLoadNodeDatachannel();
|
|
@@ -2591,7 +2740,8 @@ var init_daemon_p2p = __esm({
|
|
|
2591
2740
|
tryLoadNodeDatachannel() {
|
|
2592
2741
|
try {
|
|
2593
2742
|
this.nodeDatachannel = require_lib();
|
|
2594
|
-
|
|
2743
|
+
const keys = Object.keys(this.nodeDatachannel).join(",");
|
|
2744
|
+
log(`node-datachannel loaded \u2705 (keys: ${keys.substring(0, 100)})`);
|
|
2595
2745
|
return;
|
|
2596
2746
|
} catch (e) {
|
|
2597
2747
|
log(`node-datachannel not found: ${e?.message}`);
|
|
@@ -2725,7 +2875,12 @@ var init_daemon_p2p = __esm({
|
|
|
2725
2875
|
if (existing?.state === "connected") return;
|
|
2726
2876
|
if (existing?.state === "connecting") this.disconnectPeer(pid);
|
|
2727
2877
|
log(`initiateConnection() for peer ${pid}...`);
|
|
2728
|
-
const
|
|
2878
|
+
const mod = this.nodeDatachannel;
|
|
2879
|
+
const PeerConnectionCtor = mod.PeerConnection || mod.default?.PeerConnection || mod.default || mod;
|
|
2880
|
+
if (!PeerConnectionCtor || typeof PeerConnectionCtor !== "function") {
|
|
2881
|
+
log(`PeerConnection constructor not found in node-datachannel module. Keys: ${Object.keys(mod).join(",")}`);
|
|
2882
|
+
return;
|
|
2883
|
+
}
|
|
2729
2884
|
let iceServers = [
|
|
2730
2885
|
"stun:stun.cloudflare.com:3478",
|
|
2731
2886
|
"stun:stun.l.google.com:19302"
|
|
@@ -2738,7 +2893,7 @@ var init_daemon_p2p = __esm({
|
|
|
2738
2893
|
}
|
|
2739
2894
|
} catch {
|
|
2740
2895
|
}
|
|
2741
|
-
const pc = new
|
|
2896
|
+
const pc = new PeerConnectionCtor(`ADHDev-Daemon-${pid.substring(0, 8)}`, {
|
|
2742
2897
|
iceServers
|
|
2743
2898
|
});
|
|
2744
2899
|
const entry = {
|
|
@@ -2781,11 +2936,17 @@ var init_daemon_p2p = __esm({
|
|
|
2781
2936
|
}
|
|
2782
2937
|
});
|
|
2783
2938
|
const screenshotCh = pc.createDataChannel("screenshots");
|
|
2784
|
-
entry.screenshotChannel = screenshotCh;
|
|
2785
2939
|
screenshotCh.onOpen(() => {
|
|
2786
2940
|
log(`Screenshots channel OPEN for peer ${pid}`);
|
|
2787
|
-
|
|
2788
|
-
|
|
2941
|
+
const peer = this.peers.get(pid);
|
|
2942
|
+
if (peer) {
|
|
2943
|
+
peer.screenshotChannel = screenshotCh;
|
|
2944
|
+
peer.state = "connected";
|
|
2945
|
+
this.notifyStateChange();
|
|
2946
|
+
if (peer.screenshotActive) {
|
|
2947
|
+
log(`Screenshots auto-starting for peer ${pid} (was waiting for channel open)`);
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2789
2950
|
});
|
|
2790
2951
|
screenshotCh.onClosed(() => {
|
|
2791
2952
|
log(`Screenshots channel CLOSED for peer ${pid}`);
|
|
@@ -2819,14 +2980,24 @@ var init_daemon_p2p = __esm({
|
|
|
2819
2980
|
const text = typeof msg === "string" ? msg : msg.toString("utf-8");
|
|
2820
2981
|
try {
|
|
2821
2982
|
const parsed = JSON.parse(text);
|
|
2983
|
+
log(`Files message from peer ${peerId}: type=${parsed.type}`);
|
|
2822
2984
|
if (parsed.type === "screenshot_start") {
|
|
2823
2985
|
const peer = this.peers.get(peerId);
|
|
2824
|
-
if (peer)
|
|
2986
|
+
if (peer) {
|
|
2987
|
+
peer.screenshotActive = true;
|
|
2988
|
+
peer.screenshotIdeType = parsed.ideType || void 0;
|
|
2989
|
+
log(`screenshot_start: peer=${peerId}, ideType=${parsed.ideType || "any"}, channelOpen=${!!peer.screenshotChannel}, state=${peer.state}`);
|
|
2990
|
+
} else {
|
|
2991
|
+
log(`screenshot_start: peer ${peerId} NOT FOUND in peers map!`);
|
|
2992
|
+
}
|
|
2825
2993
|
return;
|
|
2826
2994
|
}
|
|
2827
2995
|
if (parsed.type === "screenshot_stop") {
|
|
2828
2996
|
const peer = this.peers.get(peerId);
|
|
2829
|
-
if (peer)
|
|
2997
|
+
if (peer) {
|
|
2998
|
+
peer.screenshotActive = false;
|
|
2999
|
+
log(`screenshot_stop: peer=${peerId}`);
|
|
3000
|
+
}
|
|
2830
3001
|
return;
|
|
2831
3002
|
}
|
|
2832
3003
|
if (parsed.type === "input") {
|
|
@@ -2863,14 +3034,28 @@ var init_daemon_p2p = __esm({
|
|
|
2863
3034
|
sendScreenshot(base64Data) {
|
|
2864
3035
|
let sentAny = false;
|
|
2865
3036
|
const buffer = Buffer.from(base64Data, "base64");
|
|
2866
|
-
|
|
3037
|
+
let debugOnce = !this._ssDebugDone;
|
|
3038
|
+
const CHUNK_SIZE = 6e4;
|
|
3039
|
+
for (const [pid, peer] of this.peers.entries()) {
|
|
3040
|
+
if (debugOnce) {
|
|
3041
|
+
log(`sendScreenshot peer=${pid}: state=${peer.state}, hasSsCh=${!!peer.screenshotChannel}, ssActive=${peer.screenshotActive}, chOpen=${peer.screenshotChannel?.isOpen?.() ?? "N/A"}, bufSize=${buffer.length}`);
|
|
3042
|
+
}
|
|
2867
3043
|
if (peer.state !== "connected" || !peer.screenshotChannel || !peer.screenshotActive) continue;
|
|
2868
3044
|
try {
|
|
2869
|
-
peer.screenshotChannel.
|
|
3045
|
+
if (!peer.screenshotChannel.isOpen()) continue;
|
|
3046
|
+
const header = Buffer.alloc(4);
|
|
3047
|
+
header.writeUInt32BE(buffer.length, 0);
|
|
3048
|
+
peer.screenshotChannel.sendMessageBinary(header);
|
|
3049
|
+
for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
|
|
3050
|
+
const chunk = buffer.subarray(offset, Math.min(offset + CHUNK_SIZE, buffer.length));
|
|
3051
|
+
peer.screenshotChannel.sendMessageBinary(chunk);
|
|
3052
|
+
}
|
|
2870
3053
|
sentAny = true;
|
|
2871
|
-
} catch {
|
|
3054
|
+
} catch (e) {
|
|
3055
|
+
if (debugOnce) log(`sendScreenshot ERROR for peer ${pid}: ${e?.message}`);
|
|
2872
3056
|
}
|
|
2873
3057
|
}
|
|
3058
|
+
if (debugOnce) this._ssDebugDone = true;
|
|
2874
3059
|
return sentAny;
|
|
2875
3060
|
}
|
|
2876
3061
|
// ─── 핸들러 등록 ────────────────────────────
|
|
@@ -2904,7 +3089,9 @@ var init_daemon_p2p = __esm({
|
|
|
2904
3089
|
return;
|
|
2905
3090
|
}
|
|
2906
3091
|
try {
|
|
2907
|
-
const
|
|
3092
|
+
const peer = this.peers.get(peerId);
|
|
3093
|
+
const ideType = peer?.screenshotIdeType;
|
|
3094
|
+
const result = await this.inputHandler({ action, params, _targetInstance: ideType ? `${ideType}_` : void 0 });
|
|
2908
3095
|
this.sendToPeer(peerId, { id, type: "response", success: true, result });
|
|
2909
3096
|
} catch (e) {
|
|
2910
3097
|
this.sendToPeer(peerId, { id, type: "response", success: false, error: e?.message });
|
|
@@ -3156,13 +3343,46 @@ var init_daemon_commands = __esm({
|
|
|
3156
3343
|
DaemonCommandHandler = class {
|
|
3157
3344
|
ctx;
|
|
3158
3345
|
agentStream = null;
|
|
3346
|
+
/** Get CDP manager for a specific ideType, or first connected one */
|
|
3347
|
+
getCdp(ideType) {
|
|
3348
|
+
const key = ideType || this._currentIdeType;
|
|
3349
|
+
if (key) {
|
|
3350
|
+
const m = this.ctx.cdpManagers.get(key.toLowerCase());
|
|
3351
|
+
if (m?.isConnected) return m;
|
|
3352
|
+
}
|
|
3353
|
+
for (const m of this.ctx.cdpManagers.values()) {
|
|
3354
|
+
if (m.isConnected) return m;
|
|
3355
|
+
}
|
|
3356
|
+
return null;
|
|
3357
|
+
}
|
|
3358
|
+
/** Current IDE type extracted from command args (per-request) */
|
|
3359
|
+
_currentIdeType;
|
|
3360
|
+
/** Extract ideType from _targetInstance (e.g. 'vscode_abc123' → 'vscode') */
|
|
3361
|
+
extractIdeType(args) {
|
|
3362
|
+
if (args?._targetInstance) {
|
|
3363
|
+
const parts = args._targetInstance.split("_");
|
|
3364
|
+
if (parts.length >= 2) return parts[0];
|
|
3365
|
+
}
|
|
3366
|
+
return void 0;
|
|
3367
|
+
}
|
|
3159
3368
|
constructor(ctx) {
|
|
3160
3369
|
this.ctx = ctx;
|
|
3161
3370
|
}
|
|
3371
|
+
/** Get ScriptLoader for specific ideType, fallback to first available */
|
|
3372
|
+
getScriptLoader(ideType) {
|
|
3373
|
+
const key = ideType || this._currentIdeType;
|
|
3374
|
+
if (key) {
|
|
3375
|
+
const l = this.ctx.scriptLoaders.get(key.toLowerCase());
|
|
3376
|
+
if (l) return l;
|
|
3377
|
+
}
|
|
3378
|
+
for (const l of this.ctx.scriptLoaders.values()) return l;
|
|
3379
|
+
return void 0;
|
|
3380
|
+
}
|
|
3162
3381
|
setAgentStreamManager(manager) {
|
|
3163
3382
|
this.agentStream = manager;
|
|
3164
3383
|
}
|
|
3165
3384
|
async handle(cmd, args) {
|
|
3385
|
+
this._currentIdeType = this.extractIdeType(args);
|
|
3166
3386
|
switch (cmd) {
|
|
3167
3387
|
// ─── CDP 직접 처리 ───────────────────
|
|
3168
3388
|
case "read_chat":
|
|
@@ -3205,8 +3425,13 @@ var init_daemon_commands = __esm({
|
|
|
3205
3425
|
return this.handleFileListBrowse(args);
|
|
3206
3426
|
// ─── vscode API → Extension 위임 ────
|
|
3207
3427
|
case "vscode_command_exec":
|
|
3208
|
-
case "execute_vscode_command":
|
|
3209
|
-
|
|
3428
|
+
case "execute_vscode_command": {
|
|
3429
|
+
const resolvedCmd = args?.commandId || args?.command;
|
|
3430
|
+
if (resolvedCmd === "adhdev.captureCdpScreenshot") {
|
|
3431
|
+
return this.handleScreenshot(args);
|
|
3432
|
+
}
|
|
3433
|
+
return this.delegateToExtension(resolvedCmd || cmd, args?.args);
|
|
3434
|
+
}
|
|
3210
3435
|
case "get_open_editors":
|
|
3211
3436
|
return this.delegateToExtension("adhdev.getOpenEditors", [args]);
|
|
3212
3437
|
case "open_tab":
|
|
@@ -3249,59 +3474,97 @@ var init_daemon_commands = __esm({
|
|
|
3249
3474
|
}
|
|
3250
3475
|
// ─── CDP 기반 채팅 명령 ──────────────────────
|
|
3251
3476
|
async handleReadChat(args) {
|
|
3252
|
-
if (!this.
|
|
3253
|
-
const script = this.
|
|
3477
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3478
|
+
const script = this.getScriptLoader()?.get("read_chat");
|
|
3254
3479
|
if (!script) return { success: false, error: "read_chat script not loaded" };
|
|
3255
3480
|
try {
|
|
3256
|
-
const result = await this.
|
|
3481
|
+
const result = await this.getCdp().evaluate(script, 5e4);
|
|
3257
3482
|
return { success: true, ...result };
|
|
3258
3483
|
} catch (e) {
|
|
3259
3484
|
return { success: false, error: e.message };
|
|
3260
3485
|
}
|
|
3261
3486
|
}
|
|
3262
3487
|
async handleSendChat(args) {
|
|
3263
|
-
if (!this.ctx.cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3264
3488
|
const text = args?.text || args?.message;
|
|
3265
3489
|
if (!text) return { success: false, error: "text required" };
|
|
3266
|
-
const
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3490
|
+
const targetCdp = this.getCdp();
|
|
3491
|
+
const targetLoader = this.getScriptLoader();
|
|
3492
|
+
if (targetCdp?.isConnected && targetLoader) {
|
|
3493
|
+
const script = targetLoader.getWithParams("send_message", { MESSAGE: JSON.stringify(text) });
|
|
3494
|
+
if (script) {
|
|
3495
|
+
console.log(`[send_chat] Targeting IDE: ${this._currentIdeType || "fallback-first"}`);
|
|
3496
|
+
try {
|
|
3497
|
+
await targetCdp.evaluate(script, 3e4);
|
|
3498
|
+
return { success: true, sent: true };
|
|
3499
|
+
} catch (e) {
|
|
3500
|
+
console.log(`[send_chat] Failed on ${this._currentIdeType}: ${e.message}`);
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
console.log(`[send_chat] No specific target, trying all CDPs...`);
|
|
3505
|
+
for (const [ideType, cdp] of this.ctx.cdpManagers) {
|
|
3506
|
+
if (!cdp.isConnected) continue;
|
|
3507
|
+
const loader = this.ctx.scriptLoaders.get(ideType);
|
|
3508
|
+
if (!loader) continue;
|
|
3509
|
+
const script = loader.getWithParams("send_message", { MESSAGE: JSON.stringify(text) });
|
|
3510
|
+
if (!script) continue;
|
|
3511
|
+
console.log(`[send_chat] Trying IDE: ${ideType}`);
|
|
3512
|
+
try {
|
|
3513
|
+
await cdp.evaluate(script, 3e4);
|
|
3514
|
+
return { success: true, sent: true, targetIde: ideType };
|
|
3515
|
+
} catch (e) {
|
|
3516
|
+
console.log(`[send_chat] Failed on ${ideType}: ${e.message}`);
|
|
3517
|
+
}
|
|
3273
3518
|
}
|
|
3519
|
+
return { success: false, error: "No CDP could send the message" };
|
|
3274
3520
|
}
|
|
3275
3521
|
async handleListChats(args) {
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3522
|
+
const cdp = this.getCdp();
|
|
3523
|
+
if (!cdp?.isConnected) {
|
|
3524
|
+
console.log(`[list_chats] CDP not connected, ideType=${this._currentIdeType}`);
|
|
3525
|
+
return { success: false, error: "CDP not connected" };
|
|
3526
|
+
}
|
|
3527
|
+
const script = this.getScriptLoader()?.get("list_chats");
|
|
3528
|
+
if (!script) {
|
|
3529
|
+
console.log(`[list_chats] script not loaded`);
|
|
3530
|
+
return { success: false, error: "list_chats script not loaded" };
|
|
3531
|
+
}
|
|
3279
3532
|
try {
|
|
3280
|
-
|
|
3281
|
-
|
|
3533
|
+
console.log(`[list_chats] Evaluating on ideType=${this._currentIdeType}`);
|
|
3534
|
+
const result = await cdp.evaluate(script, 3e4);
|
|
3535
|
+
let parsed = result;
|
|
3536
|
+
if (typeof result === "string") {
|
|
3537
|
+
try {
|
|
3538
|
+
parsed = JSON.parse(result);
|
|
3539
|
+
} catch {
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
console.log(`[list_chats] Result type=${typeof parsed}, isArray=${Array.isArray(parsed)}, len=${Array.isArray(parsed) ? parsed.length : "N/A"}`);
|
|
3543
|
+
return { success: true, chats: parsed };
|
|
3282
3544
|
} catch (e) {
|
|
3545
|
+
console.log(`[list_chats] Error: ${e.message}`);
|
|
3283
3546
|
return { success: false, error: e.message };
|
|
3284
3547
|
}
|
|
3285
3548
|
}
|
|
3286
3549
|
async handleNewChat(args) {
|
|
3287
|
-
if (!this.
|
|
3288
|
-
const script = this.
|
|
3550
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3551
|
+
const script = this.getScriptLoader()?.get("new_session");
|
|
3289
3552
|
if (!script) return { success: false, error: "new_session script not loaded" };
|
|
3290
3553
|
try {
|
|
3291
|
-
await this.
|
|
3554
|
+
await this.getCdp().evaluate(script, 15e3);
|
|
3292
3555
|
return { success: true };
|
|
3293
3556
|
} catch (e) {
|
|
3294
3557
|
return { success: false, error: e.message };
|
|
3295
3558
|
}
|
|
3296
3559
|
}
|
|
3297
3560
|
async handleSwitchChat(args) {
|
|
3298
|
-
if (!this.
|
|
3561
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3299
3562
|
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
3300
3563
|
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
3301
|
-
const script = this.
|
|
3564
|
+
const script = this.getScriptLoader()?.getWithParams("switch_session", { SESSION_ID: sessionId });
|
|
3302
3565
|
if (!script) return { success: false, error: "switch_session script not loaded" };
|
|
3303
3566
|
try {
|
|
3304
|
-
await this.
|
|
3567
|
+
await this.getCdp().evaluate(script, 15e3);
|
|
3305
3568
|
return { success: true };
|
|
3306
3569
|
} catch (e) {
|
|
3307
3570
|
return { success: false, error: e.message };
|
|
@@ -3315,12 +3578,12 @@ var init_daemon_commands = __esm({
|
|
|
3315
3578
|
return this.delegateToExtension("workbench.action.openSettings", [`cursor.model`]);
|
|
3316
3579
|
}
|
|
3317
3580
|
async handleResolveModal(args) {
|
|
3318
|
-
if (!this.
|
|
3581
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3319
3582
|
const button = args?.button || args?.buttonText || "Accept";
|
|
3320
|
-
const script = this.
|
|
3583
|
+
const script = this.getScriptLoader()?.getWithParams("resolve_modal", { BUTTON_TEXT: button });
|
|
3321
3584
|
if (!script) {
|
|
3322
3585
|
try {
|
|
3323
|
-
await this.
|
|
3586
|
+
await this.getCdp().evaluate(`
|
|
3324
3587
|
(() => {
|
|
3325
3588
|
const btns = [...document.querySelectorAll('button')];
|
|
3326
3589
|
const btn = btns.find(b => b.textContent?.trim() === ${JSON.stringify(button)});
|
|
@@ -3334,7 +3597,7 @@ var init_daemon_commands = __esm({
|
|
|
3334
3597
|
}
|
|
3335
3598
|
}
|
|
3336
3599
|
try {
|
|
3337
|
-
await this.
|
|
3600
|
+
await this.getCdp().evaluate(script, 1e4);
|
|
3338
3601
|
return { success: true };
|
|
3339
3602
|
} catch (e) {
|
|
3340
3603
|
return { success: false, error: e.message };
|
|
@@ -3342,22 +3605,23 @@ var init_daemon_commands = __esm({
|
|
|
3342
3605
|
}
|
|
3343
3606
|
// ─── CDP 직접 명령 ──────────────────────────
|
|
3344
3607
|
async handleCdpEval(args) {
|
|
3345
|
-
if (!this.
|
|
3608
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3346
3609
|
const expression = args?.expression || args?.script;
|
|
3347
3610
|
if (!expression) return { success: false, error: "expression required" };
|
|
3348
3611
|
try {
|
|
3349
|
-
const result = await this.
|
|
3612
|
+
const result = await this.getCdp().evaluate(expression, 5e4);
|
|
3350
3613
|
return { success: true, result };
|
|
3351
3614
|
} catch (e) {
|
|
3352
3615
|
return { success: false, error: e.message };
|
|
3353
3616
|
}
|
|
3354
3617
|
}
|
|
3355
3618
|
async handleScreenshot(args) {
|
|
3356
|
-
if (!this.
|
|
3619
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3357
3620
|
try {
|
|
3358
|
-
const buf = await this.
|
|
3621
|
+
const buf = await this.getCdp().captureScreenshot();
|
|
3359
3622
|
if (buf) {
|
|
3360
|
-
|
|
3623
|
+
const b64 = buf.toString("base64");
|
|
3624
|
+
return { success: true, result: b64, base64: b64, screenshot: b64, format: "jpeg" };
|
|
3361
3625
|
}
|
|
3362
3626
|
return { success: false, error: "Screenshot failed" };
|
|
3363
3627
|
} catch (e) {
|
|
@@ -3365,26 +3629,26 @@ var init_daemon_commands = __esm({
|
|
|
3365
3629
|
}
|
|
3366
3630
|
}
|
|
3367
3631
|
async handleCdpCommand(args) {
|
|
3368
|
-
if (!this.
|
|
3632
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3369
3633
|
const method = args?.method;
|
|
3370
3634
|
const params = args?.params || {};
|
|
3371
3635
|
if (!method) return { success: false, error: "method required" };
|
|
3372
3636
|
try {
|
|
3373
|
-
const result = await this.
|
|
3637
|
+
const result = await this.getCdp().sendCdpCommand(method, params);
|
|
3374
3638
|
return { success: true, result };
|
|
3375
3639
|
} catch (e) {
|
|
3376
3640
|
return { success: false, error: e.message };
|
|
3377
3641
|
}
|
|
3378
3642
|
}
|
|
3379
3643
|
async handleCdpBatch(args) {
|
|
3380
|
-
if (!this.
|
|
3644
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3381
3645
|
const commands = args?.commands;
|
|
3382
3646
|
const stopOnError = args?.stopOnError !== false;
|
|
3383
3647
|
if (!commands?.length) return { success: false, error: "commands array required" };
|
|
3384
3648
|
const results = [];
|
|
3385
3649
|
for (const cmd of commands) {
|
|
3386
3650
|
try {
|
|
3387
|
-
const result = await this.
|
|
3651
|
+
const result = await this.getCdp().sendCdpCommand(cmd.method, cmd.params || {});
|
|
3388
3652
|
results.push({ method: cmd.method, success: true, result });
|
|
3389
3653
|
} catch (e) {
|
|
3390
3654
|
results.push({ method: cmd.method, success: false, error: e.message });
|
|
@@ -3394,49 +3658,60 @@ var init_daemon_commands = __esm({
|
|
|
3394
3658
|
return { success: true, results };
|
|
3395
3659
|
}
|
|
3396
3660
|
async handleCdpRemoteAction(args) {
|
|
3397
|
-
if (!this.
|
|
3661
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3398
3662
|
const action = args?.action;
|
|
3399
3663
|
const params = args?.params || args;
|
|
3400
3664
|
try {
|
|
3401
3665
|
switch (action) {
|
|
3402
3666
|
case "input_key": {
|
|
3403
3667
|
const { key, modifiers } = params;
|
|
3404
|
-
await this.
|
|
3668
|
+
await this.getCdp().send("Input.dispatchKeyEvent", {
|
|
3405
3669
|
type: "keyDown",
|
|
3406
3670
|
key,
|
|
3407
3671
|
...modifiers?.ctrl ? { modifiers: 2 } : {},
|
|
3408
3672
|
...modifiers?.shift ? { modifiers: 8 } : {}
|
|
3409
3673
|
});
|
|
3410
|
-
await this.
|
|
3674
|
+
await this.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key });
|
|
3411
3675
|
return { success: true };
|
|
3412
3676
|
}
|
|
3413
3677
|
case "input_click": {
|
|
3414
|
-
|
|
3415
|
-
|
|
3678
|
+
let { x, y, nx, ny, button: btn } = params;
|
|
3679
|
+
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
3680
|
+
const viewport = await this.getCdp().evaluate(
|
|
3681
|
+
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
3682
|
+
);
|
|
3683
|
+
const { w, h } = JSON.parse(viewport);
|
|
3684
|
+
x = Math.round(nx * w);
|
|
3685
|
+
y = Math.round(ny * h);
|
|
3686
|
+
}
|
|
3687
|
+
if (x === void 0 || y === void 0) {
|
|
3688
|
+
return { success: false, error: "No coordinates provided (x,y or nx,ny required)" };
|
|
3689
|
+
}
|
|
3690
|
+
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
3416
3691
|
type: "mousePressed",
|
|
3417
3692
|
x,
|
|
3418
3693
|
y,
|
|
3419
3694
|
button: btn || "left",
|
|
3420
3695
|
clickCount: 1
|
|
3421
3696
|
});
|
|
3422
|
-
await this.
|
|
3697
|
+
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
3423
3698
|
type: "mouseReleased",
|
|
3424
3699
|
x,
|
|
3425
3700
|
y,
|
|
3426
3701
|
button: btn || "left",
|
|
3427
3702
|
clickCount: 1
|
|
3428
3703
|
});
|
|
3429
|
-
return { success: true };
|
|
3704
|
+
return { success: true, x, y };
|
|
3430
3705
|
}
|
|
3431
3706
|
case "input_type": {
|
|
3432
3707
|
const { text } = params;
|
|
3433
3708
|
for (const char of text || "") {
|
|
3434
|
-
await this.
|
|
3709
|
+
await this.getCdp().send("Input.dispatchKeyEvent", {
|
|
3435
3710
|
type: "keyDown",
|
|
3436
3711
|
text: char,
|
|
3437
3712
|
key: char
|
|
3438
3713
|
});
|
|
3439
|
-
await this.
|
|
3714
|
+
await this.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key: char });
|
|
3440
3715
|
}
|
|
3441
3716
|
return { success: true };
|
|
3442
3717
|
}
|
|
@@ -3445,9 +3720,28 @@ var init_daemon_commands = __esm({
|
|
|
3445
3720
|
case "page_eval":
|
|
3446
3721
|
return this.handleCdpEval(params);
|
|
3447
3722
|
case "dom_query": {
|
|
3448
|
-
const html = await this.
|
|
3723
|
+
const html = await this.getCdp().querySelector(params?.selector);
|
|
3449
3724
|
return { success: true, html };
|
|
3450
3725
|
}
|
|
3726
|
+
case "input_wheel": {
|
|
3727
|
+
let { x, y, nx, ny, deltaX, deltaY } = params;
|
|
3728
|
+
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
3729
|
+
const viewport = await this.getCdp().evaluate(
|
|
3730
|
+
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
3731
|
+
);
|
|
3732
|
+
const { w, h } = JSON.parse(viewport);
|
|
3733
|
+
x = Math.round(nx * w);
|
|
3734
|
+
y = Math.round(ny * h);
|
|
3735
|
+
}
|
|
3736
|
+
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
3737
|
+
type: "mouseWheel",
|
|
3738
|
+
x: x || 0,
|
|
3739
|
+
y: y || 0,
|
|
3740
|
+
deltaX: deltaX || 0,
|
|
3741
|
+
deltaY: deltaY || 0
|
|
3742
|
+
});
|
|
3743
|
+
return { success: true };
|
|
3744
|
+
}
|
|
3451
3745
|
default:
|
|
3452
3746
|
return { success: false, error: `Unknown remote action: ${action}` };
|
|
3453
3747
|
}
|
|
@@ -3456,8 +3750,8 @@ var init_daemon_commands = __esm({
|
|
|
3456
3750
|
}
|
|
3457
3751
|
}
|
|
3458
3752
|
async handleDiscoverAgents(args) {
|
|
3459
|
-
if (!this.
|
|
3460
|
-
const agents = await this.
|
|
3753
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3754
|
+
const agents = await this.getCdp().discoverAgentWebviews();
|
|
3461
3755
|
return { success: true, agents };
|
|
3462
3756
|
}
|
|
3463
3757
|
// ─── 파일 직접 처리 ─────────────────────────
|
|
@@ -3514,7 +3808,7 @@ var init_daemon_commands = __esm({
|
|
|
3514
3808
|
if (!this.ctx.localServer || this.ctx.localServer.extensionCount === 0) {
|
|
3515
3809
|
return { success: false, error: "No extension connected" };
|
|
3516
3810
|
}
|
|
3517
|
-
return this.ctx.localServer.executeVscodeCommand(command, args);
|
|
3811
|
+
return this.ctx.localServer.executeVscodeCommand(command, args, this._currentIdeType);
|
|
3518
3812
|
}
|
|
3519
3813
|
// ─── 기타 ───────────────────────────────────
|
|
3520
3814
|
async handleGetRecentWorkspaces(args) {
|
|
@@ -3533,66 +3827,67 @@ var init_daemon_commands = __esm({
|
|
|
3533
3827
|
}
|
|
3534
3828
|
}
|
|
3535
3829
|
async handleRefreshScripts(args) {
|
|
3536
|
-
|
|
3537
|
-
|
|
3830
|
+
const loader = this.getScriptLoader();
|
|
3831
|
+
if (!loader) return { success: false, error: "ScriptLoader not initialized" };
|
|
3832
|
+
await loader.refresh();
|
|
3538
3833
|
return { success: true };
|
|
3539
3834
|
}
|
|
3540
3835
|
// ─── Agent Stream 명령 ───────────────────────
|
|
3541
3836
|
async handleAgentStreamSwitch(args) {
|
|
3542
|
-
if (!this.agentStream || !this.
|
|
3837
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3543
3838
|
const agentType = args?.agentType || args?.agent || null;
|
|
3544
|
-
await this.agentStream.switchActiveAgent(this.
|
|
3839
|
+
await this.agentStream.switchActiveAgent(this.getCdp(), agentType);
|
|
3545
3840
|
return { success: true, activeAgent: agentType };
|
|
3546
3841
|
}
|
|
3547
3842
|
async handleAgentStreamRead(args) {
|
|
3548
|
-
if (!this.agentStream || !this.
|
|
3549
|
-
const streams = await this.agentStream.collectAgentStreams(this.
|
|
3843
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3844
|
+
const streams = await this.agentStream.collectAgentStreams(this.getCdp());
|
|
3550
3845
|
return { success: true, streams };
|
|
3551
3846
|
}
|
|
3552
3847
|
async handleAgentStreamSend(args) {
|
|
3553
|
-
if (!this.agentStream || !this.
|
|
3848
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3554
3849
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3555
3850
|
const text = args?.text || args?.message;
|
|
3556
3851
|
if (!agentType || !text) return { success: false, error: "agentType and text required" };
|
|
3557
|
-
const ok = await this.agentStream.sendToAgent(this.
|
|
3852
|
+
const ok = await this.agentStream.sendToAgent(this.getCdp(), agentType, text);
|
|
3558
3853
|
return { success: ok };
|
|
3559
3854
|
}
|
|
3560
3855
|
async handleAgentStreamResolve(args) {
|
|
3561
|
-
if (!this.agentStream || !this.
|
|
3856
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3562
3857
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3563
3858
|
const action = args?.action || "approve";
|
|
3564
3859
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3565
|
-
const ok = await this.agentStream.resolveAgentAction(this.
|
|
3860
|
+
const ok = await this.agentStream.resolveAgentAction(this.getCdp(), agentType, action);
|
|
3566
3861
|
return { success: ok };
|
|
3567
3862
|
}
|
|
3568
3863
|
async handleAgentStreamNew(args) {
|
|
3569
|
-
if (!this.agentStream || !this.
|
|
3864
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3570
3865
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3571
3866
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3572
|
-
const ok = await this.agentStream.newAgentSession(this.
|
|
3867
|
+
const ok = await this.agentStream.newAgentSession(this.getCdp(), agentType);
|
|
3573
3868
|
return { success: ok };
|
|
3574
3869
|
}
|
|
3575
3870
|
async handleAgentStreamListChats(args) {
|
|
3576
|
-
if (!this.agentStream || !this.
|
|
3871
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3577
3872
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3578
3873
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3579
|
-
const chats = await this.agentStream.listAgentChats(this.
|
|
3874
|
+
const chats = await this.agentStream.listAgentChats(this.getCdp(), agentType);
|
|
3580
3875
|
return { success: true, chats };
|
|
3581
3876
|
}
|
|
3582
3877
|
async handleAgentStreamSwitchSession(args) {
|
|
3583
|
-
if (!this.agentStream || !this.
|
|
3878
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3584
3879
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3585
3880
|
const sessionId = args?.sessionId || args?.id;
|
|
3586
3881
|
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
3587
|
-
const ok = await this.agentStream.switchAgentSession(this.
|
|
3882
|
+
const ok = await this.agentStream.switchAgentSession(this.getCdp(), agentType, sessionId);
|
|
3588
3883
|
return { success: ok };
|
|
3589
3884
|
}
|
|
3590
3885
|
async handleAgentStreamFocus(args) {
|
|
3591
|
-
if (!this.agentStream || !this.
|
|
3886
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3592
3887
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3593
3888
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3594
3889
|
await this.agentStream.ensureAgentPanelOpen(agentType);
|
|
3595
|
-
const ok = await this.agentStream.focusAgentEditor(this.
|
|
3890
|
+
const ok = await this.agentStream.focusAgentEditor(this.getCdp(), agentType);
|
|
3596
3891
|
return { success: ok };
|
|
3597
3892
|
}
|
|
3598
3893
|
};
|
|
@@ -4192,23 +4487,29 @@ var init_adhdev_daemon = __esm({
|
|
|
4192
4487
|
AdhdevDaemon = class {
|
|
4193
4488
|
localServer = null;
|
|
4194
4489
|
bridge = null;
|
|
4195
|
-
|
|
4196
|
-
|
|
4490
|
+
adapters = /* @__PURE__ */ new Map();
|
|
4491
|
+
cdpManagers = /* @__PURE__ */ new Map();
|
|
4197
4492
|
cdpDiscoveryTimer = null;
|
|
4198
4493
|
p2p = null;
|
|
4199
|
-
|
|
4494
|
+
scriptLoaders = /* @__PURE__ */ new Map();
|
|
4200
4495
|
commandHandler = null;
|
|
4201
4496
|
screenshotTimer = null;
|
|
4202
4497
|
agentStreamManager = null;
|
|
4203
4498
|
agentStreamTimer = null;
|
|
4204
4499
|
running = false;
|
|
4205
4500
|
statusTimer = null;
|
|
4206
|
-
lastAgentStatus =
|
|
4207
|
-
generatingStartedAt =
|
|
4501
|
+
lastAgentStatus = /* @__PURE__ */ new Map();
|
|
4502
|
+
generatingStartedAt = /* @__PURE__ */ new Map();
|
|
4503
|
+
getCliKey(cliType, dir) {
|
|
4504
|
+
const hash = require("crypto").createHash("md5").update(require("path").resolve(dir)).digest("hex").slice(0, 8);
|
|
4505
|
+
return `${cliType}_${hash}`;
|
|
4506
|
+
}
|
|
4208
4507
|
detectedIdes = [];
|
|
4209
4508
|
localPort;
|
|
4210
4509
|
ideType = "unknown";
|
|
4211
|
-
|
|
4510
|
+
_cachedAgentStreamsMap = /* @__PURE__ */ new Map();
|
|
4511
|
+
_cachedActiveChatMap = /* @__PURE__ */ new Map();
|
|
4512
|
+
_cdpChatBusy = false;
|
|
4212
4513
|
constructor() {
|
|
4213
4514
|
this.localPort = DEFAULT_DAEMON_PORT;
|
|
4214
4515
|
}
|
|
@@ -4271,18 +4572,27 @@ var init_adhdev_daemon = __esm({
|
|
|
4271
4572
|
}
|
|
4272
4573
|
this.detectedIdes = await detectIDEs();
|
|
4273
4574
|
await this.initCdp();
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
}
|
|
4575
|
+
const serverUrl = options.serverUrl || config.serverUrl;
|
|
4576
|
+
for (const ideType of this.cdpManagers.keys()) {
|
|
4577
|
+
const loader = new DaemonScriptLoader(serverUrl, ideType);
|
|
4578
|
+
loader.setToken(config.connectionToken);
|
|
4579
|
+
await loader.start().catch((e) => {
|
|
4580
|
+
console.log(import_chalk2.default.yellow(` \u26A0 ScriptLoader start failed for ${ideType}: ${e.message}`));
|
|
4581
|
+
});
|
|
4582
|
+
this.scriptLoaders.set(ideType, loader);
|
|
4583
|
+
}
|
|
4584
|
+
if (this.scriptLoaders.size === 0) {
|
|
4585
|
+
const fallbackType = this.detectedIdes.find((ide) => ide.installed)?.id || "cursor";
|
|
4586
|
+
const loader = new DaemonScriptLoader(serverUrl, fallbackType);
|
|
4587
|
+
loader.setToken(config.connectionToken);
|
|
4588
|
+
await loader.start().catch((e) => {
|
|
4589
|
+
console.log(import_chalk2.default.yellow(` \u26A0 ScriptLoader start failed: ${e.message}`));
|
|
4590
|
+
});
|
|
4591
|
+
this.scriptLoaders.set(fallbackType, loader);
|
|
4592
|
+
}
|
|
4283
4593
|
this.commandHandler = new DaemonCommandHandler({
|
|
4284
|
-
|
|
4285
|
-
|
|
4594
|
+
cdpManagers: this.cdpManagers,
|
|
4595
|
+
scriptLoaders: this.scriptLoaders,
|
|
4286
4596
|
localServer: this.localServer,
|
|
4287
4597
|
ideType: this.ideType
|
|
4288
4598
|
});
|
|
@@ -4293,26 +4603,11 @@ var init_adhdev_daemon = __esm({
|
|
|
4293
4603
|
);
|
|
4294
4604
|
this.agentStreamManager.setLocalServer(this.localServer);
|
|
4295
4605
|
this.commandHandler.setAgentStreamManager(this.agentStreamManager);
|
|
4296
|
-
|
|
4297
|
-
this.agentStreamTimer = setInterval(async () => {
|
|
4298
|
-
if (!this.cdpManager?.isConnected || !this.agentStreamManager) return;
|
|
4299
|
-
try {
|
|
4300
|
-
await this.agentStreamManager.syncAgentSessions(this.cdpManager);
|
|
4301
|
-
this._cachedAgentStreams = await this.agentStreamManager.collectAgentStreams(this.cdpManager);
|
|
4302
|
-
} catch {
|
|
4303
|
-
}
|
|
4304
|
-
}, 5e3);
|
|
4305
|
-
}
|
|
4606
|
+
this.startAgentStreamPolling();
|
|
4306
4607
|
if (options.cliType) {
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
await this.adapter.spawn();
|
|
4311
|
-
this.adapter.setOnStatusChange(() => this.sendUnifiedStatusReport());
|
|
4312
|
-
console.log(import_chalk2.default.green(` \u{1F916} CLI Agent started: ${cliInfo.displayName} v${cliInfo.version || "unknown"}`));
|
|
4313
|
-
} else {
|
|
4314
|
-
console.log(import_chalk2.default.yellow(` \u26A0 CLI ${options.cliType} not found \u2014 running without CLI agent`));
|
|
4315
|
-
}
|
|
4608
|
+
await this.startCliSession(options.cliType, workingDir).catch((e) => {
|
|
4609
|
+
console.log(import_chalk2.default.yellow(` \u26A0 Failed to start CLI ${options.cliType}: ${e.message}`));
|
|
4610
|
+
});
|
|
4316
4611
|
}
|
|
4317
4612
|
const machineId = os8.hostname().replace(/[^a-zA-Z0-9]/g, "_");
|
|
4318
4613
|
const machineHash = crypto2.createHash("md5").update(os8.hostname() + os8.homedir()).digest("hex").slice(0, 8);
|
|
@@ -4327,9 +4622,6 @@ var init_adhdev_daemon = __esm({
|
|
|
4327
4622
|
instanceId
|
|
4328
4623
|
}
|
|
4329
4624
|
});
|
|
4330
|
-
if (this.adapter && typeof this.adapter.setBridge === "function") {
|
|
4331
|
-
this.adapter.setBridge(this.bridge);
|
|
4332
|
-
}
|
|
4333
4625
|
this.p2p = new DaemonP2PSender(this.bridge);
|
|
4334
4626
|
if (this.p2p.isAvailable) {
|
|
4335
4627
|
console.log(import_chalk2.default.green(" \u{1F517} P2P available (node-datachannel)"));
|
|
@@ -4353,12 +4645,26 @@ var init_adhdev_daemon = __esm({
|
|
|
4353
4645
|
return { id: req.id, success: result.success, entries: result.files, error: result.error };
|
|
4354
4646
|
}
|
|
4355
4647
|
});
|
|
4648
|
+
let ssDebugCount = 0;
|
|
4356
4649
|
this.screenshotTimer = setInterval(async () => {
|
|
4357
|
-
|
|
4650
|
+
const active = this.p2p?.screenshotActive;
|
|
4651
|
+
const ssIdeType = this.p2p?.screenshotIdeType;
|
|
4652
|
+
const cdp = ssIdeType ? this.getCdpFor(ssIdeType) : this.getAnyCdp();
|
|
4653
|
+
if (!active || !cdp) return;
|
|
4654
|
+
ssDebugCount++;
|
|
4655
|
+
if (ssDebugCount <= 3 || ssDebugCount % 25 === 0) {
|
|
4656
|
+
console.log(`[SS] Capturing screenshot... (tick ${ssDebugCount}, active=${active}, cdp=true)`);
|
|
4657
|
+
}
|
|
4358
4658
|
try {
|
|
4359
|
-
const buf = await
|
|
4360
|
-
if (buf)
|
|
4361
|
-
|
|
4659
|
+
const buf = await cdp.captureScreenshot();
|
|
4660
|
+
if (buf) {
|
|
4661
|
+
const sent = this.p2p.sendScreenshot(buf.toString("base64"));
|
|
4662
|
+
if (ssDebugCount <= 3) console.log(`[SS] Screenshot sent: ${buf.length} bytes, delivered=${sent}`);
|
|
4663
|
+
} else {
|
|
4664
|
+
if (ssDebugCount <= 5) console.log(`[SS] captureScreenshot returned null`);
|
|
4665
|
+
}
|
|
4666
|
+
} catch (e) {
|
|
4667
|
+
if (ssDebugCount <= 5) console.log(`[SS] Screenshot error: ${e?.message}`);
|
|
4362
4668
|
}
|
|
4363
4669
|
}, 200);
|
|
4364
4670
|
} else {
|
|
@@ -4391,9 +4697,10 @@ var init_adhdev_daemon = __esm({
|
|
|
4391
4697
|
console.log(import_chalk2.default.bold(" \u{1F309} ADHDev Daemon"));
|
|
4392
4698
|
console.log(` ${import_chalk2.default.bold("Local:")} ws://127.0.0.1:${this.localPort}/ipc`);
|
|
4393
4699
|
console.log(` ${import_chalk2.default.bold("Server:")} ${serverUrl}`);
|
|
4394
|
-
|
|
4700
|
+
const cdpStatus = this.cdpManagers.size > 0 ? `\u2705 ${[...this.cdpManagers.entries()].map(([k, m]) => `${k}:${m.getPort()}`).join(", ")}` : "\u274C not connected";
|
|
4701
|
+
console.log(` ${import_chalk2.default.bold("CDP:")} ${cdpStatus}`);
|
|
4395
4702
|
console.log(` ${import_chalk2.default.bold("P2P:")} ${this.p2p?.isAvailable ? "\u2705 available" : "\u274C unavailable"}`);
|
|
4396
|
-
console.log(` ${import_chalk2.default.bold("Scripts:")} ${this.
|
|
4703
|
+
console.log(` ${import_chalk2.default.bold("Scripts:")} ${this.scriptLoaders.size > 0 ? `\u2705 ${[...this.scriptLoaders.keys()].join(", ")}` : "\u274C not loaded"}`);
|
|
4397
4704
|
if (options.cliType) {
|
|
4398
4705
|
console.log(` ${import_chalk2.default.bold("CLI:")} ${options.cliType}`);
|
|
4399
4706
|
console.log(` ${import_chalk2.default.bold("Dir:")} ${options.workingDir || process.cwd()}`);
|
|
@@ -4405,19 +4712,6 @@ var init_adhdev_daemon = __esm({
|
|
|
4405
4712
|
// ─── 서버 명령 핸들러 ───────────────────────────
|
|
4406
4713
|
registerServerHandlers() {
|
|
4407
4714
|
if (!this.bridge) return;
|
|
4408
|
-
this.bridge.on("send_chat", (msg) => {
|
|
4409
|
-
const text = msg.payload.message;
|
|
4410
|
-
if (!text || !this.adapter) {
|
|
4411
|
-
this.sendResult(msg, false, { error: "No message or CLI adapter" });
|
|
4412
|
-
return;
|
|
4413
|
-
}
|
|
4414
|
-
console.log(import_chalk2.default.cyan(` \u2190 Chat: "${text.slice(0, 60)}${text.length > 60 ? "..." : ""}"`));
|
|
4415
|
-
this.adapter.sendMessage(text).then(() => {
|
|
4416
|
-
this.sendResult(msg, true, { sent: true });
|
|
4417
|
-
}).catch((e) => {
|
|
4418
|
-
this.sendResult(msg, false, { error: e?.message || "Failed" });
|
|
4419
|
-
});
|
|
4420
|
-
});
|
|
4421
4715
|
this.bridge.on("command", async (msg) => {
|
|
4422
4716
|
const cmd = msg.payload.command;
|
|
4423
4717
|
const args = msg.payload.args;
|
|
@@ -4455,7 +4749,38 @@ var init_adhdev_daemon = __esm({
|
|
|
4455
4749
|
"file_list",
|
|
4456
4750
|
"file_list_browse",
|
|
4457
4751
|
"terminal_exec",
|
|
4458
|
-
"refresh_scripts"
|
|
4752
|
+
"refresh_scripts",
|
|
4753
|
+
// CLI/daemon-local commands (launch, restart, detect)
|
|
4754
|
+
"launch_ide",
|
|
4755
|
+
"detect_ides",
|
|
4756
|
+
"restart_session",
|
|
4757
|
+
"exec_command",
|
|
4758
|
+
"launch_cli",
|
|
4759
|
+
"stop_cli",
|
|
4760
|
+
// Extension-delegated commands (must be registered to receive WS messages)
|
|
4761
|
+
"vscode_command_exec",
|
|
4762
|
+
"execute_vscode_command",
|
|
4763
|
+
"get_open_editors",
|
|
4764
|
+
"open_tab",
|
|
4765
|
+
"close_tab",
|
|
4766
|
+
"open_folder",
|
|
4767
|
+
"open_folder_picker",
|
|
4768
|
+
"open_recent",
|
|
4769
|
+
"get_commands",
|
|
4770
|
+
"get_recent_workspaces",
|
|
4771
|
+
"open_panel",
|
|
4772
|
+
"open_file",
|
|
4773
|
+
"create_terminal",
|
|
4774
|
+
"close_terminal",
|
|
4775
|
+
// Agent stream commands
|
|
4776
|
+
"agent_stream_switch",
|
|
4777
|
+
"agent_stream_read",
|
|
4778
|
+
"agent_stream_send",
|
|
4779
|
+
"agent_stream_resolve",
|
|
4780
|
+
"agent_stream_new",
|
|
4781
|
+
"agent_stream_list_chats",
|
|
4782
|
+
"agent_stream_switch_session",
|
|
4783
|
+
"agent_stream_focus"
|
|
4459
4784
|
];
|
|
4460
4785
|
for (const cmdType of directCdpCommands) {
|
|
4461
4786
|
this.bridge.on(cmdType, async (msg) => {
|
|
@@ -4467,21 +4792,33 @@ var init_adhdev_daemon = __esm({
|
|
|
4467
4792
|
console.log(import_chalk2.default.magenta(` \u2699 Command: ${cmd}`));
|
|
4468
4793
|
try {
|
|
4469
4794
|
switch (cmd) {
|
|
4470
|
-
case "
|
|
4471
|
-
const
|
|
4472
|
-
const
|
|
4473
|
-
|
|
4474
|
-
this.
|
|
4795
|
+
case "launch_cli": {
|
|
4796
|
+
const cliType = args?.cliType;
|
|
4797
|
+
const dir = args?.dir || process.cwd();
|
|
4798
|
+
if (!cliType) throw new Error("cliType required");
|
|
4799
|
+
const key = this.getCliKey(cliType, dir);
|
|
4800
|
+
if (!this.adapters.has(key)) {
|
|
4801
|
+
await this.startCliSession(cliType, dir);
|
|
4802
|
+
}
|
|
4803
|
+
this.sendResult(msg, true, { cliType, dir, id: key });
|
|
4475
4804
|
return;
|
|
4476
4805
|
}
|
|
4477
|
-
case "
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4806
|
+
case "stop_cli": {
|
|
4807
|
+
const cliType = args?.cliType;
|
|
4808
|
+
const dir = args?.dir || process.cwd();
|
|
4809
|
+
if (!cliType) throw new Error("cliType required");
|
|
4810
|
+
const key = this.getCliKey(cliType, dir);
|
|
4811
|
+
await this.stopCliSession(key);
|
|
4812
|
+
this.sendResult(msg, true, { cliType, dir });
|
|
4481
4813
|
return;
|
|
4482
4814
|
}
|
|
4483
4815
|
case "restart_session": {
|
|
4484
|
-
|
|
4816
|
+
const cliType = args?.cliType || args?.agentType;
|
|
4817
|
+
const dir = args?.dir || process.cwd();
|
|
4818
|
+
if (!cliType) throw new Error("cliType required");
|
|
4819
|
+
const key = this.getCliKey(cliType, dir);
|
|
4820
|
+
await this.stopCliSession(key);
|
|
4821
|
+
await this.startCliSession(cliType, dir);
|
|
4485
4822
|
this.sendResult(msg, true, { restarted: true });
|
|
4486
4823
|
return;
|
|
4487
4824
|
}
|
|
@@ -4492,7 +4829,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4492
4829
|
this.sendResult(msg, false, { error: `Blocked: "${cmdStr}"` });
|
|
4493
4830
|
return;
|
|
4494
4831
|
}
|
|
4495
|
-
const cwd =
|
|
4832
|
+
const cwd = args?.dir || process.cwd();
|
|
4496
4833
|
const { exec: exec2 } = require("child_process");
|
|
4497
4834
|
exec2(cmdStr, { cwd, timeout: 6e4 }, (err, stdout, stderr) => {
|
|
4498
4835
|
if (!this.bridge) return;
|
|
@@ -4506,7 +4843,33 @@ var init_adhdev_daemon = __esm({
|
|
|
4506
4843
|
return;
|
|
4507
4844
|
}
|
|
4508
4845
|
case "launch_ide": {
|
|
4509
|
-
const
|
|
4846
|
+
const launchArgs = { ...args, ideId: args.ideId || args.ideType };
|
|
4847
|
+
const ideKey = launchArgs.ideId;
|
|
4848
|
+
console.log(`[launch_ide] target=${ideKey || "auto"}`);
|
|
4849
|
+
const result = await launchWithCdp(launchArgs);
|
|
4850
|
+
if (result.success && result.port && result.ideId && !this.cdpManagers.has(result.ideId)) {
|
|
4851
|
+
console.log(import_chalk2.default.cyan(`[launch_ide] Connecting CDP for ${result.ideId} on port ${result.port}...`));
|
|
4852
|
+
const manager = new DaemonCdpManager(result.port, (msg2) => {
|
|
4853
|
+
console.log(import_chalk2.default.gray(msg2));
|
|
4854
|
+
}, true);
|
|
4855
|
+
const connected = await manager.connect();
|
|
4856
|
+
if (connected) {
|
|
4857
|
+
this.cdpManagers.set(result.ideId, manager);
|
|
4858
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${result.ideId} (port ${result.port})`));
|
|
4859
|
+
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
4860
|
+
if (!this.scriptLoaders.has(result.ideId)) {
|
|
4861
|
+
const config = loadConfig();
|
|
4862
|
+
const serverUrl = config.serverUrl || "https://api.adhf.dev";
|
|
4863
|
+
const loader = new DaemonScriptLoader(serverUrl, result.ideId);
|
|
4864
|
+
loader.setToken(config.connectionToken || "");
|
|
4865
|
+
await loader.start().catch((e) => {
|
|
4866
|
+
console.log(import_chalk2.default.yellow(` \u26A0 ScriptLoader start failed for ${result.ideId}: ${e?.message}`));
|
|
4867
|
+
});
|
|
4868
|
+
this.scriptLoaders.set(result.ideId, loader);
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
this.startAgentStreamPolling();
|
|
4510
4873
|
this.sendResult(msg, result.success, result);
|
|
4511
4874
|
return;
|
|
4512
4875
|
}
|
|
@@ -4551,48 +4914,111 @@ var init_adhdev_daemon = __esm({
|
|
|
4551
4914
|
return new GeminiCliAdapter(workingDir);
|
|
4552
4915
|
}
|
|
4553
4916
|
}
|
|
4554
|
-
async
|
|
4555
|
-
console.log(import_chalk2.default.yellow(` \u26A1 Switching CLI to ${cliType} in ${workingDir}...`));
|
|
4556
|
-
if (this.adapter) this.adapter.shutdown();
|
|
4917
|
+
async startCliSession(cliType, workingDir) {
|
|
4557
4918
|
const cliInfo = await detectCLI(cliType);
|
|
4558
4919
|
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4920
|
+
const key = this.getCliKey(cliType, workingDir);
|
|
4921
|
+
if (this.adapters.has(key)) {
|
|
4922
|
+
console.log(import_chalk2.default.yellow(` \u26A1 CLI ${cliType} already running in ${workingDir}`));
|
|
4923
|
+
return;
|
|
4924
|
+
}
|
|
4925
|
+
console.log(import_chalk2.default.yellow(` \u26A1 Starting CLI ${cliType} in ${workingDir}...`));
|
|
4926
|
+
const adapter = this.createAdapter(cliType, workingDir);
|
|
4927
|
+
await adapter.spawn();
|
|
4928
|
+
if (this.bridge && typeof adapter.setBridge === "function") {
|
|
4929
|
+
adapter.setBridge(this.bridge);
|
|
4930
|
+
}
|
|
4931
|
+
adapter.setOnStatusChange(() => this.sendUnifiedStatusReport());
|
|
4932
|
+
this.adapters.set(key, adapter);
|
|
4933
|
+
this.lastAgentStatus.set(key, "idle");
|
|
4934
|
+
console.log(import_chalk2.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${workingDir}`));
|
|
4935
|
+
this.sendUnifiedStatusReport();
|
|
4936
|
+
}
|
|
4937
|
+
async stopCliSession(key) {
|
|
4938
|
+
const adapter = this.adapters.get(key);
|
|
4939
|
+
if (adapter) {
|
|
4940
|
+
adapter.shutdown();
|
|
4941
|
+
this.adapters.delete(key);
|
|
4942
|
+
this.lastAgentStatus.delete(key);
|
|
4943
|
+
this.generatingStartedAt.delete(key);
|
|
4944
|
+
console.log(import_chalk2.default.yellow(` \u{1F6D1} CLI Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`));
|
|
4945
|
+
this.sendUnifiedStatusReport();
|
|
4563
4946
|
}
|
|
4564
|
-
this.adapter.setOnStatusChange(() => this.sendUnifiedStatusReport());
|
|
4565
|
-
console.log(import_chalk2.default.green(` \u2713 CLI switched to ${cliType}`));
|
|
4566
4947
|
}
|
|
4567
4948
|
// ─── 통합 상태 보고 ─────────────────────────────
|
|
4568
4949
|
startStatusReporting() {
|
|
4569
4950
|
const scheduleNext = () => {
|
|
4570
|
-
const isProcessing = this.
|
|
4951
|
+
const isProcessing = Array.from(this.adapters.values()).some((a) => a.isProcessing());
|
|
4571
4952
|
const interval = isProcessing ? 2e3 : 15e3;
|
|
4572
4953
|
this.statusTimer = setTimeout(() => {
|
|
4573
|
-
this.sendUnifiedStatusReport()
|
|
4954
|
+
this.sendUnifiedStatusReport().catch(() => {
|
|
4955
|
+
});
|
|
4574
4956
|
scheduleNext();
|
|
4575
4957
|
}, interval);
|
|
4576
4958
|
};
|
|
4577
4959
|
scheduleNext();
|
|
4578
4960
|
}
|
|
4579
|
-
sendUnifiedStatusReport() {
|
|
4961
|
+
async sendUnifiedStatusReport() {
|
|
4580
4962
|
if (!this.bridge?.isConnected()) return;
|
|
4963
|
+
if (this.cdpManagers.size > 0 && this.scriptLoaders.size > 0 && !this._cdpChatBusy) {
|
|
4964
|
+
this._cdpChatBusy = true;
|
|
4965
|
+
for (const [ideType, cdp] of this.cdpManagers) {
|
|
4966
|
+
if (!cdp.isConnected) continue;
|
|
4967
|
+
const loader = this.scriptLoaders.get(ideType);
|
|
4968
|
+
if (!loader) continue;
|
|
4969
|
+
const readChatScript = loader.get("read_chat");
|
|
4970
|
+
if (!readChatScript) continue;
|
|
4971
|
+
try {
|
|
4972
|
+
const raw = await cdp.evaluate(readChatScript, 3e4);
|
|
4973
|
+
if (raw && typeof raw === "object") {
|
|
4974
|
+
let { activeModal } = raw;
|
|
4975
|
+
if (activeModal) {
|
|
4976
|
+
const w = activeModal.width ?? Infinity;
|
|
4977
|
+
const h = activeModal.height ?? Infinity;
|
|
4978
|
+
if (w < 80 || h < 40) activeModal = void 0;
|
|
4979
|
+
else activeModal = {
|
|
4980
|
+
message: activeModal.message?.slice(0, 300) ?? "",
|
|
4981
|
+
buttons: (activeModal.buttons ?? []).filter((t) => t.length < 30)
|
|
4982
|
+
};
|
|
4983
|
+
}
|
|
4984
|
+
this._cachedActiveChatMap.set(ideType, { ...raw, activeModal });
|
|
4985
|
+
}
|
|
4986
|
+
} catch {
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
this._cdpChatBusy = false;
|
|
4990
|
+
}
|
|
4581
4991
|
const now = Date.now();
|
|
4582
4992
|
const perExtData = this.localServer?.getPerExtensionData() || [];
|
|
4583
|
-
const
|
|
4993
|
+
const enabledIdesFilter = loadConfig().enabledIdes || [];
|
|
4994
|
+
const filteredExtData = enabledIdesFilter.length > 0 ? perExtData.filter((ext) => enabledIdesFilter.includes(ext.ideType.toLowerCase())) : perExtData;
|
|
4995
|
+
const extSummary = this.localServer?.getLatestExtensionData(enabledIdesFilter) || {
|
|
4584
4996
|
activeFile: null,
|
|
4585
4997
|
workspaceFolders: [],
|
|
4586
4998
|
terminals: 0,
|
|
4587
4999
|
aiAgents: [],
|
|
4588
5000
|
connectedIdes: []
|
|
4589
5001
|
};
|
|
4590
|
-
const
|
|
4591
|
-
|
|
4592
|
-
const isMainCdpIde =
|
|
5002
|
+
const managedIdes = filteredExtData.map((ext) => {
|
|
5003
|
+
const ideKey = ext.ideType.toLowerCase();
|
|
5004
|
+
const isMainCdpIde = this.cdpManagers.has(ideKey);
|
|
5005
|
+
const cdpStreamsForIde = this._cachedAgentStreamsMap.get(ideKey) || [];
|
|
5006
|
+
const extAgentsForIde = (ext.aiAgents || []).filter((a) => {
|
|
5007
|
+
const existsInCdp = cdpStreamsForIde.some((s) => s.agentType === a.id);
|
|
5008
|
+
const existsInExt = ext.agentStreams.some((s) => s.agentType === a.id);
|
|
5009
|
+
return !existsInCdp && !existsInExt;
|
|
5010
|
+
}).map((a) => ({
|
|
5011
|
+
agentType: a.id,
|
|
5012
|
+
agentName: a.name,
|
|
5013
|
+
extensionId: a.id,
|
|
5014
|
+
status: a.status === "active" || a.status === "installed" ? "connected" : "idle",
|
|
5015
|
+
messages: [],
|
|
5016
|
+
inputContent: ""
|
|
5017
|
+
}));
|
|
4593
5018
|
const ideAgentStreams = [
|
|
4594
5019
|
...ext.agentStreams,
|
|
4595
|
-
...isMainCdpIde ?
|
|
5020
|
+
...isMainCdpIde ? cdpStreamsForIde : [],
|
|
5021
|
+
...extAgentsForIde
|
|
4596
5022
|
];
|
|
4597
5023
|
return {
|
|
4598
5024
|
ideType: ext.ideType,
|
|
@@ -4602,54 +5028,57 @@ var init_adhdev_daemon = __esm({
|
|
|
4602
5028
|
activeFile: ext.activeFile,
|
|
4603
5029
|
terminals: ext.terminals,
|
|
4604
5030
|
aiAgents: ext.aiAgents,
|
|
4605
|
-
activeChat: ext.activeChat,
|
|
5031
|
+
activeChat: isMainCdpIde && this._cachedActiveChatMap.has(ideKey) ? this._cachedActiveChatMap.get(ideKey) : ext.activeChat,
|
|
4606
5032
|
chats: ext.chats,
|
|
4607
5033
|
agentStreams: ideAgentStreams,
|
|
4608
|
-
cdpConnected: isMainCdpIde ? this.
|
|
5034
|
+
cdpConnected: isMainCdpIde ? this.cdpManagers.get(ext.ideType.toLowerCase())?.isConnected || false : false
|
|
4609
5035
|
};
|
|
4610
5036
|
});
|
|
4611
5037
|
const managedClis = [];
|
|
4612
|
-
|
|
4613
|
-
const adapterStatus =
|
|
5038
|
+
for (const [key, adapter] of this.adapters.entries()) {
|
|
5039
|
+
const adapterStatus = adapter.getStatus();
|
|
4614
5040
|
const cliStatus = adapterStatus.status;
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
this.
|
|
5041
|
+
let lastStatus = this.lastAgentStatus.get(key) || "idle";
|
|
5042
|
+
if (cliStatus !== lastStatus) {
|
|
5043
|
+
if (lastStatus === "idle" && cliStatus === "generating") {
|
|
5044
|
+
this.generatingStartedAt.set(key, now);
|
|
5045
|
+
this.bridge?.sendMessage("status_event", {
|
|
4619
5046
|
event: "agent:generating_started",
|
|
4620
|
-
chatTitle: `${
|
|
5047
|
+
chatTitle: `${adapter.cliName} Session`,
|
|
4621
5048
|
timestamp: now
|
|
4622
5049
|
});
|
|
4623
|
-
} else if (
|
|
4624
|
-
const
|
|
4625
|
-
|
|
5050
|
+
} else if (lastStatus === "generating" && cliStatus === "idle") {
|
|
5051
|
+
const startedAt = this.generatingStartedAt.get(key);
|
|
5052
|
+
const duration = startedAt ? Math.round((now - startedAt) / 1e3) : 0;
|
|
5053
|
+
this.bridge?.sendMessage("status_event", {
|
|
4626
5054
|
event: "agent:generating_completed",
|
|
4627
|
-
chatTitle: `${
|
|
5055
|
+
chatTitle: `${adapter.cliName} Session`,
|
|
4628
5056
|
duration,
|
|
4629
5057
|
timestamp: now
|
|
4630
5058
|
});
|
|
4631
|
-
this.generatingStartedAt
|
|
5059
|
+
this.generatingStartedAt.delete(key);
|
|
4632
5060
|
}
|
|
4633
|
-
this.lastAgentStatus
|
|
5061
|
+
this.lastAgentStatus.set(key, cliStatus);
|
|
4634
5062
|
}
|
|
4635
5063
|
const recentMessages = adapterStatus.messages.slice(-50);
|
|
4636
5064
|
const cliMessages = recentMessages.map((m) => ({
|
|
4637
5065
|
role: m.role,
|
|
4638
5066
|
content: m.content.length > 2e3 ? m.content.slice(0, 2e3) + "\n... (truncated)" : m.content
|
|
4639
5067
|
}));
|
|
4640
|
-
const partial =
|
|
5068
|
+
const partial = adapter.getPartialResponse();
|
|
4641
5069
|
if (cliStatus === "generating" && partial) {
|
|
4642
|
-
cliMessages.push({ role: "assistant", content: partial.slice(0, 2e3) + "..." });
|
|
5070
|
+
cliMessages.push({ role: "assistant", content: partial.length > 2e3 ? partial.slice(0, 2e3) + "..." : partial + "..." });
|
|
4643
5071
|
}
|
|
4644
5072
|
managedClis.push({
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
5073
|
+
id: key,
|
|
5074
|
+
cliType: adapter.cliType,
|
|
5075
|
+
cliName: adapter.cliName,
|
|
4648
5076
|
status: cliStatus,
|
|
5077
|
+
workingDir: adapter.workingDir,
|
|
4649
5078
|
activeChat: {
|
|
4650
|
-
id:
|
|
5079
|
+
id: key,
|
|
4651
5080
|
status: cliStatus,
|
|
4652
|
-
title: `${
|
|
5081
|
+
title: `${adapter.cliName} Session`,
|
|
4653
5082
|
messages: cliMessages,
|
|
4654
5083
|
inputContent: "",
|
|
4655
5084
|
activeModal: adapterStatus.activeModal
|
|
@@ -4673,8 +5102,12 @@ var init_adhdev_daemon = __esm({
|
|
|
4673
5102
|
// 관리 중인 IDE/CLI (계층 데이터)
|
|
4674
5103
|
managedIdes,
|
|
4675
5104
|
managedClis,
|
|
4676
|
-
// IDE 감지 결과 (설치된 IDE 목록)
|
|
4677
|
-
detectedIdes: this.detectedIdes
|
|
5105
|
+
// IDE 감지 결과 (설치된 IDE 목록) — 프론트엔드 호환 매핑 (id→type)
|
|
5106
|
+
detectedIdes: this.detectedIdes.map((ide) => ({
|
|
5107
|
+
...ide,
|
|
5108
|
+
type: ide.id
|
|
5109
|
+
// 프론트엔드 MachineDetail.tsx는 'type' 필드 사용
|
|
5110
|
+
})),
|
|
4678
5111
|
// P2P 상태
|
|
4679
5112
|
p2p: {
|
|
4680
5113
|
available: this.p2p?.isAvailable || false,
|
|
@@ -4682,18 +5115,25 @@ var init_adhdev_daemon = __esm({
|
|
|
4682
5115
|
peers: this.p2p?.connectedPeerCount || 0,
|
|
4683
5116
|
screenshotActive: this.p2p?.screenshotActive || false
|
|
4684
5117
|
},
|
|
4685
|
-
cdpConnected: this.
|
|
4686
|
-
scriptLoaderReady:
|
|
5118
|
+
cdpConnected: this.getAnyCdp() !== null,
|
|
5119
|
+
scriptLoaderReady: this.scriptLoaders.size > 0,
|
|
4687
5120
|
timestamp: now,
|
|
4688
5121
|
// ─── Legacy compat (서버 기존 로직용, 점진적 제거 예정) ───
|
|
4689
5122
|
activeFile: extSummary.activeFile,
|
|
4690
|
-
workspaceFolders: extSummary.workspaceFolders.length > 0 ? extSummary.workspaceFolders : this.
|
|
5123
|
+
workspaceFolders: extSummary.workspaceFolders.length > 0 ? extSummary.workspaceFolders : Array.from(this.adapters.values()).map((a) => ({ name: path4.basename(a.workingDir), path: a.workingDir })),
|
|
4691
5124
|
terminals: extSummary.terminals,
|
|
5125
|
+
// Legacy aiAgents: managedIdes에서 각 IDE의 aiAgents를 통합
|
|
4692
5126
|
aiAgents: [
|
|
4693
|
-
...
|
|
4694
|
-
|
|
5127
|
+
...managedIdes.flatMap((ide) => (ide.aiAgents || []).map((a) => ({
|
|
5128
|
+
id: a.id,
|
|
5129
|
+
name: a.name,
|
|
5130
|
+
status: a.status,
|
|
5131
|
+
ideType: ide.ideType
|
|
5132
|
+
}))),
|
|
5133
|
+
...Array.from(this.adapters.entries()).map(([k, a]) => ({ id: a.cliType, name: a.cliName, status: this.lastAgentStatus.get(k) || "idle" }))
|
|
4695
5134
|
],
|
|
4696
5135
|
activeChat: managedClis[0]?.activeChat || managedIdes[0]?.activeChat || null,
|
|
5136
|
+
// Legacy agentStreams: managedIdes의 agentStreams를 통합 (이미 IDE별로 올바르게 구성됨)
|
|
4697
5137
|
agentStreams: [
|
|
4698
5138
|
...managedClis.map((c) => ({
|
|
4699
5139
|
agentType: c.cliType,
|
|
@@ -4703,7 +5143,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4703
5143
|
messages: c.activeChat?.messages || [],
|
|
4704
5144
|
inputContent: ""
|
|
4705
5145
|
})),
|
|
4706
|
-
...
|
|
5146
|
+
...managedIdes.flatMap((ide) => ide.agentStreams || [])
|
|
4707
5147
|
],
|
|
4708
5148
|
connectedExtensions: extSummary.connectedIdes,
|
|
4709
5149
|
system: {
|
|
@@ -4735,18 +5175,22 @@ var init_adhdev_daemon = __esm({
|
|
|
4735
5175
|
if (!this.running) return;
|
|
4736
5176
|
this.running = false;
|
|
4737
5177
|
console.log(import_chalk2.default.yellow("\n Shutting down ADHDev Daemon..."));
|
|
4738
|
-
this.adapter
|
|
5178
|
+
for (const adapter of this.adapters.values()) adapter.shutdown();
|
|
5179
|
+
this.adapters.clear();
|
|
4739
5180
|
if (this.statusTimer) clearTimeout(this.statusTimer);
|
|
4740
5181
|
if (this.cdpDiscoveryTimer) clearInterval(this.cdpDiscoveryTimer);
|
|
4741
5182
|
if (this.screenshotTimer) clearInterval(this.screenshotTimer);
|
|
4742
5183
|
if (this.agentStreamTimer) clearInterval(this.agentStreamTimer);
|
|
4743
|
-
|
|
4744
|
-
|
|
5184
|
+
const anyCdpStop = this.getAnyCdp();
|
|
5185
|
+
if (this.agentStreamManager && anyCdpStop) {
|
|
5186
|
+
await this.agentStreamManager.dispose(anyCdpStop).catch(() => {
|
|
4745
5187
|
});
|
|
4746
5188
|
}
|
|
4747
5189
|
this.p2p?.disconnect();
|
|
4748
|
-
this.
|
|
4749
|
-
this.
|
|
5190
|
+
for (const loader of this.scriptLoaders.values()) loader.stop();
|
|
5191
|
+
this.scriptLoaders.clear();
|
|
5192
|
+
for (const m of this.cdpManagers.values()) m.disconnect();
|
|
5193
|
+
this.cdpManagers.clear();
|
|
4750
5194
|
this.localServer?.stop();
|
|
4751
5195
|
this.bridge?.disconnect();
|
|
4752
5196
|
removeDaemonPid();
|
|
@@ -4754,6 +5198,33 @@ var init_adhdev_daemon = __esm({
|
|
|
4754
5198
|
process.exit(0);
|
|
4755
5199
|
}
|
|
4756
5200
|
// ─── CDP 관리 ───────────────────────────────────
|
|
5201
|
+
/** 첫 번째 연결된 CDP 매니저 반환 */
|
|
5202
|
+
getAnyCdp() {
|
|
5203
|
+
for (const m of this.cdpManagers.values()) {
|
|
5204
|
+
if (m.isConnected) return m;
|
|
5205
|
+
}
|
|
5206
|
+
return null;
|
|
5207
|
+
}
|
|
5208
|
+
/** 특정 IDE의 CDP 매니저 반환 */
|
|
5209
|
+
getCdpFor(ideType) {
|
|
5210
|
+
return this.cdpManagers.get(ideType.toLowerCase()) || null;
|
|
5211
|
+
}
|
|
5212
|
+
/** Agent stream polling 시작 (idempotent — 이미 시작됐으면 무시) */
|
|
5213
|
+
startAgentStreamPolling() {
|
|
5214
|
+
if (this.agentStreamTimer) return;
|
|
5215
|
+
this.agentStreamTimer = setInterval(async () => {
|
|
5216
|
+
if (!this.agentStreamManager || this.cdpManagers.size === 0) return;
|
|
5217
|
+
for (const [ideType, cdp] of this.cdpManagers) {
|
|
5218
|
+
if (!cdp.isConnected) continue;
|
|
5219
|
+
try {
|
|
5220
|
+
await this.agentStreamManager.syncAgentSessions(cdp);
|
|
5221
|
+
const streams = await this.agentStreamManager.collectAgentStreams(cdp);
|
|
5222
|
+
this._cachedAgentStreamsMap.set(ideType, streams);
|
|
5223
|
+
} catch {
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
}, 5e3);
|
|
5227
|
+
}
|
|
4757
5228
|
async initCdp() {
|
|
4758
5229
|
const cdpPortMap = {
|
|
4759
5230
|
cursor: 9333,
|
|
@@ -4763,7 +5234,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4763
5234
|
};
|
|
4764
5235
|
const portsToTry = [];
|
|
4765
5236
|
for (const ide of this.detectedIdes) {
|
|
4766
|
-
const ideKey = ide.
|
|
5237
|
+
const ideKey = ide.id || ide.name?.toLowerCase();
|
|
4767
5238
|
const port = cdpPortMap[ideKey];
|
|
4768
5239
|
if (port) portsToTry.push({ port, ide: ideKey });
|
|
4769
5240
|
}
|
|
@@ -4772,25 +5243,36 @@ var init_adhdev_daemon = __esm({
|
|
|
4772
5243
|
portsToTry.push({ port, ide });
|
|
4773
5244
|
}
|
|
4774
5245
|
}
|
|
4775
|
-
|
|
5246
|
+
const enabledIdes = loadConfig().enabledIdes || [];
|
|
5247
|
+
const filteredPorts = enabledIdes.length > 0 ? portsToTry.filter((p) => enabledIdes.includes(p.ide)) : portsToTry;
|
|
5248
|
+
for (const { port, ide } of filteredPorts) {
|
|
4776
5249
|
const manager = new DaemonCdpManager(port, (msg) => {
|
|
4777
5250
|
console.log(import_chalk2.default.gray(msg));
|
|
4778
|
-
});
|
|
5251
|
+
}, true);
|
|
4779
5252
|
const connected = await manager.connect();
|
|
4780
5253
|
if (connected) {
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
}, 3e4);
|
|
4789
|
-
return;
|
|
5254
|
+
const actualPort = manager.getPort();
|
|
5255
|
+
const actualIde = Object.entries(cdpPortMap).find(([, p]) => p === actualPort)?.[0] || ide;
|
|
5256
|
+
this.cdpManagers.set(actualIde, manager);
|
|
5257
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${actualIde} (port ${actualPort})`));
|
|
5258
|
+
if (this.ideType === "unknown") {
|
|
5259
|
+
this.ideType = actualIde;
|
|
5260
|
+
}
|
|
4790
5261
|
}
|
|
4791
5262
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
5263
|
+
if (this.cdpManagers.size > 0) {
|
|
5264
|
+
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
5265
|
+
this.cdpDiscoveryTimer = setInterval(async () => {
|
|
5266
|
+
for (const m of this.cdpManagers.values()) {
|
|
5267
|
+
if (m.isConnected) {
|
|
5268
|
+
await m.discoverAgentWebviews();
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5271
|
+
}, 3e4);
|
|
5272
|
+
} else {
|
|
5273
|
+
console.log(import_chalk2.default.yellow(` \u26A0 CDP not available \u2014 tried ports: ${portsToTry.map((p) => `${p.ide}:${p.port}`).join(", ")}`));
|
|
5274
|
+
console.log(import_chalk2.default.yellow(` IDE may need relaunch with --remote-debugging-port`));
|
|
5275
|
+
}
|
|
4794
5276
|
}
|
|
4795
5277
|
};
|
|
4796
5278
|
}
|
|
@@ -6170,6 +6652,7 @@ async function installCliOnly() {
|
|
|
6170
6652
|
|
|
6171
6653
|
// src/index.ts
|
|
6172
6654
|
init_detector();
|
|
6655
|
+
init_cli_detector();
|
|
6173
6656
|
init_config();
|
|
6174
6657
|
init_launch();
|
|
6175
6658
|
var import_fs3 = require("fs");
|
|
@@ -6299,6 +6782,15 @@ program.command("status").description("Show current ADHDev setup status").action
|
|
|
6299
6782
|
}
|
|
6300
6783
|
}
|
|
6301
6784
|
}
|
|
6785
|
+
const clis = await detectCLIs();
|
|
6786
|
+
const installedClis = clis.filter((c) => c.installed);
|
|
6787
|
+
if (installedClis.length > 0) {
|
|
6788
|
+
console.log(` ${import_chalk4.default.bold("CLI Agents:")}`);
|
|
6789
|
+
installedClis.forEach((cli) => {
|
|
6790
|
+
const ver = cli.version ? import_chalk4.default.gray(` v${cli.version}`) : "";
|
|
6791
|
+
console.log(` ${import_chalk4.default.green("\u2713")} ${cli.icon} ${cli.displayName}${ver}`);
|
|
6792
|
+
});
|
|
6793
|
+
}
|
|
6302
6794
|
console.log(` ${import_chalk4.default.bold("Extensions:")} ${config.installedExtensions.length} installed`);
|
|
6303
6795
|
config.installedExtensions.forEach((ext) => {
|
|
6304
6796
|
console.log(import_chalk4.default.gray(` \u2022 ${ext}`));
|
|
@@ -6326,6 +6818,17 @@ program.command("detect").description("Detect installed IDEs on your system").ac
|
|
|
6326
6818
|
console.log(` ${import_chalk4.default.gray("\u2717")} ${ide.icon} ${import_chalk4.default.gray(ide.displayName)} \u2014 not found`);
|
|
6327
6819
|
}
|
|
6328
6820
|
});
|
|
6821
|
+
console.log(import_chalk4.default.bold("\n\u{1F50D} Detecting installed CLI Agents...\n"));
|
|
6822
|
+
const clis = await detectCLIs();
|
|
6823
|
+
clis.forEach((cli) => {
|
|
6824
|
+
if (cli.installed) {
|
|
6825
|
+
const version = cli.version ? import_chalk4.default.gray(` v${cli.version}`) : "";
|
|
6826
|
+
console.log(` ${import_chalk4.default.green("\u2713")} ${cli.icon} ${import_chalk4.default.bold(cli.displayName)}${version}`);
|
|
6827
|
+
console.log(import_chalk4.default.gray(` Path: ${cli.path}`));
|
|
6828
|
+
} else {
|
|
6829
|
+
console.log(` ${import_chalk4.default.gray("\u2717")} ${cli.icon} ${import_chalk4.default.gray(cli.displayName)} \u2014 not found`);
|
|
6830
|
+
}
|
|
6831
|
+
});
|
|
6329
6832
|
console.log();
|
|
6330
6833
|
});
|
|
6331
6834
|
program.command("reset").description("Reset ADHDev configuration").action(async () => {
|