adhdev 0.1.22 → 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 +383 -174
- 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,7 +871,7 @@ 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));
|
|
824
|
-
} else if (message.type !== "auth_ok"
|
|
874
|
+
} else if (message.type !== "auth_ok") {
|
|
825
875
|
console.log(`[CliBridge] Unhandled message type: ${message.type}`);
|
|
826
876
|
}
|
|
827
877
|
} catch (error) {
|
|
@@ -883,21 +933,21 @@ function stripAnsi(str) {
|
|
|
883
933
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
884
934
|
}
|
|
885
935
|
function findGeminiBinary() {
|
|
886
|
-
const isWin =
|
|
936
|
+
const isWin = os3.platform() === "win32";
|
|
887
937
|
const cmd = isWin ? "where gemini" : "which gemini";
|
|
888
938
|
try {
|
|
889
|
-
const result = (0,
|
|
939
|
+
const result = (0, import_child_process5.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
890
940
|
return result.split("\n")[0].trim();
|
|
891
941
|
} catch {
|
|
892
942
|
return isWin ? "gemini.cmd" : "gemini";
|
|
893
943
|
}
|
|
894
944
|
}
|
|
895
|
-
var
|
|
945
|
+
var os3, import_child_process5, pty, PROMPT_PATTERNS, STARTUP_DIALOG_PATTERNS, GeminiCliAdapter;
|
|
896
946
|
var init_gemini_cli = __esm({
|
|
897
947
|
"src/cli-adapters/gemini-cli.ts"() {
|
|
898
948
|
"use strict";
|
|
899
|
-
|
|
900
|
-
|
|
949
|
+
os3 = __toESM(require("os"));
|
|
950
|
+
import_child_process5 = require("child_process");
|
|
901
951
|
try {
|
|
902
952
|
pty = require("node-pty");
|
|
903
953
|
} catch {
|
|
@@ -1149,21 +1199,21 @@ function stripAnsi2(str) {
|
|
|
1149
1199
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
1150
1200
|
}
|
|
1151
1201
|
function findClaudeBinary() {
|
|
1152
|
-
const isWin =
|
|
1202
|
+
const isWin = os4.platform() === "win32";
|
|
1153
1203
|
const cmd = isWin ? "where claude" : "which claude";
|
|
1154
1204
|
try {
|
|
1155
|
-
const result = (0,
|
|
1205
|
+
const result = (0, import_child_process6.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1156
1206
|
return result.split("\n")[0].trim();
|
|
1157
1207
|
} catch {
|
|
1158
1208
|
return isWin ? "claude.cmd" : "claude";
|
|
1159
1209
|
}
|
|
1160
1210
|
}
|
|
1161
|
-
var
|
|
1211
|
+
var os4, import_child_process6, pty2, ClaudeCliAdapter;
|
|
1162
1212
|
var init_claude_cli = __esm({
|
|
1163
1213
|
"src/cli-adapters/claude-cli.ts"() {
|
|
1164
1214
|
"use strict";
|
|
1165
|
-
|
|
1166
|
-
|
|
1215
|
+
os4 = __toESM(require("os"));
|
|
1216
|
+
import_child_process6 = require("child_process");
|
|
1167
1217
|
try {
|
|
1168
1218
|
pty2 = require("node-pty");
|
|
1169
1219
|
} catch {
|
|
@@ -1361,21 +1411,21 @@ function stripAnsi3(str) {
|
|
|
1361
1411
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
1362
1412
|
}
|
|
1363
1413
|
function findCodexBinary() {
|
|
1364
|
-
const isWin =
|
|
1414
|
+
const isWin = os5.platform() === "win32";
|
|
1365
1415
|
const cmd = isWin ? "where codex" : "which codex";
|
|
1366
1416
|
try {
|
|
1367
|
-
const result = (0,
|
|
1417
|
+
const result = (0, import_child_process7.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1368
1418
|
return result.split("\n")[0].trim();
|
|
1369
1419
|
} catch {
|
|
1370
1420
|
return isWin ? "codex.cmd" : "codex";
|
|
1371
1421
|
}
|
|
1372
1422
|
}
|
|
1373
|
-
var
|
|
1423
|
+
var os5, import_child_process7, pty3, CodexCliAdapter;
|
|
1374
1424
|
var init_codex_cli = __esm({
|
|
1375
1425
|
"src/cli-adapters/codex-cli.ts"() {
|
|
1376
1426
|
"use strict";
|
|
1377
|
-
|
|
1378
|
-
|
|
1427
|
+
os5 = __toESM(require("os"));
|
|
1428
|
+
import_child_process7 = require("child_process");
|
|
1379
1429
|
try {
|
|
1380
1430
|
pty3 = require("node-pty");
|
|
1381
1431
|
} catch {
|
|
@@ -1828,13 +1878,16 @@ var init_local_server = __esm({
|
|
|
1828
1878
|
/**
|
|
1829
1879
|
* 가장 최근 Extension 상태 데이터 (통합)
|
|
1830
1880
|
*/
|
|
1831
|
-
getLatestExtensionData() {
|
|
1881
|
+
getLatestExtensionData(enabledIdes) {
|
|
1832
1882
|
let activeFile = null;
|
|
1833
1883
|
const allWorkspaceFolders = [];
|
|
1834
1884
|
let totalTerminals = 0;
|
|
1835
1885
|
const allAgents = [];
|
|
1836
1886
|
const connectedIdes = [];
|
|
1837
1887
|
for (const ext of this.extensions.values()) {
|
|
1888
|
+
if (enabledIdes && enabledIdes.length > 0 && !enabledIdes.includes(ext.ideType.toLowerCase())) {
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1838
1891
|
connectedIdes.push({ ideType: ext.ideType, instanceId: ext.instanceId });
|
|
1839
1892
|
if (ext.lastStatus) {
|
|
1840
1893
|
if (!activeFile && ext.lastStatus.activeFile) {
|
|
@@ -1857,55 +1910,6 @@ var init_local_server = __esm({
|
|
|
1857
1910
|
}
|
|
1858
1911
|
});
|
|
1859
1912
|
|
|
1860
|
-
// src/cli-detector.ts
|
|
1861
|
-
async function detectCLIs() {
|
|
1862
|
-
const platform9 = os5.platform();
|
|
1863
|
-
const whichCmd = platform9 === "win32" ? "where" : "which";
|
|
1864
|
-
const results = [];
|
|
1865
|
-
for (const cli of KNOWN_CLIS) {
|
|
1866
|
-
try {
|
|
1867
|
-
const pathResult = (0, import_child_process7.execSync)(`${whichCmd} ${cli.command} 2>/dev/null`, {
|
|
1868
|
-
encoding: "utf-8",
|
|
1869
|
-
timeout: 5e3,
|
|
1870
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1871
|
-
}).trim().split("\n")[0];
|
|
1872
|
-
if (!pathResult) throw new Error("Not found");
|
|
1873
|
-
let version;
|
|
1874
|
-
try {
|
|
1875
|
-
const versionResult = (0, import_child_process7.execSync)(`${cli.command} --version 2>/dev/null`, {
|
|
1876
|
-
encoding: "utf-8",
|
|
1877
|
-
timeout: 5e3,
|
|
1878
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1879
|
-
}).trim();
|
|
1880
|
-
const match = versionResult.match(/(\d+\.\d+[\.\d]*)/);
|
|
1881
|
-
version = match ? match[1] : versionResult.split("\n")[0].slice(0, 30);
|
|
1882
|
-
} catch {
|
|
1883
|
-
}
|
|
1884
|
-
results.push({ ...cli, installed: true, version, path: pathResult });
|
|
1885
|
-
} catch {
|
|
1886
|
-
results.push({ ...cli, installed: false });
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
return results;
|
|
1890
|
-
}
|
|
1891
|
-
async function detectCLI(cliId) {
|
|
1892
|
-
const all = await detectCLIs();
|
|
1893
|
-
return all.find((c) => c.id === cliId && c.installed) || null;
|
|
1894
|
-
}
|
|
1895
|
-
var import_child_process7, os5, KNOWN_CLIS;
|
|
1896
|
-
var init_cli_detector = __esm({
|
|
1897
|
-
"src/cli-detector.ts"() {
|
|
1898
|
-
"use strict";
|
|
1899
|
-
import_child_process7 = require("child_process");
|
|
1900
|
-
os5 = __toESM(require("os"));
|
|
1901
|
-
KNOWN_CLIS = [
|
|
1902
|
-
{ id: "gemini-cli", displayName: "Gemini CLI", icon: "\u264A", command: "gemini" },
|
|
1903
|
-
{ id: "claude-code", displayName: "Claude Code", icon: "\u{1F916}", command: "claude" },
|
|
1904
|
-
{ id: "codex-cli", displayName: "Codex CLI", icon: "\u{1F9E0}", command: "codex" }
|
|
1905
|
-
];
|
|
1906
|
-
}
|
|
1907
|
-
});
|
|
1908
|
-
|
|
1909
1913
|
// src/daemon-cdp.ts
|
|
1910
1914
|
var import_ws3, http, fs, KNOWN_AGENTS, DaemonCdpManager;
|
|
1911
1915
|
var init_daemon_cdp = __esm({
|
|
@@ -1921,10 +1925,15 @@ var init_daemon_cdp = __esm({
|
|
|
1921
1925
|
];
|
|
1922
1926
|
DaemonCdpManager = class {
|
|
1923
1927
|
ws = null;
|
|
1928
|
+
browserWs = null;
|
|
1929
|
+
// browser-level WS for Target discovery
|
|
1930
|
+
browserMsgId = 1e4;
|
|
1931
|
+
browserPending = /* @__PURE__ */ new Map();
|
|
1924
1932
|
msgId = 1;
|
|
1925
1933
|
pending = /* @__PURE__ */ new Map();
|
|
1926
1934
|
port;
|
|
1927
1935
|
_connected = false;
|
|
1936
|
+
_browserConnected = false;
|
|
1928
1937
|
targetUrl = "";
|
|
1929
1938
|
reconnectTimer = null;
|
|
1930
1939
|
contexts = /* @__PURE__ */ new Set();
|
|
@@ -2036,6 +2045,8 @@ var init_daemon_cdp = __esm({
|
|
|
2036
2045
|
await this.sendInternal("Runtime.enable");
|
|
2037
2046
|
} catch {
|
|
2038
2047
|
}
|
|
2048
|
+
this.connectBrowserWs().catch(() => {
|
|
2049
|
+
});
|
|
2039
2050
|
resolve3(true);
|
|
2040
2051
|
});
|
|
2041
2052
|
this.ws.on("message", (data) => {
|
|
@@ -2060,6 +2071,9 @@ var init_daemon_cdp = __esm({
|
|
|
2060
2071
|
this.ws.on("close", () => {
|
|
2061
2072
|
this.log("[CDP] WebSocket closed \u2014 scheduling reconnect");
|
|
2062
2073
|
this._connected = false;
|
|
2074
|
+
this._browserConnected = false;
|
|
2075
|
+
this.browserWs?.close();
|
|
2076
|
+
this.browserWs = null;
|
|
2063
2077
|
this.connectPromise = null;
|
|
2064
2078
|
this.scheduleReconnect();
|
|
2065
2079
|
});
|
|
@@ -2070,6 +2084,89 @@ var init_daemon_cdp = __esm({
|
|
|
2070
2084
|
});
|
|
2071
2085
|
});
|
|
2072
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
|
+
}
|
|
2073
2170
|
scheduleReconnect() {
|
|
2074
2171
|
if (this.reconnectTimer) return;
|
|
2075
2172
|
this.reconnectTimer = setTimeout(async () => {
|
|
@@ -2090,6 +2187,9 @@ var init_daemon_cdp = __esm({
|
|
|
2090
2187
|
this.ws?.close();
|
|
2091
2188
|
this.ws = null;
|
|
2092
2189
|
this._connected = false;
|
|
2190
|
+
this.browserWs?.close();
|
|
2191
|
+
this.browserWs = null;
|
|
2192
|
+
this._browserConnected = false;
|
|
2093
2193
|
this.failureCount = 0;
|
|
2094
2194
|
}
|
|
2095
2195
|
get isConnected() {
|
|
@@ -2163,23 +2263,47 @@ var init_daemon_cdp = __esm({
|
|
|
2163
2263
|
// ─── Agent Webview Multi-Session ─────────────────────────
|
|
2164
2264
|
async discoverAgentWebviews() {
|
|
2165
2265
|
if (!this.isConnected) return [];
|
|
2266
|
+
if (!this._browserConnected) {
|
|
2267
|
+
await this.connectBrowserWs().catch(() => {
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2166
2270
|
try {
|
|
2167
|
-
|
|
2168
|
-
|
|
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
|
+
}
|
|
2169
2279
|
const iframes = allTargets.filter((t) => t.type === "iframe");
|
|
2170
|
-
|
|
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
|
+
}
|
|
2171
2294
|
const agents = [];
|
|
2172
2295
|
for (const target of allTargets) {
|
|
2173
2296
|
if (target.type !== "iframe") continue;
|
|
2174
|
-
const
|
|
2297
|
+
const url = target.url || "";
|
|
2298
|
+
const hasWebview = url.includes("vscode-webview");
|
|
2175
2299
|
if (!hasWebview) continue;
|
|
2176
2300
|
for (const known of KNOWN_AGENTS) {
|
|
2177
|
-
if (known.extensionIdPattern.test(
|
|
2301
|
+
if (known.extensionIdPattern.test(url)) {
|
|
2178
2302
|
agents.push({
|
|
2179
2303
|
targetId: target.targetId,
|
|
2180
2304
|
extensionId: known.extensionId,
|
|
2181
2305
|
agentType: known.agentType,
|
|
2182
|
-
url
|
|
2306
|
+
url
|
|
2183
2307
|
});
|
|
2184
2308
|
this.log(`[CDP] Found agent: ${known.agentType} (${target.targetId})`);
|
|
2185
2309
|
break;
|
|
@@ -2198,7 +2322,8 @@ var init_daemon_cdp = __esm({
|
|
|
2198
2322
|
if (t.agentType === target.agentType) return sid;
|
|
2199
2323
|
}
|
|
2200
2324
|
try {
|
|
2201
|
-
const
|
|
2325
|
+
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
2326
|
+
const result = await sendFn("Target.attachToTarget", {
|
|
2202
2327
|
targetId: target.targetId,
|
|
2203
2328
|
flatten: true
|
|
2204
2329
|
});
|
|
@@ -2214,12 +2339,15 @@ var init_daemon_cdp = __esm({
|
|
|
2214
2339
|
}
|
|
2215
2340
|
}
|
|
2216
2341
|
async evaluateInSession(sessionId, expression, timeoutMs = 15e3) {
|
|
2217
|
-
|
|
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) {
|
|
2218
2346
|
throw new Error("CDP not connected");
|
|
2219
2347
|
}
|
|
2220
2348
|
return new Promise((resolve3, reject) => {
|
|
2221
|
-
const id =
|
|
2222
|
-
|
|
2349
|
+
const id = getNextId();
|
|
2350
|
+
pendingMap.set(id, {
|
|
2223
2351
|
resolve: (result) => {
|
|
2224
2352
|
if (result?.result?.subtype === "error") {
|
|
2225
2353
|
reject(new Error(result.result.description));
|
|
@@ -2229,15 +2357,15 @@ var init_daemon_cdp = __esm({
|
|
|
2229
2357
|
},
|
|
2230
2358
|
reject
|
|
2231
2359
|
});
|
|
2232
|
-
|
|
2360
|
+
ws.send(JSON.stringify({
|
|
2233
2361
|
id,
|
|
2234
2362
|
sessionId,
|
|
2235
2363
|
method: "Runtime.evaluate",
|
|
2236
2364
|
params: { expression, returnByValue: true, awaitPromise: true }
|
|
2237
2365
|
}));
|
|
2238
2366
|
setTimeout(() => {
|
|
2239
|
-
if (
|
|
2240
|
-
|
|
2367
|
+
if (pendingMap.has(id)) {
|
|
2368
|
+
pendingMap.delete(id);
|
|
2241
2369
|
reject(new Error(`CDP agent timeout: ${sessionId.substring(0, 12)}...`));
|
|
2242
2370
|
}
|
|
2243
2371
|
}, timeoutMs);
|
|
@@ -2245,7 +2373,8 @@ var init_daemon_cdp = __esm({
|
|
|
2245
2373
|
}
|
|
2246
2374
|
async detachAgent(sessionId) {
|
|
2247
2375
|
try {
|
|
2248
|
-
|
|
2376
|
+
const sendFn = this._browserConnected ? this.sendBrowser.bind(this) : this.sendInternal.bind(this);
|
|
2377
|
+
await sendFn("Target.detachFromTarget", { sessionId });
|
|
2249
2378
|
} catch {
|
|
2250
2379
|
}
|
|
2251
2380
|
this.agentSessions.delete(sessionId);
|
|
@@ -2611,7 +2740,8 @@ var init_daemon_p2p = __esm({
|
|
|
2611
2740
|
tryLoadNodeDatachannel() {
|
|
2612
2741
|
try {
|
|
2613
2742
|
this.nodeDatachannel = require_lib();
|
|
2614
|
-
|
|
2743
|
+
const keys = Object.keys(this.nodeDatachannel).join(",");
|
|
2744
|
+
log(`node-datachannel loaded \u2705 (keys: ${keys.substring(0, 100)})`);
|
|
2615
2745
|
return;
|
|
2616
2746
|
} catch (e) {
|
|
2617
2747
|
log(`node-datachannel not found: ${e?.message}`);
|
|
@@ -2745,7 +2875,12 @@ var init_daemon_p2p = __esm({
|
|
|
2745
2875
|
if (existing?.state === "connected") return;
|
|
2746
2876
|
if (existing?.state === "connecting") this.disconnectPeer(pid);
|
|
2747
2877
|
log(`initiateConnection() for peer ${pid}...`);
|
|
2748
|
-
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
|
+
}
|
|
2749
2884
|
let iceServers = [
|
|
2750
2885
|
"stun:stun.cloudflare.com:3478",
|
|
2751
2886
|
"stun:stun.l.google.com:19302"
|
|
@@ -2758,7 +2893,7 @@ var init_daemon_p2p = __esm({
|
|
|
2758
2893
|
}
|
|
2759
2894
|
} catch {
|
|
2760
2895
|
}
|
|
2761
|
-
const pc = new
|
|
2896
|
+
const pc = new PeerConnectionCtor(`ADHDev-Daemon-${pid.substring(0, 8)}`, {
|
|
2762
2897
|
iceServers
|
|
2763
2898
|
});
|
|
2764
2899
|
const entry = {
|
|
@@ -4352,7 +4487,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4352
4487
|
AdhdevDaemon = class {
|
|
4353
4488
|
localServer = null;
|
|
4354
4489
|
bridge = null;
|
|
4355
|
-
|
|
4490
|
+
adapters = /* @__PURE__ */ new Map();
|
|
4356
4491
|
cdpManagers = /* @__PURE__ */ new Map();
|
|
4357
4492
|
cdpDiscoveryTimer = null;
|
|
4358
4493
|
p2p = null;
|
|
@@ -4363,8 +4498,12 @@ var init_adhdev_daemon = __esm({
|
|
|
4363
4498
|
agentStreamTimer = null;
|
|
4364
4499
|
running = false;
|
|
4365
4500
|
statusTimer = null;
|
|
4366
|
-
lastAgentStatus =
|
|
4367
|
-
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
|
+
}
|
|
4368
4507
|
detectedIdes = [];
|
|
4369
4508
|
localPort;
|
|
4370
4509
|
ideType = "unknown";
|
|
@@ -4466,15 +4605,9 @@ var init_adhdev_daemon = __esm({
|
|
|
4466
4605
|
this.commandHandler.setAgentStreamManager(this.agentStreamManager);
|
|
4467
4606
|
this.startAgentStreamPolling();
|
|
4468
4607
|
if (options.cliType) {
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
await this.adapter.spawn();
|
|
4473
|
-
this.adapter.setOnStatusChange(() => this.sendUnifiedStatusReport());
|
|
4474
|
-
console.log(import_chalk2.default.green(` \u{1F916} CLI Agent started: ${cliInfo.displayName} v${cliInfo.version || "unknown"}`));
|
|
4475
|
-
} else {
|
|
4476
|
-
console.log(import_chalk2.default.yellow(` \u26A0 CLI ${options.cliType} not found \u2014 running without CLI agent`));
|
|
4477
|
-
}
|
|
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
|
+
});
|
|
4478
4611
|
}
|
|
4479
4612
|
const machineId = os8.hostname().replace(/[^a-zA-Z0-9]/g, "_");
|
|
4480
4613
|
const machineHash = crypto2.createHash("md5").update(os8.hostname() + os8.homedir()).digest("hex").slice(0, 8);
|
|
@@ -4489,9 +4622,6 @@ var init_adhdev_daemon = __esm({
|
|
|
4489
4622
|
instanceId
|
|
4490
4623
|
}
|
|
4491
4624
|
});
|
|
4492
|
-
if (this.adapter && typeof this.adapter.setBridge === "function") {
|
|
4493
|
-
this.adapter.setBridge(this.bridge);
|
|
4494
|
-
}
|
|
4495
4625
|
this.p2p = new DaemonP2PSender(this.bridge);
|
|
4496
4626
|
if (this.p2p.isAvailable) {
|
|
4497
4627
|
console.log(import_chalk2.default.green(" \u{1F517} P2P available (node-datachannel)"));
|
|
@@ -4624,9 +4754,9 @@ var init_adhdev_daemon = __esm({
|
|
|
4624
4754
|
"launch_ide",
|
|
4625
4755
|
"detect_ides",
|
|
4626
4756
|
"restart_session",
|
|
4627
|
-
"switch_cli",
|
|
4628
|
-
"change_dir",
|
|
4629
4757
|
"exec_command",
|
|
4758
|
+
"launch_cli",
|
|
4759
|
+
"stop_cli",
|
|
4630
4760
|
// Extension-delegated commands (must be registered to receive WS messages)
|
|
4631
4761
|
"vscode_command_exec",
|
|
4632
4762
|
"execute_vscode_command",
|
|
@@ -4662,21 +4792,33 @@ var init_adhdev_daemon = __esm({
|
|
|
4662
4792
|
console.log(import_chalk2.default.magenta(` \u2699 Command: ${cmd}`));
|
|
4663
4793
|
try {
|
|
4664
4794
|
switch (cmd) {
|
|
4665
|
-
case "
|
|
4666
|
-
const
|
|
4667
|
-
const
|
|
4668
|
-
|
|
4669
|
-
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 });
|
|
4670
4804
|
return;
|
|
4671
4805
|
}
|
|
4672
|
-
case "
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
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 });
|
|
4676
4813
|
return;
|
|
4677
4814
|
}
|
|
4678
4815
|
case "restart_session": {
|
|
4679
|
-
|
|
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);
|
|
4680
4822
|
this.sendResult(msg, true, { restarted: true });
|
|
4681
4823
|
return;
|
|
4682
4824
|
}
|
|
@@ -4687,7 +4829,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4687
4829
|
this.sendResult(msg, false, { error: `Blocked: "${cmdStr}"` });
|
|
4688
4830
|
return;
|
|
4689
4831
|
}
|
|
4690
|
-
const cwd =
|
|
4832
|
+
const cwd = args?.dir || process.cwd();
|
|
4691
4833
|
const { exec: exec2 } = require("child_process");
|
|
4692
4834
|
exec2(cmdStr, { cwd, timeout: 6e4 }, (err, stdout, stderr) => {
|
|
4693
4835
|
if (!this.bridge) return;
|
|
@@ -4772,23 +4914,41 @@ var init_adhdev_daemon = __esm({
|
|
|
4772
4914
|
return new GeminiCliAdapter(workingDir);
|
|
4773
4915
|
}
|
|
4774
4916
|
}
|
|
4775
|
-
async
|
|
4776
|
-
console.log(import_chalk2.default.yellow(` \u26A1 Switching CLI to ${cliType} in ${workingDir}...`));
|
|
4777
|
-
if (this.adapter) this.adapter.shutdown();
|
|
4917
|
+
async startCliSession(cliType, workingDir) {
|
|
4778
4918
|
const cliInfo = await detectCLI(cliType);
|
|
4779
4919
|
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
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();
|
|
4784
4946
|
}
|
|
4785
|
-
this.adapter.setOnStatusChange(() => this.sendUnifiedStatusReport());
|
|
4786
|
-
console.log(import_chalk2.default.green(` \u2713 CLI switched to ${cliType}`));
|
|
4787
4947
|
}
|
|
4788
4948
|
// ─── 통합 상태 보고 ─────────────────────────────
|
|
4789
4949
|
startStatusReporting() {
|
|
4790
4950
|
const scheduleNext = () => {
|
|
4791
|
-
const isProcessing = this.
|
|
4951
|
+
const isProcessing = Array.from(this.adapters.values()).some((a) => a.isProcessing());
|
|
4792
4952
|
const interval = isProcessing ? 2e3 : 15e3;
|
|
4793
4953
|
this.statusTimer = setTimeout(() => {
|
|
4794
4954
|
this.sendUnifiedStatusReport().catch(() => {
|
|
@@ -4830,20 +4990,35 @@ var init_adhdev_daemon = __esm({
|
|
|
4830
4990
|
}
|
|
4831
4991
|
const now = Date.now();
|
|
4832
4992
|
const perExtData = this.localServer?.getPerExtensionData() || [];
|
|
4833
|
-
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) || {
|
|
4834
4996
|
activeFile: null,
|
|
4835
4997
|
workspaceFolders: [],
|
|
4836
4998
|
terminals: 0,
|
|
4837
4999
|
aiAgents: [],
|
|
4838
5000
|
connectedIdes: []
|
|
4839
5001
|
};
|
|
4840
|
-
const managedIdes =
|
|
5002
|
+
const managedIdes = filteredExtData.map((ext) => {
|
|
4841
5003
|
const ideKey = ext.ideType.toLowerCase();
|
|
4842
5004
|
const isMainCdpIde = this.cdpManagers.has(ideKey);
|
|
4843
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
|
+
}));
|
|
4844
5018
|
const ideAgentStreams = [
|
|
4845
5019
|
...ext.agentStreams,
|
|
4846
|
-
...isMainCdpIde ? cdpStreamsForIde : []
|
|
5020
|
+
...isMainCdpIde ? cdpStreamsForIde : [],
|
|
5021
|
+
...extAgentsForIde
|
|
4847
5022
|
];
|
|
4848
5023
|
return {
|
|
4849
5024
|
ideType: ext.ideType,
|
|
@@ -4860,47 +5035,50 @@ var init_adhdev_daemon = __esm({
|
|
|
4860
5035
|
};
|
|
4861
5036
|
});
|
|
4862
5037
|
const managedClis = [];
|
|
4863
|
-
|
|
4864
|
-
const adapterStatus =
|
|
5038
|
+
for (const [key, adapter] of this.adapters.entries()) {
|
|
5039
|
+
const adapterStatus = adapter.getStatus();
|
|
4865
5040
|
const cliStatus = adapterStatus.status;
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
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", {
|
|
4870
5046
|
event: "agent:generating_started",
|
|
4871
|
-
chatTitle: `${
|
|
5047
|
+
chatTitle: `${adapter.cliName} Session`,
|
|
4872
5048
|
timestamp: now
|
|
4873
5049
|
});
|
|
4874
|
-
} else if (
|
|
4875
|
-
const
|
|
4876
|
-
|
|
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", {
|
|
4877
5054
|
event: "agent:generating_completed",
|
|
4878
|
-
chatTitle: `${
|
|
5055
|
+
chatTitle: `${adapter.cliName} Session`,
|
|
4879
5056
|
duration,
|
|
4880
5057
|
timestamp: now
|
|
4881
5058
|
});
|
|
4882
|
-
this.generatingStartedAt
|
|
5059
|
+
this.generatingStartedAt.delete(key);
|
|
4883
5060
|
}
|
|
4884
|
-
this.lastAgentStatus
|
|
5061
|
+
this.lastAgentStatus.set(key, cliStatus);
|
|
4885
5062
|
}
|
|
4886
5063
|
const recentMessages = adapterStatus.messages.slice(-50);
|
|
4887
5064
|
const cliMessages = recentMessages.map((m) => ({
|
|
4888
5065
|
role: m.role,
|
|
4889
5066
|
content: m.content.length > 2e3 ? m.content.slice(0, 2e3) + "\n... (truncated)" : m.content
|
|
4890
5067
|
}));
|
|
4891
|
-
const partial =
|
|
5068
|
+
const partial = adapter.getPartialResponse();
|
|
4892
5069
|
if (cliStatus === "generating" && partial) {
|
|
4893
|
-
cliMessages.push({ role: "assistant", content: partial.slice(0, 2e3) + "..." });
|
|
5070
|
+
cliMessages.push({ role: "assistant", content: partial.length > 2e3 ? partial.slice(0, 2e3) + "..." : partial + "..." });
|
|
4894
5071
|
}
|
|
4895
5072
|
managedClis.push({
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
5073
|
+
id: key,
|
|
5074
|
+
cliType: adapter.cliType,
|
|
5075
|
+
cliName: adapter.cliName,
|
|
4899
5076
|
status: cliStatus,
|
|
5077
|
+
workingDir: adapter.workingDir,
|
|
4900
5078
|
activeChat: {
|
|
4901
|
-
id:
|
|
5079
|
+
id: key,
|
|
4902
5080
|
status: cliStatus,
|
|
4903
|
-
title: `${
|
|
5081
|
+
title: `${adapter.cliName} Session`,
|
|
4904
5082
|
messages: cliMessages,
|
|
4905
5083
|
inputContent: "",
|
|
4906
5084
|
activeModal: adapterStatus.activeModal
|
|
@@ -4942,13 +5120,20 @@ var init_adhdev_daemon = __esm({
|
|
|
4942
5120
|
timestamp: now,
|
|
4943
5121
|
// ─── Legacy compat (서버 기존 로직용, 점진적 제거 예정) ───
|
|
4944
5122
|
activeFile: extSummary.activeFile,
|
|
4945
|
-
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 })),
|
|
4946
5124
|
terminals: extSummary.terminals,
|
|
5125
|
+
// Legacy aiAgents: managedIdes에서 각 IDE의 aiAgents를 통합
|
|
4947
5126
|
aiAgents: [
|
|
4948
|
-
...
|
|
4949
|
-
|
|
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" }))
|
|
4950
5134
|
],
|
|
4951
5135
|
activeChat: managedClis[0]?.activeChat || managedIdes[0]?.activeChat || null,
|
|
5136
|
+
// Legacy agentStreams: managedIdes의 agentStreams를 통합 (이미 IDE별로 올바르게 구성됨)
|
|
4952
5137
|
agentStreams: [
|
|
4953
5138
|
...managedClis.map((c) => ({
|
|
4954
5139
|
agentType: c.cliType,
|
|
@@ -4958,7 +5143,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4958
5143
|
messages: c.activeChat?.messages || [],
|
|
4959
5144
|
inputContent: ""
|
|
4960
5145
|
})),
|
|
4961
|
-
...
|
|
5146
|
+
...managedIdes.flatMap((ide) => ide.agentStreams || [])
|
|
4962
5147
|
],
|
|
4963
5148
|
connectedExtensions: extSummary.connectedIdes,
|
|
4964
5149
|
system: {
|
|
@@ -4990,7 +5175,8 @@ var init_adhdev_daemon = __esm({
|
|
|
4990
5175
|
if (!this.running) return;
|
|
4991
5176
|
this.running = false;
|
|
4992
5177
|
console.log(import_chalk2.default.yellow("\n Shutting down ADHDev Daemon..."));
|
|
4993
|
-
this.adapter
|
|
5178
|
+
for (const adapter of this.adapters.values()) adapter.shutdown();
|
|
5179
|
+
this.adapters.clear();
|
|
4994
5180
|
if (this.statusTimer) clearTimeout(this.statusTimer);
|
|
4995
5181
|
if (this.cdpDiscoveryTimer) clearInterval(this.cdpDiscoveryTimer);
|
|
4996
5182
|
if (this.screenshotTimer) clearInterval(this.screenshotTimer);
|
|
@@ -5057,7 +5243,9 @@ var init_adhdev_daemon = __esm({
|
|
|
5057
5243
|
portsToTry.push({ port, ide });
|
|
5058
5244
|
}
|
|
5059
5245
|
}
|
|
5060
|
-
|
|
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) {
|
|
5061
5249
|
const manager = new DaemonCdpManager(port, (msg) => {
|
|
5062
5250
|
console.log(import_chalk2.default.gray(msg));
|
|
5063
5251
|
}, true);
|
|
@@ -6464,6 +6652,7 @@ async function installCliOnly() {
|
|
|
6464
6652
|
|
|
6465
6653
|
// src/index.ts
|
|
6466
6654
|
init_detector();
|
|
6655
|
+
init_cli_detector();
|
|
6467
6656
|
init_config();
|
|
6468
6657
|
init_launch();
|
|
6469
6658
|
var import_fs3 = require("fs");
|
|
@@ -6593,6 +6782,15 @@ program.command("status").description("Show current ADHDev setup status").action
|
|
|
6593
6782
|
}
|
|
6594
6783
|
}
|
|
6595
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
|
+
}
|
|
6596
6794
|
console.log(` ${import_chalk4.default.bold("Extensions:")} ${config.installedExtensions.length} installed`);
|
|
6597
6795
|
config.installedExtensions.forEach((ext) => {
|
|
6598
6796
|
console.log(import_chalk4.default.gray(` \u2022 ${ext}`));
|
|
@@ -6620,6 +6818,17 @@ program.command("detect").description("Detect installed IDEs on your system").ac
|
|
|
6620
6818
|
console.log(` ${import_chalk4.default.gray("\u2717")} ${ide.icon} ${import_chalk4.default.gray(ide.displayName)} \u2014 not found`);
|
|
6621
6819
|
}
|
|
6622
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
|
+
});
|
|
6623
6832
|
console.log();
|
|
6624
6833
|
});
|
|
6625
6834
|
program.command("reset").description("Reset ADHDev configuration").action(async () => {
|