adhdev 0.1.47 → 0.1.49
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 +1177 -454
- package/package.json +1 -1
- package/providers/_builtin/acp/codex-cli/provider.js +51 -0
- package/providers/_builtin/acp/goose/provider.js +32 -0
- package/providers/_builtin/acp/opencode/provider.js +32 -0
- package/providers/_builtin/extension/cline/provider.js +22 -0
- package/providers/_builtin/extension/cline/scripts/list_models.js +43 -0
- package/providers/_builtin/extension/cline/scripts/list_modes.js +35 -0
- package/providers/_builtin/extension/cline/scripts/set_mode.js +36 -0
- package/providers/_builtin/extension/cline/scripts/set_model.js +36 -0
- package/providers/_builtin/extension/roo-code/provider.js +151 -0
- package/providers/_builtin/ide/antigravity/provider.js +22 -0
- package/providers/_builtin/ide/antigravity/scripts/list_models.js +38 -0
- package/providers/_builtin/ide/antigravity/scripts/list_modes.js +48 -0
- package/providers/_builtin/ide/antigravity/scripts/resolve_action.js +55 -51
- package/providers/_builtin/ide/antigravity/scripts/set_mode.js +34 -0
- package/providers/_builtin/ide/antigravity/scripts/set_model.js +47 -0
- package/providers/_builtin/ide/cursor/provider.js +259 -11
- package/providers/_builtin/ide/kiro/provider.js +62 -0
- package/providers/_builtin/ide/pearai/provider.js +62 -0
- package/providers/_builtin/ide/trae/provider.js +62 -0
package/dist/index.js
CHANGED
|
@@ -262,7 +262,8 @@ var init_config = __esm({
|
|
|
262
262
|
recentCliWorkspaces: [],
|
|
263
263
|
machineNickname: null,
|
|
264
264
|
cliHistory: [],
|
|
265
|
-
providerSettings: {}
|
|
265
|
+
providerSettings: {},
|
|
266
|
+
ideSettings: {}
|
|
266
267
|
};
|
|
267
268
|
}
|
|
268
269
|
});
|
|
@@ -336,6 +337,54 @@ var init_provider_loader = __esm({
|
|
|
336
337
|
getAll() {
|
|
337
338
|
return [...this.providers.values()];
|
|
338
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Provider가 활성화되어 있는지 확인 (per-IDE)
|
|
342
|
+
* ideSettings[ideType].extensions[type].enabled를 참조.
|
|
343
|
+
* 설정이 없으면 기본 false (비활성) — 사용자가 명시적으로 켜야 활성화.
|
|
344
|
+
* ideType 없이 호출하면 항상 true.
|
|
345
|
+
*/
|
|
346
|
+
isEnabled(type, ideType) {
|
|
347
|
+
if (!ideType) return true;
|
|
348
|
+
try {
|
|
349
|
+
const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
350
|
+
const config = loadConfig2();
|
|
351
|
+
const val = config.ideSettings?.[ideType]?.extensions?.[type]?.enabled;
|
|
352
|
+
return val === true;
|
|
353
|
+
} catch {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* IDE별 extension enabled 설정 저장
|
|
359
|
+
*/
|
|
360
|
+
setIdeExtensionEnabled(ideType, extensionType, enabled) {
|
|
361
|
+
try {
|
|
362
|
+
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = (init_config(), __toCommonJS(config_exports));
|
|
363
|
+
const config = loadConfig2();
|
|
364
|
+
if (!config.ideSettings) config.ideSettings = {};
|
|
365
|
+
if (!config.ideSettings[ideType]) config.ideSettings[ideType] = {};
|
|
366
|
+
if (!config.ideSettings[ideType].extensions) config.ideSettings[ideType].extensions = {};
|
|
367
|
+
config.ideSettings[ideType].extensions[extensionType] = { enabled };
|
|
368
|
+
saveConfig2(config);
|
|
369
|
+
this.log(`IDE extension setting: ${ideType}.${extensionType}.enabled = ${enabled}`);
|
|
370
|
+
return true;
|
|
371
|
+
} catch (e) {
|
|
372
|
+
this.log(`Failed to save IDE extension setting: ${e.message}`);
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* 카테고리별 활성화된 프로바이더만 반환 (per-IDE)
|
|
378
|
+
*/
|
|
379
|
+
getEnabledByCategory(cat, ideType) {
|
|
380
|
+
return this.getByCategory(cat).filter((p) => this.isEnabled(p.type, ideType));
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Extension 카테고리 중 활성화되고 extensionIdPattern이 있는 것만 (per-IDE)
|
|
384
|
+
*/
|
|
385
|
+
getEnabledExtensionProviders(ideType) {
|
|
386
|
+
return this.getExtensionProviders().filter((p) => this.isEnabled(p.type, ideType));
|
|
387
|
+
}
|
|
339
388
|
/**
|
|
340
389
|
* IDE 카테고리의 CDP 포트 맵 반환
|
|
341
390
|
* launch.ts, adhdev-daemon.ts에서 사용
|
|
@@ -857,7 +906,7 @@ var init_local_server = __esm({
|
|
|
857
906
|
* 로컬 WS 서버 시작
|
|
858
907
|
*/
|
|
859
908
|
async start() {
|
|
860
|
-
return new Promise((
|
|
909
|
+
return new Promise((resolve6, reject) => {
|
|
861
910
|
try {
|
|
862
911
|
this.wss = new import_ws2.WebSocketServer({
|
|
863
912
|
port: this.port,
|
|
@@ -867,7 +916,7 @@ var init_local_server = __esm({
|
|
|
867
916
|
});
|
|
868
917
|
this.wss.on("listening", () => {
|
|
869
918
|
console.log(`[LocalServer] Listening on ws://127.0.0.1:${this.port}${DAEMON_WS_PATH}`);
|
|
870
|
-
|
|
919
|
+
resolve6();
|
|
871
920
|
});
|
|
872
921
|
this.wss.on("connection", (ws) => {
|
|
873
922
|
this.handleConnection(ws);
|
|
@@ -1046,14 +1095,14 @@ var init_local_server = __esm({
|
|
|
1046
1095
|
return { success: false, error: "No extension connected" };
|
|
1047
1096
|
}
|
|
1048
1097
|
const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1049
|
-
return new Promise((
|
|
1098
|
+
return new Promise((resolve6) => {
|
|
1050
1099
|
const timeout = setTimeout(() => {
|
|
1051
1100
|
this.commandCallbacks.delete(requestId);
|
|
1052
|
-
|
|
1101
|
+
resolve6({ success: false, error: "Command execution timeout (10s)" });
|
|
1053
1102
|
}, 1e4);
|
|
1054
1103
|
this.commandCallbacks.set(requestId, (result) => {
|
|
1055
1104
|
clearTimeout(timeout);
|
|
1056
|
-
|
|
1105
|
+
resolve6(result);
|
|
1057
1106
|
});
|
|
1058
1107
|
this.sendToExtension(targetWs, {
|
|
1059
1108
|
type: "daemon:execute_vscode",
|
|
@@ -1177,17 +1226,17 @@ async function findFreePort(ports) {
|
|
|
1177
1226
|
throw new Error("No free port found");
|
|
1178
1227
|
}
|
|
1179
1228
|
function checkPortFree(port) {
|
|
1180
|
-
return new Promise((
|
|
1229
|
+
return new Promise((resolve6) => {
|
|
1181
1230
|
const server = net.createServer();
|
|
1182
1231
|
server.unref();
|
|
1183
|
-
server.on("error", () =>
|
|
1232
|
+
server.on("error", () => resolve6(false));
|
|
1184
1233
|
server.listen(port, "127.0.0.1", () => {
|
|
1185
|
-
server.close(() =>
|
|
1234
|
+
server.close(() => resolve6(true));
|
|
1186
1235
|
});
|
|
1187
1236
|
});
|
|
1188
1237
|
}
|
|
1189
1238
|
async function isCdpActive(port) {
|
|
1190
|
-
return new Promise((
|
|
1239
|
+
return new Promise((resolve6) => {
|
|
1191
1240
|
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
1192
1241
|
timeout: 2e3
|
|
1193
1242
|
}, (res) => {
|
|
@@ -1196,16 +1245,16 @@ async function isCdpActive(port) {
|
|
|
1196
1245
|
res.on("end", () => {
|
|
1197
1246
|
try {
|
|
1198
1247
|
const info = JSON.parse(data);
|
|
1199
|
-
|
|
1248
|
+
resolve6(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
1200
1249
|
} catch {
|
|
1201
|
-
|
|
1250
|
+
resolve6(false);
|
|
1202
1251
|
}
|
|
1203
1252
|
});
|
|
1204
1253
|
});
|
|
1205
|
-
req.on("error", () =>
|
|
1254
|
+
req.on("error", () => resolve6(false));
|
|
1206
1255
|
req.on("timeout", () => {
|
|
1207
1256
|
req.destroy();
|
|
1208
|
-
|
|
1257
|
+
resolve6(false);
|
|
1209
1258
|
});
|
|
1210
1259
|
});
|
|
1211
1260
|
}
|
|
@@ -1530,12 +1579,53 @@ var init_daemon_cdp = __esm({
|
|
|
1530
1579
|
logFn;
|
|
1531
1580
|
extensionProviders = [];
|
|
1532
1581
|
_lastDiscoverSig = "";
|
|
1533
|
-
|
|
1582
|
+
_targetId = null;
|
|
1583
|
+
// 특정 targetId로 연결 (multi-window 지원)
|
|
1584
|
+
_pageTitle = "";
|
|
1585
|
+
// 연결된 페이지 제목
|
|
1586
|
+
constructor(port = 9333, logFn, targetId) {
|
|
1534
1587
|
this.port = port;
|
|
1588
|
+
this._targetId = targetId || null;
|
|
1535
1589
|
this.logFn = logFn || ((msg) => {
|
|
1536
1590
|
console.log(msg);
|
|
1537
1591
|
});
|
|
1538
1592
|
}
|
|
1593
|
+
/** 연결된 페이지의 제목 (workspace 이름 포함) */
|
|
1594
|
+
get pageTitle() {
|
|
1595
|
+
return this._pageTitle;
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* 포트에 있는 모든 workbench 페이지 목록 조회 (static)
|
|
1599
|
+
* 같은 포트에 여러 IDE 창이 열려 있으면 여러 개 반환
|
|
1600
|
+
*/
|
|
1601
|
+
static listAllTargets(port) {
|
|
1602
|
+
return new Promise((resolve6) => {
|
|
1603
|
+
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
1604
|
+
let data = "";
|
|
1605
|
+
res.on("data", (chunk) => data += chunk.toString());
|
|
1606
|
+
res.on("end", () => {
|
|
1607
|
+
try {
|
|
1608
|
+
const targets = JSON.parse(data);
|
|
1609
|
+
const pages = targets.filter(
|
|
1610
|
+
(t) => t.type === "page" && t.webSocketDebuggerUrl
|
|
1611
|
+
);
|
|
1612
|
+
const isNonMain = (title) => !title || /extension-output|ADHDev CDP|Debug Console|Output\s*$|Launchpad/i.test(title);
|
|
1613
|
+
const mainPages = pages.filter(
|
|
1614
|
+
(t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
|
|
1615
|
+
);
|
|
1616
|
+
resolve6(mainPages.length > 0 ? mainPages : pages.filter((t) => !isNonMain(t.title || "")));
|
|
1617
|
+
} catch {
|
|
1618
|
+
resolve6([]);
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
});
|
|
1622
|
+
req.on("error", () => resolve6([]));
|
|
1623
|
+
req.setTimeout(2e3, () => {
|
|
1624
|
+
req.destroy();
|
|
1625
|
+
resolve6([]);
|
|
1626
|
+
});
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1539
1629
|
setPort(port) {
|
|
1540
1630
|
this.port = port;
|
|
1541
1631
|
this.log(`[CDP] Port changed to ${port}`);
|
|
@@ -1572,7 +1662,7 @@ var init_daemon_cdp = __esm({
|
|
|
1572
1662
|
}
|
|
1573
1663
|
}
|
|
1574
1664
|
findTargetOnPort(port) {
|
|
1575
|
-
return new Promise((
|
|
1665
|
+
return new Promise((resolve6) => {
|
|
1576
1666
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
1577
1667
|
let data = "";
|
|
1578
1668
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -1583,23 +1673,35 @@ var init_daemon_cdp = __esm({
|
|
|
1583
1673
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
1584
1674
|
);
|
|
1585
1675
|
if (pages.length === 0) {
|
|
1586
|
-
|
|
1676
|
+
resolve6(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
1587
1677
|
return;
|
|
1588
1678
|
}
|
|
1589
1679
|
const isNonMain = (title) => !title || /extension-output|ADHDev CDP|Debug Console|Output\s*$|Launchpad/i.test(title);
|
|
1590
1680
|
const mainPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
1591
1681
|
const list = mainPages.length > 0 ? mainPages : pages;
|
|
1592
1682
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
1593
|
-
|
|
1683
|
+
if (this._targetId) {
|
|
1684
|
+
const specific = list.find((t) => t.id === this._targetId);
|
|
1685
|
+
if (specific) {
|
|
1686
|
+
this._pageTitle = specific.title || "";
|
|
1687
|
+
resolve6(specific);
|
|
1688
|
+
} else {
|
|
1689
|
+
this.log(`[CDP] Target ${this._targetId} not found in page list`);
|
|
1690
|
+
resolve6(null);
|
|
1691
|
+
}
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
this._pageTitle = list[0]?.title || "";
|
|
1695
|
+
resolve6(list[0]);
|
|
1594
1696
|
} catch {
|
|
1595
|
-
|
|
1697
|
+
resolve6(null);
|
|
1596
1698
|
}
|
|
1597
1699
|
});
|
|
1598
1700
|
});
|
|
1599
|
-
req.on("error", () =>
|
|
1701
|
+
req.on("error", () => resolve6(null));
|
|
1600
1702
|
req.setTimeout(2e3, () => {
|
|
1601
1703
|
req.destroy();
|
|
1602
|
-
|
|
1704
|
+
resolve6(null);
|
|
1603
1705
|
});
|
|
1604
1706
|
});
|
|
1605
1707
|
}
|
|
@@ -1610,7 +1712,7 @@ var init_daemon_cdp = __esm({
|
|
|
1610
1712
|
this.extensionProviders = providers;
|
|
1611
1713
|
}
|
|
1612
1714
|
connectToTarget(wsUrl) {
|
|
1613
|
-
return new Promise((
|
|
1715
|
+
return new Promise((resolve6) => {
|
|
1614
1716
|
this.ws = new import_ws3.default(wsUrl);
|
|
1615
1717
|
this.ws.on("open", async () => {
|
|
1616
1718
|
this._connected = true;
|
|
@@ -1620,17 +1722,17 @@ var init_daemon_cdp = __esm({
|
|
|
1620
1722
|
}
|
|
1621
1723
|
this.connectBrowserWs().catch(() => {
|
|
1622
1724
|
});
|
|
1623
|
-
|
|
1725
|
+
resolve6(true);
|
|
1624
1726
|
});
|
|
1625
1727
|
this.ws.on("message", (data) => {
|
|
1626
1728
|
try {
|
|
1627
1729
|
const msg = JSON.parse(data.toString());
|
|
1628
1730
|
if (msg.id && this.pending.has(msg.id)) {
|
|
1629
|
-
const { resolve:
|
|
1731
|
+
const { resolve: resolve7, reject } = this.pending.get(msg.id);
|
|
1630
1732
|
this.pending.delete(msg.id);
|
|
1631
1733
|
this.failureCount = 0;
|
|
1632
1734
|
if (msg.error) reject(new Error(msg.error.message));
|
|
1633
|
-
else
|
|
1735
|
+
else resolve7(msg.result);
|
|
1634
1736
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
1635
1737
|
this.contexts.add(msg.params.context.id);
|
|
1636
1738
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -1653,7 +1755,7 @@ var init_daemon_cdp = __esm({
|
|
|
1653
1755
|
this.ws.on("error", (err) => {
|
|
1654
1756
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
1655
1757
|
this._connected = false;
|
|
1656
|
-
|
|
1758
|
+
resolve6(false);
|
|
1657
1759
|
});
|
|
1658
1760
|
});
|
|
1659
1761
|
}
|
|
@@ -1667,7 +1769,7 @@ var init_daemon_cdp = __esm({
|
|
|
1667
1769
|
return;
|
|
1668
1770
|
}
|
|
1669
1771
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
1670
|
-
await new Promise((
|
|
1772
|
+
await new Promise((resolve6, reject) => {
|
|
1671
1773
|
this.browserWs = new import_ws3.default(browserWsUrl);
|
|
1672
1774
|
this.browserWs.on("open", async () => {
|
|
1673
1775
|
this._browserConnected = true;
|
|
@@ -1677,16 +1779,16 @@ var init_daemon_cdp = __esm({
|
|
|
1677
1779
|
} catch (e) {
|
|
1678
1780
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
1679
1781
|
}
|
|
1680
|
-
|
|
1782
|
+
resolve6();
|
|
1681
1783
|
});
|
|
1682
1784
|
this.browserWs.on("message", (data) => {
|
|
1683
1785
|
try {
|
|
1684
1786
|
const msg = JSON.parse(data.toString());
|
|
1685
1787
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
1686
|
-
const { resolve:
|
|
1788
|
+
const { resolve: resolve7, reject: reject2 } = this.browserPending.get(msg.id);
|
|
1687
1789
|
this.browserPending.delete(msg.id);
|
|
1688
1790
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
1689
|
-
else
|
|
1791
|
+
else resolve7(msg.result);
|
|
1690
1792
|
}
|
|
1691
1793
|
} catch {
|
|
1692
1794
|
}
|
|
@@ -1706,31 +1808,31 @@ var init_daemon_cdp = __esm({
|
|
|
1706
1808
|
}
|
|
1707
1809
|
}
|
|
1708
1810
|
getBrowserWsUrl() {
|
|
1709
|
-
return new Promise((
|
|
1811
|
+
return new Promise((resolve6) => {
|
|
1710
1812
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
1711
1813
|
let data = "";
|
|
1712
1814
|
res.on("data", (chunk) => data += chunk.toString());
|
|
1713
1815
|
res.on("end", () => {
|
|
1714
1816
|
try {
|
|
1715
1817
|
const info = JSON.parse(data);
|
|
1716
|
-
|
|
1818
|
+
resolve6(info.webSocketDebuggerUrl || null);
|
|
1717
1819
|
} catch {
|
|
1718
|
-
|
|
1820
|
+
resolve6(null);
|
|
1719
1821
|
}
|
|
1720
1822
|
});
|
|
1721
1823
|
});
|
|
1722
|
-
req.on("error", () =>
|
|
1824
|
+
req.on("error", () => resolve6(null));
|
|
1723
1825
|
req.setTimeout(3e3, () => {
|
|
1724
1826
|
req.destroy();
|
|
1725
|
-
|
|
1827
|
+
resolve6(null);
|
|
1726
1828
|
});
|
|
1727
1829
|
});
|
|
1728
1830
|
}
|
|
1729
1831
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
1730
|
-
return new Promise((
|
|
1832
|
+
return new Promise((resolve6, reject) => {
|
|
1731
1833
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
1732
1834
|
const id = this.browserMsgId++;
|
|
1733
|
-
this.browserPending.set(id, { resolve:
|
|
1835
|
+
this.browserPending.set(id, { resolve: resolve6, reject });
|
|
1734
1836
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
1735
1837
|
setTimeout(() => {
|
|
1736
1838
|
if (this.browserPending.has(id)) {
|
|
@@ -1770,11 +1872,11 @@ var init_daemon_cdp = __esm({
|
|
|
1770
1872
|
}
|
|
1771
1873
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
1772
1874
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
1773
|
-
return new Promise((
|
|
1875
|
+
return new Promise((resolve6, reject) => {
|
|
1774
1876
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
1775
1877
|
if (this.ws.readyState !== import_ws3.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
1776
1878
|
const id = this.msgId++;
|
|
1777
|
-
this.pending.set(id, { resolve:
|
|
1879
|
+
this.pending.set(id, { resolve: resolve6, reject });
|
|
1778
1880
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
1779
1881
|
setTimeout(() => {
|
|
1780
1882
|
if (this.pending.has(id)) {
|
|
@@ -1978,14 +2080,14 @@ var init_daemon_cdp = __esm({
|
|
|
1978
2080
|
if (!ws || ws.readyState !== import_ws3.default.OPEN) {
|
|
1979
2081
|
throw new Error("CDP not connected");
|
|
1980
2082
|
}
|
|
1981
|
-
return new Promise((
|
|
2083
|
+
return new Promise((resolve6, reject) => {
|
|
1982
2084
|
const id = getNextId();
|
|
1983
2085
|
pendingMap.set(id, {
|
|
1984
2086
|
resolve: (result) => {
|
|
1985
2087
|
if (result?.result?.subtype === "error") {
|
|
1986
2088
|
reject(new Error(result.result.description));
|
|
1987
2089
|
} else {
|
|
1988
|
-
|
|
2090
|
+
resolve6(result?.result?.value);
|
|
1989
2091
|
}
|
|
1990
2092
|
},
|
|
1991
2093
|
reject
|
|
@@ -2462,13 +2564,13 @@ var init_daemon_p2p = __esm({
|
|
|
2462
2564
|
} catch {
|
|
2463
2565
|
}
|
|
2464
2566
|
const http3 = require("https");
|
|
2465
|
-
const data = await new Promise((
|
|
2567
|
+
const data = await new Promise((resolve6, reject) => {
|
|
2466
2568
|
const req = http3.get(`${serverUrl}/api/v1/turn/credentials`, {
|
|
2467
2569
|
headers: { "Authorization": `Bearer ${token}` }
|
|
2468
2570
|
}, (res) => {
|
|
2469
2571
|
let d = "";
|
|
2470
2572
|
res.on("data", (c) => d += c);
|
|
2471
|
-
res.on("end", () =>
|
|
2573
|
+
res.on("end", () => resolve6(d));
|
|
2472
2574
|
});
|
|
2473
2575
|
req.on("error", reject);
|
|
2474
2576
|
req.setTimeout(5e3, () => {
|
|
@@ -2841,7 +2943,11 @@ var init_daemon_p2p = __esm({
|
|
|
2841
2943
|
return;
|
|
2842
2944
|
}
|
|
2843
2945
|
if (type === "p2p_answer") {
|
|
2844
|
-
|
|
2946
|
+
if (!peerId) {
|
|
2947
|
+
log("p2p_answer without peerId \u2014 ignoring (multi-peer requires explicit peerId)");
|
|
2948
|
+
return;
|
|
2949
|
+
}
|
|
2950
|
+
const peer = this.peers.get(peerId);
|
|
2845
2951
|
if (peer?.pc) {
|
|
2846
2952
|
log(`Received SDP answer for peer ${peer.peerId}`);
|
|
2847
2953
|
peer.pc.setRemoteDescription(payload.sdp, payload.type);
|
|
@@ -2849,16 +2955,18 @@ var init_daemon_p2p = __esm({
|
|
|
2849
2955
|
return;
|
|
2850
2956
|
}
|
|
2851
2957
|
if (type === "p2p_ice") {
|
|
2852
|
-
|
|
2958
|
+
if (!peerId) {
|
|
2959
|
+
log("p2p_ice without peerId \u2014 ignoring (multi-peer requires explicit peerId)");
|
|
2960
|
+
return;
|
|
2961
|
+
}
|
|
2962
|
+
const peer = this.peers.get(peerId);
|
|
2853
2963
|
if (peer?.pc && payload.candidate) {
|
|
2854
2964
|
peer.pc.addRemoteCandidate(payload.candidate, payload.mid || payload.sdpMid || "0");
|
|
2855
2965
|
}
|
|
2856
2966
|
return;
|
|
2857
2967
|
}
|
|
2858
2968
|
}
|
|
2859
|
-
getFirstPeer
|
|
2860
|
-
return this.peers.values().next().value;
|
|
2861
|
-
}
|
|
2969
|
+
// getFirstPeer removed — multi-peer requires explicit peerId routing
|
|
2862
2970
|
// ─── 연결 관리 ──────────────────────────────
|
|
2863
2971
|
disconnectPeer(peerId) {
|
|
2864
2972
|
const peer = this.peers.get(peerId);
|
|
@@ -3143,15 +3251,15 @@ var init_dev_server = __esm({
|
|
|
3143
3251
|
this.json(res, 500, { error: e.message });
|
|
3144
3252
|
}
|
|
3145
3253
|
});
|
|
3146
|
-
return new Promise((
|
|
3254
|
+
return new Promise((resolve6, reject) => {
|
|
3147
3255
|
this.server.listen(port, "127.0.0.1", () => {
|
|
3148
3256
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
3149
|
-
|
|
3257
|
+
resolve6();
|
|
3150
3258
|
});
|
|
3151
3259
|
this.server.on("error", (e) => {
|
|
3152
3260
|
if (e.code === "EADDRINUSE") {
|
|
3153
3261
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
3154
|
-
|
|
3262
|
+
resolve6();
|
|
3155
3263
|
} else {
|
|
3156
3264
|
reject(e);
|
|
3157
3265
|
}
|
|
@@ -3818,14 +3926,14 @@ var init_dev_server = __esm({
|
|
|
3818
3926
|
res.end(JSON.stringify(data, null, 2));
|
|
3819
3927
|
}
|
|
3820
3928
|
async readBody(req) {
|
|
3821
|
-
return new Promise((
|
|
3929
|
+
return new Promise((resolve6) => {
|
|
3822
3930
|
let body = "";
|
|
3823
3931
|
req.on("data", (chunk) => body += chunk);
|
|
3824
3932
|
req.on("end", () => {
|
|
3825
3933
|
try {
|
|
3826
|
-
|
|
3934
|
+
resolve6(JSON.parse(body));
|
|
3827
3935
|
} catch {
|
|
3828
|
-
|
|
3936
|
+
resolve6({});
|
|
3829
3937
|
}
|
|
3830
3938
|
});
|
|
3831
3939
|
});
|
|
@@ -4198,7 +4306,11 @@ var init_daemon_commands = __esm({
|
|
|
4198
4306
|
getProvider(overrideType) {
|
|
4199
4307
|
const key = overrideType || this._currentProviderType || this._currentIdeType;
|
|
4200
4308
|
if (!key || !this.ctx.providerLoader) return void 0;
|
|
4201
|
-
|
|
4309
|
+
const result = this.ctx.providerLoader.resolve(key);
|
|
4310
|
+
if (result) return result;
|
|
4311
|
+
const baseType = key.split("_")[0];
|
|
4312
|
+
if (baseType !== key) return this.ctx.providerLoader.resolve(baseType);
|
|
4313
|
+
return void 0;
|
|
4202
4314
|
}
|
|
4203
4315
|
/** Get a provider script by name from ProviderLoader.
|
|
4204
4316
|
* Returns the script string or null. */
|
|
@@ -4376,6 +4488,20 @@ var init_daemon_commands = __esm({
|
|
|
4376
4488
|
return this.handleGetProviderSettings(args);
|
|
4377
4489
|
case "set_provider_setting":
|
|
4378
4490
|
return this.handleSetProviderSetting(args);
|
|
4491
|
+
// ─── IDE Extension Settings (per-IDE on/off) ──────────────
|
|
4492
|
+
case "get_ide_extensions":
|
|
4493
|
+
return this.handleGetIdeExtensions(args);
|
|
4494
|
+
case "set_ide_extension":
|
|
4495
|
+
return this.handleSetIdeExtension(args);
|
|
4496
|
+
// ─── Extension Model / Mode Control ──────────────
|
|
4497
|
+
case "list_extension_models":
|
|
4498
|
+
return await this.handleExtensionScript(args, "listModels");
|
|
4499
|
+
case "set_extension_model":
|
|
4500
|
+
return await this.handleExtensionScript(args, "setModel");
|
|
4501
|
+
case "list_extension_modes":
|
|
4502
|
+
return await this.handleExtensionScript(args, "listModes");
|
|
4503
|
+
case "set_extension_mode":
|
|
4504
|
+
return await this.handleExtensionScript(args, "setMode");
|
|
4379
4505
|
default:
|
|
4380
4506
|
return { success: false, error: `Unknown command: ${cmd}` };
|
|
4381
4507
|
}
|
|
@@ -4686,6 +4812,7 @@ var init_daemon_commands = __esm({
|
|
|
4686
4812
|
const provider2 = this.getProvider();
|
|
4687
4813
|
const action = args?.action || "approve";
|
|
4688
4814
|
const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
|
|
4815
|
+
console.log(`[resolveAction] action=${action} button="${button}" provider=${provider2?.type}`);
|
|
4689
4816
|
if (provider2?.category === "extension" && this.agentStream && this.getCdp()) {
|
|
4690
4817
|
const ok = await this.agentStream.resolveAgentAction(
|
|
4691
4818
|
this.getCdp(),
|
|
@@ -4695,14 +4822,50 @@ var init_daemon_commands = __esm({
|
|
|
4695
4822
|
);
|
|
4696
4823
|
return { success: ok };
|
|
4697
4824
|
}
|
|
4698
|
-
|
|
4699
|
-
const
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4825
|
+
if (provider2?.scripts?.resolveAction) {
|
|
4826
|
+
const script = provider2.scripts.resolveAction({ action, button, buttonText: button });
|
|
4827
|
+
if (script) {
|
|
4828
|
+
const cdp2 = this.getCdp();
|
|
4829
|
+
if (!cdp2?.isConnected) return { success: false, error: "CDP not connected" };
|
|
4830
|
+
try {
|
|
4831
|
+
const raw = await cdp2.evaluate(script, 3e4);
|
|
4832
|
+
let result = raw;
|
|
4833
|
+
if (typeof raw === "string") {
|
|
4834
|
+
try {
|
|
4835
|
+
result = JSON.parse(raw);
|
|
4836
|
+
} catch {
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
console.log(`[resolveAction] script result:`, JSON.stringify(result));
|
|
4840
|
+
if (result?.resolved) {
|
|
4841
|
+
console.log(`[resolveAction] script-click resolved \u2014 "${result.clicked}"`);
|
|
4842
|
+
return { success: true, clicked: result.clicked };
|
|
4843
|
+
}
|
|
4844
|
+
if (result?.found && result.x != null && result.y != null) {
|
|
4845
|
+
const x = result.x;
|
|
4846
|
+
const y = result.y;
|
|
4847
|
+
await cdp2.send("Input.dispatchMouseEvent", {
|
|
4848
|
+
type: "mousePressed",
|
|
4849
|
+
x,
|
|
4850
|
+
y,
|
|
4851
|
+
button: "left",
|
|
4852
|
+
clickCount: 1
|
|
4853
|
+
});
|
|
4854
|
+
await cdp2.send("Input.dispatchMouseEvent", {
|
|
4855
|
+
type: "mouseReleased",
|
|
4856
|
+
x,
|
|
4857
|
+
y,
|
|
4858
|
+
button: "left",
|
|
4859
|
+
clickCount: 1
|
|
4860
|
+
});
|
|
4861
|
+
console.log(`[resolveAction] CDP click at (${x}, ${y}) \u2014 "${result.text}"`);
|
|
4862
|
+
return { success: true, clicked: result.text };
|
|
4863
|
+
}
|
|
4864
|
+
return { success: false, error: result?.found === false ? `Button not found: ${button}` : "No coordinates" };
|
|
4865
|
+
} catch (e) {
|
|
4866
|
+
return { success: false, error: `resolveAction failed: ${e.message}` };
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4706
4869
|
}
|
|
4707
4870
|
return { success: false, error: "resolveAction script not available for this provider" };
|
|
4708
4871
|
}
|
|
@@ -5097,6 +5260,103 @@ var init_daemon_commands = __esm({
|
|
|
5097
5260
|
}
|
|
5098
5261
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
5099
5262
|
}
|
|
5263
|
+
// ─── Extension Script Execution (Model/Mode) ─────
|
|
5264
|
+
/**
|
|
5265
|
+
* Extension provider의 CDP 스크립트를 실행하는 범용 핸들러.
|
|
5266
|
+
* args: { agentType, ideType?, model?, mode?, ... }
|
|
5267
|
+
* scriptName: 'listModels' | 'setModel' | 'listModes' | 'setMode'
|
|
5268
|
+
*/
|
|
5269
|
+
async handleExtensionScript(args, scriptName) {
|
|
5270
|
+
const { agentType, ideType } = args || {};
|
|
5271
|
+
console.log(`[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType} _currentIdeType=${this._currentIdeType}`);
|
|
5272
|
+
if (!agentType) return { success: false, error: "agentType is required" };
|
|
5273
|
+
const loader = this.ctx.providerLoader;
|
|
5274
|
+
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
5275
|
+
const provider2 = loader.get(agentType);
|
|
5276
|
+
if (!provider2) return { success: false, error: `Provider not found: ${agentType}` };
|
|
5277
|
+
if (!provider2.scripts?.[scriptName]) {
|
|
5278
|
+
return { success: false, error: `Script '${scriptName}' not available for ${agentType}` };
|
|
5279
|
+
}
|
|
5280
|
+
const script = provider2.scripts[scriptName](args);
|
|
5281
|
+
if (!script) return { success: false, error: `Script '${scriptName}' returned null` };
|
|
5282
|
+
const cdpKey = provider2.category === "ide" ? this._currentIdeType || agentType : this._currentIdeType || ideType;
|
|
5283
|
+
console.log(`[ExtScript] provider=${provider2.type} category=${provider2.category} cdpKey=${cdpKey}`);
|
|
5284
|
+
const cdp2 = this.getCdp(cdpKey);
|
|
5285
|
+
if (!cdp2?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
5286
|
+
try {
|
|
5287
|
+
let result;
|
|
5288
|
+
if (provider2.category === "extension") {
|
|
5289
|
+
const sessions = cdp2.getAgentSessions();
|
|
5290
|
+
let targetSessionId = null;
|
|
5291
|
+
for (const [sessionId, target] of sessions) {
|
|
5292
|
+
if (target.agentType === agentType) {
|
|
5293
|
+
targetSessionId = sessionId;
|
|
5294
|
+
break;
|
|
5295
|
+
}
|
|
5296
|
+
}
|
|
5297
|
+
if (!targetSessionId) {
|
|
5298
|
+
return { success: false, error: `No active session found for ${agentType}` };
|
|
5299
|
+
}
|
|
5300
|
+
result = await cdp2.evaluateInSession(targetSessionId, script);
|
|
5301
|
+
} else {
|
|
5302
|
+
result = await cdp2.evaluate(script, 3e4);
|
|
5303
|
+
}
|
|
5304
|
+
if (typeof result === "string") {
|
|
5305
|
+
try {
|
|
5306
|
+
const parsed = JSON.parse(result);
|
|
5307
|
+
return { success: true, ...parsed };
|
|
5308
|
+
} catch {
|
|
5309
|
+
return { success: true, result };
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
return { success: true, result };
|
|
5313
|
+
} catch (e) {
|
|
5314
|
+
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
// ─── IDE Extension Settings (per-IDE on/off) ─────
|
|
5318
|
+
handleGetIdeExtensions(args) {
|
|
5319
|
+
const { ideType } = args || {};
|
|
5320
|
+
const loader = this.ctx.providerLoader;
|
|
5321
|
+
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
5322
|
+
const allExtProviders = loader.getByCategory?.("extension") || [];
|
|
5323
|
+
const config = loadConfig();
|
|
5324
|
+
if (ideType) {
|
|
5325
|
+
const extensions = allExtProviders.map((p) => ({
|
|
5326
|
+
type: p.type,
|
|
5327
|
+
name: p.name,
|
|
5328
|
+
extensionId: p.extensionId,
|
|
5329
|
+
enabled: config.ideSettings?.[ideType]?.extensions?.[p.type]?.enabled === true
|
|
5330
|
+
}));
|
|
5331
|
+
return { success: true, ideType, extensions };
|
|
5332
|
+
}
|
|
5333
|
+
const connectedIdes = [...this.ctx.cdpManagers?.keys?.() || []];
|
|
5334
|
+
const result = {};
|
|
5335
|
+
for (const ide of connectedIdes) {
|
|
5336
|
+
result[ide] = allExtProviders.map((p) => ({
|
|
5337
|
+
type: p.type,
|
|
5338
|
+
name: p.name,
|
|
5339
|
+
extensionId: p.extensionId,
|
|
5340
|
+
enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true
|
|
5341
|
+
}));
|
|
5342
|
+
}
|
|
5343
|
+
return { success: true, ides: result };
|
|
5344
|
+
}
|
|
5345
|
+
handleSetIdeExtension(args) {
|
|
5346
|
+
const { ideType, extensionType, enabled } = args || {};
|
|
5347
|
+
if (!ideType || !extensionType || enabled === void 0) {
|
|
5348
|
+
return { success: false, error: "ideType, extensionType, and enabled are required" };
|
|
5349
|
+
}
|
|
5350
|
+
const loader = this.ctx.providerLoader;
|
|
5351
|
+
if (!loader?.setIdeExtensionEnabled) {
|
|
5352
|
+
return { success: false, error: "ProviderLoader not initialized" };
|
|
5353
|
+
}
|
|
5354
|
+
const ok = loader.setIdeExtensionEnabled(ideType, extensionType, !!enabled);
|
|
5355
|
+
if (ok) {
|
|
5356
|
+
return { success: true, ideType, extensionType, enabled: !!enabled };
|
|
5357
|
+
}
|
|
5358
|
+
return { success: false, error: "Failed to save setting" };
|
|
5359
|
+
}
|
|
5100
5360
|
};
|
|
5101
5361
|
}
|
|
5102
5362
|
});
|
|
@@ -5239,12 +5499,12 @@ var init_manager = __esm({
|
|
|
5239
5499
|
constructor(logFn, providerLoader) {
|
|
5240
5500
|
this.logFn = logFn || console.log;
|
|
5241
5501
|
if (providerLoader) {
|
|
5242
|
-
const
|
|
5243
|
-
|
|
5502
|
+
const allExtProviders = providerLoader.getByCategory("extension");
|
|
5503
|
+
for (const p of allExtProviders) {
|
|
5244
5504
|
const adapter = new ProviderStreamAdapter(p);
|
|
5505
|
+
this.allAdapters.push(adapter);
|
|
5245
5506
|
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name})`);
|
|
5246
|
-
|
|
5247
|
-
});
|
|
5507
|
+
}
|
|
5248
5508
|
}
|
|
5249
5509
|
}
|
|
5250
5510
|
setLocalServer(server) {
|
|
@@ -5498,14 +5758,238 @@ var init_agent_stream = __esm({
|
|
|
5498
5758
|
}
|
|
5499
5759
|
});
|
|
5500
5760
|
|
|
5761
|
+
// src/daemon-logger.ts
|
|
5762
|
+
var daemon_logger_exports = {};
|
|
5763
|
+
__export(daemon_logger_exports, {
|
|
5764
|
+
LOG: () => LOG,
|
|
5765
|
+
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
5766
|
+
LOG_PATH: () => LOG_PATH,
|
|
5767
|
+
cdpLogFn: () => cdpLogFn,
|
|
5768
|
+
daemonLog: () => daemonLog,
|
|
5769
|
+
getLogBufferSize: () => getLogBufferSize,
|
|
5770
|
+
getLogLevel: () => getLogLevel,
|
|
5771
|
+
getLogPath: () => getLogPath,
|
|
5772
|
+
getRecentLogs: () => getRecentLogs,
|
|
5773
|
+
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
5774
|
+
setLogLevel: () => setLogLevel
|
|
5775
|
+
});
|
|
5776
|
+
function setLogLevel(level) {
|
|
5777
|
+
currentLevel = level;
|
|
5778
|
+
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
5779
|
+
}
|
|
5780
|
+
function getLogLevel() {
|
|
5781
|
+
return currentLevel;
|
|
5782
|
+
}
|
|
5783
|
+
function getDateStr() {
|
|
5784
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
5785
|
+
}
|
|
5786
|
+
function checkDateRotation() {
|
|
5787
|
+
const today = getDateStr();
|
|
5788
|
+
if (today !== currentDate) {
|
|
5789
|
+
currentDate = today;
|
|
5790
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
5791
|
+
cleanOldLogs();
|
|
5792
|
+
}
|
|
5793
|
+
}
|
|
5794
|
+
function cleanOldLogs() {
|
|
5795
|
+
try {
|
|
5796
|
+
const files = fs5.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
5797
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
5798
|
+
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
5799
|
+
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
5800
|
+
for (const file of files) {
|
|
5801
|
+
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
5802
|
+
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
5803
|
+
try {
|
|
5804
|
+
fs5.unlinkSync(path6.join(LOG_DIR, file));
|
|
5805
|
+
} catch {
|
|
5806
|
+
}
|
|
5807
|
+
}
|
|
5808
|
+
}
|
|
5809
|
+
} catch {
|
|
5810
|
+
}
|
|
5811
|
+
}
|
|
5812
|
+
function rotateSizeIfNeeded() {
|
|
5813
|
+
try {
|
|
5814
|
+
const stat = fs5.statSync(currentLogFile);
|
|
5815
|
+
if (stat.size > MAX_LOG_SIZE) {
|
|
5816
|
+
const backup = currentLogFile.replace(".log", ".1.log");
|
|
5817
|
+
try {
|
|
5818
|
+
fs5.unlinkSync(backup);
|
|
5819
|
+
} catch {
|
|
5820
|
+
}
|
|
5821
|
+
fs5.renameSync(currentLogFile, backup);
|
|
5822
|
+
}
|
|
5823
|
+
} catch {
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
5826
|
+
function writeToFile(line) {
|
|
5827
|
+
try {
|
|
5828
|
+
if (++writeCount % 1e3 === 0) {
|
|
5829
|
+
checkDateRotation();
|
|
5830
|
+
rotateSizeIfNeeded();
|
|
5831
|
+
}
|
|
5832
|
+
fs5.appendFileSync(currentLogFile, line + "\n");
|
|
5833
|
+
} catch {
|
|
5834
|
+
}
|
|
5835
|
+
}
|
|
5836
|
+
function getRecentLogs(count = 50, minLevel = "info") {
|
|
5837
|
+
const minNum = LEVEL_NUM[minLevel];
|
|
5838
|
+
const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
|
|
5839
|
+
return filtered.slice(-count);
|
|
5840
|
+
}
|
|
5841
|
+
function getLogBufferSize() {
|
|
5842
|
+
return ringBuffer.length;
|
|
5843
|
+
}
|
|
5844
|
+
function ts() {
|
|
5845
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
5846
|
+
}
|
|
5847
|
+
function fullTs() {
|
|
5848
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
5849
|
+
}
|
|
5850
|
+
function daemonLog(category, msg, level = "info") {
|
|
5851
|
+
const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
|
|
5852
|
+
const label = LEVEL_LABEL[level];
|
|
5853
|
+
const line = `[${ts()}] [${label}] [${category}] ${msg}`;
|
|
5854
|
+
writeToFile(line);
|
|
5855
|
+
ringBuffer.push({ ts: Date.now(), level, category, message: msg });
|
|
5856
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5857
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5858
|
+
}
|
|
5859
|
+
if (shouldOutput) {
|
|
5860
|
+
origConsoleLog(line);
|
|
5861
|
+
}
|
|
5862
|
+
}
|
|
5863
|
+
function cdpLogFn(ideType) {
|
|
5864
|
+
return (msg) => {
|
|
5865
|
+
const isDebug = msg.includes("discoverAgentWebviews:") && !msg.includes("Found agent") || msg.includes("[P2P] sent");
|
|
5866
|
+
daemonLog(`CDP:${ideType}`, msg, isDebug ? "debug" : "info");
|
|
5867
|
+
};
|
|
5868
|
+
}
|
|
5869
|
+
function installGlobalInterceptor() {
|
|
5870
|
+
if (interceptorInstalled) return;
|
|
5871
|
+
interceptorInstalled = true;
|
|
5872
|
+
const stripAnsi2 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
5873
|
+
const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
|
|
5874
|
+
console.log = (...args) => {
|
|
5875
|
+
origConsoleLog(...args);
|
|
5876
|
+
try {
|
|
5877
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5878
|
+
const clean = stripAnsi2(msg);
|
|
5879
|
+
if (isDaemonLogLine(clean)) return;
|
|
5880
|
+
const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
|
|
5881
|
+
writeToFile(line);
|
|
5882
|
+
const catMatch = clean.match(/\[([^\]]+)\]/);
|
|
5883
|
+
ringBuffer.push({
|
|
5884
|
+
ts: Date.now(),
|
|
5885
|
+
level: "info",
|
|
5886
|
+
category: catMatch?.[1] || "System",
|
|
5887
|
+
message: clean
|
|
5888
|
+
});
|
|
5889
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5890
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5891
|
+
}
|
|
5892
|
+
} catch {
|
|
5893
|
+
}
|
|
5894
|
+
};
|
|
5895
|
+
console.error = (...args) => {
|
|
5896
|
+
origConsoleError(...args);
|
|
5897
|
+
try {
|
|
5898
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5899
|
+
const clean = stripAnsi2(msg);
|
|
5900
|
+
if (isDaemonLogLine(clean)) return;
|
|
5901
|
+
const line = `[${fullTs()}] [ERROR] ${clean}`;
|
|
5902
|
+
writeToFile(line);
|
|
5903
|
+
ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
|
|
5904
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5905
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5906
|
+
}
|
|
5907
|
+
} catch {
|
|
5908
|
+
}
|
|
5909
|
+
};
|
|
5910
|
+
console.warn = (...args) => {
|
|
5911
|
+
origConsoleWarn(...args);
|
|
5912
|
+
try {
|
|
5913
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5914
|
+
const clean = stripAnsi2(msg);
|
|
5915
|
+
if (isDaemonLogLine(clean)) return;
|
|
5916
|
+
const line = `[${fullTs()}] [WARN] ${clean}`;
|
|
5917
|
+
writeToFile(line);
|
|
5918
|
+
ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
|
|
5919
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5920
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5921
|
+
}
|
|
5922
|
+
} catch {
|
|
5923
|
+
}
|
|
5924
|
+
};
|
|
5925
|
+
writeToFile(`
|
|
5926
|
+
=== ADHDev Daemon started at ${fullTs()} ===`);
|
|
5927
|
+
writeToFile(`Log file: ${currentLogFile}`);
|
|
5928
|
+
writeToFile(`Log level: ${currentLevel}`);
|
|
5929
|
+
}
|
|
5930
|
+
function getLogPath() {
|
|
5931
|
+
return currentLogFile;
|
|
5932
|
+
}
|
|
5933
|
+
var fs5, path6, os6, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
|
|
5934
|
+
var init_daemon_logger = __esm({
|
|
5935
|
+
"src/daemon-logger.ts"() {
|
|
5936
|
+
"use strict";
|
|
5937
|
+
fs5 = __toESM(require("fs"));
|
|
5938
|
+
path6 = __toESM(require("path"));
|
|
5939
|
+
os6 = __toESM(require("os"));
|
|
5940
|
+
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
5941
|
+
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
5942
|
+
currentLevel = "info";
|
|
5943
|
+
LOG_DIR = process.platform === "darwin" ? path6.join(os6.homedir(), "Library", "Logs", "adhdev") : path6.join(os6.homedir(), ".local", "share", "adhdev", "logs");
|
|
5944
|
+
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
5945
|
+
MAX_LOG_DAYS = 7;
|
|
5946
|
+
try {
|
|
5947
|
+
fs5.mkdirSync(LOG_DIR, { recursive: true });
|
|
5948
|
+
} catch {
|
|
5949
|
+
}
|
|
5950
|
+
currentDate = getDateStr();
|
|
5951
|
+
currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
5952
|
+
cleanOldLogs();
|
|
5953
|
+
try {
|
|
5954
|
+
const oldLog = path6.join(LOG_DIR, "daemon.log");
|
|
5955
|
+
if (fs5.existsSync(oldLog)) {
|
|
5956
|
+
const stat = fs5.statSync(oldLog);
|
|
5957
|
+
const oldDate = stat.mtime.toISOString().slice(0, 10);
|
|
5958
|
+
fs5.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
5959
|
+
}
|
|
5960
|
+
const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
|
|
5961
|
+
if (fs5.existsSync(oldLogBackup)) {
|
|
5962
|
+
fs5.unlinkSync(oldLogBackup);
|
|
5963
|
+
}
|
|
5964
|
+
} catch {
|
|
5965
|
+
}
|
|
5966
|
+
writeCount = 0;
|
|
5967
|
+
RING_BUFFER_SIZE = 200;
|
|
5968
|
+
ringBuffer = [];
|
|
5969
|
+
origConsoleLog = console.log.bind(console);
|
|
5970
|
+
origConsoleError = console.error.bind(console);
|
|
5971
|
+
origConsoleWarn = console.warn.bind(console);
|
|
5972
|
+
LOG = {
|
|
5973
|
+
debug: (category, msg) => daemonLog(category, msg, "debug"),
|
|
5974
|
+
info: (category, msg) => daemonLog(category, msg, "info"),
|
|
5975
|
+
warn: (category, msg) => daemonLog(category, msg, "warn"),
|
|
5976
|
+
error: (category, msg) => daemonLog(category, msg, "error")
|
|
5977
|
+
};
|
|
5978
|
+
interceptorInstalled = false;
|
|
5979
|
+
LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
5980
|
+
LOG_DIR_PATH = LOG_DIR;
|
|
5981
|
+
}
|
|
5982
|
+
});
|
|
5983
|
+
|
|
5501
5984
|
// src/daemon-status.ts
|
|
5502
|
-
var
|
|
5985
|
+
var os7, path7, DaemonStatusReporter;
|
|
5503
5986
|
var init_daemon_status = __esm({
|
|
5504
5987
|
"src/daemon-status.ts"() {
|
|
5505
5988
|
"use strict";
|
|
5506
|
-
|
|
5507
|
-
|
|
5989
|
+
os7 = __toESM(require("os"));
|
|
5990
|
+
path7 = __toESM(require("path"));
|
|
5508
5991
|
init_config();
|
|
5992
|
+
init_daemon_logger();
|
|
5509
5993
|
DaemonStatusReporter = class {
|
|
5510
5994
|
deps;
|
|
5511
5995
|
log;
|
|
@@ -5563,7 +6047,7 @@ var init_daemon_status = __esm({
|
|
|
5563
6047
|
}
|
|
5564
6048
|
}
|
|
5565
6049
|
emitStatusEvent(event) {
|
|
5566
|
-
|
|
6050
|
+
LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
5567
6051
|
this.deps.bridge?.sendMessage("status_event", event);
|
|
5568
6052
|
}
|
|
5569
6053
|
removeAgentTracking(_key) {
|
|
@@ -5584,13 +6068,15 @@ var init_daemon_status = __esm({
|
|
|
5584
6068
|
const allStates = this.deps.instanceManager.collectAllStates();
|
|
5585
6069
|
const ideStates = allStates.filter((s) => s.category === "ide");
|
|
5586
6070
|
const cliStates = allStates.filter((s) => s.category === "cli");
|
|
6071
|
+
const acpStates = allStates.filter((s) => s.category === "acp");
|
|
5587
6072
|
const ideSummary = ideStates.map((s) => {
|
|
5588
6073
|
const msgs = s.activeChat?.messages?.length || 0;
|
|
5589
6074
|
const exts = (s.extensions || []).length;
|
|
5590
6075
|
return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
|
|
5591
6076
|
}).join(", ");
|
|
5592
|
-
const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
|
|
5593
|
-
|
|
6077
|
+
const cliSummary = [...cliStates, ...acpStates].map((s) => `${s.type}(${s.status})`).join(", ");
|
|
6078
|
+
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
6079
|
+
LOG[logLevel]("StatusReport", `\u2192${target} IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length + acpStates.length} [${cliSummary}]`);
|
|
5594
6080
|
const managedIdes = ideStates.map((s) => ({
|
|
5595
6081
|
ideType: s.type,
|
|
5596
6082
|
ideVersion: "",
|
|
@@ -5616,23 +6102,45 @@ var init_daemon_status = __esm({
|
|
|
5616
6102
|
currentAutoApprove: s.currentAutoApprove
|
|
5617
6103
|
}));
|
|
5618
6104
|
const instanceIdeTypes = new Set(ideStates.map((s) => s.type));
|
|
6105
|
+
const instanceBaseTypes = /* @__PURE__ */ new Set();
|
|
6106
|
+
for (const t of instanceIdeTypes) {
|
|
6107
|
+
instanceBaseTypes.add(t);
|
|
6108
|
+
const base = t.split("_")[0];
|
|
6109
|
+
if (base) instanceBaseTypes.add(base);
|
|
6110
|
+
}
|
|
5619
6111
|
const perExtData = localServer?.getPerExtensionData() || [];
|
|
5620
6112
|
for (const ext of perExtData) {
|
|
5621
6113
|
const ideKey = ext.ideType.toLowerCase();
|
|
5622
|
-
if (
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
6114
|
+
if (instanceBaseTypes.has(ideKey)) {
|
|
6115
|
+
const match = managedIdes.find(
|
|
6116
|
+
(m) => m.ideType === ideKey || m.ideType.split("_")[0] === ideKey
|
|
6117
|
+
);
|
|
6118
|
+
if (match) {
|
|
6119
|
+
if (!match.workspaceFolders?.length && ext.workspaceFolders?.length) {
|
|
6120
|
+
match.workspaceFolders = ext.workspaceFolders;
|
|
6121
|
+
}
|
|
6122
|
+
if (!match.activeFile && ext.activeFile) match.activeFile = ext.activeFile;
|
|
6123
|
+
if (!match.terminals && ext.terminals) match.terminals = ext.terminals;
|
|
6124
|
+
if ((!match.aiAgents || match.aiAgents.length === 0) && ext.aiAgents?.length) {
|
|
6125
|
+
match.aiAgents = ext.aiAgents;
|
|
6126
|
+
}
|
|
6127
|
+
if (!match.ideVersion && ext.ideVersion) match.ideVersion = ext.ideVersion;
|
|
6128
|
+
}
|
|
6129
|
+
} else {
|
|
6130
|
+
managedIdes.push({
|
|
6131
|
+
ideType: ext.ideType,
|
|
6132
|
+
ideVersion: ext.ideVersion,
|
|
6133
|
+
instanceId: ext.instanceId,
|
|
6134
|
+
workspaceFolders: ext.workspaceFolders,
|
|
6135
|
+
activeFile: ext.activeFile,
|
|
6136
|
+
terminals: ext.terminals,
|
|
6137
|
+
aiAgents: ext.aiAgents,
|
|
6138
|
+
activeChat: ext.activeChat,
|
|
6139
|
+
chats: ext.chats || [],
|
|
6140
|
+
agentStreams: ext.agentStreams || [],
|
|
6141
|
+
cdpConnected: false
|
|
6142
|
+
});
|
|
6143
|
+
}
|
|
5636
6144
|
}
|
|
5637
6145
|
const managedClis = cliStates.map((s) => ({
|
|
5638
6146
|
id: s.instanceId,
|
|
@@ -5643,6 +6151,19 @@ var init_daemon_status = __esm({
|
|
|
5643
6151
|
workingDir: s.workingDir || "",
|
|
5644
6152
|
activeChat: s.activeChat
|
|
5645
6153
|
}));
|
|
6154
|
+
for (const s of acpStates) {
|
|
6155
|
+
managedClis.push({
|
|
6156
|
+
id: s.instanceId,
|
|
6157
|
+
cliType: s.type,
|
|
6158
|
+
cliName: s.name,
|
|
6159
|
+
status: s.status,
|
|
6160
|
+
mode: "chat",
|
|
6161
|
+
workingDir: s.workingDir || "",
|
|
6162
|
+
activeChat: s.activeChat,
|
|
6163
|
+
currentModel: s.currentModel,
|
|
6164
|
+
isAcp: true
|
|
6165
|
+
});
|
|
6166
|
+
}
|
|
5646
6167
|
const extSummary = localServer?.getLatestExtensionData() || {
|
|
5647
6168
|
activeFile: null,
|
|
5648
6169
|
workspaceFolders: [],
|
|
@@ -5654,15 +6175,15 @@ var init_daemon_status = __esm({
|
|
|
5654
6175
|
daemonMode: true,
|
|
5655
6176
|
machineNickname: loadConfig().machineNickname || null,
|
|
5656
6177
|
machine: {
|
|
5657
|
-
hostname:
|
|
5658
|
-
platform:
|
|
5659
|
-
release:
|
|
5660
|
-
arch:
|
|
5661
|
-
cpus:
|
|
5662
|
-
totalMem:
|
|
5663
|
-
freeMem:
|
|
5664
|
-
loadavg:
|
|
5665
|
-
uptime:
|
|
6178
|
+
hostname: os7.hostname(),
|
|
6179
|
+
platform: os7.platform(),
|
|
6180
|
+
release: os7.release(),
|
|
6181
|
+
arch: os7.arch(),
|
|
6182
|
+
cpus: os7.cpus().length,
|
|
6183
|
+
totalMem: os7.totalmem(),
|
|
6184
|
+
freeMem: os7.freemem(),
|
|
6185
|
+
loadavg: os7.loadavg(),
|
|
6186
|
+
uptime: os7.uptime()
|
|
5666
6187
|
},
|
|
5667
6188
|
managedIdes,
|
|
5668
6189
|
managedClis,
|
|
@@ -5684,7 +6205,7 @@ var init_daemon_status = __esm({
|
|
|
5684
6205
|
})),
|
|
5685
6206
|
timestamp: now,
|
|
5686
6207
|
activeFile: extSummary.activeFile,
|
|
5687
|
-
workspaceFolders: extSummary.workspaceFolders?.length > 0 ? extSummary.workspaceFolders : Array.from(adapters.values()).map((a) => ({ name:
|
|
6208
|
+
workspaceFolders: extSummary.workspaceFolders?.length > 0 ? extSummary.workspaceFolders : Array.from(adapters.values()).map((a) => ({ name: path7.basename(a.workingDir), path: a.workingDir })),
|
|
5688
6209
|
terminals: extSummary.terminals,
|
|
5689
6210
|
aiAgents: [
|
|
5690
6211
|
...managedIdes.flatMap((ide) => (ide.aiAgents || []).map((a) => ({
|
|
@@ -5692,17 +6213,17 @@ var init_daemon_status = __esm({
|
|
|
5692
6213
|
name: a.name,
|
|
5693
6214
|
status: a.status,
|
|
5694
6215
|
ideType: ide.ideType
|
|
5695
|
-
})))
|
|
5696
|
-
|
|
6216
|
+
})))
|
|
6217
|
+
// CLIs are already in managedClis — don't duplicate here
|
|
5697
6218
|
],
|
|
5698
6219
|
activeChat: managedClis[0]?.activeChat || managedIdes[0]?.activeChat || null,
|
|
5699
6220
|
agentStreams: managedIdes.flatMap((ide) => ide.agentStreams || []),
|
|
5700
6221
|
connectedExtensions: extSummary.connectedIdes,
|
|
5701
|
-
system: { platform:
|
|
6222
|
+
system: { platform: os7.platform(), hostname: os7.hostname() }
|
|
5702
6223
|
};
|
|
5703
6224
|
const p2pSent = this.sendP2PPayload(payload);
|
|
5704
6225
|
if (p2pSent) {
|
|
5705
|
-
|
|
6226
|
+
LOG.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
|
|
5706
6227
|
}
|
|
5707
6228
|
if (opts?.p2pOnly) return;
|
|
5708
6229
|
const plan = bridge.getUserPlan();
|
|
@@ -5711,11 +6232,11 @@ var init_daemon_status = __esm({
|
|
|
5711
6232
|
daemonMode: true,
|
|
5712
6233
|
machineNickname: payload.machineNickname,
|
|
5713
6234
|
machine: {
|
|
5714
|
-
hostname:
|
|
5715
|
-
platform:
|
|
5716
|
-
arch:
|
|
5717
|
-
cpus:
|
|
5718
|
-
totalMem:
|
|
6235
|
+
hostname: os7.hostname(),
|
|
6236
|
+
platform: os7.platform(),
|
|
6237
|
+
arch: os7.arch(),
|
|
6238
|
+
cpus: os7.cpus().length,
|
|
6239
|
+
totalMem: os7.totalmem()
|
|
5719
6240
|
},
|
|
5720
6241
|
managedIdes: managedIdes.map((ide) => ({
|
|
5721
6242
|
ideType: ide.ideType,
|
|
@@ -5739,7 +6260,7 @@ var init_daemon_status = __esm({
|
|
|
5739
6260
|
timestamp: now
|
|
5740
6261
|
};
|
|
5741
6262
|
bridge.sendMessage("status_report", wsPayload);
|
|
5742
|
-
|
|
6263
|
+
LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
|
|
5743
6264
|
}
|
|
5744
6265
|
}
|
|
5745
6266
|
// ─── P2P ─────────────────────────────────────────
|
|
@@ -5774,7 +6295,7 @@ function stripAnsi(str) {
|
|
|
5774
6295
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
5775
6296
|
}
|
|
5776
6297
|
function findBinary(name) {
|
|
5777
|
-
const isWin =
|
|
6298
|
+
const isWin = os8.platform() === "win32";
|
|
5778
6299
|
try {
|
|
5779
6300
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
5780
6301
|
return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
@@ -5782,11 +6303,11 @@ function findBinary(name) {
|
|
|
5782
6303
|
return isWin ? `${name}.cmd` : name;
|
|
5783
6304
|
}
|
|
5784
6305
|
}
|
|
5785
|
-
var
|
|
6306
|
+
var os8, import_child_process4, pty, ProviderCliAdapter;
|
|
5786
6307
|
var init_provider_cli_adapter = __esm({
|
|
5787
6308
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
5788
6309
|
"use strict";
|
|
5789
|
-
|
|
6310
|
+
os8 = __toESM(require("os"));
|
|
5790
6311
|
import_child_process4 = require("child_process");
|
|
5791
6312
|
try {
|
|
5792
6313
|
pty = require("node-pty");
|
|
@@ -5799,7 +6320,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
5799
6320
|
this.provider = provider2;
|
|
5800
6321
|
this.cliType = provider2.type;
|
|
5801
6322
|
this.cliName = provider2.name;
|
|
5802
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
6323
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os8.homedir()) : workingDir;
|
|
5803
6324
|
const t = provider2.timeouts || {};
|
|
5804
6325
|
this.timeouts = {
|
|
5805
6326
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -5857,7 +6378,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
5857
6378
|
if (!pty) throw new Error("node-pty is not installed");
|
|
5858
6379
|
const { spawn: spawnConfig } = this.provider;
|
|
5859
6380
|
const binaryPath = findBinary(spawnConfig.command);
|
|
5860
|
-
const isWin =
|
|
6381
|
+
const isWin = os8.platform() === "win32";
|
|
5861
6382
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
5862
6383
|
console.log(`[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
5863
6384
|
let shellCmd;
|
|
@@ -6099,7 +6620,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
6099
6620
|
|
|
6100
6621
|
// src/cli-detector.ts
|
|
6101
6622
|
async function detectCLIs() {
|
|
6102
|
-
const platform7 =
|
|
6623
|
+
const platform7 = os9.platform();
|
|
6103
6624
|
const whichCmd = platform7 === "win32" ? "where" : "which";
|
|
6104
6625
|
const results = [];
|
|
6105
6626
|
for (const cli of KNOWN_CLIS) {
|
|
@@ -6133,12 +6654,12 @@ async function detectCLI(cliId) {
|
|
|
6133
6654
|
const all = await detectCLIs();
|
|
6134
6655
|
return all.find((c) => c.id === normalizedId && c.installed) || null;
|
|
6135
6656
|
}
|
|
6136
|
-
var import_child_process5,
|
|
6657
|
+
var import_child_process5, os9, KNOWN_CLIS;
|
|
6137
6658
|
var init_cli_detector = __esm({
|
|
6138
6659
|
"src/cli-detector.ts"() {
|
|
6139
6660
|
"use strict";
|
|
6140
6661
|
import_child_process5 = require("child_process");
|
|
6141
|
-
|
|
6662
|
+
os9 = __toESM(require("os"));
|
|
6142
6663
|
KNOWN_CLIS = [
|
|
6143
6664
|
{ id: "gemini-cli", displayName: "Gemini CLI", icon: "\u264A", command: "gemini" },
|
|
6144
6665
|
{ id: "claude-code", displayName: "Claude Code", icon: "\u{1F916}", command: "claude" },
|
|
@@ -6147,17 +6668,267 @@ var init_cli_detector = __esm({
|
|
|
6147
6668
|
}
|
|
6148
6669
|
});
|
|
6149
6670
|
|
|
6150
|
-
// src/
|
|
6151
|
-
var
|
|
6152
|
-
var
|
|
6153
|
-
"src/
|
|
6671
|
+
// src/providers/status-monitor.ts
|
|
6672
|
+
var DEFAULT_MONITOR_CONFIG, StatusMonitor;
|
|
6673
|
+
var init_status_monitor = __esm({
|
|
6674
|
+
"src/providers/status-monitor.ts"() {
|
|
6154
6675
|
"use strict";
|
|
6155
|
-
|
|
6156
|
-
|
|
6676
|
+
DEFAULT_MONITOR_CONFIG = {
|
|
6677
|
+
approvalAlert: true,
|
|
6678
|
+
longGeneratingAlert: true,
|
|
6679
|
+
longGeneratingThresholdSec: 180,
|
|
6680
|
+
// 3분
|
|
6681
|
+
alertCooldownSec: 60
|
|
6682
|
+
// 1분 쿨다운
|
|
6683
|
+
};
|
|
6684
|
+
StatusMonitor = class {
|
|
6685
|
+
config;
|
|
6686
|
+
lastAlertTime = /* @__PURE__ */ new Map();
|
|
6687
|
+
generatingStartTimes = /* @__PURE__ */ new Map();
|
|
6688
|
+
constructor(config) {
|
|
6689
|
+
this.config = { ...DEFAULT_MONITOR_CONFIG, ...config };
|
|
6690
|
+
}
|
|
6691
|
+
/** 설정 업데이트 (Provider Settings에서 호출) */
|
|
6692
|
+
updateConfig(partial) {
|
|
6693
|
+
Object.assign(this.config, partial);
|
|
6694
|
+
}
|
|
6695
|
+
/** 현재 설정 반환 */
|
|
6696
|
+
getConfig() {
|
|
6697
|
+
return { ...this.config };
|
|
6698
|
+
}
|
|
6699
|
+
/**
|
|
6700
|
+
* 상태 전이 체크 → 알림 이벤트 배열 반환
|
|
6701
|
+
* 각 onTick()에서 호출.
|
|
6702
|
+
*/
|
|
6703
|
+
check(agentKey, status, now) {
|
|
6704
|
+
const events = [];
|
|
6705
|
+
if (this.config.approvalAlert && status === "waiting_approval") {
|
|
6706
|
+
if (this.shouldAlert(agentKey + ":approval", now)) {
|
|
6707
|
+
events.push({
|
|
6708
|
+
type: "monitor:approval_waiting",
|
|
6709
|
+
agentKey,
|
|
6710
|
+
timestamp: now,
|
|
6711
|
+
message: `${agentKey} is waiting for approval`
|
|
6712
|
+
});
|
|
6713
|
+
}
|
|
6714
|
+
}
|
|
6715
|
+
if (status === "generating" || status === "streaming") {
|
|
6716
|
+
if (!this.generatingStartTimes.has(agentKey)) {
|
|
6717
|
+
this.generatingStartTimes.set(agentKey, now);
|
|
6718
|
+
}
|
|
6719
|
+
if (this.config.longGeneratingAlert) {
|
|
6720
|
+
const startedAt = this.generatingStartTimes.get(agentKey);
|
|
6721
|
+
const elapsedSec = Math.round((now - startedAt) / 1e3);
|
|
6722
|
+
if (elapsedSec > this.config.longGeneratingThresholdSec) {
|
|
6723
|
+
if (this.shouldAlert(agentKey + ":long_gen", now)) {
|
|
6724
|
+
events.push({
|
|
6725
|
+
type: "monitor:long_generating",
|
|
6726
|
+
agentKey,
|
|
6727
|
+
elapsedSec,
|
|
6728
|
+
timestamp: now,
|
|
6729
|
+
message: `${agentKey} has been generating for ${Math.round(elapsedSec / 60)}min`
|
|
6730
|
+
});
|
|
6731
|
+
}
|
|
6732
|
+
}
|
|
6733
|
+
}
|
|
6734
|
+
} else {
|
|
6735
|
+
this.generatingStartTimes.delete(agentKey);
|
|
6736
|
+
}
|
|
6737
|
+
return events;
|
|
6738
|
+
}
|
|
6739
|
+
/** 쿨다운 체크 — 같은 알림을 너무 자주 보내지 않도록 */
|
|
6740
|
+
shouldAlert(key, now) {
|
|
6741
|
+
const last = this.lastAlertTime.get(key) || 0;
|
|
6742
|
+
if (now - last > this.config.alertCooldownSec * 1e3) {
|
|
6743
|
+
this.lastAlertTime.set(key, now);
|
|
6744
|
+
return true;
|
|
6745
|
+
}
|
|
6746
|
+
return false;
|
|
6747
|
+
}
|
|
6748
|
+
/** 리셋 (에이전트 종료/재시작 시) */
|
|
6749
|
+
reset(agentKey) {
|
|
6750
|
+
if (agentKey) {
|
|
6751
|
+
this.generatingStartTimes.delete(agentKey);
|
|
6752
|
+
for (const k of this.lastAlertTime.keys()) {
|
|
6753
|
+
if (k.startsWith(agentKey)) this.lastAlertTime.delete(k);
|
|
6754
|
+
}
|
|
6755
|
+
} else {
|
|
6756
|
+
this.generatingStartTimes.clear();
|
|
6757
|
+
this.lastAlertTime.clear();
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
6760
|
+
};
|
|
6761
|
+
}
|
|
6762
|
+
});
|
|
6763
|
+
|
|
6764
|
+
// src/providers/cli-provider-instance.ts
|
|
6765
|
+
var path8, CliProviderInstance;
|
|
6766
|
+
var init_cli_provider_instance = __esm({
|
|
6767
|
+
"src/providers/cli-provider-instance.ts"() {
|
|
6768
|
+
"use strict";
|
|
6769
|
+
path8 = __toESM(require("path"));
|
|
6770
|
+
init_provider_cli_adapter();
|
|
6771
|
+
init_status_monitor();
|
|
6772
|
+
CliProviderInstance = class {
|
|
6773
|
+
constructor(provider2, workingDir, cliArgs = []) {
|
|
6774
|
+
this.provider = provider2;
|
|
6775
|
+
this.workingDir = workingDir;
|
|
6776
|
+
this.cliArgs = cliArgs;
|
|
6777
|
+
this.type = provider2.type;
|
|
6778
|
+
this.adapter = new ProviderCliAdapter(provider2, workingDir, cliArgs);
|
|
6779
|
+
this.monitor = new StatusMonitor();
|
|
6780
|
+
}
|
|
6781
|
+
type;
|
|
6782
|
+
category = "cli";
|
|
6783
|
+
adapter;
|
|
6784
|
+
context = null;
|
|
6785
|
+
events = [];
|
|
6786
|
+
lastStatus = "starting";
|
|
6787
|
+
generatingStartedAt = 0;
|
|
6788
|
+
settings = {};
|
|
6789
|
+
monitor;
|
|
6790
|
+
// ─── Lifecycle ─────────────────────────────────
|
|
6791
|
+
async init(context) {
|
|
6792
|
+
this.context = context;
|
|
6793
|
+
this.settings = context.settings || {};
|
|
6794
|
+
this.monitor.updateConfig({
|
|
6795
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
6796
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
6797
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
6798
|
+
});
|
|
6799
|
+
if (context.bridge) {
|
|
6800
|
+
this.adapter.setBridge(context.bridge);
|
|
6801
|
+
}
|
|
6802
|
+
if (context.onPtyData) {
|
|
6803
|
+
this.adapter.setOnPtyData(context.onPtyData);
|
|
6804
|
+
}
|
|
6805
|
+
this.adapter.setOnStatusChange(() => {
|
|
6806
|
+
this.detectStatusTransition();
|
|
6807
|
+
});
|
|
6808
|
+
await this.adapter.spawn();
|
|
6809
|
+
}
|
|
6810
|
+
async onTick() {
|
|
6811
|
+
}
|
|
6812
|
+
getState() {
|
|
6813
|
+
const adapterStatus = this.adapter.getStatus();
|
|
6814
|
+
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
6815
|
+
const recentMessages = adapterStatus.messages.slice(-50).map((m) => ({
|
|
6816
|
+
role: m.role,
|
|
6817
|
+
content: m.content.length > 2e3 ? m.content.slice(0, 2e3) + "\n... (truncated)" : m.content,
|
|
6818
|
+
timestamp: m.timestamp
|
|
6819
|
+
}));
|
|
6820
|
+
const partial = this.adapter.getPartialResponse();
|
|
6821
|
+
if (adapterStatus.status === "generating" && partial) {
|
|
6822
|
+
const cleaned = partial.trim();
|
|
6823
|
+
if (cleaned && cleaned !== "(generating...)") {
|
|
6824
|
+
recentMessages.push({
|
|
6825
|
+
role: "assistant",
|
|
6826
|
+
content: (cleaned.length > 2e3 ? cleaned.slice(0, 2e3) + "..." : cleaned) + "...",
|
|
6827
|
+
timestamp: Date.now()
|
|
6828
|
+
});
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6831
|
+
return {
|
|
6832
|
+
type: this.type,
|
|
6833
|
+
name: this.provider.name,
|
|
6834
|
+
category: "cli",
|
|
6835
|
+
status: adapterStatus.status,
|
|
6836
|
+
mode: this.settings.mode || "terminal",
|
|
6837
|
+
activeChat: {
|
|
6838
|
+
id: `${this.type}_${this.workingDir}`,
|
|
6839
|
+
title: `${this.provider.name} \xB7 ${dirName}`,
|
|
6840
|
+
status: adapterStatus.status,
|
|
6841
|
+
messages: recentMessages,
|
|
6842
|
+
activeModal: adapterStatus.activeModal,
|
|
6843
|
+
inputContent: ""
|
|
6844
|
+
},
|
|
6845
|
+
workingDir: this.workingDir,
|
|
6846
|
+
instanceId: `${this.type}_${require("crypto").createHash("md5").update(path8.resolve(this.workingDir)).digest("hex").slice(0, 8)}`,
|
|
6847
|
+
lastUpdated: Date.now(),
|
|
6848
|
+
settings: this.settings,
|
|
6849
|
+
pendingEvents: this.flushEvents()
|
|
6850
|
+
};
|
|
6851
|
+
}
|
|
6852
|
+
onEvent(event, data) {
|
|
6853
|
+
if (event === "send_message" && data?.text) {
|
|
6854
|
+
this.adapter.sendMessage(data.text);
|
|
6855
|
+
} else if (event === "bridge_connected" && data?.bridge) {
|
|
6856
|
+
this.adapter.setBridge(data.bridge);
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
dispose() {
|
|
6860
|
+
this.adapter.shutdown();
|
|
6861
|
+
this.monitor.reset();
|
|
6862
|
+
}
|
|
6863
|
+
// ─── 상태 전이 감지 (daemon-status.ts에서 이동) ──────
|
|
6864
|
+
detectStatusTransition() {
|
|
6865
|
+
const now = Date.now();
|
|
6866
|
+
const adapterStatus = this.adapter.getStatus();
|
|
6867
|
+
const newStatus = adapterStatus.status;
|
|
6868
|
+
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
6869
|
+
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
6870
|
+
if (newStatus !== this.lastStatus) {
|
|
6871
|
+
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
6872
|
+
this.generatingStartedAt = now;
|
|
6873
|
+
this.pushEvent({ event: "agent:generating_started", chatTitle, timestamp: now });
|
|
6874
|
+
} else if (newStatus === "waiting_approval") {
|
|
6875
|
+
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
6876
|
+
this.pushEvent({
|
|
6877
|
+
event: "agent:waiting_approval",
|
|
6878
|
+
chatTitle,
|
|
6879
|
+
timestamp: now,
|
|
6880
|
+
modalMessage: adapterStatus.activeModal?.message
|
|
6881
|
+
});
|
|
6882
|
+
} else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
|
|
6883
|
+
const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
6884
|
+
this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now });
|
|
6885
|
+
this.generatingStartedAt = 0;
|
|
6886
|
+
} else if (newStatus === "stopped") {
|
|
6887
|
+
this.pushEvent({ event: "agent:stopped", chatTitle, timestamp: now });
|
|
6888
|
+
}
|
|
6889
|
+
this.lastStatus = newStatus;
|
|
6890
|
+
}
|
|
6891
|
+
const agentKey = `${this.type}:cli`;
|
|
6892
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now);
|
|
6893
|
+
for (const me of monitorEvents) {
|
|
6894
|
+
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
6895
|
+
}
|
|
6896
|
+
}
|
|
6897
|
+
pushEvent(event) {
|
|
6898
|
+
this.events.push(event);
|
|
6899
|
+
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
6900
|
+
}
|
|
6901
|
+
flushEvents() {
|
|
6902
|
+
const events = [...this.events];
|
|
6903
|
+
this.events = [];
|
|
6904
|
+
return events;
|
|
6905
|
+
}
|
|
6906
|
+
// ─── Adapter 접근 (하위 호환) ──────────────────
|
|
6907
|
+
getAdapter() {
|
|
6908
|
+
return this.adapter;
|
|
6909
|
+
}
|
|
6910
|
+
get cliType() {
|
|
6911
|
+
return this.type;
|
|
6912
|
+
}
|
|
6913
|
+
get cliName() {
|
|
6914
|
+
return this.provider.name;
|
|
6915
|
+
}
|
|
6916
|
+
};
|
|
6917
|
+
}
|
|
6918
|
+
});
|
|
6919
|
+
|
|
6920
|
+
// src/daemon-cli.ts
|
|
6921
|
+
var os10, path9, import_chalk, DaemonCliManager;
|
|
6922
|
+
var init_daemon_cli = __esm({
|
|
6923
|
+
"src/daemon-cli.ts"() {
|
|
6924
|
+
"use strict";
|
|
6925
|
+
os10 = __toESM(require("os"));
|
|
6926
|
+
path9 = __toESM(require("path"));
|
|
6157
6927
|
import_chalk = __toESM(require("chalk"));
|
|
6158
6928
|
init_provider_cli_adapter();
|
|
6159
6929
|
init_cli_detector();
|
|
6160
6930
|
init_config();
|
|
6931
|
+
init_cli_provider_instance();
|
|
6161
6932
|
DaemonCliManager = class {
|
|
6162
6933
|
adapters = /* @__PURE__ */ new Map();
|
|
6163
6934
|
deps;
|
|
@@ -6191,8 +6962,8 @@ var init_daemon_cli = __esm({
|
|
|
6191
6962
|
}
|
|
6192
6963
|
// ─── 세션 시작/중지 ──────────────────────────────
|
|
6193
6964
|
async startSession(cliType, workingDir, cliArgs) {
|
|
6194
|
-
const trimmed = (workingDir ||
|
|
6195
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/,
|
|
6965
|
+
const trimmed = (workingDir || os10.homedir()).trim();
|
|
6966
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
|
|
6196
6967
|
const cliInfo = await detectCLI(cliType);
|
|
6197
6968
|
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
6198
6969
|
const key = this.getCliKey(cliType, resolvedDir);
|
|
@@ -6200,34 +6971,57 @@ var init_daemon_cli = __esm({
|
|
|
6200
6971
|
console.log(import_chalk.default.yellow(` \u26A1 CLI ${cliType} already running in ${resolvedDir}`));
|
|
6201
6972
|
return;
|
|
6202
6973
|
}
|
|
6974
|
+
const typeMap = {
|
|
6975
|
+
"claude-code": "claude-cli",
|
|
6976
|
+
"codex": "codex-cli"
|
|
6977
|
+
};
|
|
6978
|
+
const normalizedType = typeMap[cliType] || cliType;
|
|
6979
|
+
const provider2 = this.providerLoader.get(normalizedType);
|
|
6203
6980
|
console.log(import_chalk.default.yellow(` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
const bridge = this.deps.getBridge();
|
|
6207
|
-
if (bridge && typeof adapter.setBridge === "function") {
|
|
6208
|
-
adapter.setBridge(bridge);
|
|
6981
|
+
if (provider2) {
|
|
6982
|
+
console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider2.name} (${provider2.type})`));
|
|
6209
6983
|
}
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
const
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6984
|
+
const instanceManager = this.deps.getInstanceManager();
|
|
6985
|
+
if (provider2 && instanceManager) {
|
|
6986
|
+
const cliInstance = new CliProviderInstance(provider2, resolvedDir, cliArgs);
|
|
6987
|
+
await instanceManager.addInstance(key, cliInstance, {
|
|
6988
|
+
bridge: this.deps.getBridge(),
|
|
6989
|
+
settings: {},
|
|
6990
|
+
onPtyData: (data) => {
|
|
6991
|
+
this.deps.getP2p()?.broadcastPtyOutput(key, data);
|
|
6992
|
+
}
|
|
6993
|
+
});
|
|
6994
|
+
this.adapters.set(key, cliInstance.getAdapter());
|
|
6995
|
+
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6996
|
+
} else {
|
|
6997
|
+
const adapter = this.createAdapter(cliType, resolvedDir, cliArgs);
|
|
6998
|
+
await adapter.spawn();
|
|
6999
|
+
const bridge = this.deps.getBridge();
|
|
7000
|
+
if (bridge && typeof adapter.setBridge === "function") {
|
|
7001
|
+
adapter.setBridge(bridge);
|
|
7002
|
+
}
|
|
7003
|
+
adapter.setOnStatusChange(() => {
|
|
7004
|
+
this.deps.onStatusChange();
|
|
7005
|
+
const status = adapter.getStatus?.();
|
|
7006
|
+
if (status?.status === "stopped") {
|
|
7007
|
+
setTimeout(() => {
|
|
7008
|
+
if (this.adapters.get(key) === adapter) {
|
|
7009
|
+
this.adapters.delete(key);
|
|
7010
|
+
this.deps.removeAgentTracking(key);
|
|
7011
|
+
console.log(import_chalk.default.yellow(` \u{1F9F9} Auto-cleaned stopped CLI: ${adapter.cliType}`));
|
|
7012
|
+
this.deps.onStatusChange();
|
|
7013
|
+
}
|
|
7014
|
+
}, 3e3);
|
|
7015
|
+
}
|
|
6227
7016
|
});
|
|
7017
|
+
if (typeof adapter.setOnPtyData === "function") {
|
|
7018
|
+
adapter.setOnPtyData((data) => {
|
|
7019
|
+
this.deps.getP2p()?.broadcastPtyOutput(key, data);
|
|
7020
|
+
});
|
|
7021
|
+
}
|
|
7022
|
+
this.adapters.set(key, adapter);
|
|
7023
|
+
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6228
7024
|
}
|
|
6229
|
-
this.adapters.set(key, adapter);
|
|
6230
|
-
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6231
7025
|
try {
|
|
6232
7026
|
addCliHistory({ cliType, dir: resolvedDir, cliArgs });
|
|
6233
7027
|
} catch (e) {
|
|
@@ -6241,6 +7035,7 @@ var init_daemon_cli = __esm({
|
|
|
6241
7035
|
adapter.shutdown();
|
|
6242
7036
|
this.adapters.delete(key);
|
|
6243
7037
|
this.deps.removeAgentTracking(key);
|
|
7038
|
+
this.deps.getInstanceManager()?.removeInstance(key);
|
|
6244
7039
|
console.log(import_chalk.default.yellow(` \u{1F6D1} CLI Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`));
|
|
6245
7040
|
this.deps.onStatusChange();
|
|
6246
7041
|
}
|
|
@@ -6268,7 +7063,8 @@ var init_daemon_cli = __esm({
|
|
|
6268
7063
|
switch (cmd) {
|
|
6269
7064
|
case "launch_cli": {
|
|
6270
7065
|
const cliType = args?.cliType;
|
|
6271
|
-
const
|
|
7066
|
+
const defaultedToHome = !args?.dir;
|
|
7067
|
+
const dir = args?.dir || os10.homedir();
|
|
6272
7068
|
if (!cliType) throw new Error("cliType required");
|
|
6273
7069
|
const key = this.getCliKey(cliType, dir);
|
|
6274
7070
|
if (!this.adapters.has(key)) {
|
|
@@ -6286,7 +7082,7 @@ var init_daemon_cli = __esm({
|
|
|
6286
7082
|
console.error(import_chalk.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
6287
7083
|
}
|
|
6288
7084
|
}
|
|
6289
|
-
return { success: true, cliType, dir, id: key };
|
|
7085
|
+
return { success: true, cliType, dir, id: key, defaultedToHome };
|
|
6290
7086
|
}
|
|
6291
7087
|
case "stop_cli": {
|
|
6292
7088
|
const cliType = args?.cliType;
|
|
@@ -6490,99 +7286,6 @@ var init_provider_instance_manager = __esm({
|
|
|
6490
7286
|
}
|
|
6491
7287
|
});
|
|
6492
7288
|
|
|
6493
|
-
// src/providers/status-monitor.ts
|
|
6494
|
-
var DEFAULT_MONITOR_CONFIG, StatusMonitor;
|
|
6495
|
-
var init_status_monitor = __esm({
|
|
6496
|
-
"src/providers/status-monitor.ts"() {
|
|
6497
|
-
"use strict";
|
|
6498
|
-
DEFAULT_MONITOR_CONFIG = {
|
|
6499
|
-
approvalAlert: true,
|
|
6500
|
-
longGeneratingAlert: true,
|
|
6501
|
-
longGeneratingThresholdSec: 180,
|
|
6502
|
-
// 3분
|
|
6503
|
-
alertCooldownSec: 60
|
|
6504
|
-
// 1분 쿨다운
|
|
6505
|
-
};
|
|
6506
|
-
StatusMonitor = class {
|
|
6507
|
-
config;
|
|
6508
|
-
lastAlertTime = /* @__PURE__ */ new Map();
|
|
6509
|
-
generatingStartTimes = /* @__PURE__ */ new Map();
|
|
6510
|
-
constructor(config) {
|
|
6511
|
-
this.config = { ...DEFAULT_MONITOR_CONFIG, ...config };
|
|
6512
|
-
}
|
|
6513
|
-
/** 설정 업데이트 (Provider Settings에서 호출) */
|
|
6514
|
-
updateConfig(partial) {
|
|
6515
|
-
Object.assign(this.config, partial);
|
|
6516
|
-
}
|
|
6517
|
-
/** 현재 설정 반환 */
|
|
6518
|
-
getConfig() {
|
|
6519
|
-
return { ...this.config };
|
|
6520
|
-
}
|
|
6521
|
-
/**
|
|
6522
|
-
* 상태 전이 체크 → 알림 이벤트 배열 반환
|
|
6523
|
-
* 각 onTick()에서 호출.
|
|
6524
|
-
*/
|
|
6525
|
-
check(agentKey, status, now) {
|
|
6526
|
-
const events = [];
|
|
6527
|
-
if (this.config.approvalAlert && status === "waiting_approval") {
|
|
6528
|
-
if (this.shouldAlert(agentKey + ":approval", now)) {
|
|
6529
|
-
events.push({
|
|
6530
|
-
type: "monitor:approval_waiting",
|
|
6531
|
-
agentKey,
|
|
6532
|
-
timestamp: now,
|
|
6533
|
-
message: `${agentKey} is waiting for approval`
|
|
6534
|
-
});
|
|
6535
|
-
}
|
|
6536
|
-
}
|
|
6537
|
-
if (status === "generating" || status === "streaming") {
|
|
6538
|
-
if (!this.generatingStartTimes.has(agentKey)) {
|
|
6539
|
-
this.generatingStartTimes.set(agentKey, now);
|
|
6540
|
-
}
|
|
6541
|
-
if (this.config.longGeneratingAlert) {
|
|
6542
|
-
const startedAt = this.generatingStartTimes.get(agentKey);
|
|
6543
|
-
const elapsedSec = Math.round((now - startedAt) / 1e3);
|
|
6544
|
-
if (elapsedSec > this.config.longGeneratingThresholdSec) {
|
|
6545
|
-
if (this.shouldAlert(agentKey + ":long_gen", now)) {
|
|
6546
|
-
events.push({
|
|
6547
|
-
type: "monitor:long_generating",
|
|
6548
|
-
agentKey,
|
|
6549
|
-
elapsedSec,
|
|
6550
|
-
timestamp: now,
|
|
6551
|
-
message: `${agentKey} has been generating for ${Math.round(elapsedSec / 60)}min`
|
|
6552
|
-
});
|
|
6553
|
-
}
|
|
6554
|
-
}
|
|
6555
|
-
}
|
|
6556
|
-
} else {
|
|
6557
|
-
this.generatingStartTimes.delete(agentKey);
|
|
6558
|
-
}
|
|
6559
|
-
return events;
|
|
6560
|
-
}
|
|
6561
|
-
/** 쿨다운 체크 — 같은 알림을 너무 자주 보내지 않도록 */
|
|
6562
|
-
shouldAlert(key, now) {
|
|
6563
|
-
const last = this.lastAlertTime.get(key) || 0;
|
|
6564
|
-
if (now - last > this.config.alertCooldownSec * 1e3) {
|
|
6565
|
-
this.lastAlertTime.set(key, now);
|
|
6566
|
-
return true;
|
|
6567
|
-
}
|
|
6568
|
-
return false;
|
|
6569
|
-
}
|
|
6570
|
-
/** 리셋 (에이전트 종료/재시작 시) */
|
|
6571
|
-
reset(agentKey) {
|
|
6572
|
-
if (agentKey) {
|
|
6573
|
-
this.generatingStartTimes.delete(agentKey);
|
|
6574
|
-
for (const k of this.lastAlertTime.keys()) {
|
|
6575
|
-
if (k.startsWith(agentKey)) this.lastAlertTime.delete(k);
|
|
6576
|
-
}
|
|
6577
|
-
} else {
|
|
6578
|
-
this.generatingStartTimes.clear();
|
|
6579
|
-
this.lastAlertTime.clear();
|
|
6580
|
-
}
|
|
6581
|
-
}
|
|
6582
|
-
};
|
|
6583
|
-
}
|
|
6584
|
-
});
|
|
6585
|
-
|
|
6586
7289
|
// src/providers/extension-provider-instance.ts
|
|
6587
7290
|
var ExtensionProviderInstance;
|
|
6588
7291
|
var init_extension_provider_instance = __esm({
|
|
@@ -6705,11 +7408,11 @@ var init_extension_provider_instance = __esm({
|
|
|
6705
7408
|
});
|
|
6706
7409
|
|
|
6707
7410
|
// src/providers/ide-provider-instance.ts
|
|
6708
|
-
var
|
|
7411
|
+
var os11, crypto, IdeProviderInstance;
|
|
6709
7412
|
var init_ide_provider_instance = __esm({
|
|
6710
7413
|
"src/providers/ide-provider-instance.ts"() {
|
|
6711
7414
|
"use strict";
|
|
6712
|
-
|
|
7415
|
+
os11 = __toESM(require("os"));
|
|
6713
7416
|
crypto = __toESM(require("crypto"));
|
|
6714
7417
|
init_extension_provider_instance();
|
|
6715
7418
|
init_status_monitor();
|
|
@@ -6735,10 +7438,10 @@ var init_ide_provider_instance = __esm({
|
|
|
6735
7438
|
activeFile = null;
|
|
6736
7439
|
// ─── 자식 Extension Instances ────────────────────
|
|
6737
7440
|
extensions = /* @__PURE__ */ new Map();
|
|
6738
|
-
constructor(provider2) {
|
|
7441
|
+
constructor(provider2, instanceKey) {
|
|
6739
7442
|
this.type = provider2.type;
|
|
6740
7443
|
this.provider = provider2;
|
|
6741
|
-
this.instanceId = `${provider2.type}_${crypto.createHash("md5").update(
|
|
7444
|
+
this.instanceId = instanceKey ? `${instanceKey}_${crypto.createHash("md5").update(os11.hostname() + instanceKey).digest("hex").slice(0, 8)}` : `${provider2.type}_${crypto.createHash("md5").update(os11.hostname() + provider2.type).digest("hex").slice(0, 8)}`;
|
|
6742
7445
|
this.monitor = new StatusMonitor();
|
|
6743
7446
|
}
|
|
6744
7447
|
// ─── Lifecycle ─────────────────────────────────
|
|
@@ -6869,7 +7572,14 @@ var init_ide_provider_instance = __esm({
|
|
|
6869
7572
|
const readChatScript = this.getReadChatScript();
|
|
6870
7573
|
if (!readChatScript) return;
|
|
6871
7574
|
try {
|
|
6872
|
-
|
|
7575
|
+
let raw = await cdp2.evaluate(readChatScript, 3e4);
|
|
7576
|
+
if (typeof raw === "string") {
|
|
7577
|
+
try {
|
|
7578
|
+
raw = JSON.parse(raw);
|
|
7579
|
+
} catch {
|
|
7580
|
+
return;
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
6873
7583
|
if (!raw || typeof raw !== "object") return;
|
|
6874
7584
|
let { activeModal } = raw;
|
|
6875
7585
|
if (activeModal) {
|
|
@@ -6962,107 +7672,6 @@ var init_ide_provider_instance = __esm({
|
|
|
6962
7672
|
}
|
|
6963
7673
|
});
|
|
6964
7674
|
|
|
6965
|
-
// src/daemon-logger.ts
|
|
6966
|
-
var daemon_logger_exports = {};
|
|
6967
|
-
__export(daemon_logger_exports, {
|
|
6968
|
-
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
6969
|
-
LOG_PATH: () => LOG_PATH,
|
|
6970
|
-
cdpLogFn: () => cdpLogFn,
|
|
6971
|
-
daemonLog: () => daemonLog,
|
|
6972
|
-
installGlobalInterceptor: () => installGlobalInterceptor
|
|
6973
|
-
});
|
|
6974
|
-
function rotateIfNeeded() {
|
|
6975
|
-
try {
|
|
6976
|
-
const stat = fs5.statSync(LOG_FILE);
|
|
6977
|
-
if (stat.size > MAX_LOG_SIZE) {
|
|
6978
|
-
const backup = LOG_FILE + ".old";
|
|
6979
|
-
try {
|
|
6980
|
-
fs5.unlinkSync(backup);
|
|
6981
|
-
} catch {
|
|
6982
|
-
}
|
|
6983
|
-
fs5.renameSync(LOG_FILE, backup);
|
|
6984
|
-
}
|
|
6985
|
-
} catch {
|
|
6986
|
-
}
|
|
6987
|
-
}
|
|
6988
|
-
function writeToFile(line) {
|
|
6989
|
-
try {
|
|
6990
|
-
fs5.appendFileSync(LOG_FILE, line + "\n");
|
|
6991
|
-
} catch {
|
|
6992
|
-
}
|
|
6993
|
-
}
|
|
6994
|
-
function daemonLog(category, msg) {
|
|
6995
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${category}] ${msg}`;
|
|
6996
|
-
origConsoleLog(line);
|
|
6997
|
-
writeToFile(line);
|
|
6998
|
-
}
|
|
6999
|
-
function cdpLogFn(ideType) {
|
|
7000
|
-
return (msg) => {
|
|
7001
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [CDP:${ideType}] ${msg}`;
|
|
7002
|
-
origConsoleLog(line);
|
|
7003
|
-
writeToFile(line);
|
|
7004
|
-
};
|
|
7005
|
-
}
|
|
7006
|
-
function installGlobalInterceptor() {
|
|
7007
|
-
if (interceptorInstalled) return;
|
|
7008
|
-
interceptorInstalled = true;
|
|
7009
|
-
const stripAnsi2 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
7010
|
-
console.log = (...args) => {
|
|
7011
|
-
origConsoleLog(...args);
|
|
7012
|
-
try {
|
|
7013
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
7014
|
-
const clean = stripAnsi2(msg);
|
|
7015
|
-
const line = clean.startsWith("[20") ? clean : `[${(/* @__PURE__ */ new Date()).toISOString()}] ${clean}`;
|
|
7016
|
-
writeToFile(line);
|
|
7017
|
-
} catch {
|
|
7018
|
-
}
|
|
7019
|
-
};
|
|
7020
|
-
console.error = (...args) => {
|
|
7021
|
-
origConsoleError(...args);
|
|
7022
|
-
try {
|
|
7023
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
7024
|
-
const clean = stripAnsi2(msg);
|
|
7025
|
-
writeToFile(`[${(/* @__PURE__ */ new Date()).toISOString()}] [ERROR] ${clean}`);
|
|
7026
|
-
} catch {
|
|
7027
|
-
}
|
|
7028
|
-
};
|
|
7029
|
-
console.warn = (...args) => {
|
|
7030
|
-
origConsoleWarn(...args);
|
|
7031
|
-
try {
|
|
7032
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
7033
|
-
const clean = stripAnsi2(msg);
|
|
7034
|
-
writeToFile(`[${(/* @__PURE__ */ new Date()).toISOString()}] [WARN] ${clean}`);
|
|
7035
|
-
} catch {
|
|
7036
|
-
}
|
|
7037
|
-
};
|
|
7038
|
-
writeToFile(`
|
|
7039
|
-
=== ADHDev Daemon started at ${(/* @__PURE__ */ new Date()).toISOString()} ===`);
|
|
7040
|
-
writeToFile(`Log file: ${LOG_FILE}`);
|
|
7041
|
-
}
|
|
7042
|
-
var fs5, path8, os11, LOG_DIR, LOG_FILE, MAX_LOG_SIZE, origConsoleLog, origConsoleError, origConsoleWarn, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
|
|
7043
|
-
var init_daemon_logger = __esm({
|
|
7044
|
-
"src/daemon-logger.ts"() {
|
|
7045
|
-
"use strict";
|
|
7046
|
-
fs5 = __toESM(require("fs"));
|
|
7047
|
-
path8 = __toESM(require("path"));
|
|
7048
|
-
os11 = __toESM(require("os"));
|
|
7049
|
-
LOG_DIR = process.platform === "darwin" ? path8.join(os11.homedir(), "Library", "Logs", "adhdev") : path8.join(os11.homedir(), ".local", "share", "adhdev", "logs");
|
|
7050
|
-
LOG_FILE = path8.join(LOG_DIR, "daemon.log");
|
|
7051
|
-
MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
7052
|
-
try {
|
|
7053
|
-
fs5.mkdirSync(LOG_DIR, { recursive: true });
|
|
7054
|
-
} catch {
|
|
7055
|
-
}
|
|
7056
|
-
rotateIfNeeded();
|
|
7057
|
-
origConsoleLog = console.log.bind(console);
|
|
7058
|
-
origConsoleError = console.error.bind(console);
|
|
7059
|
-
origConsoleWarn = console.warn.bind(console);
|
|
7060
|
-
interceptorInstalled = false;
|
|
7061
|
-
LOG_PATH = LOG_FILE;
|
|
7062
|
-
LOG_DIR_PATH = LOG_DIR;
|
|
7063
|
-
}
|
|
7064
|
-
});
|
|
7065
|
-
|
|
7066
7675
|
// src/adhdev-daemon.ts
|
|
7067
7676
|
var adhdev_daemon_exports = {};
|
|
7068
7677
|
__export(adhdev_daemon_exports, {
|
|
@@ -7071,9 +7680,9 @@ __export(adhdev_daemon_exports, {
|
|
|
7071
7680
|
stopDaemon: () => stopDaemon
|
|
7072
7681
|
});
|
|
7073
7682
|
function getDaemonPidFile() {
|
|
7074
|
-
const dir =
|
|
7683
|
+
const dir = path10.join(os12.homedir(), ".adhdev");
|
|
7075
7684
|
if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
|
|
7076
|
-
return
|
|
7685
|
+
return path10.join(dir, "daemon.pid");
|
|
7077
7686
|
}
|
|
7078
7687
|
function writeDaemonPid(pid) {
|
|
7079
7688
|
fs6.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
@@ -7109,7 +7718,7 @@ function stopDaemon() {
|
|
|
7109
7718
|
return false;
|
|
7110
7719
|
}
|
|
7111
7720
|
}
|
|
7112
|
-
var os12, fs6,
|
|
7721
|
+
var os12, fs6, path10, crypto2, import_chalk2, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
7113
7722
|
var init_adhdev_daemon = __esm({
|
|
7114
7723
|
"src/adhdev-daemon.ts"() {
|
|
7115
7724
|
"use strict";
|
|
@@ -7129,9 +7738,10 @@ var init_adhdev_daemon = __esm({
|
|
|
7129
7738
|
init_provider_instance_manager();
|
|
7130
7739
|
init_ide_provider_instance();
|
|
7131
7740
|
init_ipc_protocol();
|
|
7741
|
+
init_daemon_logger();
|
|
7132
7742
|
os12 = __toESM(require("os"));
|
|
7133
7743
|
fs6 = __toESM(require("fs"));
|
|
7134
|
-
|
|
7744
|
+
path10 = __toESM(require("path"));
|
|
7135
7745
|
crypto2 = __toESM(require("crypto"));
|
|
7136
7746
|
import_chalk2 = __toESM(require("chalk"));
|
|
7137
7747
|
DANGEROUS_PATTERNS = [
|
|
@@ -7173,7 +7783,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7173
7783
|
getBridge: () => this.bridge,
|
|
7174
7784
|
getP2p: () => this.p2p,
|
|
7175
7785
|
onStatusChange: () => this.statusReporter?.onStatusChange(),
|
|
7176
|
-
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key)
|
|
7786
|
+
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
7787
|
+
getInstanceManager: () => this.instanceManager
|
|
7177
7788
|
}, this.providerLoader);
|
|
7178
7789
|
}
|
|
7179
7790
|
async start(options = {}) {
|
|
@@ -7328,8 +7939,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7328
7939
|
});
|
|
7329
7940
|
this.p2p.onStateChange((state) => {
|
|
7330
7941
|
if (state === "connected") {
|
|
7331
|
-
|
|
7332
|
-
this.statusReporter?.sendUnifiedStatusReport().catch((e) =>
|
|
7942
|
+
LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
|
|
7943
|
+
this.statusReporter?.sendUnifiedStatusReport().catch((e) => LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
|
|
7333
7944
|
}
|
|
7334
7945
|
});
|
|
7335
7946
|
let ssDebugCount = 0;
|
|
@@ -7340,18 +7951,18 @@ var init_adhdev_daemon = __esm({
|
|
|
7340
7951
|
if (!active || !cdp2) return;
|
|
7341
7952
|
ssDebugCount++;
|
|
7342
7953
|
if (ssDebugCount <= 3 || ssDebugCount % 25 === 0) {
|
|
7343
|
-
|
|
7954
|
+
LOG.debug("Screenshot", `Capturing... (tick ${ssDebugCount}, active=${active}, cdp=true)`);
|
|
7344
7955
|
}
|
|
7345
7956
|
try {
|
|
7346
7957
|
const buf = await cdp2.captureScreenshot();
|
|
7347
7958
|
if (buf) {
|
|
7348
7959
|
const sent = this.p2p.sendScreenshot(buf.toString("base64"));
|
|
7349
|
-
if (ssDebugCount <= 3)
|
|
7960
|
+
if (ssDebugCount <= 3) LOG.debug("Screenshot", `sent: ${buf.length} bytes, delivered=${sent}`);
|
|
7350
7961
|
} else {
|
|
7351
|
-
if (ssDebugCount <= 5)
|
|
7962
|
+
if (ssDebugCount <= 5) LOG.debug("Screenshot", "captureScreenshot returned null");
|
|
7352
7963
|
}
|
|
7353
7964
|
} catch (e) {
|
|
7354
|
-
if (ssDebugCount <= 5)
|
|
7965
|
+
if (ssDebugCount <= 5) LOG.warn("Screenshot", `error: ${e?.message}`);
|
|
7355
7966
|
}
|
|
7356
7967
|
}, 200);
|
|
7357
7968
|
} else {
|
|
@@ -7494,10 +8105,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7494
8105
|
}
|
|
7495
8106
|
}
|
|
7496
8107
|
async handleCommand(msg, cmd, args) {
|
|
7497
|
-
|
|
7498
|
-
if (cmd.startsWith("agent_stream") && args?._targetInstance) {
|
|
7499
|
-
console.log(import_chalk2.default.yellow(` \u{1F3AF} Target: ${args._targetType}:${args._targetInstance.split("_")[0]} agent=${args.agentType || ""}`));
|
|
7500
|
-
}
|
|
8108
|
+
LOG.info("Command", `${cmd}${args?._targetInstance ? ` \u2192 ${args._targetType}:${args._targetInstance.split("_")[0]}` : ""}`);
|
|
7501
8109
|
try {
|
|
7502
8110
|
switch (cmd) {
|
|
7503
8111
|
case "open_panel":
|
|
@@ -7569,17 +8177,22 @@ var init_adhdev_daemon = __esm({
|
|
|
7569
8177
|
return { success: true, nickname };
|
|
7570
8178
|
}
|
|
7571
8179
|
case "get_daemon_logs": {
|
|
7572
|
-
const
|
|
8180
|
+
const count = parseInt(data.lines) || 100;
|
|
8181
|
+
const minLevel = data.minLevel || "info";
|
|
7573
8182
|
try {
|
|
7574
|
-
const
|
|
8183
|
+
const { getRecentLogs: getRecentLogs2, LOG_PATH: LOG_PATH2 } = (init_daemon_logger(), __toCommonJS(daemon_logger_exports));
|
|
8184
|
+
const entries = getRecentLogs2(count, minLevel);
|
|
8185
|
+
if (entries.length > 0) {
|
|
8186
|
+
return { success: true, entries, totalBuffered: entries.length };
|
|
8187
|
+
}
|
|
7575
8188
|
const logFs = require("fs");
|
|
7576
|
-
if (logFs.existsSync(
|
|
7577
|
-
const content = logFs.readFileSync(
|
|
8189
|
+
if (logFs.existsSync(LOG_PATH2)) {
|
|
8190
|
+
const content = logFs.readFileSync(LOG_PATH2, "utf-8");
|
|
7578
8191
|
const allLines = content.split("\n");
|
|
7579
|
-
const recent = allLines.slice(-
|
|
8192
|
+
const recent = allLines.slice(-count).join("\n");
|
|
7580
8193
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
7581
8194
|
}
|
|
7582
|
-
return { success: true,
|
|
8195
|
+
return { success: true, entries: [], totalBuffered: 0 };
|
|
7583
8196
|
} catch (e) {
|
|
7584
8197
|
return { success: false, error: e.message };
|
|
7585
8198
|
}
|
|
@@ -7612,7 +8225,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7612
8225
|
case "launch_ide": {
|
|
7613
8226
|
const launchArgs = { ...args, ideId: args?.ideId || args?.ideType };
|
|
7614
8227
|
const ideKey = launchArgs.ideId;
|
|
7615
|
-
|
|
8228
|
+
LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
7616
8229
|
const result = await launchWithCdp(launchArgs);
|
|
7617
8230
|
if (result.success && result.port && result.ideId && !this.cdpManagers.has(result.ideId)) {
|
|
7618
8231
|
console.log(import_chalk2.default.cyan(`[launch_ide] Connecting CDP for ${result.ideId} on port ${result.port}...`));
|
|
@@ -7621,6 +8234,12 @@ var init_adhdev_daemon = __esm({
|
|
|
7621
8234
|
});
|
|
7622
8235
|
const connected = await manager.connect();
|
|
7623
8236
|
if (connected) {
|
|
8237
|
+
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(result.ideId).map((p) => ({
|
|
8238
|
+
agentType: p.type,
|
|
8239
|
+
extensionId: p.extensionId || "",
|
|
8240
|
+
extensionIdPattern: p.extensionIdPattern
|
|
8241
|
+
}));
|
|
8242
|
+
manager.setExtensionProviders(enabledExtProviders);
|
|
7624
8243
|
this.cdpManagers.set(result.ideId, manager);
|
|
7625
8244
|
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${result.ideId} (port ${result.port})`));
|
|
7626
8245
|
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
@@ -7702,6 +8321,37 @@ var init_adhdev_daemon = __esm({
|
|
|
7702
8321
|
if (this.agentStreamTimer) return;
|
|
7703
8322
|
this.agentStreamTimer = setInterval(async () => {
|
|
7704
8323
|
if (!this.agentStreamManager || this.cdpManagers.size === 0) return;
|
|
8324
|
+
for (const [ideType, cdp2] of this.cdpManagers) {
|
|
8325
|
+
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(ideType).map((p) => ({
|
|
8326
|
+
agentType: p.type,
|
|
8327
|
+
extensionId: p.extensionId || "",
|
|
8328
|
+
extensionIdPattern: p.extensionIdPattern
|
|
8329
|
+
}));
|
|
8330
|
+
cdp2.setExtensionProviders(enabledExtProviders);
|
|
8331
|
+
const ideInstance = this.instanceManager.getInstance(`ide:${ideType}`);
|
|
8332
|
+
if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
|
|
8333
|
+
const currentExtTypes = new Set(ideInstance.getExtensionTypes());
|
|
8334
|
+
const enabledExtTypes = new Set(
|
|
8335
|
+
this.providerLoader.getEnabledByCategory("extension", ideType).map((p) => p.type)
|
|
8336
|
+
);
|
|
8337
|
+
for (const extType of currentExtTypes) {
|
|
8338
|
+
if (!enabledExtTypes.has(extType)) {
|
|
8339
|
+
ideInstance.removeExtension(extType);
|
|
8340
|
+
LOG.info("AgentStream", `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
8341
|
+
}
|
|
8342
|
+
}
|
|
8343
|
+
for (const extType of enabledExtTypes) {
|
|
8344
|
+
if (!currentExtTypes.has(extType)) {
|
|
8345
|
+
const extProvider = this.providerLoader.get(extType);
|
|
8346
|
+
if (extProvider) {
|
|
8347
|
+
const extSettings = this.providerLoader.getSettings(extType);
|
|
8348
|
+
ideInstance.addExtension(extProvider, extSettings);
|
|
8349
|
+
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
}
|
|
8353
|
+
}
|
|
8354
|
+
}
|
|
7705
8355
|
if (this._agentStreamCdpIdeType) {
|
|
7706
8356
|
const cdp2 = this.cdpManagers.get(this._agentStreamCdpIdeType);
|
|
7707
8357
|
if (cdp2?.isConnected) {
|
|
@@ -7723,7 +8373,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7723
8373
|
if (discovered.length > 0) {
|
|
7724
8374
|
this._agentStreamCdpIdeType = ideType;
|
|
7725
8375
|
await this.agentStreamManager.switchActiveAgent(cdp2, discovered[0].agentType);
|
|
7726
|
-
|
|
8376
|
+
LOG.info("AgentStream", `Auto-activated: ${discovered[0].agentType} (${ideType})`);
|
|
7727
8377
|
await this.agentStreamManager.syncAgentSessions(cdp2);
|
|
7728
8378
|
const streams = await this.agentStreamManager.collectAgentStreams(cdp2);
|
|
7729
8379
|
this.statusReporter?.updateAgentStreams(ideType, streams);
|
|
@@ -7735,6 +8385,39 @@ var init_adhdev_daemon = __esm({
|
|
|
7735
8385
|
}
|
|
7736
8386
|
}, 5e3);
|
|
7737
8387
|
}
|
|
8388
|
+
/**
|
|
8389
|
+
* CdpManager 초기화 공통 로직 — extension provider 등록, ideType 설정, ProviderInstance 생성
|
|
8390
|
+
* @param ideType provider 기반 IDE 타입 (e.g., 'antigravity', 'cursor')
|
|
8391
|
+
* @param manager 연결된 CdpManager
|
|
8392
|
+
*/
|
|
8393
|
+
setupCdpManager(ideType, manager) {
|
|
8394
|
+
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(ideType).map((p) => ({
|
|
8395
|
+
agentType: p.type,
|
|
8396
|
+
extensionId: p.extensionId || "",
|
|
8397
|
+
extensionIdPattern: p.extensionIdPattern
|
|
8398
|
+
}));
|
|
8399
|
+
manager.setExtensionProviders(enabledExtProviders);
|
|
8400
|
+
if (this.ideType === "unknown") {
|
|
8401
|
+
this.ideType = ideType;
|
|
8402
|
+
}
|
|
8403
|
+
const ideProvider = this.providerLoader.get(ideType);
|
|
8404
|
+
if (ideProvider) {
|
|
8405
|
+
const managerKey = [...this.cdpManagers.entries()].find(([, m]) => m === manager)?.[0] || ideType;
|
|
8406
|
+
const ideInstance = new IdeProviderInstance(ideProvider, managerKey !== ideType ? managerKey : void 0);
|
|
8407
|
+
const resolvedSettings = this.providerLoader.getSettings(ideType);
|
|
8408
|
+
this.instanceManager.addInstance(`ide:${managerKey}`, ideInstance, {
|
|
8409
|
+
cdp: manager,
|
|
8410
|
+
bridge: this.bridge || void 0,
|
|
8411
|
+
settings: resolvedSettings
|
|
8412
|
+
}).then(async () => {
|
|
8413
|
+
const extensionProviders = this.providerLoader.getEnabledByCategory("extension", ideType);
|
|
8414
|
+
for (const extProvider of extensionProviders) {
|
|
8415
|
+
const extSettings = this.providerLoader.getSettings(extProvider.type);
|
|
8416
|
+
await ideInstance.addExtension(extProvider, extSettings);
|
|
8417
|
+
}
|
|
8418
|
+
}).catch((e) => console.warn(`[Instance] Failed to init IDE instance ${managerKey}:`, e?.message));
|
|
8419
|
+
}
|
|
8420
|
+
}
|
|
7738
8421
|
async initCdp() {
|
|
7739
8422
|
const providerCdpMap = this.providerLoader.getCdpPortMap();
|
|
7740
8423
|
const cdpPortMap = {};
|
|
@@ -7755,49 +8438,87 @@ var init_adhdev_daemon = __esm({
|
|
|
7755
8438
|
const enabledIdes = loadConfig().enabledIdes || [];
|
|
7756
8439
|
const filteredPorts = enabledIdes.length > 0 ? portsToTry.filter((p) => enabledIdes.includes(p.ide)) : portsToTry;
|
|
7757
8440
|
for (const { port, ide } of filteredPorts) {
|
|
7758
|
-
const
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
const
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
this.ideType = actualIde;
|
|
8441
|
+
const allTargets = await DaemonCdpManager.listAllTargets(port);
|
|
8442
|
+
if (allTargets.length === 0) {
|
|
8443
|
+
const manager = new DaemonCdpManager(port, (msg) => {
|
|
8444
|
+
console.log(`[CDP:${ide}] ${msg}`);
|
|
8445
|
+
});
|
|
8446
|
+
const connected = await manager.connect();
|
|
8447
|
+
if (connected) {
|
|
8448
|
+
this.cdpManagers.set(ide, manager);
|
|
8449
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${ide} (port ${port})`));
|
|
8450
|
+
this.setupCdpManager(ide, manager);
|
|
7769
8451
|
}
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
8452
|
+
continue;
|
|
8453
|
+
}
|
|
8454
|
+
for (let i = 0; i < allTargets.length; i++) {
|
|
8455
|
+
const target = allTargets[i];
|
|
8456
|
+
let managerKey;
|
|
8457
|
+
if (allTargets.length === 1) {
|
|
8458
|
+
managerKey = ide;
|
|
8459
|
+
} else {
|
|
8460
|
+
const workspaceName = (target.title || "").split(" \u2014 ")[0].trim() || `window_${i}`;
|
|
8461
|
+
managerKey = `${ide}_${workspaceName}`;
|
|
8462
|
+
}
|
|
8463
|
+
if (this.cdpManagers.has(managerKey)) continue;
|
|
8464
|
+
const manager = new DaemonCdpManager(port, (msg) => {
|
|
8465
|
+
console.log(`[CDP:${managerKey}] ${msg}`);
|
|
8466
|
+
}, target.id);
|
|
8467
|
+
const connected = await manager.connect();
|
|
8468
|
+
if (connected) {
|
|
8469
|
+
this.cdpManagers.set(managerKey, manager);
|
|
8470
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${managerKey} (port ${port}, page "${target.title}")`));
|
|
8471
|
+
this.setupCdpManager(ide, manager);
|
|
7785
8472
|
}
|
|
7786
8473
|
}
|
|
7787
8474
|
}
|
|
7788
8475
|
if (this.cdpManagers.size > 0) {
|
|
7789
8476
|
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
7790
|
-
this.cdpDiscoveryTimer = setInterval(async () => {
|
|
7791
|
-
for (const m of this.cdpManagers.values()) {
|
|
7792
|
-
if (m.isConnected) {
|
|
7793
|
-
await m.discoverAgentWebviews();
|
|
7794
|
-
}
|
|
7795
|
-
}
|
|
7796
|
-
}, 3e4);
|
|
7797
8477
|
} else {
|
|
7798
8478
|
console.log(import_chalk2.default.yellow(` \u26A0 CDP not available \u2014 tried ports: ${portsToTry.map((p) => `${p.ide}:${p.port}`).join(", ")}`));
|
|
7799
8479
|
console.log(import_chalk2.default.yellow(` IDE may need relaunch with --remote-debugging-port`));
|
|
7800
8480
|
}
|
|
8481
|
+
this.cdpDiscoveryTimer = setInterval(async () => {
|
|
8482
|
+
for (const m of this.cdpManagers.values()) {
|
|
8483
|
+
if (m.isConnected) {
|
|
8484
|
+
await m.discoverAgentWebviews();
|
|
8485
|
+
}
|
|
8486
|
+
}
|
|
8487
|
+
}, 3e4);
|
|
8488
|
+
setInterval(async () => {
|
|
8489
|
+
const portMap = this.providerLoader.getCdpPortMap();
|
|
8490
|
+
for (const [ide, ports] of Object.entries(portMap)) {
|
|
8491
|
+
const primaryPort = ports[0];
|
|
8492
|
+
const alreadyConnected = [...this.cdpManagers.entries()].some(
|
|
8493
|
+
([key, m]) => m.isConnected && (key === ide || key.startsWith(ide + "_"))
|
|
8494
|
+
);
|
|
8495
|
+
if (alreadyConnected) continue;
|
|
8496
|
+
const targets = await DaemonCdpManager.listAllTargets(primaryPort);
|
|
8497
|
+
if (targets.length === 0) continue;
|
|
8498
|
+
console.log(import_chalk2.default.cyan(`[CDP-Scan] Found ${targets.length} page(s) on ${ide}:${primaryPort}`));
|
|
8499
|
+
for (let i = 0; i < targets.length; i++) {
|
|
8500
|
+
const target = targets[i];
|
|
8501
|
+
let managerKey;
|
|
8502
|
+
if (targets.length === 1) {
|
|
8503
|
+
managerKey = ide;
|
|
8504
|
+
} else {
|
|
8505
|
+
const workspaceName = (target.title || "").split(" \u2014 ")[0].trim() || `window_${i}`;
|
|
8506
|
+
managerKey = `${ide}_${workspaceName}`;
|
|
8507
|
+
}
|
|
8508
|
+
if (this.cdpManagers.has(managerKey)) continue;
|
|
8509
|
+
const manager = new DaemonCdpManager(primaryPort, (msg) => {
|
|
8510
|
+
console.log(`[CDP:${managerKey}] ${msg}`);
|
|
8511
|
+
}, target.id);
|
|
8512
|
+
const connected = await manager.connect();
|
|
8513
|
+
if (connected) {
|
|
8514
|
+
this.cdpManagers.set(managerKey, manager);
|
|
8515
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP auto-connected: ${managerKey} (port ${primaryPort}, page "${target.title}")`));
|
|
8516
|
+
this.setupCdpManager(ide, manager);
|
|
8517
|
+
this.startAgentStreamPolling();
|
|
8518
|
+
}
|
|
8519
|
+
}
|
|
8520
|
+
}
|
|
8521
|
+
}, 3e4);
|
|
7801
8522
|
}
|
|
7802
8523
|
};
|
|
7803
8524
|
}
|
|
@@ -7945,10 +8666,10 @@ async function installExtension(ide, extension) {
|
|
|
7945
8666
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
7946
8667
|
const fs7 = await import("fs");
|
|
7947
8668
|
fs7.writeFileSync(vsixPath, buffer);
|
|
7948
|
-
return new Promise((
|
|
8669
|
+
return new Promise((resolve6) => {
|
|
7949
8670
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
7950
8671
|
(0, import_child_process2.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
7951
|
-
|
|
8672
|
+
resolve6({
|
|
7952
8673
|
extensionId: extension.id,
|
|
7953
8674
|
marketplaceId: extension.marketplaceId,
|
|
7954
8675
|
success: !error,
|
|
@@ -7979,11 +8700,11 @@ async function installExtension(ide, extension) {
|
|
|
7979
8700
|
}
|
|
7980
8701
|
}
|
|
7981
8702
|
}
|
|
7982
|
-
return new Promise((
|
|
8703
|
+
return new Promise((resolve6) => {
|
|
7983
8704
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
7984
8705
|
(0, import_child_process2.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
7985
8706
|
if (error) {
|
|
7986
|
-
|
|
8707
|
+
resolve6({
|
|
7987
8708
|
extensionId: extension.id,
|
|
7988
8709
|
marketplaceId: extension.marketplaceId,
|
|
7989
8710
|
success: false,
|
|
@@ -7991,7 +8712,7 @@ async function installExtension(ide, extension) {
|
|
|
7991
8712
|
error: stderr || error.message
|
|
7992
8713
|
});
|
|
7993
8714
|
} else {
|
|
7994
|
-
|
|
8715
|
+
resolve6({
|
|
7995
8716
|
extensionId: extension.id,
|
|
7996
8717
|
marketplaceId: extension.marketplaceId,
|
|
7997
8718
|
success: true,
|
|
@@ -8167,11 +8888,12 @@ async function quickSetup() {
|
|
|
8167
8888
|
console.log(` ${import_chalk3.default.bold("Status:")} ${import_chalk3.default.green("Ready to connect")}`);
|
|
8168
8889
|
console.log();
|
|
8169
8890
|
console.log(import_chalk3.default.gray(" Commands:"));
|
|
8170
|
-
console.log(import_chalk3.default.gray(" adhdev daemon \u2014 Start daemon (
|
|
8171
|
-
console.log(import_chalk3.default.gray(" adhdev launch
|
|
8172
|
-
console.log(import_chalk3.default.gray(" adhdev launch
|
|
8891
|
+
console.log(import_chalk3.default.gray(" adhdev daemon \u2014 Start the main daemon (required for all features)"));
|
|
8892
|
+
console.log(import_chalk3.default.gray(" adhdev launch <ide> \u2014 Launch an IDE with remote control (e.g. cursor)"));
|
|
8893
|
+
console.log(import_chalk3.default.gray(" adhdev launch <agent> \u2014 Start a CLI agent via daemon (e.g. gemini, claude)"));
|
|
8894
|
+
console.log(import_chalk3.default.gray(" adhdev cdp \u2014 Interactive CDP debug console"));
|
|
8173
8895
|
console.log(import_chalk3.default.gray(" adhdev status \u2014 Check setup status"));
|
|
8174
|
-
console.log(import_chalk3.default.gray(" adhdev setup \u2014 Reconfigure"));
|
|
8896
|
+
console.log(import_chalk3.default.gray(" adhdev setup \u2014 Reconfigure ADHDev"));
|
|
8175
8897
|
console.log();
|
|
8176
8898
|
await installCliOnly();
|
|
8177
8899
|
await startDaemonFlow();
|
|
@@ -8343,16 +9065,16 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
8343
9065
|
try {
|
|
8344
9066
|
const os13 = await import("os");
|
|
8345
9067
|
const fs7 = await import("fs");
|
|
8346
|
-
const
|
|
9068
|
+
const path11 = await import("path");
|
|
8347
9069
|
const platform7 = os13.platform();
|
|
8348
9070
|
const home = os13.homedir();
|
|
8349
9071
|
const getSettingsPath = (appName2) => {
|
|
8350
9072
|
if (platform7 === "darwin") {
|
|
8351
|
-
return
|
|
9073
|
+
return path11.join(home, "Library", "Application Support", appName2, "User", "settings.json");
|
|
8352
9074
|
} else if (platform7 === "win32") {
|
|
8353
|
-
return
|
|
9075
|
+
return path11.join(process.env.APPDATA || path11.join(home, "AppData", "Roaming"), appName2, "User", "settings.json");
|
|
8354
9076
|
} else {
|
|
8355
|
-
return
|
|
9077
|
+
return path11.join(home, ".config", appName2, "User", "settings.json");
|
|
8356
9078
|
}
|
|
8357
9079
|
};
|
|
8358
9080
|
const loader = new ProviderLoader({ logFn: () => {
|
|
@@ -8370,7 +9092,7 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
8370
9092
|
settings = {};
|
|
8371
9093
|
}
|
|
8372
9094
|
} else {
|
|
8373
|
-
fs7.mkdirSync(
|
|
9095
|
+
fs7.mkdirSync(path11.dirname(settingsPath), { recursive: true });
|
|
8374
9096
|
}
|
|
8375
9097
|
settings["adhdev.connectionToken"] = connectionToken;
|
|
8376
9098
|
settings["adhdev.autoConnect"] = true;
|
|
@@ -8392,7 +9114,7 @@ async function startDaemonFlow() {
|
|
|
8392
9114
|
{
|
|
8393
9115
|
type: "confirm",
|
|
8394
9116
|
name: "startDaemon",
|
|
8395
|
-
message: "Start ADHDev Daemon now? (
|
|
9117
|
+
message: "Start the ADHDev Daemon now? (Required for all agent/IDE routing features)",
|
|
8396
9118
|
default: true
|
|
8397
9119
|
}
|
|
8398
9120
|
]);
|
|
@@ -8406,8 +9128,8 @@ async function startDaemonFlow() {
|
|
|
8406
9128
|
const daemon = new AdhdevDaemon2();
|
|
8407
9129
|
const { execSync: execSync6 } = await import("child_process");
|
|
8408
9130
|
const os13 = await import("os");
|
|
8409
|
-
const
|
|
8410
|
-
const logPath =
|
|
9131
|
+
const path11 = await import("path");
|
|
9132
|
+
const logPath = path11.join(os13.homedir(), ".adhdev", "daemon.log");
|
|
8411
9133
|
try {
|
|
8412
9134
|
execSync6(`nohup adhdev daemon > "${logPath}" 2>&1 &`, {
|
|
8413
9135
|
timeout: 3e3,
|
|
@@ -8449,10 +9171,11 @@ async function installCliOnly() {
|
|
|
8449
9171
|
const isNpx = process.env.npm_execpath?.includes("npx") || process.argv[1]?.includes("npx") || process.argv[1]?.includes("_npx");
|
|
8450
9172
|
console.log(import_chalk3.default.bold("\n\u{1F527} ADHDev CLI\n"));
|
|
8451
9173
|
console.log(import_chalk3.default.gray(" The `adhdev` command lets you:"));
|
|
8452
|
-
console.log(import_chalk3.default.gray(" \u2022 Start
|
|
8453
|
-
console.log(import_chalk3.default.gray(" \u2022 Launch IDE with CDP
|
|
8454
|
-
console.log(import_chalk3.default.gray(" \u2022 Start CLI agents
|
|
8455
|
-
console.log(import_chalk3.default.gray(" \u2022
|
|
9174
|
+
console.log(import_chalk3.default.gray(" \u2022 Start the main daemon (adhdev daemon)"));
|
|
9175
|
+
console.log(import_chalk3.default.gray(" \u2022 Launch IDE with CDP (adhdev launch <ide>)"));
|
|
9176
|
+
console.log(import_chalk3.default.gray(" \u2022 Start CLI agents (adhdev launch <agent>)"));
|
|
9177
|
+
console.log(import_chalk3.default.gray(" \u2022 CDP Debugging Console (adhdev cdp)"));
|
|
9178
|
+
console.log(import_chalk3.default.gray(" \u2022 Check setup status (adhdev status)"));
|
|
8456
9179
|
console.log();
|
|
8457
9180
|
if (currentVersion) {
|
|
8458
9181
|
console.log(import_chalk3.default.green(` \u2713 Currently installed: v${currentVersion}`));
|
|
@@ -8834,7 +9557,7 @@ program.command("daemon:stop").description("Stop ADHDev Daemon").action(async ()
|
|
|
8834
9557
|
async function sendDaemonCommand(cmd, args = {}, port = 19222) {
|
|
8835
9558
|
const WebSocket4 = (await import("ws")).default;
|
|
8836
9559
|
const { DAEMON_WS_PATH: DAEMON_WS_PATH2 } = await Promise.resolve().then(() => (init_ipc_protocol(), ipc_protocol_exports));
|
|
8837
|
-
return new Promise((
|
|
9560
|
+
return new Promise((resolve6, reject) => {
|
|
8838
9561
|
const wsUrl = `ws://127.0.0.1:${port}${DAEMON_WS_PATH2 || "/daemon"}`;
|
|
8839
9562
|
const ws = new WebSocket4(wsUrl);
|
|
8840
9563
|
const timeout = setTimeout(() => {
|
|
@@ -8865,7 +9588,7 @@ async function sendDaemonCommand(cmd, args = {}, port = 19222) {
|
|
|
8865
9588
|
if (msg.type === "daemon:command_result" || msg.type === "command_result") {
|
|
8866
9589
|
clearTimeout(timeout);
|
|
8867
9590
|
ws.close();
|
|
8868
|
-
|
|
9591
|
+
resolve6(msg.payload?.result || msg.payload || msg);
|
|
8869
9592
|
}
|
|
8870
9593
|
} catch {
|
|
8871
9594
|
}
|
|
@@ -8882,13 +9605,13 @@ Is 'adhdev daemon' running?`));
|
|
|
8882
9605
|
}
|
|
8883
9606
|
async function directCdpEval(expression, port = 9222) {
|
|
8884
9607
|
const http3 = await import("http");
|
|
8885
|
-
const targets = await new Promise((
|
|
9608
|
+
const targets = await new Promise((resolve6, reject) => {
|
|
8886
9609
|
http3.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
8887
9610
|
let data = "";
|
|
8888
9611
|
res.on("data", (c) => data += c);
|
|
8889
9612
|
res.on("end", () => {
|
|
8890
9613
|
try {
|
|
8891
|
-
|
|
9614
|
+
resolve6(JSON.parse(data));
|
|
8892
9615
|
} catch {
|
|
8893
9616
|
reject(new Error("Invalid JSON"));
|
|
8894
9617
|
}
|
|
@@ -8901,7 +9624,7 @@ async function directCdpEval(expression, port = 9222) {
|
|
|
8901
9624
|
const target = (mainPages.length > 0 ? mainPages[0] : pages[0]) || targets[0];
|
|
8902
9625
|
if (!target?.webSocketDebuggerUrl) throw new Error("No CDP target found");
|
|
8903
9626
|
const WebSocket4 = (await import("ws")).default;
|
|
8904
|
-
return new Promise((
|
|
9627
|
+
return new Promise((resolve6, reject) => {
|
|
8905
9628
|
const ws = new WebSocket4(target.webSocketDebuggerUrl);
|
|
8906
9629
|
const timeout = setTimeout(() => {
|
|
8907
9630
|
ws.close();
|
|
@@ -8923,11 +9646,11 @@ async function directCdpEval(expression, port = 9222) {
|
|
|
8923
9646
|
clearTimeout(timeout);
|
|
8924
9647
|
ws.close();
|
|
8925
9648
|
if (msg.result?.result?.value !== void 0) {
|
|
8926
|
-
|
|
9649
|
+
resolve6(msg.result.result.value);
|
|
8927
9650
|
} else if (msg.result?.exceptionDetails) {
|
|
8928
9651
|
reject(new Error(msg.result.exceptionDetails.text));
|
|
8929
9652
|
} else {
|
|
8930
|
-
|
|
9653
|
+
resolve6(msg.result);
|
|
8931
9654
|
}
|
|
8932
9655
|
}
|
|
8933
9656
|
});
|
|
@@ -8956,11 +9679,11 @@ provider.command("list").description("List all loaded providers").option("-j, --
|
|
|
8956
9679
|
return;
|
|
8957
9680
|
}
|
|
8958
9681
|
console.log(import_chalk4.default.bold("\n\u{1F50C} ADHDev Providers\n"));
|
|
8959
|
-
const categories = ["ide", "extension", "cli"];
|
|
9682
|
+
const categories = ["ide", "extension", "cli", "acp"];
|
|
8960
9683
|
for (const cat of categories) {
|
|
8961
9684
|
const catProviders = providers.filter((p) => p.category === cat);
|
|
8962
9685
|
if (catProviders.length === 0) continue;
|
|
8963
|
-
const icons = { ide: "\u{1F4BB}", extension: "\u{1F9E9}", cli: "\u2328\uFE0F " };
|
|
9686
|
+
const icons = { ide: "\u{1F4BB}", extension: "\u{1F9E9}", cli: "\u2328\uFE0F ", acp: "\u{1F50C}" };
|
|
8964
9687
|
console.log(` ${icons[cat] || ""} ${import_chalk4.default.bold(cat.toUpperCase())} (${catProviders.length})`);
|
|
8965
9688
|
for (const p of catProviders) {
|
|
8966
9689
|
const scripts = p.scripts ? Object.keys(p.scripts).filter((k) => typeof p.scripts[k] === "function") : [];
|
|
@@ -8981,7 +9704,7 @@ provider.command("list").description("List all loaded providers").option("-j, --
|
|
|
8981
9704
|
provider.command("reload").description("Hot-reload all providers (requires daemon --dev)").action(async () => {
|
|
8982
9705
|
try {
|
|
8983
9706
|
const http3 = await import("http");
|
|
8984
|
-
const result = await new Promise((
|
|
9707
|
+
const result = await new Promise((resolve6, reject) => {
|
|
8985
9708
|
const req = http3.request({
|
|
8986
9709
|
hostname: "127.0.0.1",
|
|
8987
9710
|
port: 19280,
|
|
@@ -8993,9 +9716,9 @@ provider.command("reload").description("Hot-reload all providers (requires daemo
|
|
|
8993
9716
|
res.on("data", (c) => data += c);
|
|
8994
9717
|
res.on("end", () => {
|
|
8995
9718
|
try {
|
|
8996
|
-
|
|
9719
|
+
resolve6(JSON.parse(data));
|
|
8997
9720
|
} catch {
|
|
8998
|
-
|
|
9721
|
+
resolve6({ raw: data });
|
|
8999
9722
|
}
|
|
9000
9723
|
});
|
|
9001
9724
|
});
|
|
@@ -9029,7 +9752,7 @@ provider.command("create <type>").description("Scaffold a new provider.js from t
|
|
|
9029
9752
|
const category = options.category;
|
|
9030
9753
|
const location = options.builtin ? "builtin" : "user";
|
|
9031
9754
|
const http3 = await import("http");
|
|
9032
|
-
const result = await new Promise((
|
|
9755
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9033
9756
|
const postData = JSON.stringify({ type, name, category, location });
|
|
9034
9757
|
const req = http3.request({
|
|
9035
9758
|
hostname: "127.0.0.1",
|
|
@@ -9042,9 +9765,9 @@ provider.command("create <type>").description("Scaffold a new provider.js from t
|
|
|
9042
9765
|
res.on("data", (c) => data += c);
|
|
9043
9766
|
res.on("end", () => {
|
|
9044
9767
|
try {
|
|
9045
|
-
|
|
9768
|
+
resolve6(JSON.parse(data));
|
|
9046
9769
|
} catch {
|
|
9047
|
-
|
|
9770
|
+
resolve6({ raw: data });
|
|
9048
9771
|
}
|
|
9049
9772
|
});
|
|
9050
9773
|
});
|
|
@@ -9126,7 +9849,7 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9126
9849
|
script,
|
|
9127
9850
|
params: options.param ? { text: options.param, sessionId: options.param, buttonText: options.param } : {}
|
|
9128
9851
|
});
|
|
9129
|
-
const result = await new Promise((
|
|
9852
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9130
9853
|
const req = http3.request({
|
|
9131
9854
|
hostname: "127.0.0.1",
|
|
9132
9855
|
port: 19280,
|
|
@@ -9138,9 +9861,9 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9138
9861
|
res.on("data", (c) => data += c);
|
|
9139
9862
|
res.on("end", () => {
|
|
9140
9863
|
try {
|
|
9141
|
-
|
|
9864
|
+
resolve6(JSON.parse(data));
|
|
9142
9865
|
} catch {
|
|
9143
|
-
|
|
9866
|
+
resolve6({ raw: data });
|
|
9144
9867
|
}
|
|
9145
9868
|
});
|
|
9146
9869
|
});
|
|
@@ -9176,15 +9899,15 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9176
9899
|
provider.command("source <type>").description("View source code of a provider").action(async (type) => {
|
|
9177
9900
|
try {
|
|
9178
9901
|
const http3 = await import("http");
|
|
9179
|
-
const result = await new Promise((
|
|
9902
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9180
9903
|
http3.get(`http://127.0.0.1:19280/api/providers/${type}/source`, (res) => {
|
|
9181
9904
|
let data = "";
|
|
9182
9905
|
res.on("data", (c) => data += c);
|
|
9183
9906
|
res.on("end", () => {
|
|
9184
9907
|
try {
|
|
9185
|
-
|
|
9908
|
+
resolve6(JSON.parse(data));
|
|
9186
9909
|
} catch {
|
|
9187
|
-
|
|
9910
|
+
resolve6({ raw: data });
|
|
9188
9911
|
}
|
|
9189
9912
|
});
|
|
9190
9913
|
}).on("error", () => {
|
|
@@ -9388,13 +10111,13 @@ cdp.command("eval <expression>").description("Execute JavaScript expression via
|
|
|
9388
10111
|
cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --port <port>", "CDP port", "9222").option("-o, --output <file>", "Output file path", "/tmp/cdp_screenshot.jpg").action(async (options) => {
|
|
9389
10112
|
try {
|
|
9390
10113
|
const http3 = await import("http");
|
|
9391
|
-
const targets = await new Promise((
|
|
10114
|
+
const targets = await new Promise((resolve6, reject) => {
|
|
9392
10115
|
http3.get(`http://127.0.0.1:${options.port}/json`, (res) => {
|
|
9393
10116
|
let data = "";
|
|
9394
10117
|
res.on("data", (c) => data += c);
|
|
9395
10118
|
res.on("end", () => {
|
|
9396
10119
|
try {
|
|
9397
|
-
|
|
10120
|
+
resolve6(JSON.parse(data));
|
|
9398
10121
|
} catch {
|
|
9399
10122
|
reject(new Error("Invalid JSON"));
|
|
9400
10123
|
}
|
|
@@ -9408,7 +10131,7 @@ cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --po
|
|
|
9408
10131
|
if (!target?.webSocketDebuggerUrl) throw new Error("No CDP target");
|
|
9409
10132
|
const WebSocket4 = (await import("ws")).default;
|
|
9410
10133
|
const ws = new WebSocket4(target.webSocketDebuggerUrl);
|
|
9411
|
-
await new Promise((
|
|
10134
|
+
await new Promise((resolve6, reject) => {
|
|
9412
10135
|
ws.on("open", () => {
|
|
9413
10136
|
ws.send(JSON.stringify({ id: 1, method: "Page.captureScreenshot", params: { format: "jpeg", quality: 50 } }));
|
|
9414
10137
|
});
|
|
@@ -9421,7 +10144,7 @@ cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --po
|
|
|
9421
10144
|
\u2713 Screenshot saved to ${options.output}
|
|
9422
10145
|
`));
|
|
9423
10146
|
ws.close();
|
|
9424
|
-
|
|
10147
|
+
resolve6();
|
|
9425
10148
|
}
|
|
9426
10149
|
});
|
|
9427
10150
|
ws.on("error", (e) => reject(e));
|
|
@@ -9437,10 +10160,10 @@ if (process.argv.length <= 2) {
|
|
|
9437
10160
|
program.outputHelp();
|
|
9438
10161
|
console.log();
|
|
9439
10162
|
console.log(import_chalk4.default.gray(" Quick start:"));
|
|
9440
|
-
console.log(import_chalk4.default.gray(" adhdev
|
|
9441
|
-
console.log(import_chalk4.default.gray(" adhdev
|
|
9442
|
-
console.log(import_chalk4.default.gray(" adhdev launch claude \u2014 Launch CLI agent"));
|
|
9443
|
-
console.log(import_chalk4.default.gray(" adhdev
|
|
10163
|
+
console.log(import_chalk4.default.gray(" adhdev daemon \u2014 Start unified daemon (Required)"));
|
|
10164
|
+
console.log(import_chalk4.default.gray(" adhdev launch cursor \u2014 Launch IDE with CDP (e.g. cursor, windsurf)"));
|
|
10165
|
+
console.log(import_chalk4.default.gray(" adhdev launch claude \u2014 Launch CLI agent (e.g. gemini, claude)"));
|
|
10166
|
+
console.log(import_chalk4.default.gray(" adhdev setup \u2014 First-time setup & configuration"));
|
|
9444
10167
|
console.log(import_chalk4.default.gray(" adhdev status \u2014 Check current setup"));
|
|
9445
10168
|
console.log();
|
|
9446
10169
|
} else {
|