adhdev 0.1.47 → 0.1.48
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 +1161 -452
- package/package.json +1 -1
- 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) {
|
|
@@ -5590,7 +6074,8 @@ var init_daemon_status = __esm({
|
|
|
5590
6074
|
return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
|
|
5591
6075
|
}).join(", ");
|
|
5592
6076
|
const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
|
|
5593
|
-
|
|
6077
|
+
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
6078
|
+
LOG[logLevel]("StatusReport", `\u2192${target} IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}]`);
|
|
5594
6079
|
const managedIdes = ideStates.map((s) => ({
|
|
5595
6080
|
ideType: s.type,
|
|
5596
6081
|
ideVersion: "",
|
|
@@ -5616,23 +6101,45 @@ var init_daemon_status = __esm({
|
|
|
5616
6101
|
currentAutoApprove: s.currentAutoApprove
|
|
5617
6102
|
}));
|
|
5618
6103
|
const instanceIdeTypes = new Set(ideStates.map((s) => s.type));
|
|
6104
|
+
const instanceBaseTypes = /* @__PURE__ */ new Set();
|
|
6105
|
+
for (const t of instanceIdeTypes) {
|
|
6106
|
+
instanceBaseTypes.add(t);
|
|
6107
|
+
const base = t.split("_")[0];
|
|
6108
|
+
if (base) instanceBaseTypes.add(base);
|
|
6109
|
+
}
|
|
5619
6110
|
const perExtData = localServer?.getPerExtensionData() || [];
|
|
5620
6111
|
for (const ext of perExtData) {
|
|
5621
6112
|
const ideKey = ext.ideType.toLowerCase();
|
|
5622
|
-
if (
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
6113
|
+
if (instanceBaseTypes.has(ideKey)) {
|
|
6114
|
+
const match = managedIdes.find(
|
|
6115
|
+
(m) => m.ideType === ideKey || m.ideType.split("_")[0] === ideKey
|
|
6116
|
+
);
|
|
6117
|
+
if (match) {
|
|
6118
|
+
if (!match.workspaceFolders?.length && ext.workspaceFolders?.length) {
|
|
6119
|
+
match.workspaceFolders = ext.workspaceFolders;
|
|
6120
|
+
}
|
|
6121
|
+
if (!match.activeFile && ext.activeFile) match.activeFile = ext.activeFile;
|
|
6122
|
+
if (!match.terminals && ext.terminals) match.terminals = ext.terminals;
|
|
6123
|
+
if ((!match.aiAgents || match.aiAgents.length === 0) && ext.aiAgents?.length) {
|
|
6124
|
+
match.aiAgents = ext.aiAgents;
|
|
6125
|
+
}
|
|
6126
|
+
if (!match.ideVersion && ext.ideVersion) match.ideVersion = ext.ideVersion;
|
|
6127
|
+
}
|
|
6128
|
+
} else {
|
|
6129
|
+
managedIdes.push({
|
|
6130
|
+
ideType: ext.ideType,
|
|
6131
|
+
ideVersion: ext.ideVersion,
|
|
6132
|
+
instanceId: ext.instanceId,
|
|
6133
|
+
workspaceFolders: ext.workspaceFolders,
|
|
6134
|
+
activeFile: ext.activeFile,
|
|
6135
|
+
terminals: ext.terminals,
|
|
6136
|
+
aiAgents: ext.aiAgents,
|
|
6137
|
+
activeChat: ext.activeChat,
|
|
6138
|
+
chats: ext.chats || [],
|
|
6139
|
+
agentStreams: ext.agentStreams || [],
|
|
6140
|
+
cdpConnected: false
|
|
6141
|
+
});
|
|
6142
|
+
}
|
|
5636
6143
|
}
|
|
5637
6144
|
const managedClis = cliStates.map((s) => ({
|
|
5638
6145
|
id: s.instanceId,
|
|
@@ -5654,15 +6161,15 @@ var init_daemon_status = __esm({
|
|
|
5654
6161
|
daemonMode: true,
|
|
5655
6162
|
machineNickname: loadConfig().machineNickname || null,
|
|
5656
6163
|
machine: {
|
|
5657
|
-
hostname:
|
|
5658
|
-
platform:
|
|
5659
|
-
release:
|
|
5660
|
-
arch:
|
|
5661
|
-
cpus:
|
|
5662
|
-
totalMem:
|
|
5663
|
-
freeMem:
|
|
5664
|
-
loadavg:
|
|
5665
|
-
uptime:
|
|
6164
|
+
hostname: os7.hostname(),
|
|
6165
|
+
platform: os7.platform(),
|
|
6166
|
+
release: os7.release(),
|
|
6167
|
+
arch: os7.arch(),
|
|
6168
|
+
cpus: os7.cpus().length,
|
|
6169
|
+
totalMem: os7.totalmem(),
|
|
6170
|
+
freeMem: os7.freemem(),
|
|
6171
|
+
loadavg: os7.loadavg(),
|
|
6172
|
+
uptime: os7.uptime()
|
|
5666
6173
|
},
|
|
5667
6174
|
managedIdes,
|
|
5668
6175
|
managedClis,
|
|
@@ -5684,7 +6191,7 @@ var init_daemon_status = __esm({
|
|
|
5684
6191
|
})),
|
|
5685
6192
|
timestamp: now,
|
|
5686
6193
|
activeFile: extSummary.activeFile,
|
|
5687
|
-
workspaceFolders: extSummary.workspaceFolders?.length > 0 ? extSummary.workspaceFolders : Array.from(adapters.values()).map((a) => ({ name:
|
|
6194
|
+
workspaceFolders: extSummary.workspaceFolders?.length > 0 ? extSummary.workspaceFolders : Array.from(adapters.values()).map((a) => ({ name: path7.basename(a.workingDir), path: a.workingDir })),
|
|
5688
6195
|
terminals: extSummary.terminals,
|
|
5689
6196
|
aiAgents: [
|
|
5690
6197
|
...managedIdes.flatMap((ide) => (ide.aiAgents || []).map((a) => ({
|
|
@@ -5692,17 +6199,17 @@ var init_daemon_status = __esm({
|
|
|
5692
6199
|
name: a.name,
|
|
5693
6200
|
status: a.status,
|
|
5694
6201
|
ideType: ide.ideType
|
|
5695
|
-
})))
|
|
5696
|
-
|
|
6202
|
+
})))
|
|
6203
|
+
// CLIs are already in managedClis — don't duplicate here
|
|
5697
6204
|
],
|
|
5698
6205
|
activeChat: managedClis[0]?.activeChat || managedIdes[0]?.activeChat || null,
|
|
5699
6206
|
agentStreams: managedIdes.flatMap((ide) => ide.agentStreams || []),
|
|
5700
6207
|
connectedExtensions: extSummary.connectedIdes,
|
|
5701
|
-
system: { platform:
|
|
6208
|
+
system: { platform: os7.platform(), hostname: os7.hostname() }
|
|
5702
6209
|
};
|
|
5703
6210
|
const p2pSent = this.sendP2PPayload(payload);
|
|
5704
6211
|
if (p2pSent) {
|
|
5705
|
-
|
|
6212
|
+
LOG.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
|
|
5706
6213
|
}
|
|
5707
6214
|
if (opts?.p2pOnly) return;
|
|
5708
6215
|
const plan = bridge.getUserPlan();
|
|
@@ -5711,11 +6218,11 @@ var init_daemon_status = __esm({
|
|
|
5711
6218
|
daemonMode: true,
|
|
5712
6219
|
machineNickname: payload.machineNickname,
|
|
5713
6220
|
machine: {
|
|
5714
|
-
hostname:
|
|
5715
|
-
platform:
|
|
5716
|
-
arch:
|
|
5717
|
-
cpus:
|
|
5718
|
-
totalMem:
|
|
6221
|
+
hostname: os7.hostname(),
|
|
6222
|
+
platform: os7.platform(),
|
|
6223
|
+
arch: os7.arch(),
|
|
6224
|
+
cpus: os7.cpus().length,
|
|
6225
|
+
totalMem: os7.totalmem()
|
|
5719
6226
|
},
|
|
5720
6227
|
managedIdes: managedIdes.map((ide) => ({
|
|
5721
6228
|
ideType: ide.ideType,
|
|
@@ -5739,7 +6246,7 @@ var init_daemon_status = __esm({
|
|
|
5739
6246
|
timestamp: now
|
|
5740
6247
|
};
|
|
5741
6248
|
bridge.sendMessage("status_report", wsPayload);
|
|
5742
|
-
|
|
6249
|
+
LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
|
|
5743
6250
|
}
|
|
5744
6251
|
}
|
|
5745
6252
|
// ─── P2P ─────────────────────────────────────────
|
|
@@ -5774,7 +6281,7 @@ function stripAnsi(str) {
|
|
|
5774
6281
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
5775
6282
|
}
|
|
5776
6283
|
function findBinary(name) {
|
|
5777
|
-
const isWin =
|
|
6284
|
+
const isWin = os8.platform() === "win32";
|
|
5778
6285
|
try {
|
|
5779
6286
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
5780
6287
|
return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
@@ -5782,11 +6289,11 @@ function findBinary(name) {
|
|
|
5782
6289
|
return isWin ? `${name}.cmd` : name;
|
|
5783
6290
|
}
|
|
5784
6291
|
}
|
|
5785
|
-
var
|
|
6292
|
+
var os8, import_child_process4, pty, ProviderCliAdapter;
|
|
5786
6293
|
var init_provider_cli_adapter = __esm({
|
|
5787
6294
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
5788
6295
|
"use strict";
|
|
5789
|
-
|
|
6296
|
+
os8 = __toESM(require("os"));
|
|
5790
6297
|
import_child_process4 = require("child_process");
|
|
5791
6298
|
try {
|
|
5792
6299
|
pty = require("node-pty");
|
|
@@ -5799,7 +6306,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
5799
6306
|
this.provider = provider2;
|
|
5800
6307
|
this.cliType = provider2.type;
|
|
5801
6308
|
this.cliName = provider2.name;
|
|
5802
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
6309
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os8.homedir()) : workingDir;
|
|
5803
6310
|
const t = provider2.timeouts || {};
|
|
5804
6311
|
this.timeouts = {
|
|
5805
6312
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -5857,7 +6364,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
5857
6364
|
if (!pty) throw new Error("node-pty is not installed");
|
|
5858
6365
|
const { spawn: spawnConfig } = this.provider;
|
|
5859
6366
|
const binaryPath = findBinary(spawnConfig.command);
|
|
5860
|
-
const isWin =
|
|
6367
|
+
const isWin = os8.platform() === "win32";
|
|
5861
6368
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
5862
6369
|
console.log(`[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
5863
6370
|
let shellCmd;
|
|
@@ -6099,7 +6606,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
6099
6606
|
|
|
6100
6607
|
// src/cli-detector.ts
|
|
6101
6608
|
async function detectCLIs() {
|
|
6102
|
-
const platform7 =
|
|
6609
|
+
const platform7 = os9.platform();
|
|
6103
6610
|
const whichCmd = platform7 === "win32" ? "where" : "which";
|
|
6104
6611
|
const results = [];
|
|
6105
6612
|
for (const cli of KNOWN_CLIS) {
|
|
@@ -6133,12 +6640,12 @@ async function detectCLI(cliId) {
|
|
|
6133
6640
|
const all = await detectCLIs();
|
|
6134
6641
|
return all.find((c) => c.id === normalizedId && c.installed) || null;
|
|
6135
6642
|
}
|
|
6136
|
-
var import_child_process5,
|
|
6643
|
+
var import_child_process5, os9, KNOWN_CLIS;
|
|
6137
6644
|
var init_cli_detector = __esm({
|
|
6138
6645
|
"src/cli-detector.ts"() {
|
|
6139
6646
|
"use strict";
|
|
6140
6647
|
import_child_process5 = require("child_process");
|
|
6141
|
-
|
|
6648
|
+
os9 = __toESM(require("os"));
|
|
6142
6649
|
KNOWN_CLIS = [
|
|
6143
6650
|
{ id: "gemini-cli", displayName: "Gemini CLI", icon: "\u264A", command: "gemini" },
|
|
6144
6651
|
{ id: "claude-code", displayName: "Claude Code", icon: "\u{1F916}", command: "claude" },
|
|
@@ -6147,17 +6654,267 @@ var init_cli_detector = __esm({
|
|
|
6147
6654
|
}
|
|
6148
6655
|
});
|
|
6149
6656
|
|
|
6150
|
-
// src/
|
|
6151
|
-
var
|
|
6152
|
-
var
|
|
6153
|
-
"src/
|
|
6154
|
-
"use strict";
|
|
6155
|
-
|
|
6156
|
-
|
|
6657
|
+
// src/providers/status-monitor.ts
|
|
6658
|
+
var DEFAULT_MONITOR_CONFIG, StatusMonitor;
|
|
6659
|
+
var init_status_monitor = __esm({
|
|
6660
|
+
"src/providers/status-monitor.ts"() {
|
|
6661
|
+
"use strict";
|
|
6662
|
+
DEFAULT_MONITOR_CONFIG = {
|
|
6663
|
+
approvalAlert: true,
|
|
6664
|
+
longGeneratingAlert: true,
|
|
6665
|
+
longGeneratingThresholdSec: 180,
|
|
6666
|
+
// 3분
|
|
6667
|
+
alertCooldownSec: 60
|
|
6668
|
+
// 1분 쿨다운
|
|
6669
|
+
};
|
|
6670
|
+
StatusMonitor = class {
|
|
6671
|
+
config;
|
|
6672
|
+
lastAlertTime = /* @__PURE__ */ new Map();
|
|
6673
|
+
generatingStartTimes = /* @__PURE__ */ new Map();
|
|
6674
|
+
constructor(config) {
|
|
6675
|
+
this.config = { ...DEFAULT_MONITOR_CONFIG, ...config };
|
|
6676
|
+
}
|
|
6677
|
+
/** 설정 업데이트 (Provider Settings에서 호출) */
|
|
6678
|
+
updateConfig(partial) {
|
|
6679
|
+
Object.assign(this.config, partial);
|
|
6680
|
+
}
|
|
6681
|
+
/** 현재 설정 반환 */
|
|
6682
|
+
getConfig() {
|
|
6683
|
+
return { ...this.config };
|
|
6684
|
+
}
|
|
6685
|
+
/**
|
|
6686
|
+
* 상태 전이 체크 → 알림 이벤트 배열 반환
|
|
6687
|
+
* 각 onTick()에서 호출.
|
|
6688
|
+
*/
|
|
6689
|
+
check(agentKey, status, now) {
|
|
6690
|
+
const events = [];
|
|
6691
|
+
if (this.config.approvalAlert && status === "waiting_approval") {
|
|
6692
|
+
if (this.shouldAlert(agentKey + ":approval", now)) {
|
|
6693
|
+
events.push({
|
|
6694
|
+
type: "monitor:approval_waiting",
|
|
6695
|
+
agentKey,
|
|
6696
|
+
timestamp: now,
|
|
6697
|
+
message: `${agentKey} is waiting for approval`
|
|
6698
|
+
});
|
|
6699
|
+
}
|
|
6700
|
+
}
|
|
6701
|
+
if (status === "generating" || status === "streaming") {
|
|
6702
|
+
if (!this.generatingStartTimes.has(agentKey)) {
|
|
6703
|
+
this.generatingStartTimes.set(agentKey, now);
|
|
6704
|
+
}
|
|
6705
|
+
if (this.config.longGeneratingAlert) {
|
|
6706
|
+
const startedAt = this.generatingStartTimes.get(agentKey);
|
|
6707
|
+
const elapsedSec = Math.round((now - startedAt) / 1e3);
|
|
6708
|
+
if (elapsedSec > this.config.longGeneratingThresholdSec) {
|
|
6709
|
+
if (this.shouldAlert(agentKey + ":long_gen", now)) {
|
|
6710
|
+
events.push({
|
|
6711
|
+
type: "monitor:long_generating",
|
|
6712
|
+
agentKey,
|
|
6713
|
+
elapsedSec,
|
|
6714
|
+
timestamp: now,
|
|
6715
|
+
message: `${agentKey} has been generating for ${Math.round(elapsedSec / 60)}min`
|
|
6716
|
+
});
|
|
6717
|
+
}
|
|
6718
|
+
}
|
|
6719
|
+
}
|
|
6720
|
+
} else {
|
|
6721
|
+
this.generatingStartTimes.delete(agentKey);
|
|
6722
|
+
}
|
|
6723
|
+
return events;
|
|
6724
|
+
}
|
|
6725
|
+
/** 쿨다운 체크 — 같은 알림을 너무 자주 보내지 않도록 */
|
|
6726
|
+
shouldAlert(key, now) {
|
|
6727
|
+
const last = this.lastAlertTime.get(key) || 0;
|
|
6728
|
+
if (now - last > this.config.alertCooldownSec * 1e3) {
|
|
6729
|
+
this.lastAlertTime.set(key, now);
|
|
6730
|
+
return true;
|
|
6731
|
+
}
|
|
6732
|
+
return false;
|
|
6733
|
+
}
|
|
6734
|
+
/** 리셋 (에이전트 종료/재시작 시) */
|
|
6735
|
+
reset(agentKey) {
|
|
6736
|
+
if (agentKey) {
|
|
6737
|
+
this.generatingStartTimes.delete(agentKey);
|
|
6738
|
+
for (const k of this.lastAlertTime.keys()) {
|
|
6739
|
+
if (k.startsWith(agentKey)) this.lastAlertTime.delete(k);
|
|
6740
|
+
}
|
|
6741
|
+
} else {
|
|
6742
|
+
this.generatingStartTimes.clear();
|
|
6743
|
+
this.lastAlertTime.clear();
|
|
6744
|
+
}
|
|
6745
|
+
}
|
|
6746
|
+
};
|
|
6747
|
+
}
|
|
6748
|
+
});
|
|
6749
|
+
|
|
6750
|
+
// src/providers/cli-provider-instance.ts
|
|
6751
|
+
var path8, CliProviderInstance;
|
|
6752
|
+
var init_cli_provider_instance = __esm({
|
|
6753
|
+
"src/providers/cli-provider-instance.ts"() {
|
|
6754
|
+
"use strict";
|
|
6755
|
+
path8 = __toESM(require("path"));
|
|
6756
|
+
init_provider_cli_adapter();
|
|
6757
|
+
init_status_monitor();
|
|
6758
|
+
CliProviderInstance = class {
|
|
6759
|
+
constructor(provider2, workingDir, cliArgs = []) {
|
|
6760
|
+
this.provider = provider2;
|
|
6761
|
+
this.workingDir = workingDir;
|
|
6762
|
+
this.cliArgs = cliArgs;
|
|
6763
|
+
this.type = provider2.type;
|
|
6764
|
+
this.adapter = new ProviderCliAdapter(provider2, workingDir, cliArgs);
|
|
6765
|
+
this.monitor = new StatusMonitor();
|
|
6766
|
+
}
|
|
6767
|
+
type;
|
|
6768
|
+
category = "cli";
|
|
6769
|
+
adapter;
|
|
6770
|
+
context = null;
|
|
6771
|
+
events = [];
|
|
6772
|
+
lastStatus = "starting";
|
|
6773
|
+
generatingStartedAt = 0;
|
|
6774
|
+
settings = {};
|
|
6775
|
+
monitor;
|
|
6776
|
+
// ─── Lifecycle ─────────────────────────────────
|
|
6777
|
+
async init(context) {
|
|
6778
|
+
this.context = context;
|
|
6779
|
+
this.settings = context.settings || {};
|
|
6780
|
+
this.monitor.updateConfig({
|
|
6781
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
6782
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
6783
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
6784
|
+
});
|
|
6785
|
+
if (context.bridge) {
|
|
6786
|
+
this.adapter.setBridge(context.bridge);
|
|
6787
|
+
}
|
|
6788
|
+
if (context.onPtyData) {
|
|
6789
|
+
this.adapter.setOnPtyData(context.onPtyData);
|
|
6790
|
+
}
|
|
6791
|
+
this.adapter.setOnStatusChange(() => {
|
|
6792
|
+
this.detectStatusTransition();
|
|
6793
|
+
});
|
|
6794
|
+
await this.adapter.spawn();
|
|
6795
|
+
}
|
|
6796
|
+
async onTick() {
|
|
6797
|
+
}
|
|
6798
|
+
getState() {
|
|
6799
|
+
const adapterStatus = this.adapter.getStatus();
|
|
6800
|
+
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
6801
|
+
const recentMessages = adapterStatus.messages.slice(-50).map((m) => ({
|
|
6802
|
+
role: m.role,
|
|
6803
|
+
content: m.content.length > 2e3 ? m.content.slice(0, 2e3) + "\n... (truncated)" : m.content,
|
|
6804
|
+
timestamp: m.timestamp
|
|
6805
|
+
}));
|
|
6806
|
+
const partial = this.adapter.getPartialResponse();
|
|
6807
|
+
if (adapterStatus.status === "generating" && partial) {
|
|
6808
|
+
const cleaned = partial.trim();
|
|
6809
|
+
if (cleaned && cleaned !== "(generating...)") {
|
|
6810
|
+
recentMessages.push({
|
|
6811
|
+
role: "assistant",
|
|
6812
|
+
content: (cleaned.length > 2e3 ? cleaned.slice(0, 2e3) + "..." : cleaned) + "...",
|
|
6813
|
+
timestamp: Date.now()
|
|
6814
|
+
});
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
return {
|
|
6818
|
+
type: this.type,
|
|
6819
|
+
name: this.provider.name,
|
|
6820
|
+
category: "cli",
|
|
6821
|
+
status: adapterStatus.status,
|
|
6822
|
+
mode: this.settings.mode || "terminal",
|
|
6823
|
+
activeChat: {
|
|
6824
|
+
id: `${this.type}_${this.workingDir}`,
|
|
6825
|
+
title: `${this.provider.name} \xB7 ${dirName}`,
|
|
6826
|
+
status: adapterStatus.status,
|
|
6827
|
+
messages: recentMessages,
|
|
6828
|
+
activeModal: adapterStatus.activeModal,
|
|
6829
|
+
inputContent: ""
|
|
6830
|
+
},
|
|
6831
|
+
workingDir: this.workingDir,
|
|
6832
|
+
instanceId: `${this.type}_${require("crypto").createHash("md5").update(path8.resolve(this.workingDir)).digest("hex").slice(0, 8)}`,
|
|
6833
|
+
lastUpdated: Date.now(),
|
|
6834
|
+
settings: this.settings,
|
|
6835
|
+
pendingEvents: this.flushEvents()
|
|
6836
|
+
};
|
|
6837
|
+
}
|
|
6838
|
+
onEvent(event, data) {
|
|
6839
|
+
if (event === "send_message" && data?.text) {
|
|
6840
|
+
this.adapter.sendMessage(data.text);
|
|
6841
|
+
} else if (event === "bridge_connected" && data?.bridge) {
|
|
6842
|
+
this.adapter.setBridge(data.bridge);
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6845
|
+
dispose() {
|
|
6846
|
+
this.adapter.shutdown();
|
|
6847
|
+
this.monitor.reset();
|
|
6848
|
+
}
|
|
6849
|
+
// ─── 상태 전이 감지 (daemon-status.ts에서 이동) ──────
|
|
6850
|
+
detectStatusTransition() {
|
|
6851
|
+
const now = Date.now();
|
|
6852
|
+
const adapterStatus = this.adapter.getStatus();
|
|
6853
|
+
const newStatus = adapterStatus.status;
|
|
6854
|
+
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
6855
|
+
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
6856
|
+
if (newStatus !== this.lastStatus) {
|
|
6857
|
+
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
6858
|
+
this.generatingStartedAt = now;
|
|
6859
|
+
this.pushEvent({ event: "agent:generating_started", chatTitle, timestamp: now });
|
|
6860
|
+
} else if (newStatus === "waiting_approval") {
|
|
6861
|
+
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
6862
|
+
this.pushEvent({
|
|
6863
|
+
event: "agent:waiting_approval",
|
|
6864
|
+
chatTitle,
|
|
6865
|
+
timestamp: now,
|
|
6866
|
+
modalMessage: adapterStatus.activeModal?.message
|
|
6867
|
+
});
|
|
6868
|
+
} else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
|
|
6869
|
+
const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
6870
|
+
this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now });
|
|
6871
|
+
this.generatingStartedAt = 0;
|
|
6872
|
+
} else if (newStatus === "stopped") {
|
|
6873
|
+
this.pushEvent({ event: "agent:stopped", chatTitle, timestamp: now });
|
|
6874
|
+
}
|
|
6875
|
+
this.lastStatus = newStatus;
|
|
6876
|
+
}
|
|
6877
|
+
const agentKey = `${this.type}:cli`;
|
|
6878
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now);
|
|
6879
|
+
for (const me of monitorEvents) {
|
|
6880
|
+
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
6881
|
+
}
|
|
6882
|
+
}
|
|
6883
|
+
pushEvent(event) {
|
|
6884
|
+
this.events.push(event);
|
|
6885
|
+
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
6886
|
+
}
|
|
6887
|
+
flushEvents() {
|
|
6888
|
+
const events = [...this.events];
|
|
6889
|
+
this.events = [];
|
|
6890
|
+
return events;
|
|
6891
|
+
}
|
|
6892
|
+
// ─── Adapter 접근 (하위 호환) ──────────────────
|
|
6893
|
+
getAdapter() {
|
|
6894
|
+
return this.adapter;
|
|
6895
|
+
}
|
|
6896
|
+
get cliType() {
|
|
6897
|
+
return this.type;
|
|
6898
|
+
}
|
|
6899
|
+
get cliName() {
|
|
6900
|
+
return this.provider.name;
|
|
6901
|
+
}
|
|
6902
|
+
};
|
|
6903
|
+
}
|
|
6904
|
+
});
|
|
6905
|
+
|
|
6906
|
+
// src/daemon-cli.ts
|
|
6907
|
+
var os10, path9, import_chalk, DaemonCliManager;
|
|
6908
|
+
var init_daemon_cli = __esm({
|
|
6909
|
+
"src/daemon-cli.ts"() {
|
|
6910
|
+
"use strict";
|
|
6911
|
+
os10 = __toESM(require("os"));
|
|
6912
|
+
path9 = __toESM(require("path"));
|
|
6157
6913
|
import_chalk = __toESM(require("chalk"));
|
|
6158
6914
|
init_provider_cli_adapter();
|
|
6159
6915
|
init_cli_detector();
|
|
6160
6916
|
init_config();
|
|
6917
|
+
init_cli_provider_instance();
|
|
6161
6918
|
DaemonCliManager = class {
|
|
6162
6919
|
adapters = /* @__PURE__ */ new Map();
|
|
6163
6920
|
deps;
|
|
@@ -6191,8 +6948,8 @@ var init_daemon_cli = __esm({
|
|
|
6191
6948
|
}
|
|
6192
6949
|
// ─── 세션 시작/중지 ──────────────────────────────
|
|
6193
6950
|
async startSession(cliType, workingDir, cliArgs) {
|
|
6194
|
-
const trimmed = (workingDir ||
|
|
6195
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/,
|
|
6951
|
+
const trimmed = (workingDir || os10.homedir()).trim();
|
|
6952
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
|
|
6196
6953
|
const cliInfo = await detectCLI(cliType);
|
|
6197
6954
|
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
6198
6955
|
const key = this.getCliKey(cliType, resolvedDir);
|
|
@@ -6200,34 +6957,57 @@ var init_daemon_cli = __esm({
|
|
|
6200
6957
|
console.log(import_chalk.default.yellow(` \u26A1 CLI ${cliType} already running in ${resolvedDir}`));
|
|
6201
6958
|
return;
|
|
6202
6959
|
}
|
|
6960
|
+
const typeMap = {
|
|
6961
|
+
"claude-code": "claude-cli",
|
|
6962
|
+
"codex": "codex-cli"
|
|
6963
|
+
};
|
|
6964
|
+
const normalizedType = typeMap[cliType] || cliType;
|
|
6965
|
+
const provider2 = this.providerLoader.get(normalizedType);
|
|
6203
6966
|
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);
|
|
6967
|
+
if (provider2) {
|
|
6968
|
+
console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider2.name} (${provider2.type})`));
|
|
6209
6969
|
}
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
const
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6970
|
+
const instanceManager = this.deps.getInstanceManager();
|
|
6971
|
+
if (provider2 && instanceManager) {
|
|
6972
|
+
const cliInstance = new CliProviderInstance(provider2, resolvedDir, cliArgs);
|
|
6973
|
+
await instanceManager.addInstance(key, cliInstance, {
|
|
6974
|
+
bridge: this.deps.getBridge(),
|
|
6975
|
+
settings: {},
|
|
6976
|
+
onPtyData: (data) => {
|
|
6977
|
+
this.deps.getP2p()?.broadcastPtyOutput(key, data);
|
|
6978
|
+
}
|
|
6979
|
+
});
|
|
6980
|
+
this.adapters.set(key, cliInstance.getAdapter());
|
|
6981
|
+
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6982
|
+
} else {
|
|
6983
|
+
const adapter = this.createAdapter(cliType, resolvedDir, cliArgs);
|
|
6984
|
+
await adapter.spawn();
|
|
6985
|
+
const bridge = this.deps.getBridge();
|
|
6986
|
+
if (bridge && typeof adapter.setBridge === "function") {
|
|
6987
|
+
adapter.setBridge(bridge);
|
|
6988
|
+
}
|
|
6989
|
+
adapter.setOnStatusChange(() => {
|
|
6990
|
+
this.deps.onStatusChange();
|
|
6991
|
+
const status = adapter.getStatus?.();
|
|
6992
|
+
if (status?.status === "stopped") {
|
|
6993
|
+
setTimeout(() => {
|
|
6994
|
+
if (this.adapters.get(key) === adapter) {
|
|
6995
|
+
this.adapters.delete(key);
|
|
6996
|
+
this.deps.removeAgentTracking(key);
|
|
6997
|
+
console.log(import_chalk.default.yellow(` \u{1F9F9} Auto-cleaned stopped CLI: ${adapter.cliType}`));
|
|
6998
|
+
this.deps.onStatusChange();
|
|
6999
|
+
}
|
|
7000
|
+
}, 3e3);
|
|
7001
|
+
}
|
|
6227
7002
|
});
|
|
7003
|
+
if (typeof adapter.setOnPtyData === "function") {
|
|
7004
|
+
adapter.setOnPtyData((data) => {
|
|
7005
|
+
this.deps.getP2p()?.broadcastPtyOutput(key, data);
|
|
7006
|
+
});
|
|
7007
|
+
}
|
|
7008
|
+
this.adapters.set(key, adapter);
|
|
7009
|
+
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6228
7010
|
}
|
|
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
7011
|
try {
|
|
6232
7012
|
addCliHistory({ cliType, dir: resolvedDir, cliArgs });
|
|
6233
7013
|
} catch (e) {
|
|
@@ -6241,6 +7021,7 @@ var init_daemon_cli = __esm({
|
|
|
6241
7021
|
adapter.shutdown();
|
|
6242
7022
|
this.adapters.delete(key);
|
|
6243
7023
|
this.deps.removeAgentTracking(key);
|
|
7024
|
+
this.deps.getInstanceManager()?.removeInstance(key);
|
|
6244
7025
|
console.log(import_chalk.default.yellow(` \u{1F6D1} CLI Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`));
|
|
6245
7026
|
this.deps.onStatusChange();
|
|
6246
7027
|
}
|
|
@@ -6268,7 +7049,8 @@ var init_daemon_cli = __esm({
|
|
|
6268
7049
|
switch (cmd) {
|
|
6269
7050
|
case "launch_cli": {
|
|
6270
7051
|
const cliType = args?.cliType;
|
|
6271
|
-
const
|
|
7052
|
+
const defaultedToHome = !args?.dir;
|
|
7053
|
+
const dir = args?.dir || os10.homedir();
|
|
6272
7054
|
if (!cliType) throw new Error("cliType required");
|
|
6273
7055
|
const key = this.getCliKey(cliType, dir);
|
|
6274
7056
|
if (!this.adapters.has(key)) {
|
|
@@ -6286,7 +7068,7 @@ var init_daemon_cli = __esm({
|
|
|
6286
7068
|
console.error(import_chalk.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
6287
7069
|
}
|
|
6288
7070
|
}
|
|
6289
|
-
return { success: true, cliType, dir, id: key };
|
|
7071
|
+
return { success: true, cliType, dir, id: key, defaultedToHome };
|
|
6290
7072
|
}
|
|
6291
7073
|
case "stop_cli": {
|
|
6292
7074
|
const cliType = args?.cliType;
|
|
@@ -6490,99 +7272,6 @@ var init_provider_instance_manager = __esm({
|
|
|
6490
7272
|
}
|
|
6491
7273
|
});
|
|
6492
7274
|
|
|
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
7275
|
// src/providers/extension-provider-instance.ts
|
|
6587
7276
|
var ExtensionProviderInstance;
|
|
6588
7277
|
var init_extension_provider_instance = __esm({
|
|
@@ -6705,11 +7394,11 @@ var init_extension_provider_instance = __esm({
|
|
|
6705
7394
|
});
|
|
6706
7395
|
|
|
6707
7396
|
// src/providers/ide-provider-instance.ts
|
|
6708
|
-
var
|
|
7397
|
+
var os11, crypto, IdeProviderInstance;
|
|
6709
7398
|
var init_ide_provider_instance = __esm({
|
|
6710
7399
|
"src/providers/ide-provider-instance.ts"() {
|
|
6711
7400
|
"use strict";
|
|
6712
|
-
|
|
7401
|
+
os11 = __toESM(require("os"));
|
|
6713
7402
|
crypto = __toESM(require("crypto"));
|
|
6714
7403
|
init_extension_provider_instance();
|
|
6715
7404
|
init_status_monitor();
|
|
@@ -6735,10 +7424,10 @@ var init_ide_provider_instance = __esm({
|
|
|
6735
7424
|
activeFile = null;
|
|
6736
7425
|
// ─── 자식 Extension Instances ────────────────────
|
|
6737
7426
|
extensions = /* @__PURE__ */ new Map();
|
|
6738
|
-
constructor(provider2) {
|
|
7427
|
+
constructor(provider2, instanceKey) {
|
|
6739
7428
|
this.type = provider2.type;
|
|
6740
7429
|
this.provider = provider2;
|
|
6741
|
-
this.instanceId = `${provider2.type}_${crypto.createHash("md5").update(
|
|
7430
|
+
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
7431
|
this.monitor = new StatusMonitor();
|
|
6743
7432
|
}
|
|
6744
7433
|
// ─── Lifecycle ─────────────────────────────────
|
|
@@ -6869,7 +7558,14 @@ var init_ide_provider_instance = __esm({
|
|
|
6869
7558
|
const readChatScript = this.getReadChatScript();
|
|
6870
7559
|
if (!readChatScript) return;
|
|
6871
7560
|
try {
|
|
6872
|
-
|
|
7561
|
+
let raw = await cdp2.evaluate(readChatScript, 3e4);
|
|
7562
|
+
if (typeof raw === "string") {
|
|
7563
|
+
try {
|
|
7564
|
+
raw = JSON.parse(raw);
|
|
7565
|
+
} catch {
|
|
7566
|
+
return;
|
|
7567
|
+
}
|
|
7568
|
+
}
|
|
6873
7569
|
if (!raw || typeof raw !== "object") return;
|
|
6874
7570
|
let { activeModal } = raw;
|
|
6875
7571
|
if (activeModal) {
|
|
@@ -6962,107 +7658,6 @@ var init_ide_provider_instance = __esm({
|
|
|
6962
7658
|
}
|
|
6963
7659
|
});
|
|
6964
7660
|
|
|
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
7661
|
// src/adhdev-daemon.ts
|
|
7067
7662
|
var adhdev_daemon_exports = {};
|
|
7068
7663
|
__export(adhdev_daemon_exports, {
|
|
@@ -7071,9 +7666,9 @@ __export(adhdev_daemon_exports, {
|
|
|
7071
7666
|
stopDaemon: () => stopDaemon
|
|
7072
7667
|
});
|
|
7073
7668
|
function getDaemonPidFile() {
|
|
7074
|
-
const dir =
|
|
7669
|
+
const dir = path10.join(os12.homedir(), ".adhdev");
|
|
7075
7670
|
if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
|
|
7076
|
-
return
|
|
7671
|
+
return path10.join(dir, "daemon.pid");
|
|
7077
7672
|
}
|
|
7078
7673
|
function writeDaemonPid(pid) {
|
|
7079
7674
|
fs6.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
@@ -7109,7 +7704,7 @@ function stopDaemon() {
|
|
|
7109
7704
|
return false;
|
|
7110
7705
|
}
|
|
7111
7706
|
}
|
|
7112
|
-
var os12, fs6,
|
|
7707
|
+
var os12, fs6, path10, crypto2, import_chalk2, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
7113
7708
|
var init_adhdev_daemon = __esm({
|
|
7114
7709
|
"src/adhdev-daemon.ts"() {
|
|
7115
7710
|
"use strict";
|
|
@@ -7129,9 +7724,10 @@ var init_adhdev_daemon = __esm({
|
|
|
7129
7724
|
init_provider_instance_manager();
|
|
7130
7725
|
init_ide_provider_instance();
|
|
7131
7726
|
init_ipc_protocol();
|
|
7727
|
+
init_daemon_logger();
|
|
7132
7728
|
os12 = __toESM(require("os"));
|
|
7133
7729
|
fs6 = __toESM(require("fs"));
|
|
7134
|
-
|
|
7730
|
+
path10 = __toESM(require("path"));
|
|
7135
7731
|
crypto2 = __toESM(require("crypto"));
|
|
7136
7732
|
import_chalk2 = __toESM(require("chalk"));
|
|
7137
7733
|
DANGEROUS_PATTERNS = [
|
|
@@ -7173,7 +7769,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7173
7769
|
getBridge: () => this.bridge,
|
|
7174
7770
|
getP2p: () => this.p2p,
|
|
7175
7771
|
onStatusChange: () => this.statusReporter?.onStatusChange(),
|
|
7176
|
-
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key)
|
|
7772
|
+
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
7773
|
+
getInstanceManager: () => this.instanceManager
|
|
7177
7774
|
}, this.providerLoader);
|
|
7178
7775
|
}
|
|
7179
7776
|
async start(options = {}) {
|
|
@@ -7328,8 +7925,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7328
7925
|
});
|
|
7329
7926
|
this.p2p.onStateChange((state) => {
|
|
7330
7927
|
if (state === "connected") {
|
|
7331
|
-
|
|
7332
|
-
this.statusReporter?.sendUnifiedStatusReport().catch((e) =>
|
|
7928
|
+
LOG.info("P2P", "Peer connected \u2192 sending immediate full status report");
|
|
7929
|
+
this.statusReporter?.sendUnifiedStatusReport().catch((e) => LOG.warn("P2P", `Immediate status report failed: ${e?.message}`));
|
|
7333
7930
|
}
|
|
7334
7931
|
});
|
|
7335
7932
|
let ssDebugCount = 0;
|
|
@@ -7340,18 +7937,18 @@ var init_adhdev_daemon = __esm({
|
|
|
7340
7937
|
if (!active || !cdp2) return;
|
|
7341
7938
|
ssDebugCount++;
|
|
7342
7939
|
if (ssDebugCount <= 3 || ssDebugCount % 25 === 0) {
|
|
7343
|
-
|
|
7940
|
+
LOG.debug("Screenshot", `Capturing... (tick ${ssDebugCount}, active=${active}, cdp=true)`);
|
|
7344
7941
|
}
|
|
7345
7942
|
try {
|
|
7346
7943
|
const buf = await cdp2.captureScreenshot();
|
|
7347
7944
|
if (buf) {
|
|
7348
7945
|
const sent = this.p2p.sendScreenshot(buf.toString("base64"));
|
|
7349
|
-
if (ssDebugCount <= 3)
|
|
7946
|
+
if (ssDebugCount <= 3) LOG.debug("Screenshot", `sent: ${buf.length} bytes, delivered=${sent}`);
|
|
7350
7947
|
} else {
|
|
7351
|
-
if (ssDebugCount <= 5)
|
|
7948
|
+
if (ssDebugCount <= 5) LOG.debug("Screenshot", "captureScreenshot returned null");
|
|
7352
7949
|
}
|
|
7353
7950
|
} catch (e) {
|
|
7354
|
-
if (ssDebugCount <= 5)
|
|
7951
|
+
if (ssDebugCount <= 5) LOG.warn("Screenshot", `error: ${e?.message}`);
|
|
7355
7952
|
}
|
|
7356
7953
|
}, 200);
|
|
7357
7954
|
} else {
|
|
@@ -7494,10 +8091,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7494
8091
|
}
|
|
7495
8092
|
}
|
|
7496
8093
|
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
|
-
}
|
|
8094
|
+
LOG.info("Command", `${cmd}${args?._targetInstance ? ` \u2192 ${args._targetType}:${args._targetInstance.split("_")[0]}` : ""}`);
|
|
7501
8095
|
try {
|
|
7502
8096
|
switch (cmd) {
|
|
7503
8097
|
case "open_panel":
|
|
@@ -7569,17 +8163,22 @@ var init_adhdev_daemon = __esm({
|
|
|
7569
8163
|
return { success: true, nickname };
|
|
7570
8164
|
}
|
|
7571
8165
|
case "get_daemon_logs": {
|
|
7572
|
-
const
|
|
8166
|
+
const count = parseInt(data.lines) || 100;
|
|
8167
|
+
const minLevel = data.minLevel || "info";
|
|
7573
8168
|
try {
|
|
7574
|
-
const
|
|
8169
|
+
const { getRecentLogs: getRecentLogs2, LOG_PATH: LOG_PATH2 } = (init_daemon_logger(), __toCommonJS(daemon_logger_exports));
|
|
8170
|
+
const entries = getRecentLogs2(count, minLevel);
|
|
8171
|
+
if (entries.length > 0) {
|
|
8172
|
+
return { success: true, entries, totalBuffered: entries.length };
|
|
8173
|
+
}
|
|
7575
8174
|
const logFs = require("fs");
|
|
7576
|
-
if (logFs.existsSync(
|
|
7577
|
-
const content = logFs.readFileSync(
|
|
8175
|
+
if (logFs.existsSync(LOG_PATH2)) {
|
|
8176
|
+
const content = logFs.readFileSync(LOG_PATH2, "utf-8");
|
|
7578
8177
|
const allLines = content.split("\n");
|
|
7579
|
-
const recent = allLines.slice(-
|
|
8178
|
+
const recent = allLines.slice(-count).join("\n");
|
|
7580
8179
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
7581
8180
|
}
|
|
7582
|
-
return { success: true,
|
|
8181
|
+
return { success: true, entries: [], totalBuffered: 0 };
|
|
7583
8182
|
} catch (e) {
|
|
7584
8183
|
return { success: false, error: e.message };
|
|
7585
8184
|
}
|
|
@@ -7612,7 +8211,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7612
8211
|
case "launch_ide": {
|
|
7613
8212
|
const launchArgs = { ...args, ideId: args?.ideId || args?.ideType };
|
|
7614
8213
|
const ideKey = launchArgs.ideId;
|
|
7615
|
-
|
|
8214
|
+
LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
7616
8215
|
const result = await launchWithCdp(launchArgs);
|
|
7617
8216
|
if (result.success && result.port && result.ideId && !this.cdpManagers.has(result.ideId)) {
|
|
7618
8217
|
console.log(import_chalk2.default.cyan(`[launch_ide] Connecting CDP for ${result.ideId} on port ${result.port}...`));
|
|
@@ -7621,6 +8220,12 @@ var init_adhdev_daemon = __esm({
|
|
|
7621
8220
|
});
|
|
7622
8221
|
const connected = await manager.connect();
|
|
7623
8222
|
if (connected) {
|
|
8223
|
+
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(result.ideId).map((p) => ({
|
|
8224
|
+
agentType: p.type,
|
|
8225
|
+
extensionId: p.extensionId || "",
|
|
8226
|
+
extensionIdPattern: p.extensionIdPattern
|
|
8227
|
+
}));
|
|
8228
|
+
manager.setExtensionProviders(enabledExtProviders);
|
|
7624
8229
|
this.cdpManagers.set(result.ideId, manager);
|
|
7625
8230
|
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${result.ideId} (port ${result.port})`));
|
|
7626
8231
|
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
@@ -7702,6 +8307,37 @@ var init_adhdev_daemon = __esm({
|
|
|
7702
8307
|
if (this.agentStreamTimer) return;
|
|
7703
8308
|
this.agentStreamTimer = setInterval(async () => {
|
|
7704
8309
|
if (!this.agentStreamManager || this.cdpManagers.size === 0) return;
|
|
8310
|
+
for (const [ideType, cdp2] of this.cdpManagers) {
|
|
8311
|
+
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(ideType).map((p) => ({
|
|
8312
|
+
agentType: p.type,
|
|
8313
|
+
extensionId: p.extensionId || "",
|
|
8314
|
+
extensionIdPattern: p.extensionIdPattern
|
|
8315
|
+
}));
|
|
8316
|
+
cdp2.setExtensionProviders(enabledExtProviders);
|
|
8317
|
+
const ideInstance = this.instanceManager.getInstance(`ide:${ideType}`);
|
|
8318
|
+
if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
|
|
8319
|
+
const currentExtTypes = new Set(ideInstance.getExtensionTypes());
|
|
8320
|
+
const enabledExtTypes = new Set(
|
|
8321
|
+
this.providerLoader.getEnabledByCategory("extension", ideType).map((p) => p.type)
|
|
8322
|
+
);
|
|
8323
|
+
for (const extType of currentExtTypes) {
|
|
8324
|
+
if (!enabledExtTypes.has(extType)) {
|
|
8325
|
+
ideInstance.removeExtension(extType);
|
|
8326
|
+
LOG.info("AgentStream", `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
8327
|
+
}
|
|
8328
|
+
}
|
|
8329
|
+
for (const extType of enabledExtTypes) {
|
|
8330
|
+
if (!currentExtTypes.has(extType)) {
|
|
8331
|
+
const extProvider = this.providerLoader.get(extType);
|
|
8332
|
+
if (extProvider) {
|
|
8333
|
+
const extSettings = this.providerLoader.getSettings(extType);
|
|
8334
|
+
ideInstance.addExtension(extProvider, extSettings);
|
|
8335
|
+
LOG.info("AgentStream", `Extension added: ${extType} (enabled for ${ideType})`);
|
|
8336
|
+
}
|
|
8337
|
+
}
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8340
|
+
}
|
|
7705
8341
|
if (this._agentStreamCdpIdeType) {
|
|
7706
8342
|
const cdp2 = this.cdpManagers.get(this._agentStreamCdpIdeType);
|
|
7707
8343
|
if (cdp2?.isConnected) {
|
|
@@ -7723,7 +8359,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7723
8359
|
if (discovered.length > 0) {
|
|
7724
8360
|
this._agentStreamCdpIdeType = ideType;
|
|
7725
8361
|
await this.agentStreamManager.switchActiveAgent(cdp2, discovered[0].agentType);
|
|
7726
|
-
|
|
8362
|
+
LOG.info("AgentStream", `Auto-activated: ${discovered[0].agentType} (${ideType})`);
|
|
7727
8363
|
await this.agentStreamManager.syncAgentSessions(cdp2);
|
|
7728
8364
|
const streams = await this.agentStreamManager.collectAgentStreams(cdp2);
|
|
7729
8365
|
this.statusReporter?.updateAgentStreams(ideType, streams);
|
|
@@ -7735,6 +8371,39 @@ var init_adhdev_daemon = __esm({
|
|
|
7735
8371
|
}
|
|
7736
8372
|
}, 5e3);
|
|
7737
8373
|
}
|
|
8374
|
+
/**
|
|
8375
|
+
* CdpManager 초기화 공통 로직 — extension provider 등록, ideType 설정, ProviderInstance 생성
|
|
8376
|
+
* @param ideType provider 기반 IDE 타입 (e.g., 'antigravity', 'cursor')
|
|
8377
|
+
* @param manager 연결된 CdpManager
|
|
8378
|
+
*/
|
|
8379
|
+
setupCdpManager(ideType, manager) {
|
|
8380
|
+
const enabledExtProviders = this.providerLoader.getEnabledExtensionProviders(ideType).map((p) => ({
|
|
8381
|
+
agentType: p.type,
|
|
8382
|
+
extensionId: p.extensionId || "",
|
|
8383
|
+
extensionIdPattern: p.extensionIdPattern
|
|
8384
|
+
}));
|
|
8385
|
+
manager.setExtensionProviders(enabledExtProviders);
|
|
8386
|
+
if (this.ideType === "unknown") {
|
|
8387
|
+
this.ideType = ideType;
|
|
8388
|
+
}
|
|
8389
|
+
const ideProvider = this.providerLoader.get(ideType);
|
|
8390
|
+
if (ideProvider) {
|
|
8391
|
+
const managerKey = [...this.cdpManagers.entries()].find(([, m]) => m === manager)?.[0] || ideType;
|
|
8392
|
+
const ideInstance = new IdeProviderInstance(ideProvider, managerKey !== ideType ? managerKey : void 0);
|
|
8393
|
+
const resolvedSettings = this.providerLoader.getSettings(ideType);
|
|
8394
|
+
this.instanceManager.addInstance(`ide:${managerKey}`, ideInstance, {
|
|
8395
|
+
cdp: manager,
|
|
8396
|
+
bridge: this.bridge || void 0,
|
|
8397
|
+
settings: resolvedSettings
|
|
8398
|
+
}).then(async () => {
|
|
8399
|
+
const extensionProviders = this.providerLoader.getEnabledByCategory("extension", ideType);
|
|
8400
|
+
for (const extProvider of extensionProviders) {
|
|
8401
|
+
const extSettings = this.providerLoader.getSettings(extProvider.type);
|
|
8402
|
+
await ideInstance.addExtension(extProvider, extSettings);
|
|
8403
|
+
}
|
|
8404
|
+
}).catch((e) => console.warn(`[Instance] Failed to init IDE instance ${managerKey}:`, e?.message));
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
7738
8407
|
async initCdp() {
|
|
7739
8408
|
const providerCdpMap = this.providerLoader.getCdpPortMap();
|
|
7740
8409
|
const cdpPortMap = {};
|
|
@@ -7755,49 +8424,87 @@ var init_adhdev_daemon = __esm({
|
|
|
7755
8424
|
const enabledIdes = loadConfig().enabledIdes || [];
|
|
7756
8425
|
const filteredPorts = enabledIdes.length > 0 ? portsToTry.filter((p) => enabledIdes.includes(p.ide)) : portsToTry;
|
|
7757
8426
|
for (const { port, ide } of filteredPorts) {
|
|
7758
|
-
const
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
const
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
this.ideType = actualIde;
|
|
8427
|
+
const allTargets = await DaemonCdpManager.listAllTargets(port);
|
|
8428
|
+
if (allTargets.length === 0) {
|
|
8429
|
+
const manager = new DaemonCdpManager(port, (msg) => {
|
|
8430
|
+
console.log(`[CDP:${ide}] ${msg}`);
|
|
8431
|
+
});
|
|
8432
|
+
const connected = await manager.connect();
|
|
8433
|
+
if (connected) {
|
|
8434
|
+
this.cdpManagers.set(ide, manager);
|
|
8435
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${ide} (port ${port})`));
|
|
8436
|
+
this.setupCdpManager(ide, manager);
|
|
7769
8437
|
}
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
8438
|
+
continue;
|
|
8439
|
+
}
|
|
8440
|
+
for (let i = 0; i < allTargets.length; i++) {
|
|
8441
|
+
const target = allTargets[i];
|
|
8442
|
+
let managerKey;
|
|
8443
|
+
if (allTargets.length === 1) {
|
|
8444
|
+
managerKey = ide;
|
|
8445
|
+
} else {
|
|
8446
|
+
const workspaceName = (target.title || "").split(" \u2014 ")[0].trim() || `window_${i}`;
|
|
8447
|
+
managerKey = `${ide}_${workspaceName}`;
|
|
8448
|
+
}
|
|
8449
|
+
if (this.cdpManagers.has(managerKey)) continue;
|
|
8450
|
+
const manager = new DaemonCdpManager(port, (msg) => {
|
|
8451
|
+
console.log(`[CDP:${managerKey}] ${msg}`);
|
|
8452
|
+
}, target.id);
|
|
8453
|
+
const connected = await manager.connect();
|
|
8454
|
+
if (connected) {
|
|
8455
|
+
this.cdpManagers.set(managerKey, manager);
|
|
8456
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${managerKey} (port ${port}, page "${target.title}")`));
|
|
8457
|
+
this.setupCdpManager(ide, manager);
|
|
7785
8458
|
}
|
|
7786
8459
|
}
|
|
7787
8460
|
}
|
|
7788
8461
|
if (this.cdpManagers.size > 0) {
|
|
7789
8462
|
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
8463
|
} else {
|
|
7798
8464
|
console.log(import_chalk2.default.yellow(` \u26A0 CDP not available \u2014 tried ports: ${portsToTry.map((p) => `${p.ide}:${p.port}`).join(", ")}`));
|
|
7799
8465
|
console.log(import_chalk2.default.yellow(` IDE may need relaunch with --remote-debugging-port`));
|
|
7800
8466
|
}
|
|
8467
|
+
this.cdpDiscoveryTimer = setInterval(async () => {
|
|
8468
|
+
for (const m of this.cdpManagers.values()) {
|
|
8469
|
+
if (m.isConnected) {
|
|
8470
|
+
await m.discoverAgentWebviews();
|
|
8471
|
+
}
|
|
8472
|
+
}
|
|
8473
|
+
}, 3e4);
|
|
8474
|
+
setInterval(async () => {
|
|
8475
|
+
const portMap = this.providerLoader.getCdpPortMap();
|
|
8476
|
+
for (const [ide, ports] of Object.entries(portMap)) {
|
|
8477
|
+
const primaryPort = ports[0];
|
|
8478
|
+
const alreadyConnected = [...this.cdpManagers.entries()].some(
|
|
8479
|
+
([key, m]) => m.isConnected && (key === ide || key.startsWith(ide + "_"))
|
|
8480
|
+
);
|
|
8481
|
+
if (alreadyConnected) continue;
|
|
8482
|
+
const targets = await DaemonCdpManager.listAllTargets(primaryPort);
|
|
8483
|
+
if (targets.length === 0) continue;
|
|
8484
|
+
console.log(import_chalk2.default.cyan(`[CDP-Scan] Found ${targets.length} page(s) on ${ide}:${primaryPort}`));
|
|
8485
|
+
for (let i = 0; i < targets.length; i++) {
|
|
8486
|
+
const target = targets[i];
|
|
8487
|
+
let managerKey;
|
|
8488
|
+
if (targets.length === 1) {
|
|
8489
|
+
managerKey = ide;
|
|
8490
|
+
} else {
|
|
8491
|
+
const workspaceName = (target.title || "").split(" \u2014 ")[0].trim() || `window_${i}`;
|
|
8492
|
+
managerKey = `${ide}_${workspaceName}`;
|
|
8493
|
+
}
|
|
8494
|
+
if (this.cdpManagers.has(managerKey)) continue;
|
|
8495
|
+
const manager = new DaemonCdpManager(primaryPort, (msg) => {
|
|
8496
|
+
console.log(`[CDP:${managerKey}] ${msg}`);
|
|
8497
|
+
}, target.id);
|
|
8498
|
+
const connected = await manager.connect();
|
|
8499
|
+
if (connected) {
|
|
8500
|
+
this.cdpManagers.set(managerKey, manager);
|
|
8501
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP auto-connected: ${managerKey} (port ${primaryPort}, page "${target.title}")`));
|
|
8502
|
+
this.setupCdpManager(ide, manager);
|
|
8503
|
+
this.startAgentStreamPolling();
|
|
8504
|
+
}
|
|
8505
|
+
}
|
|
8506
|
+
}
|
|
8507
|
+
}, 3e4);
|
|
7801
8508
|
}
|
|
7802
8509
|
};
|
|
7803
8510
|
}
|
|
@@ -7945,10 +8652,10 @@ async function installExtension(ide, extension) {
|
|
|
7945
8652
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
7946
8653
|
const fs7 = await import("fs");
|
|
7947
8654
|
fs7.writeFileSync(vsixPath, buffer);
|
|
7948
|
-
return new Promise((
|
|
8655
|
+
return new Promise((resolve6) => {
|
|
7949
8656
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
7950
8657
|
(0, import_child_process2.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
7951
|
-
|
|
8658
|
+
resolve6({
|
|
7952
8659
|
extensionId: extension.id,
|
|
7953
8660
|
marketplaceId: extension.marketplaceId,
|
|
7954
8661
|
success: !error,
|
|
@@ -7979,11 +8686,11 @@ async function installExtension(ide, extension) {
|
|
|
7979
8686
|
}
|
|
7980
8687
|
}
|
|
7981
8688
|
}
|
|
7982
|
-
return new Promise((
|
|
8689
|
+
return new Promise((resolve6) => {
|
|
7983
8690
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
7984
8691
|
(0, import_child_process2.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
7985
8692
|
if (error) {
|
|
7986
|
-
|
|
8693
|
+
resolve6({
|
|
7987
8694
|
extensionId: extension.id,
|
|
7988
8695
|
marketplaceId: extension.marketplaceId,
|
|
7989
8696
|
success: false,
|
|
@@ -7991,7 +8698,7 @@ async function installExtension(ide, extension) {
|
|
|
7991
8698
|
error: stderr || error.message
|
|
7992
8699
|
});
|
|
7993
8700
|
} else {
|
|
7994
|
-
|
|
8701
|
+
resolve6({
|
|
7995
8702
|
extensionId: extension.id,
|
|
7996
8703
|
marketplaceId: extension.marketplaceId,
|
|
7997
8704
|
success: true,
|
|
@@ -8167,11 +8874,12 @@ async function quickSetup() {
|
|
|
8167
8874
|
console.log(` ${import_chalk3.default.bold("Status:")} ${import_chalk3.default.green("Ready to connect")}`);
|
|
8168
8875
|
console.log();
|
|
8169
8876
|
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
|
|
8877
|
+
console.log(import_chalk3.default.gray(" adhdev daemon \u2014 Start the main daemon (required for all features)"));
|
|
8878
|
+
console.log(import_chalk3.default.gray(" adhdev launch <ide> \u2014 Launch an IDE with remote control (e.g. cursor)"));
|
|
8879
|
+
console.log(import_chalk3.default.gray(" adhdev launch <agent> \u2014 Start a CLI agent via daemon (e.g. gemini, claude)"));
|
|
8880
|
+
console.log(import_chalk3.default.gray(" adhdev cdp \u2014 Interactive CDP debug console"));
|
|
8173
8881
|
console.log(import_chalk3.default.gray(" adhdev status \u2014 Check setup status"));
|
|
8174
|
-
console.log(import_chalk3.default.gray(" adhdev setup \u2014 Reconfigure"));
|
|
8882
|
+
console.log(import_chalk3.default.gray(" adhdev setup \u2014 Reconfigure ADHDev"));
|
|
8175
8883
|
console.log();
|
|
8176
8884
|
await installCliOnly();
|
|
8177
8885
|
await startDaemonFlow();
|
|
@@ -8343,16 +9051,16 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
8343
9051
|
try {
|
|
8344
9052
|
const os13 = await import("os");
|
|
8345
9053
|
const fs7 = await import("fs");
|
|
8346
|
-
const
|
|
9054
|
+
const path11 = await import("path");
|
|
8347
9055
|
const platform7 = os13.platform();
|
|
8348
9056
|
const home = os13.homedir();
|
|
8349
9057
|
const getSettingsPath = (appName2) => {
|
|
8350
9058
|
if (platform7 === "darwin") {
|
|
8351
|
-
return
|
|
9059
|
+
return path11.join(home, "Library", "Application Support", appName2, "User", "settings.json");
|
|
8352
9060
|
} else if (platform7 === "win32") {
|
|
8353
|
-
return
|
|
9061
|
+
return path11.join(process.env.APPDATA || path11.join(home, "AppData", "Roaming"), appName2, "User", "settings.json");
|
|
8354
9062
|
} else {
|
|
8355
|
-
return
|
|
9063
|
+
return path11.join(home, ".config", appName2, "User", "settings.json");
|
|
8356
9064
|
}
|
|
8357
9065
|
};
|
|
8358
9066
|
const loader = new ProviderLoader({ logFn: () => {
|
|
@@ -8370,7 +9078,7 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
8370
9078
|
settings = {};
|
|
8371
9079
|
}
|
|
8372
9080
|
} else {
|
|
8373
|
-
fs7.mkdirSync(
|
|
9081
|
+
fs7.mkdirSync(path11.dirname(settingsPath), { recursive: true });
|
|
8374
9082
|
}
|
|
8375
9083
|
settings["adhdev.connectionToken"] = connectionToken;
|
|
8376
9084
|
settings["adhdev.autoConnect"] = true;
|
|
@@ -8392,7 +9100,7 @@ async function startDaemonFlow() {
|
|
|
8392
9100
|
{
|
|
8393
9101
|
type: "confirm",
|
|
8394
9102
|
name: "startDaemon",
|
|
8395
|
-
message: "Start ADHDev Daemon now? (
|
|
9103
|
+
message: "Start the ADHDev Daemon now? (Required for all agent/IDE routing features)",
|
|
8396
9104
|
default: true
|
|
8397
9105
|
}
|
|
8398
9106
|
]);
|
|
@@ -8406,8 +9114,8 @@ async function startDaemonFlow() {
|
|
|
8406
9114
|
const daemon = new AdhdevDaemon2();
|
|
8407
9115
|
const { execSync: execSync6 } = await import("child_process");
|
|
8408
9116
|
const os13 = await import("os");
|
|
8409
|
-
const
|
|
8410
|
-
const logPath =
|
|
9117
|
+
const path11 = await import("path");
|
|
9118
|
+
const logPath = path11.join(os13.homedir(), ".adhdev", "daemon.log");
|
|
8411
9119
|
try {
|
|
8412
9120
|
execSync6(`nohup adhdev daemon > "${logPath}" 2>&1 &`, {
|
|
8413
9121
|
timeout: 3e3,
|
|
@@ -8449,10 +9157,11 @@ async function installCliOnly() {
|
|
|
8449
9157
|
const isNpx = process.env.npm_execpath?.includes("npx") || process.argv[1]?.includes("npx") || process.argv[1]?.includes("_npx");
|
|
8450
9158
|
console.log(import_chalk3.default.bold("\n\u{1F527} ADHDev CLI\n"));
|
|
8451
9159
|
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
|
|
9160
|
+
console.log(import_chalk3.default.gray(" \u2022 Start the main daemon (adhdev daemon)"));
|
|
9161
|
+
console.log(import_chalk3.default.gray(" \u2022 Launch IDE with CDP (adhdev launch <ide>)"));
|
|
9162
|
+
console.log(import_chalk3.default.gray(" \u2022 Start CLI agents (adhdev launch <agent>)"));
|
|
9163
|
+
console.log(import_chalk3.default.gray(" \u2022 CDP Debugging Console (adhdev cdp)"));
|
|
9164
|
+
console.log(import_chalk3.default.gray(" \u2022 Check setup status (adhdev status)"));
|
|
8456
9165
|
console.log();
|
|
8457
9166
|
if (currentVersion) {
|
|
8458
9167
|
console.log(import_chalk3.default.green(` \u2713 Currently installed: v${currentVersion}`));
|
|
@@ -8834,7 +9543,7 @@ program.command("daemon:stop").description("Stop ADHDev Daemon").action(async ()
|
|
|
8834
9543
|
async function sendDaemonCommand(cmd, args = {}, port = 19222) {
|
|
8835
9544
|
const WebSocket4 = (await import("ws")).default;
|
|
8836
9545
|
const { DAEMON_WS_PATH: DAEMON_WS_PATH2 } = await Promise.resolve().then(() => (init_ipc_protocol(), ipc_protocol_exports));
|
|
8837
|
-
return new Promise((
|
|
9546
|
+
return new Promise((resolve6, reject) => {
|
|
8838
9547
|
const wsUrl = `ws://127.0.0.1:${port}${DAEMON_WS_PATH2 || "/daemon"}`;
|
|
8839
9548
|
const ws = new WebSocket4(wsUrl);
|
|
8840
9549
|
const timeout = setTimeout(() => {
|
|
@@ -8865,7 +9574,7 @@ async function sendDaemonCommand(cmd, args = {}, port = 19222) {
|
|
|
8865
9574
|
if (msg.type === "daemon:command_result" || msg.type === "command_result") {
|
|
8866
9575
|
clearTimeout(timeout);
|
|
8867
9576
|
ws.close();
|
|
8868
|
-
|
|
9577
|
+
resolve6(msg.payload?.result || msg.payload || msg);
|
|
8869
9578
|
}
|
|
8870
9579
|
} catch {
|
|
8871
9580
|
}
|
|
@@ -8882,13 +9591,13 @@ Is 'adhdev daemon' running?`));
|
|
|
8882
9591
|
}
|
|
8883
9592
|
async function directCdpEval(expression, port = 9222) {
|
|
8884
9593
|
const http3 = await import("http");
|
|
8885
|
-
const targets = await new Promise((
|
|
9594
|
+
const targets = await new Promise((resolve6, reject) => {
|
|
8886
9595
|
http3.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
8887
9596
|
let data = "";
|
|
8888
9597
|
res.on("data", (c) => data += c);
|
|
8889
9598
|
res.on("end", () => {
|
|
8890
9599
|
try {
|
|
8891
|
-
|
|
9600
|
+
resolve6(JSON.parse(data));
|
|
8892
9601
|
} catch {
|
|
8893
9602
|
reject(new Error("Invalid JSON"));
|
|
8894
9603
|
}
|
|
@@ -8901,7 +9610,7 @@ async function directCdpEval(expression, port = 9222) {
|
|
|
8901
9610
|
const target = (mainPages.length > 0 ? mainPages[0] : pages[0]) || targets[0];
|
|
8902
9611
|
if (!target?.webSocketDebuggerUrl) throw new Error("No CDP target found");
|
|
8903
9612
|
const WebSocket4 = (await import("ws")).default;
|
|
8904
|
-
return new Promise((
|
|
9613
|
+
return new Promise((resolve6, reject) => {
|
|
8905
9614
|
const ws = new WebSocket4(target.webSocketDebuggerUrl);
|
|
8906
9615
|
const timeout = setTimeout(() => {
|
|
8907
9616
|
ws.close();
|
|
@@ -8923,11 +9632,11 @@ async function directCdpEval(expression, port = 9222) {
|
|
|
8923
9632
|
clearTimeout(timeout);
|
|
8924
9633
|
ws.close();
|
|
8925
9634
|
if (msg.result?.result?.value !== void 0) {
|
|
8926
|
-
|
|
9635
|
+
resolve6(msg.result.result.value);
|
|
8927
9636
|
} else if (msg.result?.exceptionDetails) {
|
|
8928
9637
|
reject(new Error(msg.result.exceptionDetails.text));
|
|
8929
9638
|
} else {
|
|
8930
|
-
|
|
9639
|
+
resolve6(msg.result);
|
|
8931
9640
|
}
|
|
8932
9641
|
}
|
|
8933
9642
|
});
|
|
@@ -8981,7 +9690,7 @@ provider.command("list").description("List all loaded providers").option("-j, --
|
|
|
8981
9690
|
provider.command("reload").description("Hot-reload all providers (requires daemon --dev)").action(async () => {
|
|
8982
9691
|
try {
|
|
8983
9692
|
const http3 = await import("http");
|
|
8984
|
-
const result = await new Promise((
|
|
9693
|
+
const result = await new Promise((resolve6, reject) => {
|
|
8985
9694
|
const req = http3.request({
|
|
8986
9695
|
hostname: "127.0.0.1",
|
|
8987
9696
|
port: 19280,
|
|
@@ -8993,9 +9702,9 @@ provider.command("reload").description("Hot-reload all providers (requires daemo
|
|
|
8993
9702
|
res.on("data", (c) => data += c);
|
|
8994
9703
|
res.on("end", () => {
|
|
8995
9704
|
try {
|
|
8996
|
-
|
|
9705
|
+
resolve6(JSON.parse(data));
|
|
8997
9706
|
} catch {
|
|
8998
|
-
|
|
9707
|
+
resolve6({ raw: data });
|
|
8999
9708
|
}
|
|
9000
9709
|
});
|
|
9001
9710
|
});
|
|
@@ -9029,7 +9738,7 @@ provider.command("create <type>").description("Scaffold a new provider.js from t
|
|
|
9029
9738
|
const category = options.category;
|
|
9030
9739
|
const location = options.builtin ? "builtin" : "user";
|
|
9031
9740
|
const http3 = await import("http");
|
|
9032
|
-
const result = await new Promise((
|
|
9741
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9033
9742
|
const postData = JSON.stringify({ type, name, category, location });
|
|
9034
9743
|
const req = http3.request({
|
|
9035
9744
|
hostname: "127.0.0.1",
|
|
@@ -9042,9 +9751,9 @@ provider.command("create <type>").description("Scaffold a new provider.js from t
|
|
|
9042
9751
|
res.on("data", (c) => data += c);
|
|
9043
9752
|
res.on("end", () => {
|
|
9044
9753
|
try {
|
|
9045
|
-
|
|
9754
|
+
resolve6(JSON.parse(data));
|
|
9046
9755
|
} catch {
|
|
9047
|
-
|
|
9756
|
+
resolve6({ raw: data });
|
|
9048
9757
|
}
|
|
9049
9758
|
});
|
|
9050
9759
|
});
|
|
@@ -9126,7 +9835,7 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9126
9835
|
script,
|
|
9127
9836
|
params: options.param ? { text: options.param, sessionId: options.param, buttonText: options.param } : {}
|
|
9128
9837
|
});
|
|
9129
|
-
const result = await new Promise((
|
|
9838
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9130
9839
|
const req = http3.request({
|
|
9131
9840
|
hostname: "127.0.0.1",
|
|
9132
9841
|
port: 19280,
|
|
@@ -9138,9 +9847,9 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9138
9847
|
res.on("data", (c) => data += c);
|
|
9139
9848
|
res.on("end", () => {
|
|
9140
9849
|
try {
|
|
9141
|
-
|
|
9850
|
+
resolve6(JSON.parse(data));
|
|
9142
9851
|
} catch {
|
|
9143
|
-
|
|
9852
|
+
resolve6({ raw: data });
|
|
9144
9853
|
}
|
|
9145
9854
|
});
|
|
9146
9855
|
});
|
|
@@ -9176,15 +9885,15 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9176
9885
|
provider.command("source <type>").description("View source code of a provider").action(async (type) => {
|
|
9177
9886
|
try {
|
|
9178
9887
|
const http3 = await import("http");
|
|
9179
|
-
const result = await new Promise((
|
|
9888
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9180
9889
|
http3.get(`http://127.0.0.1:19280/api/providers/${type}/source`, (res) => {
|
|
9181
9890
|
let data = "";
|
|
9182
9891
|
res.on("data", (c) => data += c);
|
|
9183
9892
|
res.on("end", () => {
|
|
9184
9893
|
try {
|
|
9185
|
-
|
|
9894
|
+
resolve6(JSON.parse(data));
|
|
9186
9895
|
} catch {
|
|
9187
|
-
|
|
9896
|
+
resolve6({ raw: data });
|
|
9188
9897
|
}
|
|
9189
9898
|
});
|
|
9190
9899
|
}).on("error", () => {
|
|
@@ -9388,13 +10097,13 @@ cdp.command("eval <expression>").description("Execute JavaScript expression via
|
|
|
9388
10097
|
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
10098
|
try {
|
|
9390
10099
|
const http3 = await import("http");
|
|
9391
|
-
const targets = await new Promise((
|
|
10100
|
+
const targets = await new Promise((resolve6, reject) => {
|
|
9392
10101
|
http3.get(`http://127.0.0.1:${options.port}/json`, (res) => {
|
|
9393
10102
|
let data = "";
|
|
9394
10103
|
res.on("data", (c) => data += c);
|
|
9395
10104
|
res.on("end", () => {
|
|
9396
10105
|
try {
|
|
9397
|
-
|
|
10106
|
+
resolve6(JSON.parse(data));
|
|
9398
10107
|
} catch {
|
|
9399
10108
|
reject(new Error("Invalid JSON"));
|
|
9400
10109
|
}
|
|
@@ -9408,7 +10117,7 @@ cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --po
|
|
|
9408
10117
|
if (!target?.webSocketDebuggerUrl) throw new Error("No CDP target");
|
|
9409
10118
|
const WebSocket4 = (await import("ws")).default;
|
|
9410
10119
|
const ws = new WebSocket4(target.webSocketDebuggerUrl);
|
|
9411
|
-
await new Promise((
|
|
10120
|
+
await new Promise((resolve6, reject) => {
|
|
9412
10121
|
ws.on("open", () => {
|
|
9413
10122
|
ws.send(JSON.stringify({ id: 1, method: "Page.captureScreenshot", params: { format: "jpeg", quality: 50 } }));
|
|
9414
10123
|
});
|
|
@@ -9421,7 +10130,7 @@ cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --po
|
|
|
9421
10130
|
\u2713 Screenshot saved to ${options.output}
|
|
9422
10131
|
`));
|
|
9423
10132
|
ws.close();
|
|
9424
|
-
|
|
10133
|
+
resolve6();
|
|
9425
10134
|
}
|
|
9426
10135
|
});
|
|
9427
10136
|
ws.on("error", (e) => reject(e));
|
|
@@ -9437,10 +10146,10 @@ if (process.argv.length <= 2) {
|
|
|
9437
10146
|
program.outputHelp();
|
|
9438
10147
|
console.log();
|
|
9439
10148
|
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
|
|
10149
|
+
console.log(import_chalk4.default.gray(" adhdev daemon \u2014 Start unified daemon (Required)"));
|
|
10150
|
+
console.log(import_chalk4.default.gray(" adhdev launch cursor \u2014 Launch IDE with CDP (e.g. cursor, windsurf)"));
|
|
10151
|
+
console.log(import_chalk4.default.gray(" adhdev launch claude \u2014 Launch CLI agent (e.g. gemini, claude)"));
|
|
10152
|
+
console.log(import_chalk4.default.gray(" adhdev setup \u2014 First-time setup & configuration"));
|
|
9444
10153
|
console.log(import_chalk4.default.gray(" adhdev status \u2014 Check current setup"));
|
|
9445
10154
|
console.log();
|
|
9446
10155
|
} else {
|