adhdev 0.1.50 → 0.1.53
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 +983 -72
- package/package.json +1 -1
- package/providers/_builtin/acp/codex-cli/provider.js +3 -3
- package/providers/_builtin/ide/antigravity/scripts/read_chat.js +22 -0
- package/providers/_builtin/ide/kiro/provider.js +25 -1
- package/providers/_builtin/ide/kiro/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/kiro/scripts/open_panel.js +47 -0
- package/providers/_builtin/ide/kiro/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/kiro/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_models.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_modes.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_sessions.js +21 -0
- package/providers/_builtin/ide/kiro/scripts/webview_new_session.js +34 -0
- package/providers/_builtin/ide/kiro/scripts/webview_read_chat.js +68 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_mode.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_model.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_switch_session.js +26 -0
- package/providers/_builtin/ide/pearai/provider.js +27 -1
- package/providers/_builtin/ide/pearai/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/pearai/scripts/open_panel.js +46 -0
- package/providers/_builtin/ide/pearai/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/pearai/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_models.js +43 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_modes.js +35 -0
- package/providers/_builtin/ide/pearai/scripts/webview_new_session.js +21 -0
- package/providers/_builtin/ide/pearai/scripts/webview_read_chat.js +92 -0
- package/providers/_builtin/ide/pearai/scripts/webview_resolve_action.js +59 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_mode.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_model.js +36 -0
- package/providers/_builtin/ide/trae/provider.js +22 -1
- package/providers/_builtin/ide/trae/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/trae/scripts/list_chats.js +24 -0
- package/providers/_builtin/ide/trae/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/trae/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/trae/scripts/new_session.js +30 -0
- package/providers/_builtin/ide/trae/scripts/open_panel.js +44 -0
- package/providers/_builtin/ide/trae/scripts/read_chat.js +113 -0
- package/providers/_builtin/ide/trae/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/trae/scripts/send_message.js +19 -0
- package/providers/_builtin/ide/trae/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/trae/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/trae/scripts/switch_session.js +23 -0
- package/providers/_builtin/ide/windsurf/provider.js +12 -0
- package/providers/_builtin/ide/windsurf/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/set_model.js +15 -0
package/dist/index.js
CHANGED
|
@@ -1991,6 +1991,193 @@ var init_daemon_cdp = __esm({
|
|
|
1991
1991
|
this.log(`[CDP] typeAndSend: sent "${text.substring(0, 50)}..."`);
|
|
1992
1992
|
return true;
|
|
1993
1993
|
}
|
|
1994
|
+
/**
|
|
1995
|
+
* 좌표 기반 typeAndSend — webview iframe 안의 입력 필드에 사용
|
|
1996
|
+
* selector 대신 직접 좌표를 받아 클릭+입력+Enter
|
|
1997
|
+
*/
|
|
1998
|
+
async typeAndSendAt(x, y, text) {
|
|
1999
|
+
if (!this.isConnected) return false;
|
|
2000
|
+
await this.sendInternal("Input.dispatchMouseEvent", {
|
|
2001
|
+
type: "mousePressed",
|
|
2002
|
+
x: Math.round(x),
|
|
2003
|
+
y: Math.round(y),
|
|
2004
|
+
button: "left",
|
|
2005
|
+
clickCount: 1
|
|
2006
|
+
});
|
|
2007
|
+
await this.sendInternal("Input.dispatchMouseEvent", {
|
|
2008
|
+
type: "mouseReleased",
|
|
2009
|
+
x: Math.round(x),
|
|
2010
|
+
y: Math.round(y),
|
|
2011
|
+
button: "left",
|
|
2012
|
+
clickCount: 1
|
|
2013
|
+
});
|
|
2014
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
2015
|
+
await this.sendInternal("Input.dispatchKeyEvent", {
|
|
2016
|
+
type: "rawKeyDown",
|
|
2017
|
+
key: "a",
|
|
2018
|
+
code: "KeyA",
|
|
2019
|
+
windowsVirtualKeyCode: 65,
|
|
2020
|
+
modifiers: 8
|
|
2021
|
+
// Meta
|
|
2022
|
+
});
|
|
2023
|
+
await this.sendInternal("Input.dispatchKeyEvent", {
|
|
2024
|
+
type: "keyUp",
|
|
2025
|
+
key: "a",
|
|
2026
|
+
code: "KeyA",
|
|
2027
|
+
windowsVirtualKeyCode: 65,
|
|
2028
|
+
modifiers: 8
|
|
2029
|
+
});
|
|
2030
|
+
await this.sendInternal("Input.dispatchKeyEvent", {
|
|
2031
|
+
type: "rawKeyDown",
|
|
2032
|
+
key: "Backspace",
|
|
2033
|
+
code: "Backspace",
|
|
2034
|
+
windowsVirtualKeyCode: 8
|
|
2035
|
+
});
|
|
2036
|
+
await this.sendInternal("Input.dispatchKeyEvent", {
|
|
2037
|
+
type: "keyUp",
|
|
2038
|
+
key: "Backspace",
|
|
2039
|
+
code: "Backspace",
|
|
2040
|
+
windowsVirtualKeyCode: 8
|
|
2041
|
+
});
|
|
2042
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
2043
|
+
await this.sendInternal("Input.insertText", { text });
|
|
2044
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
2045
|
+
await this.sendInternal("Input.dispatchKeyEvent", {
|
|
2046
|
+
type: "rawKeyDown",
|
|
2047
|
+
key: "Enter",
|
|
2048
|
+
code: "Enter",
|
|
2049
|
+
windowsVirtualKeyCode: 13,
|
|
2050
|
+
nativeVirtualKeyCode: 13
|
|
2051
|
+
});
|
|
2052
|
+
await this.sendInternal("Input.dispatchKeyEvent", {
|
|
2053
|
+
type: "keyUp",
|
|
2054
|
+
key: "Enter",
|
|
2055
|
+
code: "Enter",
|
|
2056
|
+
windowsVirtualKeyCode: 13,
|
|
2057
|
+
nativeVirtualKeyCode: 13
|
|
2058
|
+
});
|
|
2059
|
+
this.log(`[CDP] typeAndSendAt(${Math.round(x)},${Math.round(y)}): sent "${text.substring(0, 50)}..."`);
|
|
2060
|
+
return true;
|
|
2061
|
+
}
|
|
2062
|
+
/**
|
|
2063
|
+
* Webview iframe 내부에서 JS evaluate
|
|
2064
|
+
* Kiro, PearAI 등 채팅 UI가 webview iframe 안에 있는 IDE에서 사용.
|
|
2065
|
+
*
|
|
2066
|
+
* 1. browser WS로 Target.getTargets → vscode-webview iframe 찾기
|
|
2067
|
+
* 2. Target.attachToTarget → session 획득
|
|
2068
|
+
* 3. Page.getFrameTree → nested iframe 찾기
|
|
2069
|
+
* 4. Page.createIsolatedWorld → contextId 획득
|
|
2070
|
+
* 5. Runtime.evaluate → 결과 반환
|
|
2071
|
+
*
|
|
2072
|
+
* @param expression 실행할 JS 표현식
|
|
2073
|
+
* @param matchFn webview iframe URL 매칭 함수 (optional, 모든 webview 시도)
|
|
2074
|
+
* @returns evaluate 결과 또는 null
|
|
2075
|
+
*/
|
|
2076
|
+
async evaluateInWebviewFrame(expression, matchFn) {
|
|
2077
|
+
if (!this._browserConnected) {
|
|
2078
|
+
await this.connectBrowserWs().catch(() => {
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
if (!this.browserWs || !this._browserConnected) {
|
|
2082
|
+
this.log("[CDP] evaluateInWebviewFrame: no browser WS");
|
|
2083
|
+
return null;
|
|
2084
|
+
}
|
|
2085
|
+
const browserWs = this.browserWs;
|
|
2086
|
+
let msgId = this.browserMsgId;
|
|
2087
|
+
const sendWs = (method, params = {}, sessionId) => {
|
|
2088
|
+
return new Promise((resolve6, reject) => {
|
|
2089
|
+
const mid = msgId++;
|
|
2090
|
+
this.browserMsgId = msgId;
|
|
2091
|
+
const handler = (raw) => {
|
|
2092
|
+
try {
|
|
2093
|
+
const msg = JSON.parse(raw.toString());
|
|
2094
|
+
if (msg.id === mid) {
|
|
2095
|
+
browserWs.removeListener("message", handler);
|
|
2096
|
+
if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
2097
|
+
else resolve6(msg.result);
|
|
2098
|
+
}
|
|
2099
|
+
} catch {
|
|
2100
|
+
}
|
|
2101
|
+
};
|
|
2102
|
+
browserWs.on("message", handler);
|
|
2103
|
+
const payload = { id: mid, method, params };
|
|
2104
|
+
if (sessionId) payload.sessionId = sessionId;
|
|
2105
|
+
browserWs.send(JSON.stringify(payload));
|
|
2106
|
+
setTimeout(() => {
|
|
2107
|
+
browserWs.removeListener("message", handler);
|
|
2108
|
+
reject(new Error(`timeout: ${method}`));
|
|
2109
|
+
}, 1e4);
|
|
2110
|
+
});
|
|
2111
|
+
};
|
|
2112
|
+
try {
|
|
2113
|
+
const { targetInfos } = await sendWs("Target.getTargets");
|
|
2114
|
+
const webviewIframes = (targetInfos || []).filter(
|
|
2115
|
+
(t) => t.type === "iframe" && (t.url || "").includes("vscode-webview")
|
|
2116
|
+
);
|
|
2117
|
+
if (webviewIframes.length === 0) {
|
|
2118
|
+
this.log("[CDP] evaluateInWebviewFrame: no webview iframes found");
|
|
2119
|
+
return null;
|
|
2120
|
+
}
|
|
2121
|
+
for (const iframe of webviewIframes) {
|
|
2122
|
+
let sessionId = null;
|
|
2123
|
+
try {
|
|
2124
|
+
const attached = await sendWs("Target.attachToTarget", {
|
|
2125
|
+
targetId: iframe.targetId,
|
|
2126
|
+
flatten: true
|
|
2127
|
+
});
|
|
2128
|
+
sessionId = attached.sessionId;
|
|
2129
|
+
const { frameTree } = await sendWs("Page.getFrameTree", {}, sessionId);
|
|
2130
|
+
const childFrame = frameTree?.childFrames?.[0]?.frame;
|
|
2131
|
+
if (!childFrame) {
|
|
2132
|
+
await sendWs("Target.detachFromTarget", { sessionId }).catch(() => {
|
|
2133
|
+
});
|
|
2134
|
+
continue;
|
|
2135
|
+
}
|
|
2136
|
+
const { executionContextId } = await sendWs("Page.createIsolatedWorld", {
|
|
2137
|
+
frameId: childFrame.id,
|
|
2138
|
+
worldName: "adhdev-eval",
|
|
2139
|
+
grantUniveralAccess: true
|
|
2140
|
+
}, sessionId);
|
|
2141
|
+
if (matchFn) {
|
|
2142
|
+
const checkResult = await sendWs("Runtime.evaluate", {
|
|
2143
|
+
expression: `document.documentElement?.outerHTML?.substring(0, 500000) || ''`,
|
|
2144
|
+
returnByValue: true,
|
|
2145
|
+
contextId: executionContextId
|
|
2146
|
+
}, sessionId);
|
|
2147
|
+
const bodyText = checkResult?.result?.value || "";
|
|
2148
|
+
if (!matchFn(bodyText)) {
|
|
2149
|
+
await sendWs("Target.detachFromTarget", { sessionId }).catch(() => {
|
|
2150
|
+
});
|
|
2151
|
+
continue;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
const result = await sendWs("Runtime.evaluate", {
|
|
2155
|
+
expression,
|
|
2156
|
+
returnByValue: true,
|
|
2157
|
+
contextId: executionContextId
|
|
2158
|
+
}, sessionId);
|
|
2159
|
+
await sendWs("Target.detachFromTarget", { sessionId }).catch(() => {
|
|
2160
|
+
});
|
|
2161
|
+
const value = result?.result?.value;
|
|
2162
|
+
if (value != null) {
|
|
2163
|
+
this.log(`[CDP] evaluateInWebviewFrame: success in ${iframe.targetId.substring(0, 12)}`);
|
|
2164
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
2165
|
+
}
|
|
2166
|
+
} catch (e) {
|
|
2167
|
+
if (sessionId) {
|
|
2168
|
+
await sendWs("Target.detachFromTarget", { sessionId }).catch(() => {
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
this.log(`[CDP] evaluateInWebviewFrame: error in ${iframe.targetId.substring(0, 12)}: ${e.message}`);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
this.log("[CDP] evaluateInWebviewFrame: no matching webview found");
|
|
2175
|
+
return null;
|
|
2176
|
+
} catch (e) {
|
|
2177
|
+
this.log(`[CDP] evaluateInWebviewFrame error: ${e.message}`);
|
|
2178
|
+
return null;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
1994
2181
|
// ─── Agent Webview Multi-Session ─────────────────────────
|
|
1995
2182
|
async discoverAgentWebviews() {
|
|
1996
2183
|
if (!this.isConnected) return [];
|
|
@@ -3306,7 +3493,15 @@ var init_dev_server = __esm({
|
|
|
3306
3493
|
this.json(res, 500, { error: "Script function returned null" });
|
|
3307
3494
|
return;
|
|
3308
3495
|
}
|
|
3309
|
-
const
|
|
3496
|
+
const isWebviewScript = scriptName.toLowerCase().includes("webview");
|
|
3497
|
+
let raw;
|
|
3498
|
+
if (isWebviewScript) {
|
|
3499
|
+
const matchText = provider2.webviewMatchText;
|
|
3500
|
+
const matchFn = matchText ? (body2) => body2.includes(matchText) : void 0;
|
|
3501
|
+
raw = await cdp2.evaluateInWebviewFrame(scriptCode, matchFn);
|
|
3502
|
+
} else {
|
|
3503
|
+
raw = await cdp2.evaluate(scriptCode, 3e4);
|
|
3504
|
+
}
|
|
3310
3505
|
let result = raw;
|
|
3311
3506
|
if (typeof raw === "string") {
|
|
3312
3507
|
try {
|
|
@@ -4286,8 +4481,11 @@ var init_daemon_commands = __esm({
|
|
|
4286
4481
|
let raw = args._targetInstance;
|
|
4287
4482
|
const ideMatch = raw.match(/:ide:(.+)$/);
|
|
4288
4483
|
const cliMatch = raw.match(/:cli:(.+)$/);
|
|
4484
|
+
const acpMatch = raw.match(/:acp:(.+)$/);
|
|
4289
4485
|
if (ideMatch) raw = ideMatch[1];
|
|
4290
4486
|
else if (cliMatch) raw = cliMatch[1];
|
|
4487
|
+
else if (acpMatch) raw = acpMatch[1];
|
|
4488
|
+
if (raw.startsWith("acp_")) raw = raw.substring(4);
|
|
4291
4489
|
const lastUnderscore = raw.lastIndexOf("_");
|
|
4292
4490
|
if (lastUnderscore > 0) return raw.substring(0, lastUnderscore);
|
|
4293
4491
|
}
|
|
@@ -4510,16 +4708,16 @@ var init_daemon_commands = __esm({
|
|
|
4510
4708
|
async handleReadChat(args) {
|
|
4511
4709
|
const provider2 = this.getProvider();
|
|
4512
4710
|
const _log = (msg) => console.log(`[read_chat] ${msg}`);
|
|
4513
|
-
if (provider2?.category === "cli") {
|
|
4711
|
+
if (provider2?.category === "cli" || provider2?.category === "acp") {
|
|
4514
4712
|
const adapter = this.getCliAdapter(provider2.type);
|
|
4515
4713
|
if (adapter) {
|
|
4516
|
-
_log(
|
|
4714
|
+
_log(`${provider2.category} adapter: ${adapter.cliType}`);
|
|
4517
4715
|
const status = adapter.getStatus?.();
|
|
4518
4716
|
if (status) {
|
|
4519
4717
|
return { success: true, messages: status.messages || [], status: status.status, activeModal: status.activeModal };
|
|
4520
4718
|
}
|
|
4521
4719
|
}
|
|
4522
|
-
return { success: false, error:
|
|
4720
|
+
return { success: false, error: `${provider2.category} adapter not found` };
|
|
4523
4721
|
}
|
|
4524
4722
|
if (provider2?.category === "extension") {
|
|
4525
4723
|
try {
|
|
@@ -4554,15 +4752,44 @@ var init_daemon_commands = __esm({
|
|
|
4554
4752
|
}
|
|
4555
4753
|
const cdp2 = this.getCdp();
|
|
4556
4754
|
if (!cdp2?.isConnected) return { success: false, error: "CDP not connected" };
|
|
4755
|
+
const webviewScript = this.getProviderScript("webviewReadChat") || this.getProviderScript("webview_read_chat");
|
|
4756
|
+
if (webviewScript) {
|
|
4757
|
+
try {
|
|
4758
|
+
const matchText = provider2?.webviewMatchText;
|
|
4759
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4760
|
+
const raw = await cdp2.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
4761
|
+
if (raw) {
|
|
4762
|
+
let parsed = raw;
|
|
4763
|
+
if (typeof parsed === "string") {
|
|
4764
|
+
try {
|
|
4765
|
+
parsed = JSON.parse(parsed);
|
|
4766
|
+
} catch {
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
if (parsed && typeof parsed === "object") {
|
|
4770
|
+
_log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
|
|
4771
|
+
return { success: true, ...parsed };
|
|
4772
|
+
}
|
|
4773
|
+
}
|
|
4774
|
+
} catch (e) {
|
|
4775
|
+
_log(`Webview readChat error: ${e.message}`);
|
|
4776
|
+
}
|
|
4777
|
+
return { success: true, messages: [], status: "idle" };
|
|
4778
|
+
}
|
|
4557
4779
|
const script = this.getProviderScript("readChat") || this.getProviderScript("read_chat");
|
|
4558
4780
|
if (script) {
|
|
4559
4781
|
try {
|
|
4560
4782
|
const result = await cdp2.evaluate(script, 5e4);
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4783
|
+
let parsed = result;
|
|
4784
|
+
if (typeof parsed === "string") {
|
|
4785
|
+
try {
|
|
4786
|
+
parsed = JSON.parse(parsed);
|
|
4787
|
+
} catch {
|
|
4788
|
+
}
|
|
4564
4789
|
}
|
|
4565
|
-
if (
|
|
4790
|
+
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
4791
|
+
_log(`OK: ${parsed.messages?.length} msgs`);
|
|
4792
|
+
return { success: true, ...parsed };
|
|
4566
4793
|
}
|
|
4567
4794
|
} catch (e) {
|
|
4568
4795
|
console.log(`[read_chat] Script error: ${e.message}`);
|
|
@@ -4575,15 +4802,15 @@ var init_daemon_commands = __esm({
|
|
|
4575
4802
|
if (!text) return { success: false, error: "text required" };
|
|
4576
4803
|
const _log = (msg) => console.log(`[send_chat] ${msg}`);
|
|
4577
4804
|
const provider2 = this.getProvider();
|
|
4578
|
-
if (provider2?.category === "cli") {
|
|
4805
|
+
if (provider2?.category === "cli" || provider2?.category === "acp") {
|
|
4579
4806
|
const adapter = this.getCliAdapter(provider2.type);
|
|
4580
4807
|
if (adapter) {
|
|
4581
|
-
_log(
|
|
4808
|
+
_log(`${provider2.category} adapter: ${adapter.cliType}`);
|
|
4582
4809
|
try {
|
|
4583
4810
|
await adapter.sendMessage(text);
|
|
4584
|
-
return { success: true, sent: true, method:
|
|
4811
|
+
return { success: true, sent: true, method: `${provider2.category}-adapter`, targetAgent: adapter.cliType };
|
|
4585
4812
|
} catch (e) {
|
|
4586
|
-
return { success: false, error:
|
|
4813
|
+
return { success: false, error: `${provider2.category} send failed: ${e.message}` };
|
|
4587
4814
|
}
|
|
4588
4815
|
}
|
|
4589
4816
|
}
|
|
@@ -4652,10 +4879,26 @@ var init_daemon_commands = __esm({
|
|
|
4652
4879
|
return { success: true, sent: true, method: "script" };
|
|
4653
4880
|
}
|
|
4654
4881
|
if (parsed?.needsTypeAndSend && parsed?.selector) {
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4882
|
+
try {
|
|
4883
|
+
const sent = await targetCdp.typeAndSend(parsed.selector, text);
|
|
4884
|
+
if (sent) {
|
|
4885
|
+
_log(`typeAndSend(script.selector=${parsed.selector}) success`);
|
|
4886
|
+
return { success: true, sent: true, method: "typeAndSend-script" };
|
|
4887
|
+
}
|
|
4888
|
+
} catch (e) {
|
|
4889
|
+
_log(`typeAndSend(script.selector) failed: ${e.message}`);
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
if (parsed?.needsTypeAndSend && parsed?.clickCoords) {
|
|
4893
|
+
try {
|
|
4894
|
+
const { x, y } = parsed.clickCoords;
|
|
4895
|
+
const sent = await targetCdp.typeAndSendAt(x, y, text);
|
|
4896
|
+
if (sent) {
|
|
4897
|
+
_log(`typeAndSendAt(${x},${y}) success`);
|
|
4898
|
+
return { success: true, sent: true, method: "typeAndSendAt-script" };
|
|
4899
|
+
}
|
|
4900
|
+
} catch (e) {
|
|
4901
|
+
_log(`typeAndSendAt failed: ${e.message}`);
|
|
4659
4902
|
}
|
|
4660
4903
|
}
|
|
4661
4904
|
} catch (e) {
|
|
@@ -4676,6 +4919,27 @@ var init_daemon_commands = __esm({
|
|
|
4676
4919
|
console.log(`[list_chats] Extension error: ${e.message}`);
|
|
4677
4920
|
}
|
|
4678
4921
|
}
|
|
4922
|
+
try {
|
|
4923
|
+
const webviewScript = this.getProviderScript("webviewListSessions") || this.getProviderScript("webview_list_sessions");
|
|
4924
|
+
if (webviewScript) {
|
|
4925
|
+
const matchText = provider2?.webviewMatchText;
|
|
4926
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4927
|
+
const raw = await this.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
4928
|
+
let parsed = raw;
|
|
4929
|
+
if (typeof parsed === "string") {
|
|
4930
|
+
try {
|
|
4931
|
+
parsed = JSON.parse(parsed);
|
|
4932
|
+
} catch {
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
if (parsed?.sessions) {
|
|
4936
|
+
console.log(`[list_chats] Webview OK: ${parsed.sessions.length} chats`);
|
|
4937
|
+
return { success: true, chats: parsed.sessions };
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
} catch (e) {
|
|
4941
|
+
console.log(`[list_chats] Webview error: ${e.message}`);
|
|
4942
|
+
}
|
|
4679
4943
|
try {
|
|
4680
4944
|
const evalResult = await this.evaluateProviderScript("listSessions");
|
|
4681
4945
|
if (evalResult) {
|
|
@@ -4702,6 +4966,17 @@ var init_daemon_commands = __esm({
|
|
|
4702
4966
|
const ok = await this.agentStream.newAgentSession(this.getCdp(), provider2.type, this._currentIdeType);
|
|
4703
4967
|
return { success: ok };
|
|
4704
4968
|
}
|
|
4969
|
+
try {
|
|
4970
|
+
const webviewScript = this.getProviderScript("webviewNewSession") || this.getProviderScript("webview_new_session");
|
|
4971
|
+
if (webviewScript) {
|
|
4972
|
+
const matchText = provider2?.webviewMatchText;
|
|
4973
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
4974
|
+
const raw = await this.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
4975
|
+
if (raw) return { success: true, result: raw };
|
|
4976
|
+
}
|
|
4977
|
+
} catch (e) {
|
|
4978
|
+
return { success: false, error: `webviewNewSession failed: ${e.message}` };
|
|
4979
|
+
}
|
|
4705
4980
|
try {
|
|
4706
4981
|
const evalResult = await this.evaluateProviderScript("newSession");
|
|
4707
4982
|
if (evalResult) return { success: true };
|
|
@@ -4722,6 +4997,17 @@ var init_daemon_commands = __esm({
|
|
|
4722
4997
|
}
|
|
4723
4998
|
const cdp2 = this.getCdp(ideType);
|
|
4724
4999
|
if (!cdp2?.isConnected) return { success: false, error: "CDP not connected" };
|
|
5000
|
+
try {
|
|
5001
|
+
const webviewScript = this.getProviderScript("webviewSwitchSession", { SESSION_ID: JSON.stringify(sessionId) });
|
|
5002
|
+
if (webviewScript) {
|
|
5003
|
+
const matchText = provider2?.webviewMatchText;
|
|
5004
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
5005
|
+
const raw = await cdp2.evaluateInWebviewFrame?.(webviewScript, matchFn);
|
|
5006
|
+
if (raw) return { success: true, result: raw };
|
|
5007
|
+
}
|
|
5008
|
+
} catch (e) {
|
|
5009
|
+
return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
|
|
5010
|
+
}
|
|
4725
5011
|
const script = this.getProviderScript("switchSession", { SESSION_ID: JSON.stringify(sessionId) }) || this.getProviderScript("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
|
|
4726
5012
|
if (!script) return { success: false, error: "switch_session script not available" };
|
|
4727
5013
|
try {
|
|
@@ -4822,6 +5108,36 @@ var init_daemon_commands = __esm({
|
|
|
4822
5108
|
);
|
|
4823
5109
|
return { success: ok };
|
|
4824
5110
|
}
|
|
5111
|
+
if (provider2?.scripts?.webviewResolveAction || provider2?.scripts?.webview_resolve_action) {
|
|
5112
|
+
const script = this.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || this.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
|
|
5113
|
+
if (script) {
|
|
5114
|
+
const cdp2 = this.getCdp();
|
|
5115
|
+
if (cdp2?.isConnected) {
|
|
5116
|
+
try {
|
|
5117
|
+
const matchText = provider2?.webviewMatchText;
|
|
5118
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
5119
|
+
const raw = await cdp2.evaluateInWebviewFrame?.(script, matchFn);
|
|
5120
|
+
let result = raw;
|
|
5121
|
+
if (typeof raw === "string") {
|
|
5122
|
+
try {
|
|
5123
|
+
result = JSON.parse(raw);
|
|
5124
|
+
} catch {
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
console.log(`[resolveAction] webview script result:`, JSON.stringify(result));
|
|
5128
|
+
if (result?.resolved) {
|
|
5129
|
+
return { success: true, clicked: result.clicked };
|
|
5130
|
+
}
|
|
5131
|
+
if (result?.found && result.x != null && result.y != null) {
|
|
5132
|
+
console.log(`[resolveAction] Webview coordinate click not fully supported via CDP. Click directly in script.`);
|
|
5133
|
+
}
|
|
5134
|
+
if (result?.found || result?.resolved) return { success: true };
|
|
5135
|
+
} catch (e) {
|
|
5136
|
+
return { success: false, error: `webviewResolveAction failed: ${e.message}` };
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
}
|
|
5140
|
+
}
|
|
4825
5141
|
if (provider2?.scripts?.resolveAction) {
|
|
4826
5142
|
const script = provider2.scripts.resolveAction({ action, button, buttonText: button });
|
|
4827
5143
|
if (script) {
|
|
@@ -5274,11 +5590,14 @@ var init_daemon_commands = __esm({
|
|
|
5274
5590
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
5275
5591
|
const provider2 = loader.get(agentType);
|
|
5276
5592
|
if (!provider2) return { success: false, error: `Provider not found: ${agentType}` };
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5593
|
+
const isWebviewScript = provider2.category === "ide" && ["webviewListModels", "webviewSetModel", "webviewListModes", "webviewSetMode"].includes(`webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}`);
|
|
5594
|
+
const actualScriptName = isWebviewScript ? `webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}` : scriptName;
|
|
5595
|
+
if (!provider2.scripts?.[actualScriptName]) {
|
|
5596
|
+
return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
|
|
5597
|
+
}
|
|
5598
|
+
const scriptFn = provider2.scripts[actualScriptName];
|
|
5599
|
+
const scriptCode = scriptFn(args);
|
|
5600
|
+
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
5282
5601
|
const cdpKey = provider2.category === "ide" ? this._currentIdeType || agentType : this._currentIdeType || ideType;
|
|
5283
5602
|
console.log(`[ExtScript] provider=${provider2.type} category=${provider2.category} cdpKey=${cdpKey}`);
|
|
5284
5603
|
const cdp2 = this.getCdp(cdpKey);
|
|
@@ -5297,9 +5616,13 @@ var init_daemon_commands = __esm({
|
|
|
5297
5616
|
if (!targetSessionId) {
|
|
5298
5617
|
return { success: false, error: `No active session found for ${agentType}` };
|
|
5299
5618
|
}
|
|
5300
|
-
result = await cdp2.evaluateInSession(targetSessionId,
|
|
5619
|
+
result = await cdp2.evaluateInSession(targetSessionId, scriptCode);
|
|
5620
|
+
} else if (isWebviewScript && cdp2.evaluateInWebviewFrame) {
|
|
5621
|
+
const matchText = provider2.webviewMatchText;
|
|
5622
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
5623
|
+
result = await cdp2.evaluateInWebviewFrame(scriptCode, matchFn);
|
|
5301
5624
|
} else {
|
|
5302
|
-
result = await cdp2.evaluate(
|
|
5625
|
+
result = await cdp2.evaluate(scriptCode, 3e4);
|
|
5303
5626
|
}
|
|
5304
5627
|
if (typeof result === "string") {
|
|
5305
5628
|
try {
|
|
@@ -6074,9 +6397,10 @@ var init_daemon_status = __esm({
|
|
|
6074
6397
|
const exts = (s.extensions || []).length;
|
|
6075
6398
|
return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
|
|
6076
6399
|
}).join(", ");
|
|
6077
|
-
const cliSummary =
|
|
6400
|
+
const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
|
|
6401
|
+
const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
|
|
6078
6402
|
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
6079
|
-
LOG[logLevel]("StatusReport", `\u2192${target} IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length
|
|
6403
|
+
LOG[logLevel]("StatusReport", `\u2192${target} IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`);
|
|
6080
6404
|
const managedIdes = ideStates.map((s) => ({
|
|
6081
6405
|
ideType: s.type,
|
|
6082
6406
|
ideVersion: "",
|
|
@@ -6151,19 +6475,16 @@ var init_daemon_status = __esm({
|
|
|
6151
6475
|
workingDir: s.workingDir || "",
|
|
6152
6476
|
activeChat: s.activeChat
|
|
6153
6477
|
}));
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
isAcp: true
|
|
6165
|
-
});
|
|
6166
|
-
}
|
|
6478
|
+
const managedAcps = acpStates.map((s) => ({
|
|
6479
|
+
id: s.instanceId,
|
|
6480
|
+
acpType: s.type,
|
|
6481
|
+
acpName: s.name,
|
|
6482
|
+
status: s.status,
|
|
6483
|
+
mode: "chat",
|
|
6484
|
+
workingDir: s.workingDir || "",
|
|
6485
|
+
activeChat: s.activeChat,
|
|
6486
|
+
currentModel: s.currentModel
|
|
6487
|
+
}));
|
|
6167
6488
|
const extSummary = localServer?.getLatestExtensionData() || {
|
|
6168
6489
|
activeFile: null,
|
|
6169
6490
|
workspaceFolders: [],
|
|
@@ -6187,6 +6508,7 @@ var init_daemon_status = __esm({
|
|
|
6187
6508
|
},
|
|
6188
6509
|
managedIdes,
|
|
6189
6510
|
managedClis,
|
|
6511
|
+
managedAcps,
|
|
6190
6512
|
detectedIdes: this.deps.detectedIdes.map((ide) => ({ ...ide, type: ide.id })),
|
|
6191
6513
|
p2p: {
|
|
6192
6514
|
available: p2p?.isAvailable || false,
|
|
@@ -6917,18 +7239,545 @@ var init_cli_provider_instance = __esm({
|
|
|
6917
7239
|
}
|
|
6918
7240
|
});
|
|
6919
7241
|
|
|
7242
|
+
// src/providers/acp-provider-instance.ts
|
|
7243
|
+
var path9, crypto, import_child_process6, import_readline, AcpProviderInstance;
|
|
7244
|
+
var init_acp_provider_instance = __esm({
|
|
7245
|
+
"src/providers/acp-provider-instance.ts"() {
|
|
7246
|
+
"use strict";
|
|
7247
|
+
path9 = __toESM(require("path"));
|
|
7248
|
+
crypto = __toESM(require("crypto"));
|
|
7249
|
+
import_child_process6 = require("child_process");
|
|
7250
|
+
import_readline = require("readline");
|
|
7251
|
+
init_status_monitor();
|
|
7252
|
+
AcpProviderInstance = class {
|
|
7253
|
+
constructor(provider2, workingDir, cliArgs = []) {
|
|
7254
|
+
this.cliArgs = cliArgs;
|
|
7255
|
+
this.type = provider2.type;
|
|
7256
|
+
this.provider = provider2;
|
|
7257
|
+
this.workingDir = workingDir;
|
|
7258
|
+
this.instanceId = `acp_${provider2.type}_${crypto.createHash("md5").update(require("os").hostname() + provider2.type + workingDir).digest("hex").slice(0, 8)}`;
|
|
7259
|
+
this.monitor = new StatusMonitor();
|
|
7260
|
+
}
|
|
7261
|
+
type;
|
|
7262
|
+
category = "acp";
|
|
7263
|
+
provider;
|
|
7264
|
+
context = null;
|
|
7265
|
+
settings = {};
|
|
7266
|
+
events = [];
|
|
7267
|
+
monitor;
|
|
7268
|
+
// Process
|
|
7269
|
+
process = null;
|
|
7270
|
+
readline = null;
|
|
7271
|
+
requestId = 1;
|
|
7272
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
7273
|
+
// State
|
|
7274
|
+
sessionId = null;
|
|
7275
|
+
messages = [];
|
|
7276
|
+
currentStatus = "starting";
|
|
7277
|
+
lastStatus = "starting";
|
|
7278
|
+
generatingStartedAt = 0;
|
|
7279
|
+
agentCapabilities = {};
|
|
7280
|
+
currentModel;
|
|
7281
|
+
currentMode;
|
|
7282
|
+
activeToolCalls = [];
|
|
7283
|
+
stopReason = null;
|
|
7284
|
+
partialContent = "";
|
|
7285
|
+
// Config
|
|
7286
|
+
workingDir;
|
|
7287
|
+
instanceId;
|
|
7288
|
+
// ─── Lifecycle ─────────────────────────────────
|
|
7289
|
+
async init(context) {
|
|
7290
|
+
this.context = context;
|
|
7291
|
+
this.settings = context.settings || {};
|
|
7292
|
+
this.monitor.updateConfig({
|
|
7293
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
7294
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
7295
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180
|
|
7296
|
+
});
|
|
7297
|
+
await this.spawnAgent();
|
|
7298
|
+
}
|
|
7299
|
+
async onTick() {
|
|
7300
|
+
if (this.process && this.process.exitCode !== null) {
|
|
7301
|
+
this.currentStatus = "stopped";
|
|
7302
|
+
this.detectStatusTransition();
|
|
7303
|
+
}
|
|
7304
|
+
}
|
|
7305
|
+
getState() {
|
|
7306
|
+
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
7307
|
+
const recentMessages = this.messages.slice(-50).map((m) => ({
|
|
7308
|
+
role: m.role,
|
|
7309
|
+
content: m.content.length > 2e3 ? m.content.slice(0, 2e3) + "\n... (truncated)" : m.content,
|
|
7310
|
+
timestamp: m.timestamp
|
|
7311
|
+
}));
|
|
7312
|
+
if (this.currentStatus === "generating" && this.partialContent) {
|
|
7313
|
+
const cleaned = this.partialContent.trim();
|
|
7314
|
+
if (cleaned) {
|
|
7315
|
+
recentMessages.push({
|
|
7316
|
+
role: "assistant",
|
|
7317
|
+
content: (cleaned.length > 2e3 ? cleaned.slice(0, 2e3) + "..." : cleaned) + "...",
|
|
7318
|
+
timestamp: Date.now()
|
|
7319
|
+
});
|
|
7320
|
+
}
|
|
7321
|
+
}
|
|
7322
|
+
return {
|
|
7323
|
+
type: this.type,
|
|
7324
|
+
name: this.provider.name,
|
|
7325
|
+
category: "acp",
|
|
7326
|
+
status: this.currentStatus,
|
|
7327
|
+
mode: "chat",
|
|
7328
|
+
activeChat: {
|
|
7329
|
+
id: this.sessionId || `${this.type}_${this.workingDir}`,
|
|
7330
|
+
title: `${this.provider.name} \xB7 ${dirName}`,
|
|
7331
|
+
status: this.currentStatus,
|
|
7332
|
+
messages: recentMessages,
|
|
7333
|
+
activeModal: this.currentStatus === "waiting_approval" ? {
|
|
7334
|
+
message: this.activeToolCalls.find((t) => t.status === "running")?.name || "Permission requested",
|
|
7335
|
+
buttons: ["Approve", "Reject"]
|
|
7336
|
+
} : null,
|
|
7337
|
+
inputContent: ""
|
|
7338
|
+
},
|
|
7339
|
+
workingDir: this.workingDir,
|
|
7340
|
+
currentModel: this.currentModel,
|
|
7341
|
+
currentPlan: this.currentMode,
|
|
7342
|
+
instanceId: this.instanceId,
|
|
7343
|
+
lastUpdated: Date.now(),
|
|
7344
|
+
settings: this.settings,
|
|
7345
|
+
pendingEvents: this.flushEvents()
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
onEvent(event, data) {
|
|
7349
|
+
if (event === "send_message" && data?.text) {
|
|
7350
|
+
this.sendPrompt(data.text).catch(
|
|
7351
|
+
(e) => console.warn(`[ACP:${this.type}] sendPrompt error:`, e?.message)
|
|
7352
|
+
);
|
|
7353
|
+
} else if (event === "resolve_action") {
|
|
7354
|
+
const action = data?.action || "approve";
|
|
7355
|
+
this.resolvePermission(action === "approve" || action === "accept").catch((e) => console.warn(`[ACP:${this.type}] resolvePermission error:`, e?.message));
|
|
7356
|
+
} else if (event === "cancel") {
|
|
7357
|
+
this.cancelSession().catch(
|
|
7358
|
+
(e) => console.warn(`[ACP:${this.type}] cancel error:`, e?.message)
|
|
7359
|
+
);
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7362
|
+
dispose() {
|
|
7363
|
+
if (this.process) {
|
|
7364
|
+
try {
|
|
7365
|
+
this.process.kill("SIGTERM");
|
|
7366
|
+
} catch {
|
|
7367
|
+
}
|
|
7368
|
+
this.process = null;
|
|
7369
|
+
}
|
|
7370
|
+
if (this.readline) {
|
|
7371
|
+
this.readline.close();
|
|
7372
|
+
this.readline = null;
|
|
7373
|
+
}
|
|
7374
|
+
for (const [, req] of this.pendingRequests) {
|
|
7375
|
+
clearTimeout(req.timer);
|
|
7376
|
+
req.reject(new Error("Instance disposed"));
|
|
7377
|
+
}
|
|
7378
|
+
this.pendingRequests.clear();
|
|
7379
|
+
this.monitor.reset();
|
|
7380
|
+
}
|
|
7381
|
+
// ─── ACP Process Management ──────────────────────
|
|
7382
|
+
async spawnAgent() {
|
|
7383
|
+
const spawnConfig = this.provider.spawn;
|
|
7384
|
+
if (!spawnConfig) {
|
|
7385
|
+
throw new Error(`[ACP:${this.type}] No spawn config defined`);
|
|
7386
|
+
}
|
|
7387
|
+
const command = spawnConfig.command;
|
|
7388
|
+
const args = [...spawnConfig.args || [], ...this.cliArgs];
|
|
7389
|
+
const env = { ...process.env, ...spawnConfig.env || {} };
|
|
7390
|
+
console.log(`[ACP:${this.type}] Spawning: ${command} ${args.join(" ")} in ${this.workingDir}`);
|
|
7391
|
+
this.process = (0, import_child_process6.spawn)(command, args, {
|
|
7392
|
+
cwd: this.workingDir,
|
|
7393
|
+
env,
|
|
7394
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
7395
|
+
shell: spawnConfig.shell || false
|
|
7396
|
+
});
|
|
7397
|
+
this.readline = (0, import_readline.createInterface)({ input: this.process.stdout });
|
|
7398
|
+
this.readline.on("line", (line) => {
|
|
7399
|
+
const trimmed = line.trim();
|
|
7400
|
+
if (!trimmed) return;
|
|
7401
|
+
try {
|
|
7402
|
+
const msg = JSON.parse(trimmed);
|
|
7403
|
+
this.handleMessage(msg);
|
|
7404
|
+
} catch (e) {
|
|
7405
|
+
}
|
|
7406
|
+
});
|
|
7407
|
+
this.process.stderr?.on("data", (data) => {
|
|
7408
|
+
const text = data.toString().trim();
|
|
7409
|
+
if (text) {
|
|
7410
|
+
console.log(`[ACP:${this.type}:stderr] ${text.slice(0, 200)}`);
|
|
7411
|
+
}
|
|
7412
|
+
});
|
|
7413
|
+
this.process.on("exit", (code, signal) => {
|
|
7414
|
+
console.log(`[ACP:${this.type}] Process exited: code=${code} signal=${signal}`);
|
|
7415
|
+
this.currentStatus = "stopped";
|
|
7416
|
+
this.detectStatusTransition();
|
|
7417
|
+
});
|
|
7418
|
+
this.process.on("error", (err) => {
|
|
7419
|
+
console.error(`[ACP:${this.type}] Process error:`, err.message);
|
|
7420
|
+
this.currentStatus = "error";
|
|
7421
|
+
this.detectStatusTransition();
|
|
7422
|
+
});
|
|
7423
|
+
await this.initialize();
|
|
7424
|
+
}
|
|
7425
|
+
// ─── ACP Protocol ────────────────────────────────
|
|
7426
|
+
async initialize() {
|
|
7427
|
+
try {
|
|
7428
|
+
const result = await this.sendRequest("initialize", {
|
|
7429
|
+
protocolVersion: "0.1.0",
|
|
7430
|
+
clientInfo: {
|
|
7431
|
+
name: "adhdev",
|
|
7432
|
+
version: "0.1.0"
|
|
7433
|
+
},
|
|
7434
|
+
clientCapabilities: {
|
|
7435
|
+
roots: true
|
|
7436
|
+
},
|
|
7437
|
+
workspaceFolders: [{
|
|
7438
|
+
name: path9.basename(this.workingDir),
|
|
7439
|
+
uri: `file://${this.workingDir}`
|
|
7440
|
+
}]
|
|
7441
|
+
});
|
|
7442
|
+
this.agentCapabilities = result?.capabilities || {};
|
|
7443
|
+
console.log(`[ACP:${this.type}] Initialized. Agent capabilities:`, JSON.stringify(this.agentCapabilities));
|
|
7444
|
+
this.sendNotification("initialized");
|
|
7445
|
+
await this.createSession();
|
|
7446
|
+
} catch (e) {
|
|
7447
|
+
console.error(`[ACP:${this.type}] Initialize failed:`, e?.message);
|
|
7448
|
+
this.currentStatus = "error";
|
|
7449
|
+
}
|
|
7450
|
+
}
|
|
7451
|
+
async createSession() {
|
|
7452
|
+
try {
|
|
7453
|
+
const result = await this.sendRequest("session/new", {
|
|
7454
|
+
cwd: this.workingDir,
|
|
7455
|
+
mcpServers: []
|
|
7456
|
+
});
|
|
7457
|
+
this.sessionId = result?.sessionId || null;
|
|
7458
|
+
this.currentStatus = "idle";
|
|
7459
|
+
this.messages = [];
|
|
7460
|
+
if (result?.models?.currentModelId) {
|
|
7461
|
+
this.currentModel = result.models.currentModelId;
|
|
7462
|
+
}
|
|
7463
|
+
console.log(`[ACP:${this.type}] Session created: ${this.sessionId}${this.currentModel ? ` (model: ${this.currentModel})` : ""}`);
|
|
7464
|
+
} catch (e) {
|
|
7465
|
+
console.warn(`[ACP:${this.type}] session/new failed:`, e?.message);
|
|
7466
|
+
this.currentStatus = "idle";
|
|
7467
|
+
}
|
|
7468
|
+
}
|
|
7469
|
+
async sendPrompt(text) {
|
|
7470
|
+
this.messages.push({
|
|
7471
|
+
role: "user",
|
|
7472
|
+
content: text,
|
|
7473
|
+
timestamp: Date.now()
|
|
7474
|
+
});
|
|
7475
|
+
this.currentStatus = "generating";
|
|
7476
|
+
this.partialContent = "";
|
|
7477
|
+
this.detectStatusTransition();
|
|
7478
|
+
try {
|
|
7479
|
+
const result = await this.sendRequest("session/prompt", {
|
|
7480
|
+
sessionId: this.sessionId,
|
|
7481
|
+
prompt: [{ type: "text", text }]
|
|
7482
|
+
}, 3e5);
|
|
7483
|
+
if (result?.stopReason) {
|
|
7484
|
+
this.stopReason = result.stopReason;
|
|
7485
|
+
}
|
|
7486
|
+
if (this.partialContent.trim()) {
|
|
7487
|
+
this.messages.push({
|
|
7488
|
+
role: "assistant",
|
|
7489
|
+
content: this.partialContent.trim(),
|
|
7490
|
+
timestamp: Date.now()
|
|
7491
|
+
});
|
|
7492
|
+
this.partialContent = "";
|
|
7493
|
+
}
|
|
7494
|
+
this.currentStatus = "idle";
|
|
7495
|
+
this.detectStatusTransition();
|
|
7496
|
+
} catch (e) {
|
|
7497
|
+
console.warn(`[ACP:${this.type}] prompt error:`, e?.message);
|
|
7498
|
+
if (this.partialContent.trim()) {
|
|
7499
|
+
this.messages.push({
|
|
7500
|
+
role: "assistant",
|
|
7501
|
+
content: this.partialContent.trim(),
|
|
7502
|
+
timestamp: Date.now()
|
|
7503
|
+
});
|
|
7504
|
+
this.partialContent = "";
|
|
7505
|
+
}
|
|
7506
|
+
this.currentStatus = "idle";
|
|
7507
|
+
this.detectStatusTransition();
|
|
7508
|
+
}
|
|
7509
|
+
}
|
|
7510
|
+
async cancelSession() {
|
|
7511
|
+
this.sendNotification("session/cancel", {
|
|
7512
|
+
sessionId: this.sessionId
|
|
7513
|
+
});
|
|
7514
|
+
this.currentStatus = "idle";
|
|
7515
|
+
this.detectStatusTransition();
|
|
7516
|
+
}
|
|
7517
|
+
permissionResolvers = [];
|
|
7518
|
+
async resolvePermission(approved) {
|
|
7519
|
+
const resolver = this.permissionResolvers.shift();
|
|
7520
|
+
if (resolver) {
|
|
7521
|
+
resolver(approved);
|
|
7522
|
+
}
|
|
7523
|
+
if (this.currentStatus === "waiting_approval") {
|
|
7524
|
+
this.currentStatus = "generating";
|
|
7525
|
+
this.detectStatusTransition();
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7528
|
+
// ─── JSON-RPC Transport ──────────────────────────
|
|
7529
|
+
sendRequest(method, params, timeoutMs = 3e4) {
|
|
7530
|
+
return new Promise((resolve6, reject) => {
|
|
7531
|
+
if (!this.process?.stdin?.writable) {
|
|
7532
|
+
reject(new Error("Process stdin not writable"));
|
|
7533
|
+
return;
|
|
7534
|
+
}
|
|
7535
|
+
const id = this.requestId++;
|
|
7536
|
+
const msg = {
|
|
7537
|
+
jsonrpc: "2.0",
|
|
7538
|
+
id,
|
|
7539
|
+
method,
|
|
7540
|
+
params
|
|
7541
|
+
};
|
|
7542
|
+
const timer = setTimeout(() => {
|
|
7543
|
+
this.pendingRequests.delete(id);
|
|
7544
|
+
reject(new Error(`Request ${method} timed out after ${timeoutMs}ms`));
|
|
7545
|
+
}, timeoutMs);
|
|
7546
|
+
this.pendingRequests.set(id, { resolve: resolve6, reject, timer });
|
|
7547
|
+
const line = JSON.stringify(msg) + "\n";
|
|
7548
|
+
this.process.stdin.write(line);
|
|
7549
|
+
});
|
|
7550
|
+
}
|
|
7551
|
+
sendNotification(method, params) {
|
|
7552
|
+
if (!this.process?.stdin?.writable) return;
|
|
7553
|
+
const msg = {
|
|
7554
|
+
jsonrpc: "2.0",
|
|
7555
|
+
method,
|
|
7556
|
+
...params && { params }
|
|
7557
|
+
};
|
|
7558
|
+
const line = JSON.stringify(msg) + "\n";
|
|
7559
|
+
this.process.stdin.write(line);
|
|
7560
|
+
}
|
|
7561
|
+
handleMessage(msg) {
|
|
7562
|
+
if ("id" in msg && msg.id !== void 0 && !("method" in msg && msg.method)) {
|
|
7563
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
7564
|
+
if (pending) {
|
|
7565
|
+
clearTimeout(pending.timer);
|
|
7566
|
+
this.pendingRequests.delete(msg.id);
|
|
7567
|
+
const resp = msg;
|
|
7568
|
+
if (resp.error) {
|
|
7569
|
+
pending.reject(new Error(`${resp.error.message} (${resp.error.code})`));
|
|
7570
|
+
} else {
|
|
7571
|
+
pending.resolve(resp.result);
|
|
7572
|
+
}
|
|
7573
|
+
}
|
|
7574
|
+
return;
|
|
7575
|
+
}
|
|
7576
|
+
if ("method" in msg) {
|
|
7577
|
+
this.handleNotification(msg);
|
|
7578
|
+
if ("id" in msg && msg.id !== void 0) {
|
|
7579
|
+
this.handleAgentRequest(msg);
|
|
7580
|
+
}
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7583
|
+
handleNotification(msg) {
|
|
7584
|
+
switch (msg.method) {
|
|
7585
|
+
case "session/update": {
|
|
7586
|
+
const params = msg.params;
|
|
7587
|
+
this.handleSessionUpdate(params);
|
|
7588
|
+
break;
|
|
7589
|
+
}
|
|
7590
|
+
default:
|
|
7591
|
+
break;
|
|
7592
|
+
}
|
|
7593
|
+
}
|
|
7594
|
+
handleAgentRequest(msg) {
|
|
7595
|
+
switch (msg.method) {
|
|
7596
|
+
case "fs/readTextFile":
|
|
7597
|
+
case "fs/writeTextFile": {
|
|
7598
|
+
this.sendResponse(msg.id, null, {
|
|
7599
|
+
code: -32601,
|
|
7600
|
+
message: "File system access not supported by ADHDev client"
|
|
7601
|
+
});
|
|
7602
|
+
break;
|
|
7603
|
+
}
|
|
7604
|
+
case "requestPermission": {
|
|
7605
|
+
this.currentStatus = "waiting_approval";
|
|
7606
|
+
this.detectStatusTransition();
|
|
7607
|
+
const promise = new Promise((resolve6) => {
|
|
7608
|
+
this.permissionResolvers.push(resolve6);
|
|
7609
|
+
setTimeout(() => {
|
|
7610
|
+
const idx = this.permissionResolvers.indexOf(resolve6);
|
|
7611
|
+
if (idx >= 0) {
|
|
7612
|
+
this.permissionResolvers.splice(idx, 1);
|
|
7613
|
+
resolve6(false);
|
|
7614
|
+
}
|
|
7615
|
+
}, 3e5);
|
|
7616
|
+
});
|
|
7617
|
+
promise.then((approved) => {
|
|
7618
|
+
this.sendResponse(msg.id, {
|
|
7619
|
+
outcome: approved ? "approved" : "denied"
|
|
7620
|
+
});
|
|
7621
|
+
});
|
|
7622
|
+
break;
|
|
7623
|
+
}
|
|
7624
|
+
case "terminal/create":
|
|
7625
|
+
case "terminal/output":
|
|
7626
|
+
case "terminal/release":
|
|
7627
|
+
case "terminal/kill":
|
|
7628
|
+
case "terminal/waitForExit": {
|
|
7629
|
+
this.sendResponse(msg.id, null, {
|
|
7630
|
+
code: -32601,
|
|
7631
|
+
message: "Terminal not supported by ADHDev client"
|
|
7632
|
+
});
|
|
7633
|
+
break;
|
|
7634
|
+
}
|
|
7635
|
+
default: {
|
|
7636
|
+
this.sendResponse(msg.id, null, {
|
|
7637
|
+
code: -32601,
|
|
7638
|
+
message: `Method ${msg.method} not supported`
|
|
7639
|
+
});
|
|
7640
|
+
}
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
sendResponse(id, result, error) {
|
|
7644
|
+
if (!this.process?.stdin?.writable) return;
|
|
7645
|
+
const msg = {
|
|
7646
|
+
jsonrpc: "2.0",
|
|
7647
|
+
id,
|
|
7648
|
+
...error ? { error } : { result }
|
|
7649
|
+
};
|
|
7650
|
+
const line = JSON.stringify(msg) + "\n";
|
|
7651
|
+
this.process.stdin.write(line);
|
|
7652
|
+
}
|
|
7653
|
+
// ─── ACP session/update 처리 ─────────────────────
|
|
7654
|
+
handleSessionUpdate(params) {
|
|
7655
|
+
if (!params) return;
|
|
7656
|
+
if (params.messageDelta) {
|
|
7657
|
+
const delta = params.messageDelta;
|
|
7658
|
+
if (delta.content) {
|
|
7659
|
+
for (const part of Array.isArray(delta.content) ? delta.content : [delta.content]) {
|
|
7660
|
+
if (part.type === "text" && part.text) {
|
|
7661
|
+
this.partialContent += part.text;
|
|
7662
|
+
}
|
|
7663
|
+
}
|
|
7664
|
+
}
|
|
7665
|
+
this.currentStatus = "generating";
|
|
7666
|
+
}
|
|
7667
|
+
if (params.message) {
|
|
7668
|
+
const m = params.message;
|
|
7669
|
+
let content = "";
|
|
7670
|
+
if (typeof m.content === "string") {
|
|
7671
|
+
content = m.content;
|
|
7672
|
+
} else if (Array.isArray(m.content)) {
|
|
7673
|
+
content = m.content.filter((p) => p.type === "text").map((p) => p.text || "").join("\n");
|
|
7674
|
+
}
|
|
7675
|
+
if (content.trim()) {
|
|
7676
|
+
this.messages.push({
|
|
7677
|
+
role: m.role || "assistant",
|
|
7678
|
+
content: content.trim(),
|
|
7679
|
+
timestamp: Date.now()
|
|
7680
|
+
});
|
|
7681
|
+
this.partialContent = "";
|
|
7682
|
+
}
|
|
7683
|
+
}
|
|
7684
|
+
if (params.toolCallUpdate) {
|
|
7685
|
+
const tc = params.toolCallUpdate;
|
|
7686
|
+
const existing = this.activeToolCalls.find((t) => t.id === tc.id);
|
|
7687
|
+
if (existing) {
|
|
7688
|
+
if (tc.status) existing.status = tc.status;
|
|
7689
|
+
if (tc.output) existing.output = tc.output;
|
|
7690
|
+
} else {
|
|
7691
|
+
this.activeToolCalls.push({
|
|
7692
|
+
id: tc.id || `tc_${Date.now()}`,
|
|
7693
|
+
name: tc.name || "unknown",
|
|
7694
|
+
status: tc.status || "running",
|
|
7695
|
+
input: typeof tc.input === "string" ? tc.input : JSON.stringify(tc.input)
|
|
7696
|
+
});
|
|
7697
|
+
}
|
|
7698
|
+
}
|
|
7699
|
+
if (params.stopReason) {
|
|
7700
|
+
this.stopReason = params.stopReason;
|
|
7701
|
+
if (params.stopReason !== "cancelled") {
|
|
7702
|
+
this.currentStatus = "idle";
|
|
7703
|
+
}
|
|
7704
|
+
this.activeToolCalls = [];
|
|
7705
|
+
this.detectStatusTransition();
|
|
7706
|
+
}
|
|
7707
|
+
if (params.model) {
|
|
7708
|
+
this.currentModel = params.model;
|
|
7709
|
+
}
|
|
7710
|
+
}
|
|
7711
|
+
// ─── 상태 전이 감지 ────────────────────────────
|
|
7712
|
+
detectStatusTransition() {
|
|
7713
|
+
const now = Date.now();
|
|
7714
|
+
const newStatus = this.currentStatus;
|
|
7715
|
+
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
7716
|
+
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
7717
|
+
if (newStatus !== this.lastStatus) {
|
|
7718
|
+
if (this.lastStatus === "idle" && newStatus === "generating") {
|
|
7719
|
+
this.generatingStartedAt = now;
|
|
7720
|
+
this.pushEvent({ event: "agent:generating_started", chatTitle, timestamp: now });
|
|
7721
|
+
} else if (newStatus === "waiting_approval") {
|
|
7722
|
+
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
7723
|
+
this.pushEvent({
|
|
7724
|
+
event: "agent:waiting_approval",
|
|
7725
|
+
chatTitle,
|
|
7726
|
+
timestamp: now,
|
|
7727
|
+
modalMessage: this.activeToolCalls.find((t) => t.status === "running")?.name
|
|
7728
|
+
});
|
|
7729
|
+
} else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
|
|
7730
|
+
const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
|
|
7731
|
+
this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now });
|
|
7732
|
+
this.generatingStartedAt = 0;
|
|
7733
|
+
} else if (newStatus === "stopped") {
|
|
7734
|
+
this.pushEvent({ event: "agent:stopped", chatTitle, timestamp: now });
|
|
7735
|
+
}
|
|
7736
|
+
this.lastStatus = newStatus;
|
|
7737
|
+
}
|
|
7738
|
+
const agentKey = `${this.type}:acp`;
|
|
7739
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now);
|
|
7740
|
+
for (const me of monitorEvents) {
|
|
7741
|
+
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
7742
|
+
}
|
|
7743
|
+
}
|
|
7744
|
+
pushEvent(event) {
|
|
7745
|
+
this.events.push(event);
|
|
7746
|
+
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
7747
|
+
}
|
|
7748
|
+
flushEvents() {
|
|
7749
|
+
const events = [...this.events];
|
|
7750
|
+
this.events = [];
|
|
7751
|
+
return events;
|
|
7752
|
+
}
|
|
7753
|
+
// ─── 외부 접근 ─────────────────────────────────
|
|
7754
|
+
get cliType() {
|
|
7755
|
+
return this.type;
|
|
7756
|
+
}
|
|
7757
|
+
get cliName() {
|
|
7758
|
+
return this.provider.name;
|
|
7759
|
+
}
|
|
7760
|
+
/** ACP Agent capabilities (initialize 후 사용 가능) */
|
|
7761
|
+
getCapabilities() {
|
|
7762
|
+
return this.agentCapabilities;
|
|
7763
|
+
}
|
|
7764
|
+
};
|
|
7765
|
+
}
|
|
7766
|
+
});
|
|
7767
|
+
|
|
6920
7768
|
// src/daemon-cli.ts
|
|
6921
|
-
var os10,
|
|
7769
|
+
var os10, path10, import_chalk, DaemonCliManager;
|
|
6922
7770
|
var init_daemon_cli = __esm({
|
|
6923
7771
|
"src/daemon-cli.ts"() {
|
|
6924
7772
|
"use strict";
|
|
6925
7773
|
os10 = __toESM(require("os"));
|
|
6926
|
-
|
|
7774
|
+
path10 = __toESM(require("path"));
|
|
6927
7775
|
import_chalk = __toESM(require("chalk"));
|
|
6928
7776
|
init_provider_cli_adapter();
|
|
6929
7777
|
init_cli_detector();
|
|
6930
7778
|
init_config();
|
|
6931
7779
|
init_cli_provider_instance();
|
|
7780
|
+
init_acp_provider_instance();
|
|
6932
7781
|
DaemonCliManager = class {
|
|
6933
7782
|
adapters = /* @__PURE__ */ new Map();
|
|
6934
7783
|
deps;
|
|
@@ -6963,20 +7812,61 @@ var init_daemon_cli = __esm({
|
|
|
6963
7812
|
// ─── 세션 시작/중지 ──────────────────────────────
|
|
6964
7813
|
async startSession(cliType, workingDir, cliArgs) {
|
|
6965
7814
|
const trimmed = (workingDir || os10.homedir()).trim();
|
|
6966
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) :
|
|
6967
|
-
const cliInfo = await detectCLI(cliType);
|
|
6968
|
-
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
6969
|
-
const key = this.getCliKey(cliType, resolvedDir);
|
|
6970
|
-
if (this.adapters.has(key)) {
|
|
6971
|
-
console.log(import_chalk.default.yellow(` \u26A1 CLI ${cliType} already running in ${resolvedDir}`));
|
|
6972
|
-
return;
|
|
6973
|
-
}
|
|
7815
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path10.resolve(trimmed);
|
|
6974
7816
|
const typeMap = {
|
|
6975
7817
|
"claude-code": "claude-cli",
|
|
6976
7818
|
"codex": "codex-cli"
|
|
6977
7819
|
};
|
|
6978
7820
|
const normalizedType = typeMap[cliType] || cliType;
|
|
6979
7821
|
const provider2 = this.providerLoader.get(normalizedType);
|
|
7822
|
+
const key = this.getCliKey(normalizedType, resolvedDir);
|
|
7823
|
+
if (this.adapters.has(key)) {
|
|
7824
|
+
console.log(import_chalk.default.yellow(` \u26A1 ${cliType} already running in ${resolvedDir}`));
|
|
7825
|
+
return;
|
|
7826
|
+
}
|
|
7827
|
+
if (provider2 && provider2.category === "acp") {
|
|
7828
|
+
const instanceManager2 = this.deps.getInstanceManager();
|
|
7829
|
+
if (!instanceManager2) throw new Error("InstanceManager not available");
|
|
7830
|
+
console.log(import_chalk.default.cyan(` \u{1F50C} Starting ACP agent: ${provider2.name} (${provider2.type}) in ${resolvedDir}`));
|
|
7831
|
+
const acpInstance = new AcpProviderInstance(provider2, resolvedDir, cliArgs);
|
|
7832
|
+
await instanceManager2.addInstance(key, acpInstance, {
|
|
7833
|
+
settings: this.providerLoader.getSettings(normalizedType)
|
|
7834
|
+
});
|
|
7835
|
+
this.adapters.set(key, {
|
|
7836
|
+
cliType: normalizedType,
|
|
7837
|
+
workingDir: resolvedDir,
|
|
7838
|
+
spawn: async () => {
|
|
7839
|
+
},
|
|
7840
|
+
shutdown: () => {
|
|
7841
|
+
instanceManager2.removeInstance(key);
|
|
7842
|
+
},
|
|
7843
|
+
sendMessage: async (text) => {
|
|
7844
|
+
acpInstance.onEvent("send_message", { text });
|
|
7845
|
+
},
|
|
7846
|
+
getStatus: () => {
|
|
7847
|
+
const state = acpInstance.getState();
|
|
7848
|
+
return {
|
|
7849
|
+
status: state.status,
|
|
7850
|
+
messages: state.activeChat?.messages || [],
|
|
7851
|
+
activeModal: state.activeChat?.activeModal || null
|
|
7852
|
+
};
|
|
7853
|
+
},
|
|
7854
|
+
setOnStatusChange: () => {
|
|
7855
|
+
},
|
|
7856
|
+
setOnPtyData: () => {
|
|
7857
|
+
}
|
|
7858
|
+
});
|
|
7859
|
+
console.log(import_chalk.default.green(` \u2713 ACP agent started: ${provider2.name} in ${resolvedDir}`));
|
|
7860
|
+
try {
|
|
7861
|
+
addCliHistory({ cliType: normalizedType, dir: resolvedDir, cliArgs });
|
|
7862
|
+
} catch (e) {
|
|
7863
|
+
console.warn("[ACP] History save failed:", e?.message);
|
|
7864
|
+
}
|
|
7865
|
+
this.deps.onStatusChange();
|
|
7866
|
+
return;
|
|
7867
|
+
}
|
|
7868
|
+
const cliInfo = await detectCLI(cliType);
|
|
7869
|
+
if (!cliInfo) throw new Error(`${cliType} not found`);
|
|
6980
7870
|
console.log(import_chalk.default.yellow(` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
|
|
6981
7871
|
if (provider2) {
|
|
6982
7872
|
console.log(import_chalk.default.cyan(` \u{1F4E6} Using provider: ${provider2.name} (${provider2.type})`));
|
|
@@ -7408,12 +8298,12 @@ var init_extension_provider_instance = __esm({
|
|
|
7408
8298
|
});
|
|
7409
8299
|
|
|
7410
8300
|
// src/providers/ide-provider-instance.ts
|
|
7411
|
-
var os11,
|
|
8301
|
+
var os11, crypto2, IdeProviderInstance;
|
|
7412
8302
|
var init_ide_provider_instance = __esm({
|
|
7413
8303
|
"src/providers/ide-provider-instance.ts"() {
|
|
7414
8304
|
"use strict";
|
|
7415
8305
|
os11 = __toESM(require("os"));
|
|
7416
|
-
|
|
8306
|
+
crypto2 = __toESM(require("crypto"));
|
|
7417
8307
|
init_extension_provider_instance();
|
|
7418
8308
|
init_status_monitor();
|
|
7419
8309
|
IdeProviderInstance = class {
|
|
@@ -7441,7 +8331,7 @@ var init_ide_provider_instance = __esm({
|
|
|
7441
8331
|
constructor(provider2, instanceKey) {
|
|
7442
8332
|
this.type = provider2.type;
|
|
7443
8333
|
this.provider = provider2;
|
|
7444
|
-
this.instanceId = instanceKey ? `${instanceKey}_${
|
|
8334
|
+
this.instanceId = instanceKey ? `${instanceKey}_${crypto2.createHash("md5").update(os11.hostname() + instanceKey).digest("hex").slice(0, 8)}` : `${provider2.type}_${crypto2.createHash("md5").update(os11.hostname() + provider2.type).digest("hex").slice(0, 8)}`;
|
|
7445
8335
|
this.monitor = new StatusMonitor();
|
|
7446
8336
|
}
|
|
7447
8337
|
// ─── Lifecycle ─────────────────────────────────
|
|
@@ -7569,15 +8459,36 @@ var init_ide_provider_instance = __esm({
|
|
|
7569
8459
|
async readChat() {
|
|
7570
8460
|
const { cdp: cdp2 } = this.context;
|
|
7571
8461
|
if (!cdp2?.isConnected) return;
|
|
7572
|
-
const readChatScript = this.getReadChatScript();
|
|
7573
|
-
if (!readChatScript) return;
|
|
7574
8462
|
try {
|
|
7575
|
-
let raw =
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
8463
|
+
let raw = null;
|
|
8464
|
+
const webviewFn = this.provider.scripts?.webviewReadChat;
|
|
8465
|
+
if (typeof webviewFn === "function" && cdp2.evaluateInWebviewFrame) {
|
|
8466
|
+
const webviewScript = webviewFn();
|
|
8467
|
+
if (webviewScript) {
|
|
8468
|
+
const matchText = this.provider.webviewMatchText;
|
|
8469
|
+
const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
|
|
8470
|
+
const webviewRaw = await cdp2.evaluateInWebviewFrame(webviewScript, matchFn);
|
|
8471
|
+
if (webviewRaw) {
|
|
8472
|
+
raw = typeof webviewRaw === "string" ? (() => {
|
|
8473
|
+
try {
|
|
8474
|
+
return JSON.parse(webviewRaw);
|
|
8475
|
+
} catch {
|
|
8476
|
+
return null;
|
|
8477
|
+
}
|
|
8478
|
+
})() : webviewRaw;
|
|
8479
|
+
}
|
|
8480
|
+
}
|
|
8481
|
+
}
|
|
8482
|
+
if (!raw) {
|
|
8483
|
+
const readChatScript = this.getReadChatScript();
|
|
8484
|
+
if (!readChatScript) return;
|
|
8485
|
+
raw = await cdp2.evaluate(readChatScript, 3e4);
|
|
8486
|
+
if (typeof raw === "string") {
|
|
8487
|
+
try {
|
|
8488
|
+
raw = JSON.parse(raw);
|
|
8489
|
+
} catch {
|
|
8490
|
+
return;
|
|
8491
|
+
}
|
|
7581
8492
|
}
|
|
7582
8493
|
}
|
|
7583
8494
|
if (!raw || typeof raw !== "object") return;
|
|
@@ -7680,9 +8591,9 @@ __export(adhdev_daemon_exports, {
|
|
|
7680
8591
|
stopDaemon: () => stopDaemon
|
|
7681
8592
|
});
|
|
7682
8593
|
function getDaemonPidFile() {
|
|
7683
|
-
const dir =
|
|
8594
|
+
const dir = path11.join(os12.homedir(), ".adhdev");
|
|
7684
8595
|
if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
|
|
7685
|
-
return
|
|
8596
|
+
return path11.join(dir, "daemon.pid");
|
|
7686
8597
|
}
|
|
7687
8598
|
function writeDaemonPid(pid) {
|
|
7688
8599
|
fs6.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
|
|
@@ -7718,7 +8629,7 @@ function stopDaemon() {
|
|
|
7718
8629
|
return false;
|
|
7719
8630
|
}
|
|
7720
8631
|
}
|
|
7721
|
-
var os12, fs6,
|
|
8632
|
+
var os12, fs6, path11, crypto3, import_chalk2, DANGEROUS_PATTERNS, AdhdevDaemon;
|
|
7722
8633
|
var init_adhdev_daemon = __esm({
|
|
7723
8634
|
"src/adhdev-daemon.ts"() {
|
|
7724
8635
|
"use strict";
|
|
@@ -7741,8 +8652,8 @@ var init_adhdev_daemon = __esm({
|
|
|
7741
8652
|
init_daemon_logger();
|
|
7742
8653
|
os12 = __toESM(require("os"));
|
|
7743
8654
|
fs6 = __toESM(require("fs"));
|
|
7744
|
-
|
|
7745
|
-
|
|
8655
|
+
path11 = __toESM(require("path"));
|
|
8656
|
+
crypto3 = __toESM(require("crypto"));
|
|
7746
8657
|
import_chalk2 = __toESM(require("chalk"));
|
|
7747
8658
|
DANGEROUS_PATTERNS = [
|
|
7748
8659
|
/\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/i,
|
|
@@ -7877,7 +8788,7 @@ var init_adhdev_daemon = __esm({
|
|
|
7877
8788
|
this.commandHandler.setAgentStreamManager(this.agentStreamManager);
|
|
7878
8789
|
this.startAgentStreamPolling();
|
|
7879
8790
|
const machineId = os12.hostname().replace(/[^a-zA-Z0-9]/g, "_");
|
|
7880
|
-
const machineHash =
|
|
8791
|
+
const machineHash = crypto3.createHash("md5").update(os12.hostname() + os12.homedir()).digest("hex").slice(0, 8);
|
|
7881
8792
|
const instanceId = `daemon_${machineId}_${machineHash}`;
|
|
7882
8793
|
this.bridge = new CliBridgeConnection({
|
|
7883
8794
|
serverUrl: options.serverUrl || config.serverUrl,
|
|
@@ -9065,16 +9976,16 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
9065
9976
|
try {
|
|
9066
9977
|
const os13 = await import("os");
|
|
9067
9978
|
const fs7 = await import("fs");
|
|
9068
|
-
const
|
|
9979
|
+
const path12 = await import("path");
|
|
9069
9980
|
const platform7 = os13.platform();
|
|
9070
9981
|
const home = os13.homedir();
|
|
9071
9982
|
const getSettingsPath = (appName2) => {
|
|
9072
9983
|
if (platform7 === "darwin") {
|
|
9073
|
-
return
|
|
9984
|
+
return path12.join(home, "Library", "Application Support", appName2, "User", "settings.json");
|
|
9074
9985
|
} else if (platform7 === "win32") {
|
|
9075
|
-
return
|
|
9986
|
+
return path12.join(process.env.APPDATA || path12.join(home, "AppData", "Roaming"), appName2, "User", "settings.json");
|
|
9076
9987
|
} else {
|
|
9077
|
-
return
|
|
9988
|
+
return path12.join(home, ".config", appName2, "User", "settings.json");
|
|
9078
9989
|
}
|
|
9079
9990
|
};
|
|
9080
9991
|
const loader = new ProviderLoader({ logFn: () => {
|
|
@@ -9092,7 +10003,7 @@ async function injectTokenToIDE(ide, connectionToken) {
|
|
|
9092
10003
|
settings = {};
|
|
9093
10004
|
}
|
|
9094
10005
|
} else {
|
|
9095
|
-
fs7.mkdirSync(
|
|
10006
|
+
fs7.mkdirSync(path12.dirname(settingsPath), { recursive: true });
|
|
9096
10007
|
}
|
|
9097
10008
|
settings["adhdev.connectionToken"] = connectionToken;
|
|
9098
10009
|
settings["adhdev.autoConnect"] = true;
|
|
@@ -9128,8 +10039,8 @@ async function startDaemonFlow() {
|
|
|
9128
10039
|
const daemon = new AdhdevDaemon2();
|
|
9129
10040
|
const { execSync: execSync6 } = await import("child_process");
|
|
9130
10041
|
const os13 = await import("os");
|
|
9131
|
-
const
|
|
9132
|
-
const logPath =
|
|
10042
|
+
const path12 = await import("path");
|
|
10043
|
+
const logPath = path12.join(os13.homedir(), ".adhdev", "daemon.log");
|
|
9133
10044
|
try {
|
|
9134
10045
|
execSync6(`nohup adhdev daemon > "${logPath}" 2>&1 &`, {
|
|
9135
10046
|
timeout: 3e3,
|