adhdev 0.1.51 → 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 +390 -40
- package/package.json +1 -1
- 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
|
}
|
|
@@ -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}`);
|
|
@@ -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,
|
|
@@ -7521,7 +7843,14 @@ var init_daemon_cli = __esm({
|
|
|
7521
7843
|
sendMessage: async (text) => {
|
|
7522
7844
|
acpInstance.onEvent("send_message", { text });
|
|
7523
7845
|
},
|
|
7524
|
-
getStatus: () =>
|
|
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
|
+
},
|
|
7525
7854
|
setOnStatusChange: () => {
|
|
7526
7855
|
},
|
|
7527
7856
|
setOnPtyData: () => {
|
|
@@ -8130,15 +8459,36 @@ var init_ide_provider_instance = __esm({
|
|
|
8130
8459
|
async readChat() {
|
|
8131
8460
|
const { cdp: cdp2 } = this.context;
|
|
8132
8461
|
if (!cdp2?.isConnected) return;
|
|
8133
|
-
const readChatScript = this.getReadChatScript();
|
|
8134
|
-
if (!readChatScript) return;
|
|
8135
8462
|
try {
|
|
8136
|
-
let raw =
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
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
|
+
}
|
|
8142
8492
|
}
|
|
8143
8493
|
}
|
|
8144
8494
|
if (!raw || typeof raw !== "object") return;
|
package/package.json
CHANGED
|
@@ -229,6 +229,28 @@
|
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
|
+
// C: footer 기반 사용량/quota 다이얼로그 (Dismiss / See Plans / Enable Overages 등)
|
|
233
|
+
// <footer> 요소가 conv 안에 존재하고 2개 이상 버튼이 있으면 사용자 액션이 필요한 카드로 판단
|
|
234
|
+
if (!activeModal) {
|
|
235
|
+
const footers = Array.from(conv.querySelectorAll('footer')).filter(f => f.offsetWidth > 0 && f.offsetHeight > 0);
|
|
236
|
+
for (const footer of footers) {
|
|
237
|
+
const footerBtns = Array.from(footer.querySelectorAll('button, a')).filter(b => b.offsetWidth > 0);
|
|
238
|
+
if (footerBtns.length >= 2) {
|
|
239
|
+
// 카드 컨테이너: footer 상위에서 충분한 높이를 가진 첫 번째 요소
|
|
240
|
+
let card = footer.parentElement;
|
|
241
|
+
for (let up = 0; up < 4 && card; up++) {
|
|
242
|
+
if (card.offsetHeight > 60) break;
|
|
243
|
+
card = card.parentElement;
|
|
244
|
+
}
|
|
245
|
+
const msg = card ? (card.innerText || '').trim().slice(0, 300) : '';
|
|
246
|
+
const btnTexts = footerBtns.map(b => (b.innerText || '').trim()).filter(t => t.length > 0 && t.length < 40);
|
|
247
|
+
if (btnTexts.length >= 2) {
|
|
248
|
+
activeModal = { message: msg, buttons: btnTexts, width: card ? card.offsetWidth : 300, height: card ? card.offsetHeight : 100 };
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
232
254
|
// 모달이 감지되면 status를 waiting_approval로 변경
|
|
233
255
|
if (activeModal) status = 'waiting_approval';
|
|
234
256
|
} catch (e) { activeModal = null; }
|
|
@@ -45,8 +45,11 @@ module.exports = {
|
|
|
45
45
|
inputMethod: 'cdp-type-and-send',
|
|
46
46
|
inputSelector: '[contenteditable="true"][role="textbox"]',
|
|
47
47
|
|
|
48
|
+
// Kiro의 채팅 UI는 webview iframe 내부
|
|
49
|
+
webviewMatchText: 'kiro-chat',
|
|
50
|
+
|
|
48
51
|
scripts: {
|
|
49
|
-
|
|
52
|
+
webviewReadChat() { return loadScript('webview_read_chat.js'); },
|
|
50
53
|
sendMessage(text) {
|
|
51
54
|
const s = loadScript('send_message.js');
|
|
52
55
|
return s ? s.replace(/\$\{\s*MESSAGE\s*\}/g, JSON.stringify(text)) : null;
|
|
@@ -58,5 +61,26 @@ module.exports = {
|
|
|
58
61
|
const s = loadScript('resolve_action.js');
|
|
59
62
|
return s ? s.replace(/\$\{\s*BUTTON_TEXT\s*\}/g, JSON.stringify(buttonText)) : null;
|
|
60
63
|
},
|
|
64
|
+
openPanel() { return loadScript('open_panel.js'); },
|
|
65
|
+
focusEditor() { return loadScript('focus_editor.js'); },
|
|
66
|
+
// 세션 관리 (webview)
|
|
67
|
+
webviewListSessions() { return loadScript('webview_list_sessions.js'); },
|
|
68
|
+
webviewNewSession() { return loadScript('webview_new_session.js'); },
|
|
69
|
+
webviewSwitchSession(sessionId) {
|
|
70
|
+
const s = loadScript('webview_switch_session.js');
|
|
71
|
+
return s ? s.replace(/\$\{\s*SESSION_ID\s*\}/g, JSON.stringify(sessionId)) : null;
|
|
72
|
+
},
|
|
73
|
+
webviewListModels() { return loadScript('webview_list_models.js'); },
|
|
74
|
+
webviewSetModel(params) {
|
|
75
|
+
const model = typeof params === 'string' ? params : params?.model;
|
|
76
|
+
const s = loadScript('webview_set_model.js');
|
|
77
|
+
return s ? s.replace(/\$\{\s*MODEL\s*\}/g, JSON.stringify(model)) : null;
|
|
78
|
+
},
|
|
79
|
+
webviewListModes() { return loadScript('webview_list_modes.js'); },
|
|
80
|
+
webviewSetMode(params) {
|
|
81
|
+
const mode = typeof params === 'string' ? params : params?.mode;
|
|
82
|
+
const s = loadScript('webview_set_mode.js');
|
|
83
|
+
return s ? s.replace(/\$\{\s*MODE\s*\}/g, JSON.stringify(mode)) : null;
|
|
84
|
+
},
|
|
61
85
|
},
|
|
62
86
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor v1 — focus_editor
|
|
3
|
+
*
|
|
4
|
+
* CURSOR.md 4-5: 셀렉터 우선순위
|
|
5
|
+
* [contenteditable="true"][role="textbox"]
|
|
6
|
+
* → .chat-input textarea
|
|
7
|
+
* → .composer-input
|
|
8
|
+
* → textarea
|
|
9
|
+
*
|
|
10
|
+
* 최종 확인: 2026-03-06
|
|
11
|
+
*/
|
|
12
|
+
(() => {
|
|
13
|
+
const editor = document.querySelector('[contenteditable="true"][role="textbox"]')
|
|
14
|
+
|| document.querySelector('.chat-input textarea')
|
|
15
|
+
|| document.querySelector('.composer-input')
|
|
16
|
+
|| document.querySelector('textarea.native-input')
|
|
17
|
+
|| document.querySelector('textarea');
|
|
18
|
+
if (editor) { editor.focus(); return 'focused'; }
|
|
19
|
+
return 'no editor found';
|
|
20
|
+
})()
|