adhdev 0.1.46 → 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 +1178 -459
- 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
|
}
|
|
@@ -1529,12 +1578,54 @@ var init_daemon_cdp = __esm({
|
|
|
1529
1578
|
agentSessions = /* @__PURE__ */ new Map();
|
|
1530
1579
|
logFn;
|
|
1531
1580
|
extensionProviders = [];
|
|
1532
|
-
|
|
1581
|
+
_lastDiscoverSig = "";
|
|
1582
|
+
_targetId = null;
|
|
1583
|
+
// 특정 targetId로 연결 (multi-window 지원)
|
|
1584
|
+
_pageTitle = "";
|
|
1585
|
+
// 연결된 페이지 제목
|
|
1586
|
+
constructor(port = 9333, logFn, targetId) {
|
|
1533
1587
|
this.port = port;
|
|
1588
|
+
this._targetId = targetId || null;
|
|
1534
1589
|
this.logFn = logFn || ((msg) => {
|
|
1535
1590
|
console.log(msg);
|
|
1536
1591
|
});
|
|
1537
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
|
+
}
|
|
1538
1629
|
setPort(port) {
|
|
1539
1630
|
this.port = port;
|
|
1540
1631
|
this.log(`[CDP] Port changed to ${port}`);
|
|
@@ -1571,7 +1662,7 @@ var init_daemon_cdp = __esm({
|
|
|
1571
1662
|
}
|
|
1572
1663
|
}
|
|
1573
1664
|
findTargetOnPort(port) {
|
|
1574
|
-
return new Promise((
|
|
1665
|
+
return new Promise((resolve6) => {
|
|
1575
1666
|
const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
1576
1667
|
let data = "";
|
|
1577
1668
|
res.on("data", (chunk) => data += chunk.toString());
|
|
@@ -1582,23 +1673,35 @@ var init_daemon_cdp = __esm({
|
|
|
1582
1673
|
(t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
|
|
1583
1674
|
);
|
|
1584
1675
|
if (pages.length === 0) {
|
|
1585
|
-
|
|
1676
|
+
resolve6(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
1586
1677
|
return;
|
|
1587
1678
|
}
|
|
1588
1679
|
const isNonMain = (title) => !title || /extension-output|ADHDev CDP|Debug Console|Output\s*$|Launchpad/i.test(title);
|
|
1589
1680
|
const mainPages = pages.filter((t) => !isNonMain(t.title || ""));
|
|
1590
1681
|
const list = mainPages.length > 0 ? mainPages : pages;
|
|
1591
1682
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
1592
|
-
|
|
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]);
|
|
1593
1696
|
} catch {
|
|
1594
|
-
|
|
1697
|
+
resolve6(null);
|
|
1595
1698
|
}
|
|
1596
1699
|
});
|
|
1597
1700
|
});
|
|
1598
|
-
req.on("error", () =>
|
|
1701
|
+
req.on("error", () => resolve6(null));
|
|
1599
1702
|
req.setTimeout(2e3, () => {
|
|
1600
1703
|
req.destroy();
|
|
1601
|
-
|
|
1704
|
+
resolve6(null);
|
|
1602
1705
|
});
|
|
1603
1706
|
});
|
|
1604
1707
|
}
|
|
@@ -1609,7 +1712,7 @@ var init_daemon_cdp = __esm({
|
|
|
1609
1712
|
this.extensionProviders = providers;
|
|
1610
1713
|
}
|
|
1611
1714
|
connectToTarget(wsUrl) {
|
|
1612
|
-
return new Promise((
|
|
1715
|
+
return new Promise((resolve6) => {
|
|
1613
1716
|
this.ws = new import_ws3.default(wsUrl);
|
|
1614
1717
|
this.ws.on("open", async () => {
|
|
1615
1718
|
this._connected = true;
|
|
@@ -1619,17 +1722,17 @@ var init_daemon_cdp = __esm({
|
|
|
1619
1722
|
}
|
|
1620
1723
|
this.connectBrowserWs().catch(() => {
|
|
1621
1724
|
});
|
|
1622
|
-
|
|
1725
|
+
resolve6(true);
|
|
1623
1726
|
});
|
|
1624
1727
|
this.ws.on("message", (data) => {
|
|
1625
1728
|
try {
|
|
1626
1729
|
const msg = JSON.parse(data.toString());
|
|
1627
1730
|
if (msg.id && this.pending.has(msg.id)) {
|
|
1628
|
-
const { resolve:
|
|
1731
|
+
const { resolve: resolve7, reject } = this.pending.get(msg.id);
|
|
1629
1732
|
this.pending.delete(msg.id);
|
|
1630
1733
|
this.failureCount = 0;
|
|
1631
1734
|
if (msg.error) reject(new Error(msg.error.message));
|
|
1632
|
-
else
|
|
1735
|
+
else resolve7(msg.result);
|
|
1633
1736
|
} else if (msg.method === "Runtime.executionContextCreated") {
|
|
1634
1737
|
this.contexts.add(msg.params.context.id);
|
|
1635
1738
|
} else if (msg.method === "Runtime.executionContextDestroyed") {
|
|
@@ -1652,7 +1755,7 @@ var init_daemon_cdp = __esm({
|
|
|
1652
1755
|
this.ws.on("error", (err) => {
|
|
1653
1756
|
this.log(`[CDP] WebSocket error: ${err.message}`);
|
|
1654
1757
|
this._connected = false;
|
|
1655
|
-
|
|
1758
|
+
resolve6(false);
|
|
1656
1759
|
});
|
|
1657
1760
|
});
|
|
1658
1761
|
}
|
|
@@ -1666,7 +1769,7 @@ var init_daemon_cdp = __esm({
|
|
|
1666
1769
|
return;
|
|
1667
1770
|
}
|
|
1668
1771
|
this.log(`[CDP] Connecting browser WS for target discovery...`);
|
|
1669
|
-
await new Promise((
|
|
1772
|
+
await new Promise((resolve6, reject) => {
|
|
1670
1773
|
this.browserWs = new import_ws3.default(browserWsUrl);
|
|
1671
1774
|
this.browserWs.on("open", async () => {
|
|
1672
1775
|
this._browserConnected = true;
|
|
@@ -1676,16 +1779,16 @@ var init_daemon_cdp = __esm({
|
|
|
1676
1779
|
} catch (e) {
|
|
1677
1780
|
this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
|
|
1678
1781
|
}
|
|
1679
|
-
|
|
1782
|
+
resolve6();
|
|
1680
1783
|
});
|
|
1681
1784
|
this.browserWs.on("message", (data) => {
|
|
1682
1785
|
try {
|
|
1683
1786
|
const msg = JSON.parse(data.toString());
|
|
1684
1787
|
if (msg.id && this.browserPending.has(msg.id)) {
|
|
1685
|
-
const { resolve:
|
|
1788
|
+
const { resolve: resolve7, reject: reject2 } = this.browserPending.get(msg.id);
|
|
1686
1789
|
this.browserPending.delete(msg.id);
|
|
1687
1790
|
if (msg.error) reject2(new Error(msg.error.message));
|
|
1688
|
-
else
|
|
1791
|
+
else resolve7(msg.result);
|
|
1689
1792
|
}
|
|
1690
1793
|
} catch {
|
|
1691
1794
|
}
|
|
@@ -1705,31 +1808,31 @@ var init_daemon_cdp = __esm({
|
|
|
1705
1808
|
}
|
|
1706
1809
|
}
|
|
1707
1810
|
getBrowserWsUrl() {
|
|
1708
|
-
return new Promise((
|
|
1811
|
+
return new Promise((resolve6) => {
|
|
1709
1812
|
const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
|
|
1710
1813
|
let data = "";
|
|
1711
1814
|
res.on("data", (chunk) => data += chunk.toString());
|
|
1712
1815
|
res.on("end", () => {
|
|
1713
1816
|
try {
|
|
1714
1817
|
const info = JSON.parse(data);
|
|
1715
|
-
|
|
1818
|
+
resolve6(info.webSocketDebuggerUrl || null);
|
|
1716
1819
|
} catch {
|
|
1717
|
-
|
|
1820
|
+
resolve6(null);
|
|
1718
1821
|
}
|
|
1719
1822
|
});
|
|
1720
1823
|
});
|
|
1721
|
-
req.on("error", () =>
|
|
1824
|
+
req.on("error", () => resolve6(null));
|
|
1722
1825
|
req.setTimeout(3e3, () => {
|
|
1723
1826
|
req.destroy();
|
|
1724
|
-
|
|
1827
|
+
resolve6(null);
|
|
1725
1828
|
});
|
|
1726
1829
|
});
|
|
1727
1830
|
}
|
|
1728
1831
|
sendBrowser(method, params = {}, timeoutMs = 15e3) {
|
|
1729
|
-
return new Promise((
|
|
1832
|
+
return new Promise((resolve6, reject) => {
|
|
1730
1833
|
if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
|
|
1731
1834
|
const id = this.browserMsgId++;
|
|
1732
|
-
this.browserPending.set(id, { resolve:
|
|
1835
|
+
this.browserPending.set(id, { resolve: resolve6, reject });
|
|
1733
1836
|
this.browserWs.send(JSON.stringify({ id, method, params }));
|
|
1734
1837
|
setTimeout(() => {
|
|
1735
1838
|
if (this.browserPending.has(id)) {
|
|
@@ -1769,11 +1872,11 @@ var init_daemon_cdp = __esm({
|
|
|
1769
1872
|
}
|
|
1770
1873
|
// ─── CDP Protocol ────────────────────────────────────────
|
|
1771
1874
|
sendInternal(method, params = {}, timeoutMs = 15e3) {
|
|
1772
|
-
return new Promise((
|
|
1875
|
+
return new Promise((resolve6, reject) => {
|
|
1773
1876
|
if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
|
|
1774
1877
|
if (this.ws.readyState !== import_ws3.default.OPEN) return reject(new Error("WebSocket not open"));
|
|
1775
1878
|
const id = this.msgId++;
|
|
1776
|
-
this.pending.set(id, { resolve:
|
|
1879
|
+
this.pending.set(id, { resolve: resolve6, reject });
|
|
1777
1880
|
this.ws.send(JSON.stringify({ id, method, params }));
|
|
1778
1881
|
setTimeout(() => {
|
|
1779
1882
|
if (this.pending.has(id)) {
|
|
@@ -1910,13 +2013,17 @@ var init_daemon_cdp = __esm({
|
|
|
1910
2013
|
typeMap.set(t.type, (typeMap.get(t.type) || 0) + 1);
|
|
1911
2014
|
}
|
|
1912
2015
|
const typeSummary = [...typeMap.entries()].map(([k, v]) => `${k}:${v}`).join(",");
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
2016
|
+
const sig = `${allTargets.length}:${iframes.length}:${typeSummary}`;
|
|
2017
|
+
if (sig !== this._lastDiscoverSig) {
|
|
2018
|
+
this._lastDiscoverSig = sig;
|
|
2019
|
+
this.log(`[CDP] discoverAgentWebviews: ${allTargets.length} total [${typeSummary}], ${iframes.length} iframes (browser=${this._browserConnected})`);
|
|
2020
|
+
for (const t of allTargets) {
|
|
2021
|
+
if (t.type !== "page" && t.type !== "worker" && t.type !== "service_worker") {
|
|
2022
|
+
this.log(`[CDP] target: type=${t.type} url=${(t.url || "").substring(0, 120)}`);
|
|
2023
|
+
}
|
|
2024
|
+
if ((t.url || "").includes("vscode-webview")) {
|
|
2025
|
+
this.log(`[CDP] webview: type=${t.type} url=${(t.url || "").substring(0, 150)}`);
|
|
2026
|
+
}
|
|
1920
2027
|
}
|
|
1921
2028
|
}
|
|
1922
2029
|
const agents = [];
|
|
@@ -1973,14 +2080,14 @@ var init_daemon_cdp = __esm({
|
|
|
1973
2080
|
if (!ws || ws.readyState !== import_ws3.default.OPEN) {
|
|
1974
2081
|
throw new Error("CDP not connected");
|
|
1975
2082
|
}
|
|
1976
|
-
return new Promise((
|
|
2083
|
+
return new Promise((resolve6, reject) => {
|
|
1977
2084
|
const id = getNextId();
|
|
1978
2085
|
pendingMap.set(id, {
|
|
1979
2086
|
resolve: (result) => {
|
|
1980
2087
|
if (result?.result?.subtype === "error") {
|
|
1981
2088
|
reject(new Error(result.result.description));
|
|
1982
2089
|
} else {
|
|
1983
|
-
|
|
2090
|
+
resolve6(result?.result?.value);
|
|
1984
2091
|
}
|
|
1985
2092
|
},
|
|
1986
2093
|
reject
|
|
@@ -2457,13 +2564,13 @@ var init_daemon_p2p = __esm({
|
|
|
2457
2564
|
} catch {
|
|
2458
2565
|
}
|
|
2459
2566
|
const http3 = require("https");
|
|
2460
|
-
const data = await new Promise((
|
|
2567
|
+
const data = await new Promise((resolve6, reject) => {
|
|
2461
2568
|
const req = http3.get(`${serverUrl}/api/v1/turn/credentials`, {
|
|
2462
2569
|
headers: { "Authorization": `Bearer ${token}` }
|
|
2463
2570
|
}, (res) => {
|
|
2464
2571
|
let d = "";
|
|
2465
2572
|
res.on("data", (c) => d += c);
|
|
2466
|
-
res.on("end", () =>
|
|
2573
|
+
res.on("end", () => resolve6(d));
|
|
2467
2574
|
});
|
|
2468
2575
|
req.on("error", reject);
|
|
2469
2576
|
req.setTimeout(5e3, () => {
|
|
@@ -2613,7 +2720,9 @@ var init_daemon_p2p = __esm({
|
|
|
2613
2720
|
const text = typeof msg === "string" ? msg : msg.toString("utf-8");
|
|
2614
2721
|
try {
|
|
2615
2722
|
const parsed = JSON.parse(text);
|
|
2616
|
-
|
|
2723
|
+
if (parsed.type !== "command" && parsed.type !== "pty_input" && parsed.type !== "pty_resize") {
|
|
2724
|
+
log(`Files message from peer ${peerId}: type=${parsed.type}`);
|
|
2725
|
+
}
|
|
2617
2726
|
if (parsed.type === "screenshot_start") {
|
|
2618
2727
|
const peer = this.peers.get(peerId);
|
|
2619
2728
|
if (peer) {
|
|
@@ -2834,7 +2943,11 @@ var init_daemon_p2p = __esm({
|
|
|
2834
2943
|
return;
|
|
2835
2944
|
}
|
|
2836
2945
|
if (type === "p2p_answer") {
|
|
2837
|
-
|
|
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);
|
|
2838
2951
|
if (peer?.pc) {
|
|
2839
2952
|
log(`Received SDP answer for peer ${peer.peerId}`);
|
|
2840
2953
|
peer.pc.setRemoteDescription(payload.sdp, payload.type);
|
|
@@ -2842,16 +2955,18 @@ var init_daemon_p2p = __esm({
|
|
|
2842
2955
|
return;
|
|
2843
2956
|
}
|
|
2844
2957
|
if (type === "p2p_ice") {
|
|
2845
|
-
|
|
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);
|
|
2846
2963
|
if (peer?.pc && payload.candidate) {
|
|
2847
2964
|
peer.pc.addRemoteCandidate(payload.candidate, payload.mid || payload.sdpMid || "0");
|
|
2848
2965
|
}
|
|
2849
2966
|
return;
|
|
2850
2967
|
}
|
|
2851
2968
|
}
|
|
2852
|
-
getFirstPeer
|
|
2853
|
-
return this.peers.values().next().value;
|
|
2854
|
-
}
|
|
2969
|
+
// getFirstPeer removed — multi-peer requires explicit peerId routing
|
|
2855
2970
|
// ─── 연결 관리 ──────────────────────────────
|
|
2856
2971
|
disconnectPeer(peerId) {
|
|
2857
2972
|
const peer = this.peers.get(peerId);
|
|
@@ -3136,15 +3251,15 @@ var init_dev_server = __esm({
|
|
|
3136
3251
|
this.json(res, 500, { error: e.message });
|
|
3137
3252
|
}
|
|
3138
3253
|
});
|
|
3139
|
-
return new Promise((
|
|
3254
|
+
return new Promise((resolve6, reject) => {
|
|
3140
3255
|
this.server.listen(port, "127.0.0.1", () => {
|
|
3141
3256
|
this.log(`Dev server listening on http://127.0.0.1:${port}`);
|
|
3142
|
-
|
|
3257
|
+
resolve6();
|
|
3143
3258
|
});
|
|
3144
3259
|
this.server.on("error", (e) => {
|
|
3145
3260
|
if (e.code === "EADDRINUSE") {
|
|
3146
3261
|
this.log(`Port ${port} in use, skipping dev server`);
|
|
3147
|
-
|
|
3262
|
+
resolve6();
|
|
3148
3263
|
} else {
|
|
3149
3264
|
reject(e);
|
|
3150
3265
|
}
|
|
@@ -3811,14 +3926,14 @@ var init_dev_server = __esm({
|
|
|
3811
3926
|
res.end(JSON.stringify(data, null, 2));
|
|
3812
3927
|
}
|
|
3813
3928
|
async readBody(req) {
|
|
3814
|
-
return new Promise((
|
|
3929
|
+
return new Promise((resolve6) => {
|
|
3815
3930
|
let body = "";
|
|
3816
3931
|
req.on("data", (chunk) => body += chunk);
|
|
3817
3932
|
req.on("end", () => {
|
|
3818
3933
|
try {
|
|
3819
|
-
|
|
3934
|
+
resolve6(JSON.parse(body));
|
|
3820
3935
|
} catch {
|
|
3821
|
-
|
|
3936
|
+
resolve6({});
|
|
3822
3937
|
}
|
|
3823
3938
|
});
|
|
3824
3939
|
});
|
|
@@ -4153,12 +4268,10 @@ var init_daemon_commands = __esm({
|
|
|
4153
4268
|
getCdp(ideType) {
|
|
4154
4269
|
const key = ideType || this._currentIdeType;
|
|
4155
4270
|
if (!key) {
|
|
4156
|
-
console.log(`[getCdp] \u26A0 No ideType specified, cannot resolve CDP`);
|
|
4157
4271
|
return null;
|
|
4158
4272
|
}
|
|
4159
4273
|
const m = this.ctx.cdpManagers.get(key.toLowerCase());
|
|
4160
4274
|
if (m?.isConnected) return m;
|
|
4161
|
-
console.log(`[getCdp] \u26A0 Target IDE "${key}" CDP not available`);
|
|
4162
4275
|
return null;
|
|
4163
4276
|
}
|
|
4164
4277
|
/** Current IDE type extracted from command args (per-request) */
|
|
@@ -4193,7 +4306,11 @@ var init_daemon_commands = __esm({
|
|
|
4193
4306
|
getProvider(overrideType) {
|
|
4194
4307
|
const key = overrideType || this._currentProviderType || this._currentIdeType;
|
|
4195
4308
|
if (!key || !this.ctx.providerLoader) return void 0;
|
|
4196
|
-
|
|
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;
|
|
4197
4314
|
}
|
|
4198
4315
|
/** Get a provider script by name from ProviderLoader.
|
|
4199
4316
|
* Returns the script string or null. */
|
|
@@ -4264,7 +4381,12 @@ var init_daemon_commands = __esm({
|
|
|
4264
4381
|
async handle(cmd, args) {
|
|
4265
4382
|
this._currentIdeType = this.extractIdeType(args);
|
|
4266
4383
|
this._currentProviderType = args?.agentType || args?.providerType || this._currentIdeType;
|
|
4267
|
-
|
|
4384
|
+
if (!this._currentIdeType && !this._currentProviderType) {
|
|
4385
|
+
const cdpCommands = ["send_chat", "read_chat", "list_chats", "new_chat", "switch_chat", "set_mode", "change_model", "resolve_action"];
|
|
4386
|
+
if (cdpCommands.includes(cmd)) {
|
|
4387
|
+
return { success: false, error: "No ideType specified \u2014 cannot route command" };
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4268
4390
|
switch (cmd) {
|
|
4269
4391
|
// ─── CDP 직접 처리 ───────────────────
|
|
4270
4392
|
case "read_chat":
|
|
@@ -4366,6 +4488,20 @@ var init_daemon_commands = __esm({
|
|
|
4366
4488
|
return this.handleGetProviderSettings(args);
|
|
4367
4489
|
case "set_provider_setting":
|
|
4368
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");
|
|
4369
4505
|
default:
|
|
4370
4506
|
return { success: false, error: `Unknown command: ${cmd}` };
|
|
4371
4507
|
}
|
|
@@ -4676,6 +4812,7 @@ var init_daemon_commands = __esm({
|
|
|
4676
4812
|
const provider2 = this.getProvider();
|
|
4677
4813
|
const action = args?.action || "approve";
|
|
4678
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}`);
|
|
4679
4816
|
if (provider2?.category === "extension" && this.agentStream && this.getCdp()) {
|
|
4680
4817
|
const ok = await this.agentStream.resolveAgentAction(
|
|
4681
4818
|
this.getCdp(),
|
|
@@ -4685,14 +4822,50 @@ var init_daemon_commands = __esm({
|
|
|
4685
4822
|
);
|
|
4686
4823
|
return { success: ok };
|
|
4687
4824
|
}
|
|
4688
|
-
|
|
4689
|
-
const
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
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
|
+
}
|
|
4696
4869
|
}
|
|
4697
4870
|
return { success: false, error: "resolveAction script not available for this provider" };
|
|
4698
4871
|
}
|
|
@@ -5087,6 +5260,103 @@ var init_daemon_commands = __esm({
|
|
|
5087
5260
|
}
|
|
5088
5261
|
return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
|
|
5089
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
|
+
}
|
|
5090
5360
|
};
|
|
5091
5361
|
}
|
|
5092
5362
|
});
|
|
@@ -5229,12 +5499,12 @@ var init_manager = __esm({
|
|
|
5229
5499
|
constructor(logFn, providerLoader) {
|
|
5230
5500
|
this.logFn = logFn || console.log;
|
|
5231
5501
|
if (providerLoader) {
|
|
5232
|
-
const
|
|
5233
|
-
|
|
5502
|
+
const allExtProviders = providerLoader.getByCategory("extension");
|
|
5503
|
+
for (const p of allExtProviders) {
|
|
5234
5504
|
const adapter = new ProviderStreamAdapter(p);
|
|
5505
|
+
this.allAdapters.push(adapter);
|
|
5235
5506
|
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name})`);
|
|
5236
|
-
|
|
5237
|
-
});
|
|
5507
|
+
}
|
|
5238
5508
|
}
|
|
5239
5509
|
}
|
|
5240
5510
|
setLocalServer(server) {
|
|
@@ -5488,14 +5758,238 @@ var init_agent_stream = __esm({
|
|
|
5488
5758
|
}
|
|
5489
5759
|
});
|
|
5490
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
|
+
|
|
5491
5984
|
// src/daemon-status.ts
|
|
5492
|
-
var
|
|
5985
|
+
var os7, path7, DaemonStatusReporter;
|
|
5493
5986
|
var init_daemon_status = __esm({
|
|
5494
5987
|
"src/daemon-status.ts"() {
|
|
5495
5988
|
"use strict";
|
|
5496
|
-
|
|
5497
|
-
|
|
5989
|
+
os7 = __toESM(require("os"));
|
|
5990
|
+
path7 = __toESM(require("path"));
|
|
5498
5991
|
init_config();
|
|
5992
|
+
init_daemon_logger();
|
|
5499
5993
|
DaemonStatusReporter = class {
|
|
5500
5994
|
deps;
|
|
5501
5995
|
log;
|
|
@@ -5553,7 +6047,7 @@ var init_daemon_status = __esm({
|
|
|
5553
6047
|
}
|
|
5554
6048
|
}
|
|
5555
6049
|
emitStatusEvent(event) {
|
|
5556
|
-
|
|
6050
|
+
LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
5557
6051
|
this.deps.bridge?.sendMessage("status_event", event);
|
|
5558
6052
|
}
|
|
5559
6053
|
removeAgentTracking(_key) {
|
|
@@ -5580,7 +6074,8 @@ var init_daemon_status = __esm({
|
|
|
5580
6074
|
return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
|
|
5581
6075
|
}).join(", ");
|
|
5582
6076
|
const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
|
|
5583
|
-
|
|
6077
|
+
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
6078
|
+
LOG[logLevel]("StatusReport", `\u2192${target} IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}]`);
|
|
5584
6079
|
const managedIdes = ideStates.map((s) => ({
|
|
5585
6080
|
ideType: s.type,
|
|
5586
6081
|
ideVersion: "",
|
|
@@ -5606,23 +6101,45 @@ var init_daemon_status = __esm({
|
|
|
5606
6101
|
currentAutoApprove: s.currentAutoApprove
|
|
5607
6102
|
}));
|
|
5608
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
|
+
}
|
|
5609
6110
|
const perExtData = localServer?.getPerExtensionData() || [];
|
|
5610
6111
|
for (const ext of perExtData) {
|
|
5611
6112
|
const ideKey = ext.ideType.toLowerCase();
|
|
5612
|
-
if (
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
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
|
+
}
|
|
5626
6143
|
}
|
|
5627
6144
|
const managedClis = cliStates.map((s) => ({
|
|
5628
6145
|
id: s.instanceId,
|
|
@@ -5644,15 +6161,15 @@ var init_daemon_status = __esm({
|
|
|
5644
6161
|
daemonMode: true,
|
|
5645
6162
|
machineNickname: loadConfig().machineNickname || null,
|
|
5646
6163
|
machine: {
|
|
5647
|
-
hostname:
|
|
5648
|
-
platform:
|
|
5649
|
-
release:
|
|
5650
|
-
arch:
|
|
5651
|
-
cpus:
|
|
5652
|
-
totalMem:
|
|
5653
|
-
freeMem:
|
|
5654
|
-
loadavg:
|
|
5655
|
-
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()
|
|
5656
6173
|
},
|
|
5657
6174
|
managedIdes,
|
|
5658
6175
|
managedClis,
|
|
@@ -5674,7 +6191,7 @@ var init_daemon_status = __esm({
|
|
|
5674
6191
|
})),
|
|
5675
6192
|
timestamp: now,
|
|
5676
6193
|
activeFile: extSummary.activeFile,
|
|
5677
|
-
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 })),
|
|
5678
6195
|
terminals: extSummary.terminals,
|
|
5679
6196
|
aiAgents: [
|
|
5680
6197
|
...managedIdes.flatMap((ide) => (ide.aiAgents || []).map((a) => ({
|
|
@@ -5682,17 +6199,17 @@ var init_daemon_status = __esm({
|
|
|
5682
6199
|
name: a.name,
|
|
5683
6200
|
status: a.status,
|
|
5684
6201
|
ideType: ide.ideType
|
|
5685
|
-
})))
|
|
5686
|
-
|
|
6202
|
+
})))
|
|
6203
|
+
// CLIs are already in managedClis — don't duplicate here
|
|
5687
6204
|
],
|
|
5688
6205
|
activeChat: managedClis[0]?.activeChat || managedIdes[0]?.activeChat || null,
|
|
5689
6206
|
agentStreams: managedIdes.flatMap((ide) => ide.agentStreams || []),
|
|
5690
6207
|
connectedExtensions: extSummary.connectedIdes,
|
|
5691
|
-
system: { platform:
|
|
6208
|
+
system: { platform: os7.platform(), hostname: os7.hostname() }
|
|
5692
6209
|
};
|
|
5693
6210
|
const p2pSent = this.sendP2PPayload(payload);
|
|
5694
6211
|
if (p2pSent) {
|
|
5695
|
-
|
|
6212
|
+
LOG.debug("P2P", `sent (${JSON.stringify(payload).length} bytes)`);
|
|
5696
6213
|
}
|
|
5697
6214
|
if (opts?.p2pOnly) return;
|
|
5698
6215
|
const plan = bridge.getUserPlan();
|
|
@@ -5701,11 +6218,11 @@ var init_daemon_status = __esm({
|
|
|
5701
6218
|
daemonMode: true,
|
|
5702
6219
|
machineNickname: payload.machineNickname,
|
|
5703
6220
|
machine: {
|
|
5704
|
-
hostname:
|
|
5705
|
-
platform:
|
|
5706
|
-
arch:
|
|
5707
|
-
cpus:
|
|
5708
|
-
totalMem:
|
|
6221
|
+
hostname: os7.hostname(),
|
|
6222
|
+
platform: os7.platform(),
|
|
6223
|
+
arch: os7.arch(),
|
|
6224
|
+
cpus: os7.cpus().length,
|
|
6225
|
+
totalMem: os7.totalmem()
|
|
5709
6226
|
},
|
|
5710
6227
|
managedIdes: managedIdes.map((ide) => ({
|
|
5711
6228
|
ideType: ide.ideType,
|
|
@@ -5729,7 +6246,7 @@ var init_daemon_status = __esm({
|
|
|
5729
6246
|
timestamp: now
|
|
5730
6247
|
};
|
|
5731
6248
|
bridge.sendMessage("status_report", wsPayload);
|
|
5732
|
-
|
|
6249
|
+
LOG.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)`);
|
|
5733
6250
|
}
|
|
5734
6251
|
}
|
|
5735
6252
|
// ─── P2P ─────────────────────────────────────────
|
|
@@ -5764,7 +6281,7 @@ function stripAnsi(str) {
|
|
|
5764
6281
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "");
|
|
5765
6282
|
}
|
|
5766
6283
|
function findBinary(name) {
|
|
5767
|
-
const isWin =
|
|
6284
|
+
const isWin = os8.platform() === "win32";
|
|
5768
6285
|
try {
|
|
5769
6286
|
const cmd = isWin ? `where ${name}` : `which ${name}`;
|
|
5770
6287
|
return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
|
|
@@ -5772,11 +6289,11 @@ function findBinary(name) {
|
|
|
5772
6289
|
return isWin ? `${name}.cmd` : name;
|
|
5773
6290
|
}
|
|
5774
6291
|
}
|
|
5775
|
-
var
|
|
6292
|
+
var os8, import_child_process4, pty, ProviderCliAdapter;
|
|
5776
6293
|
var init_provider_cli_adapter = __esm({
|
|
5777
6294
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
5778
6295
|
"use strict";
|
|
5779
|
-
|
|
6296
|
+
os8 = __toESM(require("os"));
|
|
5780
6297
|
import_child_process4 = require("child_process");
|
|
5781
6298
|
try {
|
|
5782
6299
|
pty = require("node-pty");
|
|
@@ -5789,7 +6306,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
5789
6306
|
this.provider = provider2;
|
|
5790
6307
|
this.cliType = provider2.type;
|
|
5791
6308
|
this.cliName = provider2.name;
|
|
5792
|
-
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/,
|
|
6309
|
+
this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os8.homedir()) : workingDir;
|
|
5793
6310
|
const t = provider2.timeouts || {};
|
|
5794
6311
|
this.timeouts = {
|
|
5795
6312
|
ptyFlush: t.ptyFlush ?? 50,
|
|
@@ -5847,7 +6364,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
5847
6364
|
if (!pty) throw new Error("node-pty is not installed");
|
|
5848
6365
|
const { spawn: spawnConfig } = this.provider;
|
|
5849
6366
|
const binaryPath = findBinary(spawnConfig.command);
|
|
5850
|
-
const isWin =
|
|
6367
|
+
const isWin = os8.platform() === "win32";
|
|
5851
6368
|
const allArgs = [...spawnConfig.args, ...this.extraArgs];
|
|
5852
6369
|
console.log(`[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
5853
6370
|
let shellCmd;
|
|
@@ -6089,7 +6606,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
6089
6606
|
|
|
6090
6607
|
// src/cli-detector.ts
|
|
6091
6608
|
async function detectCLIs() {
|
|
6092
|
-
const platform7 =
|
|
6609
|
+
const platform7 = os9.platform();
|
|
6093
6610
|
const whichCmd = platform7 === "win32" ? "where" : "which";
|
|
6094
6611
|
const results = [];
|
|
6095
6612
|
for (const cli of KNOWN_CLIS) {
|
|
@@ -6123,12 +6640,12 @@ async function detectCLI(cliId) {
|
|
|
6123
6640
|
const all = await detectCLIs();
|
|
6124
6641
|
return all.find((c) => c.id === normalizedId && c.installed) || null;
|
|
6125
6642
|
}
|
|
6126
|
-
var import_child_process5,
|
|
6643
|
+
var import_child_process5, os9, KNOWN_CLIS;
|
|
6127
6644
|
var init_cli_detector = __esm({
|
|
6128
6645
|
"src/cli-detector.ts"() {
|
|
6129
6646
|
"use strict";
|
|
6130
6647
|
import_child_process5 = require("child_process");
|
|
6131
|
-
|
|
6648
|
+
os9 = __toESM(require("os"));
|
|
6132
6649
|
KNOWN_CLIS = [
|
|
6133
6650
|
{ id: "gemini-cli", displayName: "Gemini CLI", icon: "\u264A", command: "gemini" },
|
|
6134
6651
|
{ id: "claude-code", displayName: "Claude Code", icon: "\u{1F916}", command: "claude" },
|
|
@@ -6137,17 +6654,267 @@ var init_cli_detector = __esm({
|
|
|
6137
6654
|
}
|
|
6138
6655
|
});
|
|
6139
6656
|
|
|
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
|
+
|
|
6140
6906
|
// src/daemon-cli.ts
|
|
6141
|
-
var
|
|
6907
|
+
var os10, path9, import_chalk, DaemonCliManager;
|
|
6142
6908
|
var init_daemon_cli = __esm({
|
|
6143
6909
|
"src/daemon-cli.ts"() {
|
|
6144
6910
|
"use strict";
|
|
6145
|
-
|
|
6146
|
-
|
|
6911
|
+
os10 = __toESM(require("os"));
|
|
6912
|
+
path9 = __toESM(require("path"));
|
|
6147
6913
|
import_chalk = __toESM(require("chalk"));
|
|
6148
6914
|
init_provider_cli_adapter();
|
|
6149
6915
|
init_cli_detector();
|
|
6150
6916
|
init_config();
|
|
6917
|
+
init_cli_provider_instance();
|
|
6151
6918
|
DaemonCliManager = class {
|
|
6152
6919
|
adapters = /* @__PURE__ */ new Map();
|
|
6153
6920
|
deps;
|
|
@@ -6181,8 +6948,8 @@ var init_daemon_cli = __esm({
|
|
|
6181
6948
|
}
|
|
6182
6949
|
// ─── 세션 시작/중지 ──────────────────────────────
|
|
6183
6950
|
async startSession(cliType, workingDir, cliArgs) {
|
|
6184
|
-
const trimmed = (workingDir ||
|
|
6185
|
-
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);
|
|
6186
6953
|
const cliInfo = await detectCLI(cliType);
|
|
6187
6954
|
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
6188
6955
|
const key = this.getCliKey(cliType, resolvedDir);
|
|
@@ -6190,34 +6957,57 @@ var init_daemon_cli = __esm({
|
|
|
6190
6957
|
console.log(import_chalk.default.yellow(` \u26A1 CLI ${cliType} already running in ${resolvedDir}`));
|
|
6191
6958
|
return;
|
|
6192
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);
|
|
6193
6966
|
console.log(import_chalk.default.yellow(` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
const bridge = this.deps.getBridge();
|
|
6197
|
-
if (bridge && typeof adapter.setBridge === "function") {
|
|
6198
|
-
adapter.setBridge(bridge);
|
|
6967
|
+
if (provider2) {
|
|
6968
|
+
console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider2.name} (${provider2.type})`));
|
|
6199
6969
|
}
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
const
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
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
|
+
}
|
|
6217
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}`));
|
|
6218
7010
|
}
|
|
6219
|
-
this.adapters.set(key, adapter);
|
|
6220
|
-
console.log(import_chalk.default.green(` \u2713 CLI started: ${cliInfo.displayName} v${cliInfo.version || "unknown"} in ${resolvedDir}`));
|
|
6221
7011
|
try {
|
|
6222
7012
|
addCliHistory({ cliType, dir: resolvedDir, cliArgs });
|
|
6223
7013
|
} catch (e) {
|
|
@@ -6231,6 +7021,7 @@ var init_daemon_cli = __esm({
|
|
|
6231
7021
|
adapter.shutdown();
|
|
6232
7022
|
this.adapters.delete(key);
|
|
6233
7023
|
this.deps.removeAgentTracking(key);
|
|
7024
|
+
this.deps.getInstanceManager()?.removeInstance(key);
|
|
6234
7025
|
console.log(import_chalk.default.yellow(` \u{1F6D1} CLI Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`));
|
|
6235
7026
|
this.deps.onStatusChange();
|
|
6236
7027
|
}
|
|
@@ -6258,7 +7049,8 @@ var init_daemon_cli = __esm({
|
|
|
6258
7049
|
switch (cmd) {
|
|
6259
7050
|
case "launch_cli": {
|
|
6260
7051
|
const cliType = args?.cliType;
|
|
6261
|
-
const
|
|
7052
|
+
const defaultedToHome = !args?.dir;
|
|
7053
|
+
const dir = args?.dir || os10.homedir();
|
|
6262
7054
|
if (!cliType) throw new Error("cliType required");
|
|
6263
7055
|
const key = this.getCliKey(cliType, dir);
|
|
6264
7056
|
if (!this.adapters.has(key)) {
|
|
@@ -6276,7 +7068,7 @@ var init_daemon_cli = __esm({
|
|
|
6276
7068
|
console.error(import_chalk.default.red(` \u2717 Failed to save recent workspace: ${e}`));
|
|
6277
7069
|
}
|
|
6278
7070
|
}
|
|
6279
|
-
return { success: true, cliType, dir, id: key };
|
|
7071
|
+
return { success: true, cliType, dir, id: key, defaultedToHome };
|
|
6280
7072
|
}
|
|
6281
7073
|
case "stop_cli": {
|
|
6282
7074
|
const cliType = args?.cliType;
|
|
@@ -6480,99 +7272,6 @@ var init_provider_instance_manager = __esm({
|
|
|
6480
7272
|
}
|
|
6481
7273
|
});
|
|
6482
7274
|
|
|
6483
|
-
// src/providers/status-monitor.ts
|
|
6484
|
-
var DEFAULT_MONITOR_CONFIG, StatusMonitor;
|
|
6485
|
-
var init_status_monitor = __esm({
|
|
6486
|
-
"src/providers/status-monitor.ts"() {
|
|
6487
|
-
"use strict";
|
|
6488
|
-
DEFAULT_MONITOR_CONFIG = {
|
|
6489
|
-
approvalAlert: true,
|
|
6490
|
-
longGeneratingAlert: true,
|
|
6491
|
-
longGeneratingThresholdSec: 180,
|
|
6492
|
-
// 3분
|
|
6493
|
-
alertCooldownSec: 60
|
|
6494
|
-
// 1분 쿨다운
|
|
6495
|
-
};
|
|
6496
|
-
StatusMonitor = class {
|
|
6497
|
-
config;
|
|
6498
|
-
lastAlertTime = /* @__PURE__ */ new Map();
|
|
6499
|
-
generatingStartTimes = /* @__PURE__ */ new Map();
|
|
6500
|
-
constructor(config) {
|
|
6501
|
-
this.config = { ...DEFAULT_MONITOR_CONFIG, ...config };
|
|
6502
|
-
}
|
|
6503
|
-
/** 설정 업데이트 (Provider Settings에서 호출) */
|
|
6504
|
-
updateConfig(partial) {
|
|
6505
|
-
Object.assign(this.config, partial);
|
|
6506
|
-
}
|
|
6507
|
-
/** 현재 설정 반환 */
|
|
6508
|
-
getConfig() {
|
|
6509
|
-
return { ...this.config };
|
|
6510
|
-
}
|
|
6511
|
-
/**
|
|
6512
|
-
* 상태 전이 체크 → 알림 이벤트 배열 반환
|
|
6513
|
-
* 각 onTick()에서 호출.
|
|
6514
|
-
*/
|
|
6515
|
-
check(agentKey, status, now) {
|
|
6516
|
-
const events = [];
|
|
6517
|
-
if (this.config.approvalAlert && status === "waiting_approval") {
|
|
6518
|
-
if (this.shouldAlert(agentKey + ":approval", now)) {
|
|
6519
|
-
events.push({
|
|
6520
|
-
type: "monitor:approval_waiting",
|
|
6521
|
-
agentKey,
|
|
6522
|
-
timestamp: now,
|
|
6523
|
-
message: `${agentKey} is waiting for approval`
|
|
6524
|
-
});
|
|
6525
|
-
}
|
|
6526
|
-
}
|
|
6527
|
-
if (status === "generating" || status === "streaming") {
|
|
6528
|
-
if (!this.generatingStartTimes.has(agentKey)) {
|
|
6529
|
-
this.generatingStartTimes.set(agentKey, now);
|
|
6530
|
-
}
|
|
6531
|
-
if (this.config.longGeneratingAlert) {
|
|
6532
|
-
const startedAt = this.generatingStartTimes.get(agentKey);
|
|
6533
|
-
const elapsedSec = Math.round((now - startedAt) / 1e3);
|
|
6534
|
-
if (elapsedSec > this.config.longGeneratingThresholdSec) {
|
|
6535
|
-
if (this.shouldAlert(agentKey + ":long_gen", now)) {
|
|
6536
|
-
events.push({
|
|
6537
|
-
type: "monitor:long_generating",
|
|
6538
|
-
agentKey,
|
|
6539
|
-
elapsedSec,
|
|
6540
|
-
timestamp: now,
|
|
6541
|
-
message: `${agentKey} has been generating for ${Math.round(elapsedSec / 60)}min`
|
|
6542
|
-
});
|
|
6543
|
-
}
|
|
6544
|
-
}
|
|
6545
|
-
}
|
|
6546
|
-
} else {
|
|
6547
|
-
this.generatingStartTimes.delete(agentKey);
|
|
6548
|
-
}
|
|
6549
|
-
return events;
|
|
6550
|
-
}
|
|
6551
|
-
/** 쿨다운 체크 — 같은 알림을 너무 자주 보내지 않도록 */
|
|
6552
|
-
shouldAlert(key, now) {
|
|
6553
|
-
const last = this.lastAlertTime.get(key) || 0;
|
|
6554
|
-
if (now - last > this.config.alertCooldownSec * 1e3) {
|
|
6555
|
-
this.lastAlertTime.set(key, now);
|
|
6556
|
-
return true;
|
|
6557
|
-
}
|
|
6558
|
-
return false;
|
|
6559
|
-
}
|
|
6560
|
-
/** 리셋 (에이전트 종료/재시작 시) */
|
|
6561
|
-
reset(agentKey) {
|
|
6562
|
-
if (agentKey) {
|
|
6563
|
-
this.generatingStartTimes.delete(agentKey);
|
|
6564
|
-
for (const k of this.lastAlertTime.keys()) {
|
|
6565
|
-
if (k.startsWith(agentKey)) this.lastAlertTime.delete(k);
|
|
6566
|
-
}
|
|
6567
|
-
} else {
|
|
6568
|
-
this.generatingStartTimes.clear();
|
|
6569
|
-
this.lastAlertTime.clear();
|
|
6570
|
-
}
|
|
6571
|
-
}
|
|
6572
|
-
};
|
|
6573
|
-
}
|
|
6574
|
-
});
|
|
6575
|
-
|
|
6576
7275
|
// src/providers/extension-provider-instance.ts
|
|
6577
7276
|
var ExtensionProviderInstance;
|
|
6578
7277
|
var init_extension_provider_instance = __esm({
|
|
@@ -6695,11 +7394,11 @@ var init_extension_provider_instance = __esm({
|
|
|
6695
7394
|
});
|
|
6696
7395
|
|
|
6697
7396
|
// src/providers/ide-provider-instance.ts
|
|
6698
|
-
var
|
|
7397
|
+
var os11, crypto, IdeProviderInstance;
|
|
6699
7398
|
var init_ide_provider_instance = __esm({
|
|
6700
7399
|
"src/providers/ide-provider-instance.ts"() {
|
|
6701
7400
|
"use strict";
|
|
6702
|
-
|
|
7401
|
+
os11 = __toESM(require("os"));
|
|
6703
7402
|
crypto = __toESM(require("crypto"));
|
|
6704
7403
|
init_extension_provider_instance();
|
|
6705
7404
|
init_status_monitor();
|
|
@@ -6725,10 +7424,10 @@ var init_ide_provider_instance = __esm({
|
|
|
6725
7424
|
activeFile = null;
|
|
6726
7425
|
// ─── 자식 Extension Instances ────────────────────
|
|
6727
7426
|
extensions = /* @__PURE__ */ new Map();
|
|
6728
|
-
constructor(provider2) {
|
|
7427
|
+
constructor(provider2, instanceKey) {
|
|
6729
7428
|
this.type = provider2.type;
|
|
6730
7429
|
this.provider = provider2;
|
|
6731
|
-
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)}`;
|
|
6732
7431
|
this.monitor = new StatusMonitor();
|
|
6733
7432
|
}
|
|
6734
7433
|
// ─── Lifecycle ─────────────────────────────────
|
|
@@ -6859,7 +7558,14 @@ var init_ide_provider_instance = __esm({
|
|
|
6859
7558
|
const readChatScript = this.getReadChatScript();
|
|
6860
7559
|
if (!readChatScript) return;
|
|
6861
7560
|
try {
|
|
6862
|
-
|
|
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
|
+
}
|
|
6863
7569
|
if (!raw || typeof raw !== "object") return;
|
|
6864
7570
|
let { activeModal } = raw;
|
|
6865
7571
|
if (activeModal) {
|
|
@@ -6952,107 +7658,6 @@ var init_ide_provider_instance = __esm({
|
|
|
6952
7658
|
}
|
|
6953
7659
|
});
|
|
6954
7660
|
|
|
6955
|
-
// src/daemon-logger.ts
|
|
6956
|
-
var daemon_logger_exports = {};
|
|
6957
|
-
__export(daemon_logger_exports, {
|
|
6958
|
-
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
6959
|
-
LOG_PATH: () => LOG_PATH,
|
|
6960
|
-
cdpLogFn: () => cdpLogFn,
|
|
6961
|
-
daemonLog: () => daemonLog,
|
|
6962
|
-
installGlobalInterceptor: () => installGlobalInterceptor
|
|
6963
|
-
});
|
|
6964
|
-
function rotateIfNeeded() {
|
|
6965
|
-
try {
|
|
6966
|
-
const stat = fs5.statSync(LOG_FILE);
|
|
6967
|
-
if (stat.size > MAX_LOG_SIZE) {
|
|
6968
|
-
const backup = LOG_FILE + ".old";
|
|
6969
|
-
try {
|
|
6970
|
-
fs5.unlinkSync(backup);
|
|
6971
|
-
} catch {
|
|
6972
|
-
}
|
|
6973
|
-
fs5.renameSync(LOG_FILE, backup);
|
|
6974
|
-
}
|
|
6975
|
-
} catch {
|
|
6976
|
-
}
|
|
6977
|
-
}
|
|
6978
|
-
function writeToFile(line) {
|
|
6979
|
-
try {
|
|
6980
|
-
fs5.appendFileSync(LOG_FILE, line + "\n");
|
|
6981
|
-
} catch {
|
|
6982
|
-
}
|
|
6983
|
-
}
|
|
6984
|
-
function daemonLog(category, msg) {
|
|
6985
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${category}] ${msg}`;
|
|
6986
|
-
origConsoleLog(line);
|
|
6987
|
-
writeToFile(line);
|
|
6988
|
-
}
|
|
6989
|
-
function cdpLogFn(ideType) {
|
|
6990
|
-
return (msg) => {
|
|
6991
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [CDP:${ideType}] ${msg}`;
|
|
6992
|
-
origConsoleLog(line);
|
|
6993
|
-
writeToFile(line);
|
|
6994
|
-
};
|
|
6995
|
-
}
|
|
6996
|
-
function installGlobalInterceptor() {
|
|
6997
|
-
if (interceptorInstalled) return;
|
|
6998
|
-
interceptorInstalled = true;
|
|
6999
|
-
const stripAnsi2 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
7000
|
-
console.log = (...args) => {
|
|
7001
|
-
origConsoleLog(...args);
|
|
7002
|
-
try {
|
|
7003
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
7004
|
-
const clean = stripAnsi2(msg);
|
|
7005
|
-
const line = clean.startsWith("[20") ? clean : `[${(/* @__PURE__ */ new Date()).toISOString()}] ${clean}`;
|
|
7006
|
-
writeToFile(line);
|
|
7007
|
-
} catch {
|
|
7008
|
-
}
|
|
7009
|
-
};
|
|
7010
|
-
console.error = (...args) => {
|
|
7011
|
-
origConsoleError(...args);
|
|
7012
|
-
try {
|
|
7013
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
7014
|
-
const clean = stripAnsi2(msg);
|
|
7015
|
-
writeToFile(`[${(/* @__PURE__ */ new Date()).toISOString()}] [ERROR] ${clean}`);
|
|
7016
|
-
} catch {
|
|
7017
|
-
}
|
|
7018
|
-
};
|
|
7019
|
-
console.warn = (...args) => {
|
|
7020
|
-
origConsoleWarn(...args);
|
|
7021
|
-
try {
|
|
7022
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
7023
|
-
const clean = stripAnsi2(msg);
|
|
7024
|
-
writeToFile(`[${(/* @__PURE__ */ new Date()).toISOString()}] [WARN] ${clean}`);
|
|
7025
|
-
} catch {
|
|
7026
|
-
}
|
|
7027
|
-
};
|
|
7028
|
-
writeToFile(`
|
|
7029
|
-
=== ADHDev Daemon started at ${(/* @__PURE__ */ new Date()).toISOString()} ===`);
|
|
7030
|
-
writeToFile(`Log file: ${LOG_FILE}`);
|
|
7031
|
-
}
|
|
7032
|
-
var fs5, path8, os11, LOG_DIR, LOG_FILE, MAX_LOG_SIZE, origConsoleLog, origConsoleError, origConsoleWarn, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
|
|
7033
|
-
var init_daemon_logger = __esm({
|
|
7034
|
-
"src/daemon-logger.ts"() {
|
|
7035
|
-
"use strict";
|
|
7036
|
-
fs5 = __toESM(require("fs"));
|
|
7037
|
-
path8 = __toESM(require("path"));
|
|
7038
|
-
os11 = __toESM(require("os"));
|
|
7039
|
-
LOG_DIR = process.platform === "darwin" ? path8.join(os11.homedir(), "Library", "Logs", "adhdev") : path8.join(os11.homedir(), ".local", "share", "adhdev", "logs");
|
|
7040
|
-
LOG_FILE = path8.join(LOG_DIR, "daemon.log");
|
|
7041
|
-
MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
7042
|
-
try {
|
|
7043
|
-
fs5.mkdirSync(LOG_DIR, { recursive: true });
|
|
7044
|
-
} catch {
|
|
7045
|
-
}
|
|
7046
|
-
rotateIfNeeded();
|
|
7047
|
-
origConsoleLog = console.log.bind(console);
|
|
7048
|
-
origConsoleError = console.error.bind(console);
|
|
7049
|
-
origConsoleWarn = console.warn.bind(console);
|
|
7050
|
-
interceptorInstalled = false;
|
|
7051
|
-
LOG_PATH = LOG_FILE;
|
|
7052
|
-
LOG_DIR_PATH = LOG_DIR;
|
|
7053
|
-
}
|
|
7054
|
-
});
|
|
7055
|
-
|
|
7056
7661
|
// src/adhdev-daemon.ts
|
|
7057
7662
|
var adhdev_daemon_exports = {};
|
|
7058
7663
|
__export(adhdev_daemon_exports, {
|
|
@@ -7061,9 +7666,9 @@ __export(adhdev_daemon_exports, {
|
|
|
7061
7666
|
stopDaemon: () => stopDaemon
|
|
7062
7667
|
});
|
|
7063
7668
|
function getDaemonPidFile() {
|
|
7064
|
-
const dir =
|
|
7669
|
+
const dir = path10.join(os12.homedir(), ".adhdev");
|
|
7065
7670
|
if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
|
|
7066
|
-
return
|
|
7671
|
+
return path10.join(dir, "daemon.pid");
|
|
7067
7672
|
}
|
|
7068
7673
|
function writeDaemonPid(pid) {
|
|
7069
7674
|
fs6.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
@@ -7099,7 +7704,7 @@ function stopDaemon() {
|
|
|
7099
7704
|
return false;
|
|
7100
7705
|
}
|
|
7101
7706
|
}
|
|
7102
|
-
var os12, fs6,
|
|
7707
|
+
var os12, fs6, path10, crypto2, import_chalk2, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
7103
7708
|
var init_adhdev_daemon = __esm({
|
|
7104
7709
|
"src/adhdev-daemon.ts"() {
|
|
7105
7710
|
"use strict";
|
|
@@ -7119,9 +7724,10 @@ var init_adhdev_daemon = __esm({
|
|
|
7119
7724
|
init_provider_instance_manager();
|
|
7120
7725
|
init_ide_provider_instance();
|
|
7121
7726
|
init_ipc_protocol();
|
|
7727
|
+
init_daemon_logger();
|
|
7122
7728
|
os12 = __toESM(require("os"));
|
|
7123
7729
|
fs6 = __toESM(require("fs"));
|
|
7124
|
-
|
|
7730
|
+
path10 = __toESM(require("path"));
|
|
7125
7731
|
crypto2 = __toESM(require("crypto"));
|
|
7126
7732
|
import_chalk2 = __toESM(require("chalk"));
|
|
7127
7733
|
DANGEROUS_PATTERNS = [
|
|
@@ -7163,7 +7769,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7163
7769
|
getBridge: () => this.bridge,
|
|
7164
7770
|
getP2p: () => this.p2p,
|
|
7165
7771
|
onStatusChange: () => this.statusReporter?.onStatusChange(),
|
|
7166
|
-
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key)
|
|
7772
|
+
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
7773
|
+
getInstanceManager: () => this.instanceManager
|
|
7167
7774
|
}, this.providerLoader);
|
|
7168
7775
|
}
|
|
7169
7776
|
async start(options = {}) {
|
|
@@ -7318,8 +7925,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7318
7925
|
});
|
|
7319
7926
|
this.p2p.onStateChange((state) => {
|
|
7320
7927
|
if (state === "connected") {
|
|
7321
|
-
|
|
7322
|
-
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}`));
|
|
7323
7930
|
}
|
|
7324
7931
|
});
|
|
7325
7932
|
let ssDebugCount = 0;
|
|
@@ -7330,18 +7937,18 @@ var init_adhdev_daemon = __esm({
|
|
|
7330
7937
|
if (!active || !cdp2) return;
|
|
7331
7938
|
ssDebugCount++;
|
|
7332
7939
|
if (ssDebugCount <= 3 || ssDebugCount % 25 === 0) {
|
|
7333
|
-
|
|
7940
|
+
LOG.debug("Screenshot", `Capturing... (tick ${ssDebugCount}, active=${active}, cdp=true)`);
|
|
7334
7941
|
}
|
|
7335
7942
|
try {
|
|
7336
7943
|
const buf = await cdp2.captureScreenshot();
|
|
7337
7944
|
if (buf) {
|
|
7338
7945
|
const sent = this.p2p.sendScreenshot(buf.toString("base64"));
|
|
7339
|
-
if (ssDebugCount <= 3)
|
|
7946
|
+
if (ssDebugCount <= 3) LOG.debug("Screenshot", `sent: ${buf.length} bytes, delivered=${sent}`);
|
|
7340
7947
|
} else {
|
|
7341
|
-
if (ssDebugCount <= 5)
|
|
7948
|
+
if (ssDebugCount <= 5) LOG.debug("Screenshot", "captureScreenshot returned null");
|
|
7342
7949
|
}
|
|
7343
7950
|
} catch (e) {
|
|
7344
|
-
if (ssDebugCount <= 5)
|
|
7951
|
+
if (ssDebugCount <= 5) LOG.warn("Screenshot", `error: ${e?.message}`);
|
|
7345
7952
|
}
|
|
7346
7953
|
}, 200);
|
|
7347
7954
|
} else {
|
|
@@ -7484,10 +8091,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7484
8091
|
}
|
|
7485
8092
|
}
|
|
7486
8093
|
async handleCommand(msg, cmd, args) {
|
|
7487
|
-
|
|
7488
|
-
if (cmd.startsWith("agent_stream") && args?._targetInstance) {
|
|
7489
|
-
console.log(import_chalk2.default.yellow(` \u{1F3AF} Target: ${args._targetType}:${args._targetInstance.split("_")[0]} agent=${args.agentType || ""}`));
|
|
7490
|
-
}
|
|
8094
|
+
LOG.info("Command", `${cmd}${args?._targetInstance ? ` \u2192 ${args._targetType}:${args._targetInstance.split("_")[0]}` : ""}`);
|
|
7491
8095
|
try {
|
|
7492
8096
|
switch (cmd) {
|
|
7493
8097
|
case "open_panel":
|
|
@@ -7559,17 +8163,22 @@ var init_adhdev_daemon = __esm({
|
|
|
7559
8163
|
return { success: true, nickname };
|
|
7560
8164
|
}
|
|
7561
8165
|
case "get_daemon_logs": {
|
|
7562
|
-
const
|
|
8166
|
+
const count = parseInt(data.lines) || 100;
|
|
8167
|
+
const minLevel = data.minLevel || "info";
|
|
7563
8168
|
try {
|
|
7564
|
-
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
|
+
}
|
|
7565
8174
|
const logFs = require("fs");
|
|
7566
|
-
if (logFs.existsSync(
|
|
7567
|
-
const content = logFs.readFileSync(
|
|
8175
|
+
if (logFs.existsSync(LOG_PATH2)) {
|
|
8176
|
+
const content = logFs.readFileSync(LOG_PATH2, "utf-8");
|
|
7568
8177
|
const allLines = content.split("\n");
|
|
7569
|
-
const recent = allLines.slice(-
|
|
8178
|
+
const recent = allLines.slice(-count).join("\n");
|
|
7570
8179
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
7571
8180
|
}
|
|
7572
|
-
return { success: true,
|
|
8181
|
+
return { success: true, entries: [], totalBuffered: 0 };
|
|
7573
8182
|
} catch (e) {
|
|
7574
8183
|
return { success: false, error: e.message };
|
|
7575
8184
|
}
|
|
@@ -7602,7 +8211,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7602
8211
|
case "launch_ide": {
|
|
7603
8212
|
const launchArgs = { ...args, ideId: args?.ideId || args?.ideType };
|
|
7604
8213
|
const ideKey = launchArgs.ideId;
|
|
7605
|
-
|
|
8214
|
+
LOG.info("LaunchIDE", `target=${ideKey || "auto"}`);
|
|
7606
8215
|
const result = await launchWithCdp(launchArgs);
|
|
7607
8216
|
if (result.success && result.port && result.ideId && !this.cdpManagers.has(result.ideId)) {
|
|
7608
8217
|
console.log(import_chalk2.default.cyan(`[launch_ide] Connecting CDP for ${result.ideId} on port ${result.port}...`));
|
|
@@ -7611,6 +8220,12 @@ var init_adhdev_daemon = __esm({
|
|
|
7611
8220
|
});
|
|
7612
8221
|
const connected = await manager.connect();
|
|
7613
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);
|
|
7614
8229
|
this.cdpManagers.set(result.ideId, manager);
|
|
7615
8230
|
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${result.ideId} (port ${result.port})`));
|
|
7616
8231
|
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
@@ -7692,6 +8307,37 @@ var init_adhdev_daemon = __esm({
|
|
|
7692
8307
|
if (this.agentStreamTimer) return;
|
|
7693
8308
|
this.agentStreamTimer = setInterval(async () => {
|
|
7694
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
|
+
}
|
|
7695
8341
|
if (this._agentStreamCdpIdeType) {
|
|
7696
8342
|
const cdp2 = this.cdpManagers.get(this._agentStreamCdpIdeType);
|
|
7697
8343
|
if (cdp2?.isConnected) {
|
|
@@ -7713,7 +8359,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7713
8359
|
if (discovered.length > 0) {
|
|
7714
8360
|
this._agentStreamCdpIdeType = ideType;
|
|
7715
8361
|
await this.agentStreamManager.switchActiveAgent(cdp2, discovered[0].agentType);
|
|
7716
|
-
|
|
8362
|
+
LOG.info("AgentStream", `Auto-activated: ${discovered[0].agentType} (${ideType})`);
|
|
7717
8363
|
await this.agentStreamManager.syncAgentSessions(cdp2);
|
|
7718
8364
|
const streams = await this.agentStreamManager.collectAgentStreams(cdp2);
|
|
7719
8365
|
this.statusReporter?.updateAgentStreams(ideType, streams);
|
|
@@ -7725,6 +8371,39 @@ var init_adhdev_daemon = __esm({
|
|
|
7725
8371
|
}
|
|
7726
8372
|
}, 5e3);
|
|
7727
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
|
+
}
|
|
7728
8407
|
async initCdp() {
|
|
7729
8408
|
const providerCdpMap = this.providerLoader.getCdpPortMap();
|
|
7730
8409
|
const cdpPortMap = {};
|
|
@@ -7745,49 +8424,87 @@ var init_adhdev_daemon = __esm({
|
|
|
7745
8424
|
const enabledIdes = loadConfig().enabledIdes || [];
|
|
7746
8425
|
const filteredPorts = enabledIdes.length > 0 ? portsToTry.filter((p) => enabledIdes.includes(p.ide)) : portsToTry;
|
|
7747
8426
|
for (const { port, ide } of filteredPorts) {
|
|
7748
|
-
const
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
const
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
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);
|
|
7759
8437
|
}
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
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);
|
|
7775
8458
|
}
|
|
7776
8459
|
}
|
|
7777
8460
|
}
|
|
7778
8461
|
if (this.cdpManagers.size > 0) {
|
|
7779
8462
|
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
7780
|
-
this.cdpDiscoveryTimer = setInterval(async () => {
|
|
7781
|
-
for (const m of this.cdpManagers.values()) {
|
|
7782
|
-
if (m.isConnected) {
|
|
7783
|
-
await m.discoverAgentWebviews();
|
|
7784
|
-
}
|
|
7785
|
-
}
|
|
7786
|
-
}, 3e4);
|
|
7787
8463
|
} else {
|
|
7788
8464
|
console.log(import_chalk2.default.yellow(` \u26A0 CDP not available \u2014 tried ports: ${portsToTry.map((p) => `${p.ide}:${p.port}`).join(", ")}`));
|
|
7789
8465
|
console.log(import_chalk2.default.yellow(` IDE may need relaunch with --remote-debugging-port`));
|
|
7790
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);
|
|
7791
8508
|
}
|
|
7792
8509
|
};
|
|
7793
8510
|
}
|
|
@@ -7935,10 +8652,10 @@ async function installExtension(ide, extension) {
|
|
|
7935
8652
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
7936
8653
|
const fs7 = await import("fs");
|
|
7937
8654
|
fs7.writeFileSync(vsixPath, buffer);
|
|
7938
|
-
return new Promise((
|
|
8655
|
+
return new Promise((resolve6) => {
|
|
7939
8656
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
7940
8657
|
(0, import_child_process2.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
7941
|
-
|
|
8658
|
+
resolve6({
|
|
7942
8659
|
extensionId: extension.id,
|
|
7943
8660
|
marketplaceId: extension.marketplaceId,
|
|
7944
8661
|
success: !error,
|
|
@@ -7969,11 +8686,11 @@ async function installExtension(ide, extension) {
|
|
|
7969
8686
|
}
|
|
7970
8687
|
}
|
|
7971
8688
|
}
|
|
7972
|
-
return new Promise((
|
|
8689
|
+
return new Promise((resolve6) => {
|
|
7973
8690
|
const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
|
|
7974
8691
|
(0, import_child_process2.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
|
|
7975
8692
|
if (error) {
|
|
7976
|
-
|
|
8693
|
+
resolve6({
|
|
7977
8694
|
extensionId: extension.id,
|
|
7978
8695
|
marketplaceId: extension.marketplaceId,
|
|
7979
8696
|
success: false,
|
|
@@ -7981,7 +8698,7 @@ async function installExtension(ide, extension) {
|
|
|
7981
8698
|
error: stderr || error.message
|
|
7982
8699
|
});
|
|
7983
8700
|
} else {
|
|
7984
|
-
|
|
8701
|
+
resolve6({
|
|
7985
8702
|
extensionId: extension.id,
|
|
7986
8703
|
marketplaceId: extension.marketplaceId,
|
|
7987
8704
|
success: true,
|
|
@@ -8157,11 +8874,12 @@ async function quickSetup() {
|
|
|
8157
8874
|
console.log(` ${import_chalk3.default.bold("Status:")} ${import_chalk3.default.green("Ready to connect")}`);
|
|
8158
8875
|
console.log();
|
|
8159
8876
|
console.log(import_chalk3.default.gray(" Commands:"));
|
|
8160
|
-
console.log(import_chalk3.default.gray(" adhdev daemon \u2014 Start daemon (
|
|
8161
|
-
console.log(import_chalk3.default.gray(" adhdev launch
|
|
8162
|
-
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"));
|
|
8163
8881
|
console.log(import_chalk3.default.gray(" adhdev status \u2014 Check setup status"));
|
|
8164
|
-
console.log(import_chalk3.default.gray(" adhdev setup \u2014 Reconfigure"));
|
|
8882
|
+
console.log(import_chalk3.default.gray(" adhdev setup \u2014 Reconfigure ADHDev"));
|
|
8165
8883
|
console.log();
|
|
8166
8884
|
await installCliOnly();
|
|
8167
8885
|
await startDaemonFlow();
|
|
@@ -8333,16 +9051,16 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
8333
9051
|
try {
|
|
8334
9052
|
const os13 = await import("os");
|
|
8335
9053
|
const fs7 = await import("fs");
|
|
8336
|
-
const
|
|
9054
|
+
const path11 = await import("path");
|
|
8337
9055
|
const platform7 = os13.platform();
|
|
8338
9056
|
const home = os13.homedir();
|
|
8339
9057
|
const getSettingsPath = (appName2) => {
|
|
8340
9058
|
if (platform7 === "darwin") {
|
|
8341
|
-
return
|
|
9059
|
+
return path11.join(home, "Library", "Application Support", appName2, "User", "settings.json");
|
|
8342
9060
|
} else if (platform7 === "win32") {
|
|
8343
|
-
return
|
|
9061
|
+
return path11.join(process.env.APPDATA || path11.join(home, "AppData", "Roaming"), appName2, "User", "settings.json");
|
|
8344
9062
|
} else {
|
|
8345
|
-
return
|
|
9063
|
+
return path11.join(home, ".config", appName2, "User", "settings.json");
|
|
8346
9064
|
}
|
|
8347
9065
|
};
|
|
8348
9066
|
const loader = new ProviderLoader({ logFn: () => {
|
|
@@ -8360,7 +9078,7 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
8360
9078
|
settings = {};
|
|
8361
9079
|
}
|
|
8362
9080
|
} else {
|
|
8363
|
-
fs7.mkdirSync(
|
|
9081
|
+
fs7.mkdirSync(path11.dirname(settingsPath), { recursive: true });
|
|
8364
9082
|
}
|
|
8365
9083
|
settings["adhdev.connectionToken"] = connectionToken;
|
|
8366
9084
|
settings["adhdev.autoConnect"] = true;
|
|
@@ -8382,7 +9100,7 @@ async function startDaemonFlow() {
|
|
|
8382
9100
|
{
|
|
8383
9101
|
type: "confirm",
|
|
8384
9102
|
name: "startDaemon",
|
|
8385
|
-
message: "Start ADHDev Daemon now? (
|
|
9103
|
+
message: "Start the ADHDev Daemon now? (Required for all agent/IDE routing features)",
|
|
8386
9104
|
default: true
|
|
8387
9105
|
}
|
|
8388
9106
|
]);
|
|
@@ -8396,8 +9114,8 @@ async function startDaemonFlow() {
|
|
|
8396
9114
|
const daemon = new AdhdevDaemon2();
|
|
8397
9115
|
const { execSync: execSync6 } = await import("child_process");
|
|
8398
9116
|
const os13 = await import("os");
|
|
8399
|
-
const
|
|
8400
|
-
const logPath =
|
|
9117
|
+
const path11 = await import("path");
|
|
9118
|
+
const logPath = path11.join(os13.homedir(), ".adhdev", "daemon.log");
|
|
8401
9119
|
try {
|
|
8402
9120
|
execSync6(`nohup adhdev daemon > "${logPath}" 2>&1 &`, {
|
|
8403
9121
|
timeout: 3e3,
|
|
@@ -8439,10 +9157,11 @@ async function installCliOnly() {
|
|
|
8439
9157
|
const isNpx = process.env.npm_execpath?.includes("npx") || process.argv[1]?.includes("npx") || process.argv[1]?.includes("_npx");
|
|
8440
9158
|
console.log(import_chalk3.default.bold("\n\u{1F527} ADHDev CLI\n"));
|
|
8441
9159
|
console.log(import_chalk3.default.gray(" The `adhdev` command lets you:"));
|
|
8442
|
-
console.log(import_chalk3.default.gray(" \u2022 Start
|
|
8443
|
-
console.log(import_chalk3.default.gray(" \u2022 Launch IDE with CDP
|
|
8444
|
-
console.log(import_chalk3.default.gray(" \u2022 Start CLI agents
|
|
8445
|
-
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)"));
|
|
8446
9165
|
console.log();
|
|
8447
9166
|
if (currentVersion) {
|
|
8448
9167
|
console.log(import_chalk3.default.green(` \u2713 Currently installed: v${currentVersion}`));
|
|
@@ -8824,7 +9543,7 @@ program.command("daemon:stop").description("Stop ADHDev Daemon").action(async ()
|
|
|
8824
9543
|
async function sendDaemonCommand(cmd, args = {}, port = 19222) {
|
|
8825
9544
|
const WebSocket4 = (await import("ws")).default;
|
|
8826
9545
|
const { DAEMON_WS_PATH: DAEMON_WS_PATH2 } = await Promise.resolve().then(() => (init_ipc_protocol(), ipc_protocol_exports));
|
|
8827
|
-
return new Promise((
|
|
9546
|
+
return new Promise((resolve6, reject) => {
|
|
8828
9547
|
const wsUrl = `ws://127.0.0.1:${port}${DAEMON_WS_PATH2 || "/daemon"}`;
|
|
8829
9548
|
const ws = new WebSocket4(wsUrl);
|
|
8830
9549
|
const timeout = setTimeout(() => {
|
|
@@ -8855,7 +9574,7 @@ async function sendDaemonCommand(cmd, args = {}, port = 19222) {
|
|
|
8855
9574
|
if (msg.type === "daemon:command_result" || msg.type === "command_result") {
|
|
8856
9575
|
clearTimeout(timeout);
|
|
8857
9576
|
ws.close();
|
|
8858
|
-
|
|
9577
|
+
resolve6(msg.payload?.result || msg.payload || msg);
|
|
8859
9578
|
}
|
|
8860
9579
|
} catch {
|
|
8861
9580
|
}
|
|
@@ -8872,13 +9591,13 @@ Is 'adhdev daemon' running?`));
|
|
|
8872
9591
|
}
|
|
8873
9592
|
async function directCdpEval(expression, port = 9222) {
|
|
8874
9593
|
const http3 = await import("http");
|
|
8875
|
-
const targets = await new Promise((
|
|
9594
|
+
const targets = await new Promise((resolve6, reject) => {
|
|
8876
9595
|
http3.get(`http://127.0.0.1:${port}/json`, (res) => {
|
|
8877
9596
|
let data = "";
|
|
8878
9597
|
res.on("data", (c) => data += c);
|
|
8879
9598
|
res.on("end", () => {
|
|
8880
9599
|
try {
|
|
8881
|
-
|
|
9600
|
+
resolve6(JSON.parse(data));
|
|
8882
9601
|
} catch {
|
|
8883
9602
|
reject(new Error("Invalid JSON"));
|
|
8884
9603
|
}
|
|
@@ -8891,7 +9610,7 @@ async function directCdpEval(expression, port = 9222) {
|
|
|
8891
9610
|
const target = (mainPages.length > 0 ? mainPages[0] : pages[0]) || targets[0];
|
|
8892
9611
|
if (!target?.webSocketDebuggerUrl) throw new Error("No CDP target found");
|
|
8893
9612
|
const WebSocket4 = (await import("ws")).default;
|
|
8894
|
-
return new Promise((
|
|
9613
|
+
return new Promise((resolve6, reject) => {
|
|
8895
9614
|
const ws = new WebSocket4(target.webSocketDebuggerUrl);
|
|
8896
9615
|
const timeout = setTimeout(() => {
|
|
8897
9616
|
ws.close();
|
|
@@ -8913,11 +9632,11 @@ async function directCdpEval(expression, port = 9222) {
|
|
|
8913
9632
|
clearTimeout(timeout);
|
|
8914
9633
|
ws.close();
|
|
8915
9634
|
if (msg.result?.result?.value !== void 0) {
|
|
8916
|
-
|
|
9635
|
+
resolve6(msg.result.result.value);
|
|
8917
9636
|
} else if (msg.result?.exceptionDetails) {
|
|
8918
9637
|
reject(new Error(msg.result.exceptionDetails.text));
|
|
8919
9638
|
} else {
|
|
8920
|
-
|
|
9639
|
+
resolve6(msg.result);
|
|
8921
9640
|
}
|
|
8922
9641
|
}
|
|
8923
9642
|
});
|
|
@@ -8971,7 +9690,7 @@ provider.command("list").description("List all loaded providers").option("-j, --
|
|
|
8971
9690
|
provider.command("reload").description("Hot-reload all providers (requires daemon --dev)").action(async () => {
|
|
8972
9691
|
try {
|
|
8973
9692
|
const http3 = await import("http");
|
|
8974
|
-
const result = await new Promise((
|
|
9693
|
+
const result = await new Promise((resolve6, reject) => {
|
|
8975
9694
|
const req = http3.request({
|
|
8976
9695
|
hostname: "127.0.0.1",
|
|
8977
9696
|
port: 19280,
|
|
@@ -8983,9 +9702,9 @@ provider.command("reload").description("Hot-reload all providers (requires daemo
|
|
|
8983
9702
|
res.on("data", (c) => data += c);
|
|
8984
9703
|
res.on("end", () => {
|
|
8985
9704
|
try {
|
|
8986
|
-
|
|
9705
|
+
resolve6(JSON.parse(data));
|
|
8987
9706
|
} catch {
|
|
8988
|
-
|
|
9707
|
+
resolve6({ raw: data });
|
|
8989
9708
|
}
|
|
8990
9709
|
});
|
|
8991
9710
|
});
|
|
@@ -9019,7 +9738,7 @@ provider.command("create <type>").description("Scaffold a new provider.js from t
|
|
|
9019
9738
|
const category = options.category;
|
|
9020
9739
|
const location = options.builtin ? "builtin" : "user";
|
|
9021
9740
|
const http3 = await import("http");
|
|
9022
|
-
const result = await new Promise((
|
|
9741
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9023
9742
|
const postData = JSON.stringify({ type, name, category, location });
|
|
9024
9743
|
const req = http3.request({
|
|
9025
9744
|
hostname: "127.0.0.1",
|
|
@@ -9032,9 +9751,9 @@ provider.command("create <type>").description("Scaffold a new provider.js from t
|
|
|
9032
9751
|
res.on("data", (c) => data += c);
|
|
9033
9752
|
res.on("end", () => {
|
|
9034
9753
|
try {
|
|
9035
|
-
|
|
9754
|
+
resolve6(JSON.parse(data));
|
|
9036
9755
|
} catch {
|
|
9037
|
-
|
|
9756
|
+
resolve6({ raw: data });
|
|
9038
9757
|
}
|
|
9039
9758
|
});
|
|
9040
9759
|
});
|
|
@@ -9116,7 +9835,7 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9116
9835
|
script,
|
|
9117
9836
|
params: options.param ? { text: options.param, sessionId: options.param, buttonText: options.param } : {}
|
|
9118
9837
|
});
|
|
9119
|
-
const result = await new Promise((
|
|
9838
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9120
9839
|
const req = http3.request({
|
|
9121
9840
|
hostname: "127.0.0.1",
|
|
9122
9841
|
port: 19280,
|
|
@@ -9128,9 +9847,9 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9128
9847
|
res.on("data", (c) => data += c);
|
|
9129
9848
|
res.on("end", () => {
|
|
9130
9849
|
try {
|
|
9131
|
-
|
|
9850
|
+
resolve6(JSON.parse(data));
|
|
9132
9851
|
} catch {
|
|
9133
|
-
|
|
9852
|
+
resolve6({ raw: data });
|
|
9134
9853
|
}
|
|
9135
9854
|
});
|
|
9136
9855
|
});
|
|
@@ -9166,15 +9885,15 @@ provider.command("run <type> <script>").description("Run a specific provider scr
|
|
|
9166
9885
|
provider.command("source <type>").description("View source code of a provider").action(async (type) => {
|
|
9167
9886
|
try {
|
|
9168
9887
|
const http3 = await import("http");
|
|
9169
|
-
const result = await new Promise((
|
|
9888
|
+
const result = await new Promise((resolve6, reject) => {
|
|
9170
9889
|
http3.get(`http://127.0.0.1:19280/api/providers/${type}/source`, (res) => {
|
|
9171
9890
|
let data = "";
|
|
9172
9891
|
res.on("data", (c) => data += c);
|
|
9173
9892
|
res.on("end", () => {
|
|
9174
9893
|
try {
|
|
9175
|
-
|
|
9894
|
+
resolve6(JSON.parse(data));
|
|
9176
9895
|
} catch {
|
|
9177
|
-
|
|
9896
|
+
resolve6({ raw: data });
|
|
9178
9897
|
}
|
|
9179
9898
|
});
|
|
9180
9899
|
}).on("error", () => {
|
|
@@ -9378,13 +10097,13 @@ cdp.command("eval <expression>").description("Execute JavaScript expression via
|
|
|
9378
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) => {
|
|
9379
10098
|
try {
|
|
9380
10099
|
const http3 = await import("http");
|
|
9381
|
-
const targets = await new Promise((
|
|
10100
|
+
const targets = await new Promise((resolve6, reject) => {
|
|
9382
10101
|
http3.get(`http://127.0.0.1:${options.port}/json`, (res) => {
|
|
9383
10102
|
let data = "";
|
|
9384
10103
|
res.on("data", (c) => data += c);
|
|
9385
10104
|
res.on("end", () => {
|
|
9386
10105
|
try {
|
|
9387
|
-
|
|
10106
|
+
resolve6(JSON.parse(data));
|
|
9388
10107
|
} catch {
|
|
9389
10108
|
reject(new Error("Invalid JSON"));
|
|
9390
10109
|
}
|
|
@@ -9398,7 +10117,7 @@ cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --po
|
|
|
9398
10117
|
if (!target?.webSocketDebuggerUrl) throw new Error("No CDP target");
|
|
9399
10118
|
const WebSocket4 = (await import("ws")).default;
|
|
9400
10119
|
const ws = new WebSocket4(target.webSocketDebuggerUrl);
|
|
9401
|
-
await new Promise((
|
|
10120
|
+
await new Promise((resolve6, reject) => {
|
|
9402
10121
|
ws.on("open", () => {
|
|
9403
10122
|
ws.send(JSON.stringify({ id: 1, method: "Page.captureScreenshot", params: { format: "jpeg", quality: 50 } }));
|
|
9404
10123
|
});
|
|
@@ -9411,7 +10130,7 @@ cdp.command("screenshot").description("Capture IDE screenshot").option("-p, --po
|
|
|
9411
10130
|
\u2713 Screenshot saved to ${options.output}
|
|
9412
10131
|
`));
|
|
9413
10132
|
ws.close();
|
|
9414
|
-
|
|
10133
|
+
resolve6();
|
|
9415
10134
|
}
|
|
9416
10135
|
});
|
|
9417
10136
|
ws.on("error", (e) => reject(e));
|
|
@@ -9427,10 +10146,10 @@ if (process.argv.length <= 2) {
|
|
|
9427
10146
|
program.outputHelp();
|
|
9428
10147
|
console.log();
|
|
9429
10148
|
console.log(import_chalk4.default.gray(" Quick start:"));
|
|
9430
|
-
console.log(import_chalk4.default.gray(" adhdev
|
|
9431
|
-
console.log(import_chalk4.default.gray(" adhdev
|
|
9432
|
-
console.log(import_chalk4.default.gray(" adhdev launch claude \u2014 Launch CLI agent"));
|
|
9433
|
-
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"));
|
|
9434
10153
|
console.log(import_chalk4.default.gray(" adhdev status \u2014 Check current setup"));
|
|
9435
10154
|
console.log();
|
|
9436
10155
|
} else {
|