adhdev 0.1.21 → 0.1.22
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 +448 -154
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -821,6 +821,8 @@ var init_cli_bridge = __esm({
|
|
|
821
821
|
const handlers = this.messageHandlers.get(message.type);
|
|
822
822
|
if (handlers) {
|
|
823
823
|
handlers.forEach((h) => h(message));
|
|
824
|
+
} else if (message.type !== "auth_ok" && message.type !== "auth_error") {
|
|
825
|
+
console.log(`[CliBridge] Unhandled message type: ${message.type}`);
|
|
824
826
|
}
|
|
825
827
|
} catch (error) {
|
|
826
828
|
console.error("[CliBridge] Failed to parse message:", error);
|
|
@@ -1931,8 +1933,10 @@ var init_daemon_cdp = __esm({
|
|
|
1931
1933
|
MAX_FAILURES = 5;
|
|
1932
1934
|
agentSessions = /* @__PURE__ */ new Map();
|
|
1933
1935
|
logFn;
|
|
1934
|
-
|
|
1936
|
+
disableFallback;
|
|
1937
|
+
constructor(port = 9333, logFn, disableFallback = false) {
|
|
1935
1938
|
this.port = port;
|
|
1939
|
+
this.disableFallback = disableFallback;
|
|
1936
1940
|
this.logFn = logFn || ((msg) => {
|
|
1937
1941
|
console.log(msg);
|
|
1938
1942
|
try {
|
|
@@ -2011,6 +2015,7 @@ var init_daemon_cdp = __esm({
|
|
|
2011
2015
|
async findTarget() {
|
|
2012
2016
|
let target = await this.findTargetOnPort(this.port);
|
|
2013
2017
|
if (target) return target;
|
|
2018
|
+
if (this.disableFallback) return null;
|
|
2014
2019
|
const fallbackPorts = [9222, 9333, 9335, 9337, 9339].filter((p) => p !== this.port);
|
|
2015
2020
|
for (const port of fallbackPorts) {
|
|
2016
2021
|
target = await this.findTargetOnPort(port);
|
|
@@ -2070,7 +2075,10 @@ var init_daemon_cdp = __esm({
|
|
|
2070
2075
|
this.reconnectTimer = setTimeout(async () => {
|
|
2071
2076
|
this.reconnectTimer = null;
|
|
2072
2077
|
if (!this._connected) {
|
|
2073
|
-
await this.connect();
|
|
2078
|
+
const ok = await this.connect();
|
|
2079
|
+
if (!ok && !this._connected) {
|
|
2080
|
+
this.scheduleReconnect();
|
|
2081
|
+
}
|
|
2074
2082
|
}
|
|
2075
2083
|
}, 5e3);
|
|
2076
2084
|
}
|
|
@@ -2256,7 +2264,9 @@ var init_daemon_cdp = __esm({
|
|
|
2256
2264
|
try {
|
|
2257
2265
|
const result = await this.sendInternal("Page.captureScreenshot", {
|
|
2258
2266
|
format: "jpeg",
|
|
2259
|
-
quality:
|
|
2267
|
+
quality: 25,
|
|
2268
|
+
clip: void 0
|
|
2269
|
+
// full viewport
|
|
2260
2270
|
}, 1e4);
|
|
2261
2271
|
if (result?.data) {
|
|
2262
2272
|
return Buffer.from(result.data, "base64");
|
|
@@ -2577,12 +2587,22 @@ var init_daemon_p2p = __esm({
|
|
|
2577
2587
|
fileRequestHandler = null;
|
|
2578
2588
|
inputHandler = null;
|
|
2579
2589
|
commandHandler = null;
|
|
2590
|
+
_ssDebugDone = false;
|
|
2580
2591
|
get screenshotActive() {
|
|
2581
2592
|
for (const peer of this.peers.values()) {
|
|
2582
2593
|
if (peer.screenshotActive && peer.state === "connected") return true;
|
|
2583
2594
|
}
|
|
2584
2595
|
return false;
|
|
2585
2596
|
}
|
|
2597
|
+
/** Get the ideType for the currently active screenshot request */
|
|
2598
|
+
get screenshotIdeType() {
|
|
2599
|
+
for (const peer of this.peers.values()) {
|
|
2600
|
+
if (peer.screenshotActive && peer.state === "connected" && peer.screenshotIdeType) {
|
|
2601
|
+
return peer.screenshotIdeType;
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
return void 0;
|
|
2605
|
+
}
|
|
2586
2606
|
constructor(bridge) {
|
|
2587
2607
|
this.bridge = bridge;
|
|
2588
2608
|
this.tryLoadNodeDatachannel();
|
|
@@ -2781,11 +2801,17 @@ var init_daemon_p2p = __esm({
|
|
|
2781
2801
|
}
|
|
2782
2802
|
});
|
|
2783
2803
|
const screenshotCh = pc.createDataChannel("screenshots");
|
|
2784
|
-
entry.screenshotChannel = screenshotCh;
|
|
2785
2804
|
screenshotCh.onOpen(() => {
|
|
2786
2805
|
log(`Screenshots channel OPEN for peer ${pid}`);
|
|
2787
|
-
|
|
2788
|
-
|
|
2806
|
+
const peer = this.peers.get(pid);
|
|
2807
|
+
if (peer) {
|
|
2808
|
+
peer.screenshotChannel = screenshotCh;
|
|
2809
|
+
peer.state = "connected";
|
|
2810
|
+
this.notifyStateChange();
|
|
2811
|
+
if (peer.screenshotActive) {
|
|
2812
|
+
log(`Screenshots auto-starting for peer ${pid} (was waiting for channel open)`);
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2789
2815
|
});
|
|
2790
2816
|
screenshotCh.onClosed(() => {
|
|
2791
2817
|
log(`Screenshots channel CLOSED for peer ${pid}`);
|
|
@@ -2819,14 +2845,24 @@ var init_daemon_p2p = __esm({
|
|
|
2819
2845
|
const text = typeof msg === "string" ? msg : msg.toString("utf-8");
|
|
2820
2846
|
try {
|
|
2821
2847
|
const parsed = JSON.parse(text);
|
|
2848
|
+
log(`Files message from peer ${peerId}: type=${parsed.type}`);
|
|
2822
2849
|
if (parsed.type === "screenshot_start") {
|
|
2823
2850
|
const peer = this.peers.get(peerId);
|
|
2824
|
-
if (peer)
|
|
2851
|
+
if (peer) {
|
|
2852
|
+
peer.screenshotActive = true;
|
|
2853
|
+
peer.screenshotIdeType = parsed.ideType || void 0;
|
|
2854
|
+
log(`screenshot_start: peer=${peerId}, ideType=${parsed.ideType || "any"}, channelOpen=${!!peer.screenshotChannel}, state=${peer.state}`);
|
|
2855
|
+
} else {
|
|
2856
|
+
log(`screenshot_start: peer ${peerId} NOT FOUND in peers map!`);
|
|
2857
|
+
}
|
|
2825
2858
|
return;
|
|
2826
2859
|
}
|
|
2827
2860
|
if (parsed.type === "screenshot_stop") {
|
|
2828
2861
|
const peer = this.peers.get(peerId);
|
|
2829
|
-
if (peer)
|
|
2862
|
+
if (peer) {
|
|
2863
|
+
peer.screenshotActive = false;
|
|
2864
|
+
log(`screenshot_stop: peer=${peerId}`);
|
|
2865
|
+
}
|
|
2830
2866
|
return;
|
|
2831
2867
|
}
|
|
2832
2868
|
if (parsed.type === "input") {
|
|
@@ -2863,14 +2899,28 @@ var init_daemon_p2p = __esm({
|
|
|
2863
2899
|
sendScreenshot(base64Data) {
|
|
2864
2900
|
let sentAny = false;
|
|
2865
2901
|
const buffer = Buffer.from(base64Data, "base64");
|
|
2866
|
-
|
|
2902
|
+
let debugOnce = !this._ssDebugDone;
|
|
2903
|
+
const CHUNK_SIZE = 6e4;
|
|
2904
|
+
for (const [pid, peer] of this.peers.entries()) {
|
|
2905
|
+
if (debugOnce) {
|
|
2906
|
+
log(`sendScreenshot peer=${pid}: state=${peer.state}, hasSsCh=${!!peer.screenshotChannel}, ssActive=${peer.screenshotActive}, chOpen=${peer.screenshotChannel?.isOpen?.() ?? "N/A"}, bufSize=${buffer.length}`);
|
|
2907
|
+
}
|
|
2867
2908
|
if (peer.state !== "connected" || !peer.screenshotChannel || !peer.screenshotActive) continue;
|
|
2868
2909
|
try {
|
|
2869
|
-
peer.screenshotChannel.
|
|
2910
|
+
if (!peer.screenshotChannel.isOpen()) continue;
|
|
2911
|
+
const header = Buffer.alloc(4);
|
|
2912
|
+
header.writeUInt32BE(buffer.length, 0);
|
|
2913
|
+
peer.screenshotChannel.sendMessageBinary(header);
|
|
2914
|
+
for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
|
|
2915
|
+
const chunk = buffer.subarray(offset, Math.min(offset + CHUNK_SIZE, buffer.length));
|
|
2916
|
+
peer.screenshotChannel.sendMessageBinary(chunk);
|
|
2917
|
+
}
|
|
2870
2918
|
sentAny = true;
|
|
2871
|
-
} catch {
|
|
2919
|
+
} catch (e) {
|
|
2920
|
+
if (debugOnce) log(`sendScreenshot ERROR for peer ${pid}: ${e?.message}`);
|
|
2872
2921
|
}
|
|
2873
2922
|
}
|
|
2923
|
+
if (debugOnce) this._ssDebugDone = true;
|
|
2874
2924
|
return sentAny;
|
|
2875
2925
|
}
|
|
2876
2926
|
// ─── 핸들러 등록 ────────────────────────────
|
|
@@ -2904,7 +2954,9 @@ var init_daemon_p2p = __esm({
|
|
|
2904
2954
|
return;
|
|
2905
2955
|
}
|
|
2906
2956
|
try {
|
|
2907
|
-
const
|
|
2957
|
+
const peer = this.peers.get(peerId);
|
|
2958
|
+
const ideType = peer?.screenshotIdeType;
|
|
2959
|
+
const result = await this.inputHandler({ action, params, _targetInstance: ideType ? `${ideType}_` : void 0 });
|
|
2908
2960
|
this.sendToPeer(peerId, { id, type: "response", success: true, result });
|
|
2909
2961
|
} catch (e) {
|
|
2910
2962
|
this.sendToPeer(peerId, { id, type: "response", success: false, error: e?.message });
|
|
@@ -3156,13 +3208,46 @@ var init_daemon_commands = __esm({
|
|
|
3156
3208
|
DaemonCommandHandler = class {
|
|
3157
3209
|
ctx;
|
|
3158
3210
|
agentStream = null;
|
|
3211
|
+
/** Get CDP manager for a specific ideType, or first connected one */
|
|
3212
|
+
getCdp(ideType) {
|
|
3213
|
+
const key = ideType || this._currentIdeType;
|
|
3214
|
+
if (key) {
|
|
3215
|
+
const m = this.ctx.cdpManagers.get(key.toLowerCase());
|
|
3216
|
+
if (m?.isConnected) return m;
|
|
3217
|
+
}
|
|
3218
|
+
for (const m of this.ctx.cdpManagers.values()) {
|
|
3219
|
+
if (m.isConnected) return m;
|
|
3220
|
+
}
|
|
3221
|
+
return null;
|
|
3222
|
+
}
|
|
3223
|
+
/** Current IDE type extracted from command args (per-request) */
|
|
3224
|
+
_currentIdeType;
|
|
3225
|
+
/** Extract ideType from _targetInstance (e.g. 'vscode_abc123' → 'vscode') */
|
|
3226
|
+
extractIdeType(args) {
|
|
3227
|
+
if (args?._targetInstance) {
|
|
3228
|
+
const parts = args._targetInstance.split("_");
|
|
3229
|
+
if (parts.length >= 2) return parts[0];
|
|
3230
|
+
}
|
|
3231
|
+
return void 0;
|
|
3232
|
+
}
|
|
3159
3233
|
constructor(ctx) {
|
|
3160
3234
|
this.ctx = ctx;
|
|
3161
3235
|
}
|
|
3236
|
+
/** Get ScriptLoader for specific ideType, fallback to first available */
|
|
3237
|
+
getScriptLoader(ideType) {
|
|
3238
|
+
const key = ideType || this._currentIdeType;
|
|
3239
|
+
if (key) {
|
|
3240
|
+
const l = this.ctx.scriptLoaders.get(key.toLowerCase());
|
|
3241
|
+
if (l) return l;
|
|
3242
|
+
}
|
|
3243
|
+
for (const l of this.ctx.scriptLoaders.values()) return l;
|
|
3244
|
+
return void 0;
|
|
3245
|
+
}
|
|
3162
3246
|
setAgentStreamManager(manager) {
|
|
3163
3247
|
this.agentStream = manager;
|
|
3164
3248
|
}
|
|
3165
3249
|
async handle(cmd, args) {
|
|
3250
|
+
this._currentIdeType = this.extractIdeType(args);
|
|
3166
3251
|
switch (cmd) {
|
|
3167
3252
|
// ─── CDP 직접 처리 ───────────────────
|
|
3168
3253
|
case "read_chat":
|
|
@@ -3205,8 +3290,13 @@ var init_daemon_commands = __esm({
|
|
|
3205
3290
|
return this.handleFileListBrowse(args);
|
|
3206
3291
|
// ─── vscode API → Extension 위임 ────
|
|
3207
3292
|
case "vscode_command_exec":
|
|
3208
|
-
case "execute_vscode_command":
|
|
3209
|
-
|
|
3293
|
+
case "execute_vscode_command": {
|
|
3294
|
+
const resolvedCmd = args?.commandId || args?.command;
|
|
3295
|
+
if (resolvedCmd === "adhdev.captureCdpScreenshot") {
|
|
3296
|
+
return this.handleScreenshot(args);
|
|
3297
|
+
}
|
|
3298
|
+
return this.delegateToExtension(resolvedCmd || cmd, args?.args);
|
|
3299
|
+
}
|
|
3210
3300
|
case "get_open_editors":
|
|
3211
3301
|
return this.delegateToExtension("adhdev.getOpenEditors", [args]);
|
|
3212
3302
|
case "open_tab":
|
|
@@ -3249,59 +3339,97 @@ var init_daemon_commands = __esm({
|
|
|
3249
3339
|
}
|
|
3250
3340
|
// ─── CDP 기반 채팅 명령 ──────────────────────
|
|
3251
3341
|
async handleReadChat(args) {
|
|
3252
|
-
if (!this.
|
|
3253
|
-
const script = this.
|
|
3342
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3343
|
+
const script = this.getScriptLoader()?.get("read_chat");
|
|
3254
3344
|
if (!script) return { success: false, error: "read_chat script not loaded" };
|
|
3255
3345
|
try {
|
|
3256
|
-
const result = await this.
|
|
3346
|
+
const result = await this.getCdp().evaluate(script, 5e4);
|
|
3257
3347
|
return { success: true, ...result };
|
|
3258
3348
|
} catch (e) {
|
|
3259
3349
|
return { success: false, error: e.message };
|
|
3260
3350
|
}
|
|
3261
3351
|
}
|
|
3262
3352
|
async handleSendChat(args) {
|
|
3263
|
-
if (!this.ctx.cdp?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3264
3353
|
const text = args?.text || args?.message;
|
|
3265
3354
|
if (!text) return { success: false, error: "text required" };
|
|
3266
|
-
const
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3355
|
+
const targetCdp = this.getCdp();
|
|
3356
|
+
const targetLoader = this.getScriptLoader();
|
|
3357
|
+
if (targetCdp?.isConnected && targetLoader) {
|
|
3358
|
+
const script = targetLoader.getWithParams("send_message", { MESSAGE: JSON.stringify(text) });
|
|
3359
|
+
if (script) {
|
|
3360
|
+
console.log(`[send_chat] Targeting IDE: ${this._currentIdeType || "fallback-first"}`);
|
|
3361
|
+
try {
|
|
3362
|
+
await targetCdp.evaluate(script, 3e4);
|
|
3363
|
+
return { success: true, sent: true };
|
|
3364
|
+
} catch (e) {
|
|
3365
|
+
console.log(`[send_chat] Failed on ${this._currentIdeType}: ${e.message}`);
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3273
3368
|
}
|
|
3369
|
+
console.log(`[send_chat] No specific target, trying all CDPs...`);
|
|
3370
|
+
for (const [ideType, cdp] of this.ctx.cdpManagers) {
|
|
3371
|
+
if (!cdp.isConnected) continue;
|
|
3372
|
+
const loader = this.ctx.scriptLoaders.get(ideType);
|
|
3373
|
+
if (!loader) continue;
|
|
3374
|
+
const script = loader.getWithParams("send_message", { MESSAGE: JSON.stringify(text) });
|
|
3375
|
+
if (!script) continue;
|
|
3376
|
+
console.log(`[send_chat] Trying IDE: ${ideType}`);
|
|
3377
|
+
try {
|
|
3378
|
+
await cdp.evaluate(script, 3e4);
|
|
3379
|
+
return { success: true, sent: true, targetIde: ideType };
|
|
3380
|
+
} catch (e) {
|
|
3381
|
+
console.log(`[send_chat] Failed on ${ideType}: ${e.message}`);
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
return { success: false, error: "No CDP could send the message" };
|
|
3274
3385
|
}
|
|
3275
3386
|
async handleListChats(args) {
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3387
|
+
const cdp = this.getCdp();
|
|
3388
|
+
if (!cdp?.isConnected) {
|
|
3389
|
+
console.log(`[list_chats] CDP not connected, ideType=${this._currentIdeType}`);
|
|
3390
|
+
return { success: false, error: "CDP not connected" };
|
|
3391
|
+
}
|
|
3392
|
+
const script = this.getScriptLoader()?.get("list_chats");
|
|
3393
|
+
if (!script) {
|
|
3394
|
+
console.log(`[list_chats] script not loaded`);
|
|
3395
|
+
return { success: false, error: "list_chats script not loaded" };
|
|
3396
|
+
}
|
|
3279
3397
|
try {
|
|
3280
|
-
|
|
3281
|
-
|
|
3398
|
+
console.log(`[list_chats] Evaluating on ideType=${this._currentIdeType}`);
|
|
3399
|
+
const result = await cdp.evaluate(script, 3e4);
|
|
3400
|
+
let parsed = result;
|
|
3401
|
+
if (typeof result === "string") {
|
|
3402
|
+
try {
|
|
3403
|
+
parsed = JSON.parse(result);
|
|
3404
|
+
} catch {
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
console.log(`[list_chats] Result type=${typeof parsed}, isArray=${Array.isArray(parsed)}, len=${Array.isArray(parsed) ? parsed.length : "N/A"}`);
|
|
3408
|
+
return { success: true, chats: parsed };
|
|
3282
3409
|
} catch (e) {
|
|
3410
|
+
console.log(`[list_chats] Error: ${e.message}`);
|
|
3283
3411
|
return { success: false, error: e.message };
|
|
3284
3412
|
}
|
|
3285
3413
|
}
|
|
3286
3414
|
async handleNewChat(args) {
|
|
3287
|
-
if (!this.
|
|
3288
|
-
const script = this.
|
|
3415
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3416
|
+
const script = this.getScriptLoader()?.get("new_session");
|
|
3289
3417
|
if (!script) return { success: false, error: "new_session script not loaded" };
|
|
3290
3418
|
try {
|
|
3291
|
-
await this.
|
|
3419
|
+
await this.getCdp().evaluate(script, 15e3);
|
|
3292
3420
|
return { success: true };
|
|
3293
3421
|
} catch (e) {
|
|
3294
3422
|
return { success: false, error: e.message };
|
|
3295
3423
|
}
|
|
3296
3424
|
}
|
|
3297
3425
|
async handleSwitchChat(args) {
|
|
3298
|
-
if (!this.
|
|
3426
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3299
3427
|
const sessionId = args?.sessionId || args?.id || args?.chatId;
|
|
3300
3428
|
if (!sessionId) return { success: false, error: "sessionId required" };
|
|
3301
|
-
const script = this.
|
|
3429
|
+
const script = this.getScriptLoader()?.getWithParams("switch_session", { SESSION_ID: sessionId });
|
|
3302
3430
|
if (!script) return { success: false, error: "switch_session script not loaded" };
|
|
3303
3431
|
try {
|
|
3304
|
-
await this.
|
|
3432
|
+
await this.getCdp().evaluate(script, 15e3);
|
|
3305
3433
|
return { success: true };
|
|
3306
3434
|
} catch (e) {
|
|
3307
3435
|
return { success: false, error: e.message };
|
|
@@ -3315,12 +3443,12 @@ var init_daemon_commands = __esm({
|
|
|
3315
3443
|
return this.delegateToExtension("workbench.action.openSettings", [`cursor.model`]);
|
|
3316
3444
|
}
|
|
3317
3445
|
async handleResolveModal(args) {
|
|
3318
|
-
if (!this.
|
|
3446
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3319
3447
|
const button = args?.button || args?.buttonText || "Accept";
|
|
3320
|
-
const script = this.
|
|
3448
|
+
const script = this.getScriptLoader()?.getWithParams("resolve_modal", { BUTTON_TEXT: button });
|
|
3321
3449
|
if (!script) {
|
|
3322
3450
|
try {
|
|
3323
|
-
await this.
|
|
3451
|
+
await this.getCdp().evaluate(`
|
|
3324
3452
|
(() => {
|
|
3325
3453
|
const btns = [...document.querySelectorAll('button')];
|
|
3326
3454
|
const btn = btns.find(b => b.textContent?.trim() === ${JSON.stringify(button)});
|
|
@@ -3334,7 +3462,7 @@ var init_daemon_commands = __esm({
|
|
|
3334
3462
|
}
|
|
3335
3463
|
}
|
|
3336
3464
|
try {
|
|
3337
|
-
await this.
|
|
3465
|
+
await this.getCdp().evaluate(script, 1e4);
|
|
3338
3466
|
return { success: true };
|
|
3339
3467
|
} catch (e) {
|
|
3340
3468
|
return { success: false, error: e.message };
|
|
@@ -3342,22 +3470,23 @@ var init_daemon_commands = __esm({
|
|
|
3342
3470
|
}
|
|
3343
3471
|
// ─── CDP 직접 명령 ──────────────────────────
|
|
3344
3472
|
async handleCdpEval(args) {
|
|
3345
|
-
if (!this.
|
|
3473
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3346
3474
|
const expression = args?.expression || args?.script;
|
|
3347
3475
|
if (!expression) return { success: false, error: "expression required" };
|
|
3348
3476
|
try {
|
|
3349
|
-
const result = await this.
|
|
3477
|
+
const result = await this.getCdp().evaluate(expression, 5e4);
|
|
3350
3478
|
return { success: true, result };
|
|
3351
3479
|
} catch (e) {
|
|
3352
3480
|
return { success: false, error: e.message };
|
|
3353
3481
|
}
|
|
3354
3482
|
}
|
|
3355
3483
|
async handleScreenshot(args) {
|
|
3356
|
-
if (!this.
|
|
3484
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3357
3485
|
try {
|
|
3358
|
-
const buf = await this.
|
|
3486
|
+
const buf = await this.getCdp().captureScreenshot();
|
|
3359
3487
|
if (buf) {
|
|
3360
|
-
|
|
3488
|
+
const b64 = buf.toString("base64");
|
|
3489
|
+
return { success: true, result: b64, base64: b64, screenshot: b64, format: "jpeg" };
|
|
3361
3490
|
}
|
|
3362
3491
|
return { success: false, error: "Screenshot failed" };
|
|
3363
3492
|
} catch (e) {
|
|
@@ -3365,26 +3494,26 @@ var init_daemon_commands = __esm({
|
|
|
3365
3494
|
}
|
|
3366
3495
|
}
|
|
3367
3496
|
async handleCdpCommand(args) {
|
|
3368
|
-
if (!this.
|
|
3497
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3369
3498
|
const method = args?.method;
|
|
3370
3499
|
const params = args?.params || {};
|
|
3371
3500
|
if (!method) return { success: false, error: "method required" };
|
|
3372
3501
|
try {
|
|
3373
|
-
const result = await this.
|
|
3502
|
+
const result = await this.getCdp().sendCdpCommand(method, params);
|
|
3374
3503
|
return { success: true, result };
|
|
3375
3504
|
} catch (e) {
|
|
3376
3505
|
return { success: false, error: e.message };
|
|
3377
3506
|
}
|
|
3378
3507
|
}
|
|
3379
3508
|
async handleCdpBatch(args) {
|
|
3380
|
-
if (!this.
|
|
3509
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3381
3510
|
const commands = args?.commands;
|
|
3382
3511
|
const stopOnError = args?.stopOnError !== false;
|
|
3383
3512
|
if (!commands?.length) return { success: false, error: "commands array required" };
|
|
3384
3513
|
const results = [];
|
|
3385
3514
|
for (const cmd of commands) {
|
|
3386
3515
|
try {
|
|
3387
|
-
const result = await this.
|
|
3516
|
+
const result = await this.getCdp().sendCdpCommand(cmd.method, cmd.params || {});
|
|
3388
3517
|
results.push({ method: cmd.method, success: true, result });
|
|
3389
3518
|
} catch (e) {
|
|
3390
3519
|
results.push({ method: cmd.method, success: false, error: e.message });
|
|
@@ -3394,49 +3523,60 @@ var init_daemon_commands = __esm({
|
|
|
3394
3523
|
return { success: true, results };
|
|
3395
3524
|
}
|
|
3396
3525
|
async handleCdpRemoteAction(args) {
|
|
3397
|
-
if (!this.
|
|
3526
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3398
3527
|
const action = args?.action;
|
|
3399
3528
|
const params = args?.params || args;
|
|
3400
3529
|
try {
|
|
3401
3530
|
switch (action) {
|
|
3402
3531
|
case "input_key": {
|
|
3403
3532
|
const { key, modifiers } = params;
|
|
3404
|
-
await this.
|
|
3533
|
+
await this.getCdp().send("Input.dispatchKeyEvent", {
|
|
3405
3534
|
type: "keyDown",
|
|
3406
3535
|
key,
|
|
3407
3536
|
...modifiers?.ctrl ? { modifiers: 2 } : {},
|
|
3408
3537
|
...modifiers?.shift ? { modifiers: 8 } : {}
|
|
3409
3538
|
});
|
|
3410
|
-
await this.
|
|
3539
|
+
await this.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key });
|
|
3411
3540
|
return { success: true };
|
|
3412
3541
|
}
|
|
3413
3542
|
case "input_click": {
|
|
3414
|
-
|
|
3415
|
-
|
|
3543
|
+
let { x, y, nx, ny, button: btn } = params;
|
|
3544
|
+
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
3545
|
+
const viewport = await this.getCdp().evaluate(
|
|
3546
|
+
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
3547
|
+
);
|
|
3548
|
+
const { w, h } = JSON.parse(viewport);
|
|
3549
|
+
x = Math.round(nx * w);
|
|
3550
|
+
y = Math.round(ny * h);
|
|
3551
|
+
}
|
|
3552
|
+
if (x === void 0 || y === void 0) {
|
|
3553
|
+
return { success: false, error: "No coordinates provided (x,y or nx,ny required)" };
|
|
3554
|
+
}
|
|
3555
|
+
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
3416
3556
|
type: "mousePressed",
|
|
3417
3557
|
x,
|
|
3418
3558
|
y,
|
|
3419
3559
|
button: btn || "left",
|
|
3420
3560
|
clickCount: 1
|
|
3421
3561
|
});
|
|
3422
|
-
await this.
|
|
3562
|
+
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
3423
3563
|
type: "mouseReleased",
|
|
3424
3564
|
x,
|
|
3425
3565
|
y,
|
|
3426
3566
|
button: btn || "left",
|
|
3427
3567
|
clickCount: 1
|
|
3428
3568
|
});
|
|
3429
|
-
return { success: true };
|
|
3569
|
+
return { success: true, x, y };
|
|
3430
3570
|
}
|
|
3431
3571
|
case "input_type": {
|
|
3432
3572
|
const { text } = params;
|
|
3433
3573
|
for (const char of text || "") {
|
|
3434
|
-
await this.
|
|
3574
|
+
await this.getCdp().send("Input.dispatchKeyEvent", {
|
|
3435
3575
|
type: "keyDown",
|
|
3436
3576
|
text: char,
|
|
3437
3577
|
key: char
|
|
3438
3578
|
});
|
|
3439
|
-
await this.
|
|
3579
|
+
await this.getCdp().send("Input.dispatchKeyEvent", { type: "keyUp", key: char });
|
|
3440
3580
|
}
|
|
3441
3581
|
return { success: true };
|
|
3442
3582
|
}
|
|
@@ -3445,9 +3585,28 @@ var init_daemon_commands = __esm({
|
|
|
3445
3585
|
case "page_eval":
|
|
3446
3586
|
return this.handleCdpEval(params);
|
|
3447
3587
|
case "dom_query": {
|
|
3448
|
-
const html = await this.
|
|
3588
|
+
const html = await this.getCdp().querySelector(params?.selector);
|
|
3449
3589
|
return { success: true, html };
|
|
3450
3590
|
}
|
|
3591
|
+
case "input_wheel": {
|
|
3592
|
+
let { x, y, nx, ny, deltaX, deltaY } = params;
|
|
3593
|
+
if ((x === void 0 || y === void 0) && nx !== void 0 && ny !== void 0) {
|
|
3594
|
+
const viewport = await this.getCdp().evaluate(
|
|
3595
|
+
"JSON.stringify({ w: window.innerWidth, h: window.innerHeight })"
|
|
3596
|
+
);
|
|
3597
|
+
const { w, h } = JSON.parse(viewport);
|
|
3598
|
+
x = Math.round(nx * w);
|
|
3599
|
+
y = Math.round(ny * h);
|
|
3600
|
+
}
|
|
3601
|
+
await this.getCdp().send("Input.dispatchMouseEvent", {
|
|
3602
|
+
type: "mouseWheel",
|
|
3603
|
+
x: x || 0,
|
|
3604
|
+
y: y || 0,
|
|
3605
|
+
deltaX: deltaX || 0,
|
|
3606
|
+
deltaY: deltaY || 0
|
|
3607
|
+
});
|
|
3608
|
+
return { success: true };
|
|
3609
|
+
}
|
|
3451
3610
|
default:
|
|
3452
3611
|
return { success: false, error: `Unknown remote action: ${action}` };
|
|
3453
3612
|
}
|
|
@@ -3456,8 +3615,8 @@ var init_daemon_commands = __esm({
|
|
|
3456
3615
|
}
|
|
3457
3616
|
}
|
|
3458
3617
|
async handleDiscoverAgents(args) {
|
|
3459
|
-
if (!this.
|
|
3460
|
-
const agents = await this.
|
|
3618
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
3619
|
+
const agents = await this.getCdp().discoverAgentWebviews();
|
|
3461
3620
|
return { success: true, agents };
|
|
3462
3621
|
}
|
|
3463
3622
|
// ─── 파일 직접 처리 ─────────────────────────
|
|
@@ -3514,7 +3673,7 @@ var init_daemon_commands = __esm({
|
|
|
3514
3673
|
if (!this.ctx.localServer || this.ctx.localServer.extensionCount === 0) {
|
|
3515
3674
|
return { success: false, error: "No extension connected" };
|
|
3516
3675
|
}
|
|
3517
|
-
return this.ctx.localServer.executeVscodeCommand(command, args);
|
|
3676
|
+
return this.ctx.localServer.executeVscodeCommand(command, args, this._currentIdeType);
|
|
3518
3677
|
}
|
|
3519
3678
|
// ─── 기타 ───────────────────────────────────
|
|
3520
3679
|
async handleGetRecentWorkspaces(args) {
|
|
@@ -3533,66 +3692,67 @@ var init_daemon_commands = __esm({
|
|
|
3533
3692
|
}
|
|
3534
3693
|
}
|
|
3535
3694
|
async handleRefreshScripts(args) {
|
|
3536
|
-
|
|
3537
|
-
|
|
3695
|
+
const loader = this.getScriptLoader();
|
|
3696
|
+
if (!loader) return { success: false, error: "ScriptLoader not initialized" };
|
|
3697
|
+
await loader.refresh();
|
|
3538
3698
|
return { success: true };
|
|
3539
3699
|
}
|
|
3540
3700
|
// ─── Agent Stream 명령 ───────────────────────
|
|
3541
3701
|
async handleAgentStreamSwitch(args) {
|
|
3542
|
-
if (!this.agentStream || !this.
|
|
3702
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3543
3703
|
const agentType = args?.agentType || args?.agent || null;
|
|
3544
|
-
await this.agentStream.switchActiveAgent(this.
|
|
3704
|
+
await this.agentStream.switchActiveAgent(this.getCdp(), agentType);
|
|
3545
3705
|
return { success: true, activeAgent: agentType };
|
|
3546
3706
|
}
|
|
3547
3707
|
async handleAgentStreamRead(args) {
|
|
3548
|
-
if (!this.agentStream || !this.
|
|
3549
|
-
const streams = await this.agentStream.collectAgentStreams(this.
|
|
3708
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3709
|
+
const streams = await this.agentStream.collectAgentStreams(this.getCdp());
|
|
3550
3710
|
return { success: true, streams };
|
|
3551
3711
|
}
|
|
3552
3712
|
async handleAgentStreamSend(args) {
|
|
3553
|
-
if (!this.agentStream || !this.
|
|
3713
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3554
3714
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3555
3715
|
const text = args?.text || args?.message;
|
|
3556
3716
|
if (!agentType || !text) return { success: false, error: "agentType and text required" };
|
|
3557
|
-
const ok = await this.agentStream.sendToAgent(this.
|
|
3717
|
+
const ok = await this.agentStream.sendToAgent(this.getCdp(), agentType, text);
|
|
3558
3718
|
return { success: ok };
|
|
3559
3719
|
}
|
|
3560
3720
|
async handleAgentStreamResolve(args) {
|
|
3561
|
-
if (!this.agentStream || !this.
|
|
3721
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3562
3722
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3563
3723
|
const action = args?.action || "approve";
|
|
3564
3724
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3565
|
-
const ok = await this.agentStream.resolveAgentAction(this.
|
|
3725
|
+
const ok = await this.agentStream.resolveAgentAction(this.getCdp(), agentType, action);
|
|
3566
3726
|
return { success: ok };
|
|
3567
3727
|
}
|
|
3568
3728
|
async handleAgentStreamNew(args) {
|
|
3569
|
-
if (!this.agentStream || !this.
|
|
3729
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3570
3730
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3571
3731
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3572
|
-
const ok = await this.agentStream.newAgentSession(this.
|
|
3732
|
+
const ok = await this.agentStream.newAgentSession(this.getCdp(), agentType);
|
|
3573
3733
|
return { success: ok };
|
|
3574
3734
|
}
|
|
3575
3735
|
async handleAgentStreamListChats(args) {
|
|
3576
|
-
if (!this.agentStream || !this.
|
|
3736
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3577
3737
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3578
3738
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3579
|
-
const chats = await this.agentStream.listAgentChats(this.
|
|
3739
|
+
const chats = await this.agentStream.listAgentChats(this.getCdp(), agentType);
|
|
3580
3740
|
return { success: true, chats };
|
|
3581
3741
|
}
|
|
3582
3742
|
async handleAgentStreamSwitchSession(args) {
|
|
3583
|
-
if (!this.agentStream || !this.
|
|
3743
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3584
3744
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3585
3745
|
const sessionId = args?.sessionId || args?.id;
|
|
3586
3746
|
if (!agentType || !sessionId) return { success: false, error: "agentType and sessionId required" };
|
|
3587
|
-
const ok = await this.agentStream.switchAgentSession(this.
|
|
3747
|
+
const ok = await this.agentStream.switchAgentSession(this.getCdp(), agentType, sessionId);
|
|
3588
3748
|
return { success: ok };
|
|
3589
3749
|
}
|
|
3590
3750
|
async handleAgentStreamFocus(args) {
|
|
3591
|
-
if (!this.agentStream || !this.
|
|
3751
|
+
if (!this.agentStream || !this.getCdp()) return { success: false, error: "AgentStream or CDP not available" };
|
|
3592
3752
|
const agentType = args?.agentType || args?.agent || this.agentStream.activeAgentType;
|
|
3593
3753
|
if (!agentType) return { success: false, error: "agentType required" };
|
|
3594
3754
|
await this.agentStream.ensureAgentPanelOpen(agentType);
|
|
3595
|
-
const ok = await this.agentStream.focusAgentEditor(this.
|
|
3755
|
+
const ok = await this.agentStream.focusAgentEditor(this.getCdp(), agentType);
|
|
3596
3756
|
return { success: ok };
|
|
3597
3757
|
}
|
|
3598
3758
|
};
|
|
@@ -4193,10 +4353,10 @@ var init_adhdev_daemon = __esm({
|
|
|
4193
4353
|
localServer = null;
|
|
4194
4354
|
bridge = null;
|
|
4195
4355
|
adapter = null;
|
|
4196
|
-
|
|
4356
|
+
cdpManagers = /* @__PURE__ */ new Map();
|
|
4197
4357
|
cdpDiscoveryTimer = null;
|
|
4198
4358
|
p2p = null;
|
|
4199
|
-
|
|
4359
|
+
scriptLoaders = /* @__PURE__ */ new Map();
|
|
4200
4360
|
commandHandler = null;
|
|
4201
4361
|
screenshotTimer = null;
|
|
4202
4362
|
agentStreamManager = null;
|
|
@@ -4208,7 +4368,9 @@ var init_adhdev_daemon = __esm({
|
|
|
4208
4368
|
detectedIdes = [];
|
|
4209
4369
|
localPort;
|
|
4210
4370
|
ideType = "unknown";
|
|
4211
|
-
|
|
4371
|
+
_cachedAgentStreamsMap = /* @__PURE__ */ new Map();
|
|
4372
|
+
_cachedActiveChatMap = /* @__PURE__ */ new Map();
|
|
4373
|
+
_cdpChatBusy = false;
|
|
4212
4374
|
constructor() {
|
|
4213
4375
|
this.localPort = DEFAULT_DAEMON_PORT;
|
|
4214
4376
|
}
|
|
@@ -4271,18 +4433,27 @@ var init_adhdev_daemon = __esm({
|
|
|
4271
4433
|
}
|
|
4272
4434
|
this.detectedIdes = await detectIDEs();
|
|
4273
4435
|
await this.initCdp();
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
}
|
|
4436
|
+
const serverUrl = options.serverUrl || config.serverUrl;
|
|
4437
|
+
for (const ideType of this.cdpManagers.keys()) {
|
|
4438
|
+
const loader = new DaemonScriptLoader(serverUrl, ideType);
|
|
4439
|
+
loader.setToken(config.connectionToken);
|
|
4440
|
+
await loader.start().catch((e) => {
|
|
4441
|
+
console.log(import_chalk2.default.yellow(` \u26A0 ScriptLoader start failed for ${ideType}: ${e.message}`));
|
|
4442
|
+
});
|
|
4443
|
+
this.scriptLoaders.set(ideType, loader);
|
|
4444
|
+
}
|
|
4445
|
+
if (this.scriptLoaders.size === 0) {
|
|
4446
|
+
const fallbackType = this.detectedIdes.find((ide) => ide.installed)?.id || "cursor";
|
|
4447
|
+
const loader = new DaemonScriptLoader(serverUrl, fallbackType);
|
|
4448
|
+
loader.setToken(config.connectionToken);
|
|
4449
|
+
await loader.start().catch((e) => {
|
|
4450
|
+
console.log(import_chalk2.default.yellow(` \u26A0 ScriptLoader start failed: ${e.message}`));
|
|
4451
|
+
});
|
|
4452
|
+
this.scriptLoaders.set(fallbackType, loader);
|
|
4453
|
+
}
|
|
4283
4454
|
this.commandHandler = new DaemonCommandHandler({
|
|
4284
|
-
|
|
4285
|
-
|
|
4455
|
+
cdpManagers: this.cdpManagers,
|
|
4456
|
+
scriptLoaders: this.scriptLoaders,
|
|
4286
4457
|
localServer: this.localServer,
|
|
4287
4458
|
ideType: this.ideType
|
|
4288
4459
|
});
|
|
@@ -4293,16 +4464,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4293
4464
|
);
|
|
4294
4465
|
this.agentStreamManager.setLocalServer(this.localServer);
|
|
4295
4466
|
this.commandHandler.setAgentStreamManager(this.agentStreamManager);
|
|
4296
|
-
|
|
4297
|
-
this.agentStreamTimer = setInterval(async () => {
|
|
4298
|
-
if (!this.cdpManager?.isConnected || !this.agentStreamManager) return;
|
|
4299
|
-
try {
|
|
4300
|
-
await this.agentStreamManager.syncAgentSessions(this.cdpManager);
|
|
4301
|
-
this._cachedAgentStreams = await this.agentStreamManager.collectAgentStreams(this.cdpManager);
|
|
4302
|
-
} catch {
|
|
4303
|
-
}
|
|
4304
|
-
}, 5e3);
|
|
4305
|
-
}
|
|
4467
|
+
this.startAgentStreamPolling();
|
|
4306
4468
|
if (options.cliType) {
|
|
4307
4469
|
const cliInfo = await detectCLI(options.cliType);
|
|
4308
4470
|
if (cliInfo) {
|
|
@@ -4353,12 +4515,26 @@ var init_adhdev_daemon = __esm({
|
|
|
4353
4515
|
return { id: req.id, success: result.success, entries: result.files, error: result.error };
|
|
4354
4516
|
}
|
|
4355
4517
|
});
|
|
4518
|
+
let ssDebugCount = 0;
|
|
4356
4519
|
this.screenshotTimer = setInterval(async () => {
|
|
4357
|
-
|
|
4520
|
+
const active = this.p2p?.screenshotActive;
|
|
4521
|
+
const ssIdeType = this.p2p?.screenshotIdeType;
|
|
4522
|
+
const cdp = ssIdeType ? this.getCdpFor(ssIdeType) : this.getAnyCdp();
|
|
4523
|
+
if (!active || !cdp) return;
|
|
4524
|
+
ssDebugCount++;
|
|
4525
|
+
if (ssDebugCount <= 3 || ssDebugCount % 25 === 0) {
|
|
4526
|
+
console.log(`[SS] Capturing screenshot... (tick ${ssDebugCount}, active=${active}, cdp=true)`);
|
|
4527
|
+
}
|
|
4358
4528
|
try {
|
|
4359
|
-
const buf = await
|
|
4360
|
-
if (buf)
|
|
4361
|
-
|
|
4529
|
+
const buf = await cdp.captureScreenshot();
|
|
4530
|
+
if (buf) {
|
|
4531
|
+
const sent = this.p2p.sendScreenshot(buf.toString("base64"));
|
|
4532
|
+
if (ssDebugCount <= 3) console.log(`[SS] Screenshot sent: ${buf.length} bytes, delivered=${sent}`);
|
|
4533
|
+
} else {
|
|
4534
|
+
if (ssDebugCount <= 5) console.log(`[SS] captureScreenshot returned null`);
|
|
4535
|
+
}
|
|
4536
|
+
} catch (e) {
|
|
4537
|
+
if (ssDebugCount <= 5) console.log(`[SS] Screenshot error: ${e?.message}`);
|
|
4362
4538
|
}
|
|
4363
4539
|
}, 200);
|
|
4364
4540
|
} else {
|
|
@@ -4391,9 +4567,10 @@ var init_adhdev_daemon = __esm({
|
|
|
4391
4567
|
console.log(import_chalk2.default.bold(" \u{1F309} ADHDev Daemon"));
|
|
4392
4568
|
console.log(` ${import_chalk2.default.bold("Local:")} ws://127.0.0.1:${this.localPort}/ipc`);
|
|
4393
4569
|
console.log(` ${import_chalk2.default.bold("Server:")} ${serverUrl}`);
|
|
4394
|
-
|
|
4570
|
+
const cdpStatus = this.cdpManagers.size > 0 ? `\u2705 ${[...this.cdpManagers.entries()].map(([k, m]) => `${k}:${m.getPort()}`).join(", ")}` : "\u274C not connected";
|
|
4571
|
+
console.log(` ${import_chalk2.default.bold("CDP:")} ${cdpStatus}`);
|
|
4395
4572
|
console.log(` ${import_chalk2.default.bold("P2P:")} ${this.p2p?.isAvailable ? "\u2705 available" : "\u274C unavailable"}`);
|
|
4396
|
-
console.log(` ${import_chalk2.default.bold("Scripts:")} ${this.
|
|
4573
|
+
console.log(` ${import_chalk2.default.bold("Scripts:")} ${this.scriptLoaders.size > 0 ? `\u2705 ${[...this.scriptLoaders.keys()].join(", ")}` : "\u274C not loaded"}`);
|
|
4397
4574
|
if (options.cliType) {
|
|
4398
4575
|
console.log(` ${import_chalk2.default.bold("CLI:")} ${options.cliType}`);
|
|
4399
4576
|
console.log(` ${import_chalk2.default.bold("Dir:")} ${options.workingDir || process.cwd()}`);
|
|
@@ -4405,19 +4582,6 @@ var init_adhdev_daemon = __esm({
|
|
|
4405
4582
|
// ─── 서버 명령 핸들러 ───────────────────────────
|
|
4406
4583
|
registerServerHandlers() {
|
|
4407
4584
|
if (!this.bridge) return;
|
|
4408
|
-
this.bridge.on("send_chat", (msg) => {
|
|
4409
|
-
const text = msg.payload.message;
|
|
4410
|
-
if (!text || !this.adapter) {
|
|
4411
|
-
this.sendResult(msg, false, { error: "No message or CLI adapter" });
|
|
4412
|
-
return;
|
|
4413
|
-
}
|
|
4414
|
-
console.log(import_chalk2.default.cyan(` \u2190 Chat: "${text.slice(0, 60)}${text.length > 60 ? "..." : ""}"`));
|
|
4415
|
-
this.adapter.sendMessage(text).then(() => {
|
|
4416
|
-
this.sendResult(msg, true, { sent: true });
|
|
4417
|
-
}).catch((e) => {
|
|
4418
|
-
this.sendResult(msg, false, { error: e?.message || "Failed" });
|
|
4419
|
-
});
|
|
4420
|
-
});
|
|
4421
4585
|
this.bridge.on("command", async (msg) => {
|
|
4422
4586
|
const cmd = msg.payload.command;
|
|
4423
4587
|
const args = msg.payload.args;
|
|
@@ -4455,7 +4619,38 @@ var init_adhdev_daemon = __esm({
|
|
|
4455
4619
|
"file_list",
|
|
4456
4620
|
"file_list_browse",
|
|
4457
4621
|
"terminal_exec",
|
|
4458
|
-
"refresh_scripts"
|
|
4622
|
+
"refresh_scripts",
|
|
4623
|
+
// CLI/daemon-local commands (launch, restart, detect)
|
|
4624
|
+
"launch_ide",
|
|
4625
|
+
"detect_ides",
|
|
4626
|
+
"restart_session",
|
|
4627
|
+
"switch_cli",
|
|
4628
|
+
"change_dir",
|
|
4629
|
+
"exec_command",
|
|
4630
|
+
// Extension-delegated commands (must be registered to receive WS messages)
|
|
4631
|
+
"vscode_command_exec",
|
|
4632
|
+
"execute_vscode_command",
|
|
4633
|
+
"get_open_editors",
|
|
4634
|
+
"open_tab",
|
|
4635
|
+
"close_tab",
|
|
4636
|
+
"open_folder",
|
|
4637
|
+
"open_folder_picker",
|
|
4638
|
+
"open_recent",
|
|
4639
|
+
"get_commands",
|
|
4640
|
+
"get_recent_workspaces",
|
|
4641
|
+
"open_panel",
|
|
4642
|
+
"open_file",
|
|
4643
|
+
"create_terminal",
|
|
4644
|
+
"close_terminal",
|
|
4645
|
+
// Agent stream commands
|
|
4646
|
+
"agent_stream_switch",
|
|
4647
|
+
"agent_stream_read",
|
|
4648
|
+
"agent_stream_send",
|
|
4649
|
+
"agent_stream_resolve",
|
|
4650
|
+
"agent_stream_new",
|
|
4651
|
+
"agent_stream_list_chats",
|
|
4652
|
+
"agent_stream_switch_session",
|
|
4653
|
+
"agent_stream_focus"
|
|
4459
4654
|
];
|
|
4460
4655
|
for (const cmdType of directCdpCommands) {
|
|
4461
4656
|
this.bridge.on(cmdType, async (msg) => {
|
|
@@ -4506,7 +4701,33 @@ var init_adhdev_daemon = __esm({
|
|
|
4506
4701
|
return;
|
|
4507
4702
|
}
|
|
4508
4703
|
case "launch_ide": {
|
|
4509
|
-
const
|
|
4704
|
+
const launchArgs = { ...args, ideId: args.ideId || args.ideType };
|
|
4705
|
+
const ideKey = launchArgs.ideId;
|
|
4706
|
+
console.log(`[launch_ide] target=${ideKey || "auto"}`);
|
|
4707
|
+
const result = await launchWithCdp(launchArgs);
|
|
4708
|
+
if (result.success && result.port && result.ideId && !this.cdpManagers.has(result.ideId)) {
|
|
4709
|
+
console.log(import_chalk2.default.cyan(`[launch_ide] Connecting CDP for ${result.ideId} on port ${result.port}...`));
|
|
4710
|
+
const manager = new DaemonCdpManager(result.port, (msg2) => {
|
|
4711
|
+
console.log(import_chalk2.default.gray(msg2));
|
|
4712
|
+
}, true);
|
|
4713
|
+
const connected = await manager.connect();
|
|
4714
|
+
if (connected) {
|
|
4715
|
+
this.cdpManagers.set(result.ideId, manager);
|
|
4716
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${result.ideId} (port ${result.port})`));
|
|
4717
|
+
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
4718
|
+
if (!this.scriptLoaders.has(result.ideId)) {
|
|
4719
|
+
const config = loadConfig();
|
|
4720
|
+
const serverUrl = config.serverUrl || "https://api.adhf.dev";
|
|
4721
|
+
const loader = new DaemonScriptLoader(serverUrl, result.ideId);
|
|
4722
|
+
loader.setToken(config.connectionToken || "");
|
|
4723
|
+
await loader.start().catch((e) => {
|
|
4724
|
+
console.log(import_chalk2.default.yellow(` \u26A0 ScriptLoader start failed for ${result.ideId}: ${e?.message}`));
|
|
4725
|
+
});
|
|
4726
|
+
this.scriptLoaders.set(result.ideId, loader);
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
this.startAgentStreamPolling();
|
|
4510
4731
|
this.sendResult(msg, result.success, result);
|
|
4511
4732
|
return;
|
|
4512
4733
|
}
|
|
@@ -4570,14 +4791,43 @@ var init_adhdev_daemon = __esm({
|
|
|
4570
4791
|
const isProcessing = this.adapter?.isProcessing();
|
|
4571
4792
|
const interval = isProcessing ? 2e3 : 15e3;
|
|
4572
4793
|
this.statusTimer = setTimeout(() => {
|
|
4573
|
-
this.sendUnifiedStatusReport()
|
|
4794
|
+
this.sendUnifiedStatusReport().catch(() => {
|
|
4795
|
+
});
|
|
4574
4796
|
scheduleNext();
|
|
4575
4797
|
}, interval);
|
|
4576
4798
|
};
|
|
4577
4799
|
scheduleNext();
|
|
4578
4800
|
}
|
|
4579
|
-
sendUnifiedStatusReport() {
|
|
4801
|
+
async sendUnifiedStatusReport() {
|
|
4580
4802
|
if (!this.bridge?.isConnected()) return;
|
|
4803
|
+
if (this.cdpManagers.size > 0 && this.scriptLoaders.size > 0 && !this._cdpChatBusy) {
|
|
4804
|
+
this._cdpChatBusy = true;
|
|
4805
|
+
for (const [ideType, cdp] of this.cdpManagers) {
|
|
4806
|
+
if (!cdp.isConnected) continue;
|
|
4807
|
+
const loader = this.scriptLoaders.get(ideType);
|
|
4808
|
+
if (!loader) continue;
|
|
4809
|
+
const readChatScript = loader.get("read_chat");
|
|
4810
|
+
if (!readChatScript) continue;
|
|
4811
|
+
try {
|
|
4812
|
+
const raw = await cdp.evaluate(readChatScript, 3e4);
|
|
4813
|
+
if (raw && typeof raw === "object") {
|
|
4814
|
+
let { activeModal } = raw;
|
|
4815
|
+
if (activeModal) {
|
|
4816
|
+
const w = activeModal.width ?? Infinity;
|
|
4817
|
+
const h = activeModal.height ?? Infinity;
|
|
4818
|
+
if (w < 80 || h < 40) activeModal = void 0;
|
|
4819
|
+
else activeModal = {
|
|
4820
|
+
message: activeModal.message?.slice(0, 300) ?? "",
|
|
4821
|
+
buttons: (activeModal.buttons ?? []).filter((t) => t.length < 30)
|
|
4822
|
+
};
|
|
4823
|
+
}
|
|
4824
|
+
this._cachedActiveChatMap.set(ideType, { ...raw, activeModal });
|
|
4825
|
+
}
|
|
4826
|
+
} catch {
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
this._cdpChatBusy = false;
|
|
4830
|
+
}
|
|
4581
4831
|
const now = Date.now();
|
|
4582
4832
|
const perExtData = this.localServer?.getPerExtensionData() || [];
|
|
4583
4833
|
const extSummary = this.localServer?.getLatestExtensionData() || {
|
|
@@ -4587,12 +4837,13 @@ var init_adhdev_daemon = __esm({
|
|
|
4587
4837
|
aiAgents: [],
|
|
4588
4838
|
connectedIdes: []
|
|
4589
4839
|
};
|
|
4590
|
-
const cdpAgentStreams = this._cachedAgentStreams || [];
|
|
4591
4840
|
const managedIdes = perExtData.map((ext) => {
|
|
4592
|
-
const
|
|
4841
|
+
const ideKey = ext.ideType.toLowerCase();
|
|
4842
|
+
const isMainCdpIde = this.cdpManagers.has(ideKey);
|
|
4843
|
+
const cdpStreamsForIde = this._cachedAgentStreamsMap.get(ideKey) || [];
|
|
4593
4844
|
const ideAgentStreams = [
|
|
4594
4845
|
...ext.agentStreams,
|
|
4595
|
-
...isMainCdpIde ?
|
|
4846
|
+
...isMainCdpIde ? cdpStreamsForIde : []
|
|
4596
4847
|
];
|
|
4597
4848
|
return {
|
|
4598
4849
|
ideType: ext.ideType,
|
|
@@ -4602,10 +4853,10 @@ var init_adhdev_daemon = __esm({
|
|
|
4602
4853
|
activeFile: ext.activeFile,
|
|
4603
4854
|
terminals: ext.terminals,
|
|
4604
4855
|
aiAgents: ext.aiAgents,
|
|
4605
|
-
activeChat: ext.activeChat,
|
|
4856
|
+
activeChat: isMainCdpIde && this._cachedActiveChatMap.has(ideKey) ? this._cachedActiveChatMap.get(ideKey) : ext.activeChat,
|
|
4606
4857
|
chats: ext.chats,
|
|
4607
4858
|
agentStreams: ideAgentStreams,
|
|
4608
|
-
cdpConnected: isMainCdpIde ? this.
|
|
4859
|
+
cdpConnected: isMainCdpIde ? this.cdpManagers.get(ext.ideType.toLowerCase())?.isConnected || false : false
|
|
4609
4860
|
};
|
|
4610
4861
|
});
|
|
4611
4862
|
const managedClis = [];
|
|
@@ -4673,8 +4924,12 @@ var init_adhdev_daemon = __esm({
|
|
|
4673
4924
|
// 관리 중인 IDE/CLI (계층 데이터)
|
|
4674
4925
|
managedIdes,
|
|
4675
4926
|
managedClis,
|
|
4676
|
-
// IDE 감지 결과 (설치된 IDE 목록)
|
|
4677
|
-
detectedIdes: this.detectedIdes
|
|
4927
|
+
// IDE 감지 결과 (설치된 IDE 목록) — 프론트엔드 호환 매핑 (id→type)
|
|
4928
|
+
detectedIdes: this.detectedIdes.map((ide) => ({
|
|
4929
|
+
...ide,
|
|
4930
|
+
type: ide.id
|
|
4931
|
+
// 프론트엔드 MachineDetail.tsx는 'type' 필드 사용
|
|
4932
|
+
})),
|
|
4678
4933
|
// P2P 상태
|
|
4679
4934
|
p2p: {
|
|
4680
4935
|
available: this.p2p?.isAvailable || false,
|
|
@@ -4682,8 +4937,8 @@ var init_adhdev_daemon = __esm({
|
|
|
4682
4937
|
peers: this.p2p?.connectedPeerCount || 0,
|
|
4683
4938
|
screenshotActive: this.p2p?.screenshotActive || false
|
|
4684
4939
|
},
|
|
4685
|
-
cdpConnected: this.
|
|
4686
|
-
scriptLoaderReady:
|
|
4940
|
+
cdpConnected: this.getAnyCdp() !== null,
|
|
4941
|
+
scriptLoaderReady: this.scriptLoaders.size > 0,
|
|
4687
4942
|
timestamp: now,
|
|
4688
4943
|
// ─── Legacy compat (서버 기존 로직용, 점진적 제거 예정) ───
|
|
4689
4944
|
activeFile: extSummary.activeFile,
|
|
@@ -4703,7 +4958,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4703
4958
|
messages: c.activeChat?.messages || [],
|
|
4704
4959
|
inputContent: ""
|
|
4705
4960
|
})),
|
|
4706
|
-
...
|
|
4961
|
+
...[...this._cachedAgentStreamsMap.values()].flat()
|
|
4707
4962
|
],
|
|
4708
4963
|
connectedExtensions: extSummary.connectedIdes,
|
|
4709
4964
|
system: {
|
|
@@ -4740,13 +4995,16 @@ var init_adhdev_daemon = __esm({
|
|
|
4740
4995
|
if (this.cdpDiscoveryTimer) clearInterval(this.cdpDiscoveryTimer);
|
|
4741
4996
|
if (this.screenshotTimer) clearInterval(this.screenshotTimer);
|
|
4742
4997
|
if (this.agentStreamTimer) clearInterval(this.agentStreamTimer);
|
|
4743
|
-
|
|
4744
|
-
|
|
4998
|
+
const anyCdpStop = this.getAnyCdp();
|
|
4999
|
+
if (this.agentStreamManager && anyCdpStop) {
|
|
5000
|
+
await this.agentStreamManager.dispose(anyCdpStop).catch(() => {
|
|
4745
5001
|
});
|
|
4746
5002
|
}
|
|
4747
5003
|
this.p2p?.disconnect();
|
|
4748
|
-
this.
|
|
4749
|
-
this.
|
|
5004
|
+
for (const loader of this.scriptLoaders.values()) loader.stop();
|
|
5005
|
+
this.scriptLoaders.clear();
|
|
5006
|
+
for (const m of this.cdpManagers.values()) m.disconnect();
|
|
5007
|
+
this.cdpManagers.clear();
|
|
4750
5008
|
this.localServer?.stop();
|
|
4751
5009
|
this.bridge?.disconnect();
|
|
4752
5010
|
removeDaemonPid();
|
|
@@ -4754,6 +5012,33 @@ var init_adhdev_daemon = __esm({
|
|
|
4754
5012
|
process.exit(0);
|
|
4755
5013
|
}
|
|
4756
5014
|
// ─── CDP 관리 ───────────────────────────────────
|
|
5015
|
+
/** 첫 번째 연결된 CDP 매니저 반환 */
|
|
5016
|
+
getAnyCdp() {
|
|
5017
|
+
for (const m of this.cdpManagers.values()) {
|
|
5018
|
+
if (m.isConnected) return m;
|
|
5019
|
+
}
|
|
5020
|
+
return null;
|
|
5021
|
+
}
|
|
5022
|
+
/** 특정 IDE의 CDP 매니저 반환 */
|
|
5023
|
+
getCdpFor(ideType) {
|
|
5024
|
+
return this.cdpManagers.get(ideType.toLowerCase()) || null;
|
|
5025
|
+
}
|
|
5026
|
+
/** Agent stream polling 시작 (idempotent — 이미 시작됐으면 무시) */
|
|
5027
|
+
startAgentStreamPolling() {
|
|
5028
|
+
if (this.agentStreamTimer) return;
|
|
5029
|
+
this.agentStreamTimer = setInterval(async () => {
|
|
5030
|
+
if (!this.agentStreamManager || this.cdpManagers.size === 0) return;
|
|
5031
|
+
for (const [ideType, cdp] of this.cdpManagers) {
|
|
5032
|
+
if (!cdp.isConnected) continue;
|
|
5033
|
+
try {
|
|
5034
|
+
await this.agentStreamManager.syncAgentSessions(cdp);
|
|
5035
|
+
const streams = await this.agentStreamManager.collectAgentStreams(cdp);
|
|
5036
|
+
this._cachedAgentStreamsMap.set(ideType, streams);
|
|
5037
|
+
} catch {
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
}, 5e3);
|
|
5041
|
+
}
|
|
4757
5042
|
async initCdp() {
|
|
4758
5043
|
const cdpPortMap = {
|
|
4759
5044
|
cursor: 9333,
|
|
@@ -4763,7 +5048,7 @@ var init_adhdev_daemon = __esm({
|
|
|
4763
5048
|
};
|
|
4764
5049
|
const portsToTry = [];
|
|
4765
5050
|
for (const ide of this.detectedIdes) {
|
|
4766
|
-
const ideKey = ide.
|
|
5051
|
+
const ideKey = ide.id || ide.name?.toLowerCase();
|
|
4767
5052
|
const port = cdpPortMap[ideKey];
|
|
4768
5053
|
if (port) portsToTry.push({ port, ide: ideKey });
|
|
4769
5054
|
}
|
|
@@ -4775,22 +5060,31 @@ var init_adhdev_daemon = __esm({
|
|
|
4775
5060
|
for (const { port, ide } of portsToTry) {
|
|
4776
5061
|
const manager = new DaemonCdpManager(port, (msg) => {
|
|
4777
5062
|
console.log(import_chalk2.default.gray(msg));
|
|
4778
|
-
});
|
|
5063
|
+
}, true);
|
|
4779
5064
|
const connected = await manager.connect();
|
|
4780
5065
|
if (connected) {
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
}, 3e4);
|
|
4789
|
-
return;
|
|
5066
|
+
const actualPort = manager.getPort();
|
|
5067
|
+
const actualIde = Object.entries(cdpPortMap).find(([, p]) => p === actualPort)?.[0] || ide;
|
|
5068
|
+
this.cdpManagers.set(actualIde, manager);
|
|
5069
|
+
console.log(import_chalk2.default.green(` \u{1F50D} CDP connected: ${actualIde} (port ${actualPort})`));
|
|
5070
|
+
if (this.ideType === "unknown") {
|
|
5071
|
+
this.ideType = actualIde;
|
|
5072
|
+
}
|
|
4790
5073
|
}
|
|
4791
5074
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
5075
|
+
if (this.cdpManagers.size > 0) {
|
|
5076
|
+
console.log(import_chalk2.default.green(` \u{1F4E1} CDP: ${this.cdpManagers.size} IDE(s) connected`));
|
|
5077
|
+
this.cdpDiscoveryTimer = setInterval(async () => {
|
|
5078
|
+
for (const m of this.cdpManagers.values()) {
|
|
5079
|
+
if (m.isConnected) {
|
|
5080
|
+
await m.discoverAgentWebviews();
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
}, 3e4);
|
|
5084
|
+
} else {
|
|
5085
|
+
console.log(import_chalk2.default.yellow(` \u26A0 CDP not available \u2014 tried ports: ${portsToTry.map((p) => `${p.ide}:${p.port}`).join(", ")}`));
|
|
5086
|
+
console.log(import_chalk2.default.yellow(` IDE may need relaunch with --remote-debugging-port`));
|
|
5087
|
+
}
|
|
4794
5088
|
}
|
|
4795
5089
|
};
|
|
4796
5090
|
}
|