@browserbridge/bbx 1.0.0 → 1.0.1
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/README.md +3 -1
- package/docs/api-reference.md +33 -33
- package/docs/mcp-vs-cli.md +104 -104
- package/docs/publishing.md +1 -3
- package/docs/quickstart.md +6 -6
- package/docs/unpacked-extension.md +72 -0
- package/manifest.json +3 -17
- package/package.json +44 -42
- package/packages/agent-client/src/cli-helpers.js +10 -5
- package/packages/agent-client/src/cli.js +65 -135
- package/packages/agent-client/src/client.js +37 -17
- package/packages/agent-client/src/command-registry.js +101 -69
- package/packages/agent-client/src/detect.js +3 -6
- package/packages/agent-client/src/install.js +10 -27
- package/packages/agent-client/src/mcp-config.js +11 -30
- package/packages/agent-client/src/runtime.js +41 -20
- package/packages/agent-client/src/setup-status.js +13 -28
- package/packages/extension/src/background-helpers.js +51 -36
- package/packages/extension/src/background-routing.js +11 -13
- package/packages/extension/src/background.js +562 -299
- package/packages/extension/src/content-script-helpers.js +17 -16
- package/packages/extension/src/content-script.js +175 -109
- package/packages/extension/src/sidepanel-helpers.js +3 -1
- package/packages/extension/ui/popup.js +39 -20
- package/packages/extension/ui/sidepanel.js +108 -191
- package/packages/extension/ui/ui.css +2 -1
- package/packages/mcp-server/src/handlers.js +546 -250
- package/packages/mcp-server/src/server.js +558 -257
- package/packages/native-host/bin/bridge-daemon.js +6 -2
- package/packages/native-host/bin/install-manifest.js +2 -2
- package/packages/native-host/bin/postinstall.js +4 -2
- package/packages/native-host/src/config.js +11 -7
- package/packages/native-host/src/daemon.js +143 -92
- package/packages/native-host/src/install-manifest.js +73 -22
- package/packages/native-host/src/native-host.js +55 -40
- package/packages/protocol/src/budget.js +3 -7
- package/packages/protocol/src/capabilities.js +3 -3
- package/packages/protocol/src/errors.js +11 -11
- package/packages/protocol/src/protocol.js +104 -71
- package/packages/protocol/src/registry.js +300 -45
- package/packages/protocol/src/summary.js +249 -106
- package/packages/protocol/src/types.js +1 -1
- package/skills/browser-bridge/SKILL.md +1 -1
- package/skills/browser-bridge/agents/openai.yaml +3 -3
- package/skills/browser-bridge/references/interaction.md +33 -11
- package/skills/browser-bridge/references/patch-workflow.md +3 -0
- package/skills/browser-bridge/references/protocol.md +125 -70
- package/skills/browser-bridge/references/tailwind.md +12 -11
- package/skills/browser-bridge/references/token-efficiency.md +23 -22
- package/skills/browser-bridge/references/ui-workflows.md +8 -0
- package/packages/extension/ui/offscreen.html +0 -6
- package/packages/extension/ui/offscreen.js +0 -61
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
(() => {
|
|
4
|
-
const globalState =
|
|
4
|
+
const globalState =
|
|
5
|
+
/** @type {typeof globalThis & { __BBX_CONTENT_HELPERS__?: Record<string, unknown> }} */ (
|
|
6
|
+
globalThis
|
|
7
|
+
);
|
|
5
8
|
|
|
6
9
|
if (globalState.__BBX_CONTENT_HELPERS__) {
|
|
7
10
|
return;
|
|
@@ -27,7 +30,7 @@
|
|
|
27
30
|
'radio',
|
|
28
31
|
'range',
|
|
29
32
|
'reset',
|
|
30
|
-
'submit'
|
|
33
|
+
'submit',
|
|
31
34
|
]);
|
|
32
35
|
|
|
33
36
|
/**
|
|
@@ -49,11 +52,7 @@
|
|
|
49
52
|
return [];
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
return [
|
|
53
|
-
...new Set(
|
|
54
|
-
value.filter((item) => typeof item === 'string' && item.trim())
|
|
55
|
-
)
|
|
56
|
-
];
|
|
55
|
+
return [...new Set(value.filter((item) => typeof item === 'string' && item.trim()))];
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
/**
|
|
@@ -66,7 +65,7 @@
|
|
|
66
65
|
maxDepth: clamp(options.maxDepth ?? 4, 1, 20),
|
|
67
66
|
textBudget: clamp(options.textBudget ?? 600, 32, 10000),
|
|
68
67
|
includeBbox: options.includeBbox !== false,
|
|
69
|
-
attributeAllowlist: normalizeList(options.attributeAllowlist)
|
|
68
|
+
attributeAllowlist: normalizeList(options.attributeAllowlist),
|
|
70
69
|
};
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -87,7 +86,7 @@
|
|
|
87
86
|
return {
|
|
88
87
|
value: `${value.slice(0, Math.max(0, budget - 1))}\u2026`,
|
|
89
88
|
truncated: true,
|
|
90
|
-
omitted: value.length - budget
|
|
89
|
+
omitted: value.length - budget,
|
|
91
90
|
};
|
|
92
91
|
}
|
|
93
92
|
|
|
@@ -118,7 +117,7 @@
|
|
|
118
117
|
search: 'searchbox',
|
|
119
118
|
submit: 'button',
|
|
120
119
|
reset: 'button',
|
|
121
|
-
image: 'button'
|
|
120
|
+
image: 'button',
|
|
122
121
|
};
|
|
123
122
|
return map[type] || 'textbox';
|
|
124
123
|
}
|
|
@@ -160,7 +159,7 @@
|
|
|
160
159
|
textarea: 'textbox',
|
|
161
160
|
th: 'columnheader',
|
|
162
161
|
tr: 'row',
|
|
163
|
-
ul: 'list'
|
|
162
|
+
ul: 'list',
|
|
164
163
|
};
|
|
165
164
|
return roleMap[tag] || '';
|
|
166
165
|
}
|
|
@@ -175,14 +174,16 @@
|
|
|
175
174
|
link: 'a[href]',
|
|
176
175
|
article: 'article',
|
|
177
176
|
complementary: 'aside',
|
|
178
|
-
button:
|
|
177
|
+
button:
|
|
178
|
+
'button, input[type=button], input[type=submit], input[type=reset], input[type=image]',
|
|
179
179
|
dialog: 'dialog',
|
|
180
180
|
contentinfo: 'footer',
|
|
181
181
|
form: 'form',
|
|
182
182
|
heading: 'h1, h2, h3, h4, h5, h6',
|
|
183
183
|
banner: 'header',
|
|
184
184
|
img: 'img',
|
|
185
|
-
textbox:
|
|
185
|
+
textbox:
|
|
186
|
+
'input:not([type=button]):not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=reset]):not([type=image]):not([type=hidden]), textarea',
|
|
186
187
|
listitem: 'li',
|
|
187
188
|
main: 'main',
|
|
188
189
|
navigation: 'nav',
|
|
@@ -198,7 +199,7 @@
|
|
|
198
199
|
checkbox: 'input[type=checkbox]',
|
|
199
200
|
radio: 'input[type=radio]',
|
|
200
201
|
slider: 'input[type=range]',
|
|
201
|
-
searchbox: 'input[type=search]'
|
|
202
|
+
searchbox: 'input[type=search]',
|
|
202
203
|
};
|
|
203
204
|
return map[role] || '';
|
|
204
205
|
}
|
|
@@ -212,7 +213,7 @@
|
|
|
212
213
|
x: rect.x + window.scrollX,
|
|
213
214
|
y: rect.y + window.scrollY,
|
|
214
215
|
width: rect.width,
|
|
215
|
-
height: rect.height
|
|
216
|
+
height: rect.height,
|
|
216
217
|
};
|
|
217
218
|
}
|
|
218
219
|
|
|
@@ -276,6 +277,6 @@
|
|
|
276
277
|
getInputImplicitRole,
|
|
277
278
|
normalizeList,
|
|
278
279
|
toRect,
|
|
279
|
-
truncateText
|
|
280
|
+
truncateText,
|
|
280
281
|
});
|
|
281
282
|
})();
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
(() => {
|
|
4
|
-
const contentScriptGlobal =
|
|
4
|
+
const contentScriptGlobal =
|
|
5
|
+
/** @type {typeof globalThis & { __chromeCodexBridgeContentScriptLoaded?: boolean }} */ (
|
|
6
|
+
globalThis
|
|
7
|
+
);
|
|
5
8
|
if (contentScriptGlobal.__chromeCodexBridgeContentScriptLoaded) {
|
|
6
9
|
return;
|
|
7
10
|
}
|
|
@@ -43,7 +46,8 @@
|
|
|
43
46
|
const MAX_REGISTRY_SIZE = 5000;
|
|
44
47
|
const MAX_PATCH_REGISTRY_SIZE = 2000;
|
|
45
48
|
let registryPruned = false;
|
|
46
|
-
const contentHelpers =
|
|
49
|
+
const contentHelpers =
|
|
50
|
+
/** @type {typeof globalThis & { __BBX_CONTENT_HELPERS__?: {
|
|
47
51
|
NON_TEXT_INPUT_TYPES: Set<string>,
|
|
48
52
|
applyBudget: (options?: Record<string, any>) => Budget,
|
|
49
53
|
clamp: (value: number | string | null | undefined, minimum: number, maximum: number) => number,
|
|
@@ -66,7 +70,7 @@
|
|
|
66
70
|
getImplicitRole,
|
|
67
71
|
getImplicitRoleSelector,
|
|
68
72
|
toRect,
|
|
69
|
-
truncateText
|
|
73
|
+
truncateText,
|
|
70
74
|
} = contentHelpers;
|
|
71
75
|
|
|
72
76
|
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
@@ -81,11 +85,17 @@
|
|
|
81
85
|
|
|
82
86
|
try {
|
|
83
87
|
const result = handleCommand(message.method, message.params);
|
|
84
|
-
Promise.resolve(result)
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
Promise.resolve(result)
|
|
89
|
+
.then(sendResponse)
|
|
90
|
+
.catch((err) => {
|
|
91
|
+
sendResponse({
|
|
92
|
+
error: err instanceof Error ? err.message : String(err),
|
|
93
|
+
});
|
|
94
|
+
});
|
|
87
95
|
} catch (error) {
|
|
88
|
-
sendResponse({
|
|
96
|
+
sendResponse({
|
|
97
|
+
error: error instanceof Error ? error.message : String(error),
|
|
98
|
+
});
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
return true;
|
|
@@ -128,7 +138,7 @@
|
|
|
128
138
|
case 'dom.get_html':
|
|
129
139
|
return getHtml({
|
|
130
140
|
...params,
|
|
131
|
-
elementRef: resolveElementRefFromParams(params)
|
|
141
|
+
elementRef: resolveElementRefFromParams(params),
|
|
132
142
|
});
|
|
133
143
|
case 'layout.get_box_model':
|
|
134
144
|
return getBoxModel(resolveElementRefFromParams(params));
|
|
@@ -194,8 +204,7 @@
|
|
|
194
204
|
* }}
|
|
195
205
|
*/
|
|
196
206
|
function getPageState() {
|
|
197
|
-
const scrollingElement =
|
|
198
|
-
document.scrollingElement || document.documentElement || document.body;
|
|
207
|
+
const scrollingElement = document.scrollingElement || document.documentElement || document.body;
|
|
199
208
|
const selection = document.getSelection?.()?.toString() || '';
|
|
200
209
|
|
|
201
210
|
return {
|
|
@@ -215,22 +224,22 @@
|
|
|
215
224
|
maxX: Math.max(
|
|
216
225
|
0,
|
|
217
226
|
(scrollingElement?.scrollWidth || document.documentElement.scrollWidth || 0) -
|
|
218
|
-
window.innerWidth
|
|
227
|
+
window.innerWidth
|
|
219
228
|
),
|
|
220
229
|
maxY: Math.max(
|
|
221
230
|
0,
|
|
222
231
|
(scrollingElement?.scrollHeight || document.documentElement.scrollHeight || 0) -
|
|
223
|
-
window.innerHeight
|
|
232
|
+
window.innerHeight
|
|
224
233
|
),
|
|
225
234
|
},
|
|
226
235
|
activeElement:
|
|
227
236
|
document.activeElement instanceof Element
|
|
228
237
|
? summarizeNode(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
238
|
+
document.activeElement,
|
|
239
|
+
['id', 'class', 'name', 'type', 'href', 'role'],
|
|
240
|
+
120,
|
|
241
|
+
true
|
|
242
|
+
).node
|
|
234
243
|
: null,
|
|
235
244
|
selection: truncateText(selection.trim(), 200),
|
|
236
245
|
hints: detectPageHints(),
|
|
@@ -258,7 +267,8 @@
|
|
|
258
267
|
if (!tailwind) {
|
|
259
268
|
// Check for Tailwind's characteristic class patterns on a sample of elements
|
|
260
269
|
const sample = document.querySelectorAll('[class]');
|
|
261
|
-
const twPattern =
|
|
270
|
+
const twPattern =
|
|
271
|
+
/\b(?:flex|grid|bg-|text-|p[xytblr]?-|m[xytblr]?-|w-|h-|rounded|shadow|border)-/;
|
|
262
272
|
for (let i = 0; i < Math.min(sample.length, 30); i++) {
|
|
263
273
|
const cls = sample[i].className;
|
|
264
274
|
if (typeof cls === 'string' && twPattern.test(cls)) {
|
|
@@ -291,7 +301,7 @@
|
|
|
291
301
|
value: result.value,
|
|
292
302
|
truncated: result.truncated,
|
|
293
303
|
omitted: result.omitted,
|
|
294
|
-
length: raw.length
|
|
304
|
+
length: raw.length,
|
|
295
305
|
};
|
|
296
306
|
}
|
|
297
307
|
|
|
@@ -308,7 +318,11 @@
|
|
|
308
318
|
? getRequiredElement(query.withinRef)
|
|
309
319
|
: document.querySelector(query.selector);
|
|
310
320
|
if (!root) {
|
|
311
|
-
return {
|
|
321
|
+
return {
|
|
322
|
+
nodes: [],
|
|
323
|
+
revision: getDocumentRevision(),
|
|
324
|
+
registrySize: elementRegistry.size,
|
|
325
|
+
};
|
|
312
326
|
}
|
|
313
327
|
|
|
314
328
|
/** @type {NodeSummary[]} */
|
|
@@ -317,11 +331,7 @@
|
|
|
317
331
|
/** @type {Array<{ element: Element, depth: number }>} */
|
|
318
332
|
const queue = [{ element: root, depth: 0 }];
|
|
319
333
|
|
|
320
|
-
while (
|
|
321
|
-
queue.length &&
|
|
322
|
-
nodes.length < query.budget.maxNodes &&
|
|
323
|
-
remaining > 0
|
|
324
|
-
) {
|
|
334
|
+
while (queue.length && nodes.length < query.budget.maxNodes && remaining > 0) {
|
|
325
335
|
const next = queue.shift();
|
|
326
336
|
if (!next) {
|
|
327
337
|
continue;
|
|
@@ -335,7 +345,7 @@
|
|
|
335
345
|
element,
|
|
336
346
|
query.budget.attributeAllowlist,
|
|
337
347
|
remaining,
|
|
338
|
-
query.budget.includeBbox
|
|
348
|
+
query.budget.includeBbox
|
|
339
349
|
);
|
|
340
350
|
remaining -= summary.textLength;
|
|
341
351
|
nodes.push(summary.node);
|
|
@@ -369,7 +379,7 @@
|
|
|
369
379
|
const elementRef = rememberElement(element);
|
|
370
380
|
const text = truncateText(
|
|
371
381
|
extractElementText(element),
|
|
372
|
-
Math.min(Math.max(0, remainingText), 160)
|
|
382
|
+
Math.min(Math.max(0, remainingText), 160)
|
|
373
383
|
);
|
|
374
384
|
return {
|
|
375
385
|
textLength: text.value.length,
|
|
@@ -377,10 +387,7 @@
|
|
|
377
387
|
elementRef,
|
|
378
388
|
tag: element.tagName.toLowerCase(),
|
|
379
389
|
role: element.getAttribute('role'),
|
|
380
|
-
name:
|
|
381
|
-
element.getAttribute('aria-label') ||
|
|
382
|
-
element.getAttribute('name') ||
|
|
383
|
-
null,
|
|
390
|
+
name: element.getAttribute('aria-label') || element.getAttribute('name') || null,
|
|
384
391
|
textExcerpt: text.value,
|
|
385
392
|
attrs: summarizeAttributes(element, attributeAllowlist),
|
|
386
393
|
...(includeBbox ? { bbox: toRect(element.getBoundingClientRect()) } : {}),
|
|
@@ -432,10 +439,7 @@
|
|
|
432
439
|
*/
|
|
433
440
|
function getText(elementRef, budget = 600) {
|
|
434
441
|
const element = /** @type {HTMLElement} */ (getRequiredElement(elementRef));
|
|
435
|
-
return truncateText(
|
|
436
|
-
(element.innerText || element.textContent || '').trim(),
|
|
437
|
-
budget,
|
|
438
|
-
);
|
|
442
|
+
return truncateText((element.innerText || element.textContent || '').trim(), budget);
|
|
439
443
|
}
|
|
440
444
|
|
|
441
445
|
/**
|
|
@@ -707,10 +711,7 @@
|
|
|
707
711
|
|
|
708
712
|
const result = runKeyAction(target, key, params.modifiers);
|
|
709
713
|
return {
|
|
710
|
-
elementRef:
|
|
711
|
-
result.target instanceof Element
|
|
712
|
-
? rememberElement(result.target)
|
|
713
|
-
: null,
|
|
714
|
+
elementRef: result.target instanceof Element ? rememberElement(result.target) : null,
|
|
714
715
|
key: result.key,
|
|
715
716
|
handled: result.handled,
|
|
716
717
|
};
|
|
@@ -765,8 +766,8 @@
|
|
|
765
766
|
: [];
|
|
766
767
|
const indexes = Array.isArray(params.indexes)
|
|
767
768
|
? params.indexes
|
|
768
|
-
|
|
769
|
-
|
|
769
|
+
.map((index) => Number(index))
|
|
770
|
+
.filter((index) => Number.isInteger(index) && index >= 0)
|
|
770
771
|
: [];
|
|
771
772
|
|
|
772
773
|
if (!values.length && !labels.length && !indexes.length) {
|
|
@@ -828,11 +829,7 @@
|
|
|
828
829
|
const previous = {};
|
|
829
830
|
for (const [property, value] of Object.entries(params.declarations || {})) {
|
|
830
831
|
previous[property] = element.style.getPropertyValue(property);
|
|
831
|
-
element.style.setProperty(
|
|
832
|
-
property,
|
|
833
|
-
value,
|
|
834
|
-
params.important ? 'important' : '',
|
|
835
|
-
);
|
|
832
|
+
element.style.setProperty(property, value, params.important ? 'important' : '');
|
|
836
833
|
}
|
|
837
834
|
pruneRegistry(patchRegistry, MAX_PATCH_REGISTRY_SIZE);
|
|
838
835
|
const elementRef = rememberElement(element);
|
|
@@ -991,12 +988,16 @@
|
|
|
991
988
|
function getElementRect(elementRef) {
|
|
992
989
|
const el = getRequiredElement(elementRef);
|
|
993
990
|
// Scroll into view so CDP can capture it in the visible viewport
|
|
994
|
-
el.scrollIntoView({
|
|
991
|
+
el.scrollIntoView({
|
|
992
|
+
block: 'center',
|
|
993
|
+
inline: 'center',
|
|
994
|
+
behavior: 'instant',
|
|
995
|
+
});
|
|
995
996
|
const rect = el.getBoundingClientRect();
|
|
996
997
|
if (rect.width < 1 || rect.height < 1) {
|
|
997
998
|
throw new Error(
|
|
998
999
|
`Element has no visible area (${rect.width}\u00d7${rect.height}). ` +
|
|
999
|
-
|
|
1000
|
+
'It may be hidden, collapsed, or not yet rendered.'
|
|
1000
1001
|
);
|
|
1001
1002
|
}
|
|
1002
1003
|
const x = Math.max(0, rect.x);
|
|
@@ -1006,8 +1007,8 @@
|
|
|
1006
1007
|
if (width < 1 || height < 1) {
|
|
1007
1008
|
throw new Error(
|
|
1008
1009
|
'Element is outside the visible viewport after scroll ' +
|
|
1009
|
-
|
|
1010
|
-
|
|
1010
|
+
`(${Math.round(rect.x)},${Math.round(rect.y)} ${Math.round(rect.width)}\u00d7${Math.round(rect.height)}). ` +
|
|
1011
|
+
'It may be in a fixed/sticky container or an iframe.'
|
|
1011
1012
|
);
|
|
1012
1013
|
}
|
|
1013
1014
|
return { x, y, width, height, scale: window.devicePixelRatio || 1 };
|
|
@@ -1157,7 +1158,9 @@
|
|
|
1157
1158
|
? visibleText === searchText
|
|
1158
1159
|
: visibleText.toLowerCase().includes(searchText.toLowerCase());
|
|
1159
1160
|
if (matches) {
|
|
1160
|
-
results.push(
|
|
1161
|
+
results.push(
|
|
1162
|
+
summarizeNode(el, ['id', 'class', 'role', 'href', 'data-testid'], 120, true).node
|
|
1163
|
+
);
|
|
1161
1164
|
}
|
|
1162
1165
|
}
|
|
1163
1166
|
|
|
@@ -1181,9 +1184,12 @@
|
|
|
1181
1184
|
|
|
1182
1185
|
const implicitSelector = getImplicitRoleSelector(role);
|
|
1183
1186
|
const attrSelector = `[role="${CSS.escape(role)}"]`;
|
|
1184
|
-
const combinedSelector =
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
+
const combinedSelector =
|
|
1188
|
+
scope === '*'
|
|
1189
|
+
? implicitSelector
|
|
1190
|
+
? `${attrSelector}, ${implicitSelector}`
|
|
1191
|
+
: attrSelector
|
|
1192
|
+
: scope;
|
|
1187
1193
|
const candidates = document.querySelectorAll(combinedSelector);
|
|
1188
1194
|
const results = [];
|
|
1189
1195
|
|
|
@@ -1201,7 +1207,9 @@
|
|
|
1201
1207
|
continue;
|
|
1202
1208
|
}
|
|
1203
1209
|
}
|
|
1204
|
-
results.push(
|
|
1210
|
+
results.push(
|
|
1211
|
+
summarizeNode(el, ['id', 'class', 'role', 'aria-label', 'href'], 120, true).node
|
|
1212
|
+
);
|
|
1205
1213
|
}
|
|
1206
1214
|
|
|
1207
1215
|
return { nodes: results, count: results.length };
|
|
@@ -1264,47 +1272,100 @@
|
|
|
1264
1272
|
const offsetX = Number(params.offsetX) || 0;
|
|
1265
1273
|
const offsetY = Number(params.offsetY) || 0;
|
|
1266
1274
|
const endPoint = { x: destPoint.x + offsetX, y: destPoint.y + offsetY };
|
|
1267
|
-
const emptyMods = {
|
|
1275
|
+
const emptyMods = {
|
|
1276
|
+
altKey: false,
|
|
1277
|
+
ctrlKey: false,
|
|
1278
|
+
metaKey: false,
|
|
1279
|
+
shiftKey: false,
|
|
1280
|
+
};
|
|
1268
1281
|
|
|
1269
1282
|
scrollTargetIntoView(source);
|
|
1270
1283
|
|
|
1271
1284
|
const dataTransfer = new DataTransfer();
|
|
1272
1285
|
|
|
1273
|
-
source.dispatchEvent(
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1286
|
+
source.dispatchEvent(
|
|
1287
|
+
new MouseEvent('mousedown', {
|
|
1288
|
+
bubbles: true,
|
|
1289
|
+
cancelable: true,
|
|
1290
|
+
composed: true,
|
|
1291
|
+
clientX: sourcePoint.x,
|
|
1292
|
+
clientY: sourcePoint.y,
|
|
1293
|
+
...emptyMods,
|
|
1294
|
+
})
|
|
1295
|
+
);
|
|
1296
|
+
source.dispatchEvent(
|
|
1297
|
+
new DragEvent('dragstart', {
|
|
1298
|
+
bubbles: true,
|
|
1299
|
+
cancelable: true,
|
|
1300
|
+
composed: true,
|
|
1301
|
+
clientX: sourcePoint.x,
|
|
1302
|
+
clientY: sourcePoint.y,
|
|
1303
|
+
dataTransfer,
|
|
1304
|
+
})
|
|
1305
|
+
);
|
|
1306
|
+
source.dispatchEvent(
|
|
1307
|
+
new DragEvent('drag', {
|
|
1308
|
+
bubbles: true,
|
|
1309
|
+
cancelable: true,
|
|
1310
|
+
composed: true,
|
|
1311
|
+
clientX: sourcePoint.x,
|
|
1312
|
+
clientY: sourcePoint.y,
|
|
1313
|
+
dataTransfer,
|
|
1314
|
+
})
|
|
1315
|
+
);
|
|
1285
1316
|
|
|
1286
1317
|
scrollTargetIntoView(destination);
|
|
1287
1318
|
|
|
1288
|
-
destination.dispatchEvent(
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1319
|
+
destination.dispatchEvent(
|
|
1320
|
+
new DragEvent('dragenter', {
|
|
1321
|
+
bubbles: true,
|
|
1322
|
+
cancelable: true,
|
|
1323
|
+
composed: true,
|
|
1324
|
+
clientX: endPoint.x,
|
|
1325
|
+
clientY: endPoint.y,
|
|
1326
|
+
dataTransfer,
|
|
1327
|
+
})
|
|
1328
|
+
);
|
|
1329
|
+
destination.dispatchEvent(
|
|
1330
|
+
new DragEvent('dragover', {
|
|
1331
|
+
bubbles: true,
|
|
1332
|
+
cancelable: true,
|
|
1333
|
+
composed: true,
|
|
1334
|
+
clientX: endPoint.x,
|
|
1335
|
+
clientY: endPoint.y,
|
|
1336
|
+
dataTransfer,
|
|
1337
|
+
})
|
|
1338
|
+
);
|
|
1339
|
+
destination.dispatchEvent(
|
|
1340
|
+
new DragEvent('drop', {
|
|
1341
|
+
bubbles: true,
|
|
1342
|
+
cancelable: true,
|
|
1343
|
+
composed: true,
|
|
1344
|
+
clientX: endPoint.x,
|
|
1345
|
+
clientY: endPoint.y,
|
|
1346
|
+
dataTransfer,
|
|
1347
|
+
})
|
|
1348
|
+
);
|
|
1349
|
+
source.dispatchEvent(
|
|
1350
|
+
new DragEvent('dragend', {
|
|
1351
|
+
bubbles: true,
|
|
1352
|
+
cancelable: true,
|
|
1353
|
+
composed: true,
|
|
1354
|
+
clientX: endPoint.x,
|
|
1355
|
+
clientY: endPoint.y,
|
|
1356
|
+
dataTransfer,
|
|
1357
|
+
})
|
|
1358
|
+
);
|
|
1359
|
+
source.dispatchEvent(
|
|
1360
|
+
new MouseEvent('mouseup', {
|
|
1361
|
+
bubbles: true,
|
|
1362
|
+
cancelable: true,
|
|
1363
|
+
composed: true,
|
|
1364
|
+
clientX: endPoint.x,
|
|
1365
|
+
clientY: endPoint.y,
|
|
1366
|
+
...emptyMods,
|
|
1367
|
+
})
|
|
1368
|
+
);
|
|
1308
1369
|
|
|
1309
1370
|
return {
|
|
1310
1371
|
sourceRef: rememberElement(source),
|
|
@@ -1334,7 +1395,9 @@
|
|
|
1334
1395
|
function getStorageData(params) {
|
|
1335
1396
|
const type = params.type === 'session' ? 'session' : 'local';
|
|
1336
1397
|
const storage = type === 'session' ? sessionStorage : localStorage;
|
|
1337
|
-
const keys = Array.isArray(params.keys)
|
|
1398
|
+
const keys = Array.isArray(params.keys)
|
|
1399
|
+
? params.keys.filter((k) => typeof k === 'string')
|
|
1400
|
+
: null;
|
|
1338
1401
|
/** @type {Record<string, string | null>} */
|
|
1339
1402
|
const result = {};
|
|
1340
1403
|
if (keys) {
|
|
@@ -1452,7 +1515,10 @@
|
|
|
1452
1515
|
return element;
|
|
1453
1516
|
}
|
|
1454
1517
|
|
|
1455
|
-
if (
|
|
1518
|
+
if (
|
|
1519
|
+
element instanceof HTMLOptionElement &&
|
|
1520
|
+
element.parentElement instanceof HTMLSelectElement
|
|
1521
|
+
) {
|
|
1456
1522
|
return element.parentElement;
|
|
1457
1523
|
}
|
|
1458
1524
|
|
|
@@ -1578,9 +1644,7 @@
|
|
|
1578
1644
|
});
|
|
1579
1645
|
}
|
|
1580
1646
|
|
|
1581
|
-
return document.activeElement instanceof Element
|
|
1582
|
-
? document.activeElement
|
|
1583
|
-
: element;
|
|
1647
|
+
return document.activeElement instanceof Element ? document.activeElement : element;
|
|
1584
1648
|
}
|
|
1585
1649
|
|
|
1586
1650
|
/**
|
|
@@ -1664,7 +1728,7 @@
|
|
|
1664
1728
|
button: buttonState.button,
|
|
1665
1729
|
buttons: buttonState.buttons,
|
|
1666
1730
|
...modifiers,
|
|
1667
|
-
})
|
|
1731
|
+
})
|
|
1668
1732
|
);
|
|
1669
1733
|
}
|
|
1670
1734
|
|
|
@@ -1681,7 +1745,9 @@
|
|
|
1681
1745
|
return null;
|
|
1682
1746
|
}
|
|
1683
1747
|
|
|
1684
|
-
const editable = element.querySelector(
|
|
1748
|
+
const editable = element.querySelector(
|
|
1749
|
+
"input, textarea, [contenteditable=''], [contenteditable='true']"
|
|
1750
|
+
);
|
|
1685
1751
|
return editable && isEditableElement(editable)
|
|
1686
1752
|
? /** @type {HTMLInputElement | HTMLTextAreaElement | HTMLElement} */ (editable)
|
|
1687
1753
|
: null;
|
|
@@ -1810,7 +1876,7 @@
|
|
|
1810
1876
|
cancelable: true,
|
|
1811
1877
|
composed: true,
|
|
1812
1878
|
...modifiers,
|
|
1813
|
-
})
|
|
1879
|
+
})
|
|
1814
1880
|
);
|
|
1815
1881
|
}
|
|
1816
1882
|
|
|
@@ -1828,7 +1894,7 @@
|
|
|
1828
1894
|
bubbles: true,
|
|
1829
1895
|
cancelable: true,
|
|
1830
1896
|
composed: true,
|
|
1831
|
-
})
|
|
1897
|
+
})
|
|
1832
1898
|
);
|
|
1833
1899
|
}
|
|
1834
1900
|
|
|
@@ -1845,7 +1911,7 @@
|
|
|
1845
1911
|
inputType,
|
|
1846
1912
|
bubbles: true,
|
|
1847
1913
|
composed: true,
|
|
1848
|
-
})
|
|
1914
|
+
})
|
|
1849
1915
|
);
|
|
1850
1916
|
}
|
|
1851
1917
|
|
|
@@ -1877,8 +1943,7 @@
|
|
|
1877
1943
|
* @returns {boolean}
|
|
1878
1944
|
*/
|
|
1879
1945
|
function deleteTextFromEditable(element, direction) {
|
|
1880
|
-
const inputType =
|
|
1881
|
-
direction === 'backward' ? 'deleteContentBackward' : 'deleteContentForward';
|
|
1946
|
+
const inputType = direction === 'backward' ? 'deleteContentBackward' : 'deleteContentForward';
|
|
1882
1947
|
if (!dispatchBeforeInputEvent(element, '', inputType)) {
|
|
1883
1948
|
return false;
|
|
1884
1949
|
}
|
|
@@ -1896,9 +1961,7 @@
|
|
|
1896
1961
|
} else {
|
|
1897
1962
|
const text = element.textContent || '';
|
|
1898
1963
|
element.textContent =
|
|
1899
|
-
direction === 'backward'
|
|
1900
|
-
? text.slice(0, Math.max(0, text.length - 1))
|
|
1901
|
-
: text.slice(1);
|
|
1964
|
+
direction === 'backward' ? text.slice(0, Math.max(0, text.length - 1)) : text.slice(1);
|
|
1902
1965
|
}
|
|
1903
1966
|
|
|
1904
1967
|
dispatchInputEvent(element, '', inputType);
|
|
@@ -1911,7 +1974,10 @@
|
|
|
1911
1974
|
*/
|
|
1912
1975
|
function handleEnterKey(element) {
|
|
1913
1976
|
const editable = getEditableTarget(element);
|
|
1914
|
-
if (
|
|
1977
|
+
if (
|
|
1978
|
+
editable instanceof HTMLTextAreaElement ||
|
|
1979
|
+
(editable instanceof HTMLElement && editable.isContentEditable)
|
|
1980
|
+
) {
|
|
1915
1981
|
return insertTextIntoEditable(editable, '\n');
|
|
1916
1982
|
}
|
|
1917
1983
|
|
|
@@ -1920,7 +1986,10 @@
|
|
|
1920
1986
|
return true;
|
|
1921
1987
|
}
|
|
1922
1988
|
|
|
1923
|
-
if (
|
|
1989
|
+
if (
|
|
1990
|
+
element instanceof HTMLButtonElement ||
|
|
1991
|
+
(element instanceof HTMLInputElement && ['button', 'submit'].includes(element.type))
|
|
1992
|
+
) {
|
|
1924
1993
|
element.click();
|
|
1925
1994
|
return true;
|
|
1926
1995
|
}
|
|
@@ -1964,14 +2033,11 @@
|
|
|
1964
2033
|
*/
|
|
1965
2034
|
function normalizeDomQuery(params = {}) {
|
|
1966
2035
|
const rawSelector =
|
|
1967
|
-
typeof params.selector === 'string' && params.selector.trim()
|
|
1968
|
-
? params.selector
|
|
1969
|
-
: 'body';
|
|
2036
|
+
typeof params.selector === 'string' && params.selector.trim() ? params.selector : 'body';
|
|
1970
2037
|
return {
|
|
1971
2038
|
selector: escapeTailwindSelector(rawSelector),
|
|
1972
2039
|
withinRef: typeof params.withinRef === 'string' ? params.withinRef : null,
|
|
1973
2040
|
budget: applyBudget(params),
|
|
1974
2041
|
};
|
|
1975
2042
|
}
|
|
1976
|
-
|
|
1977
2043
|
})();
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
*/
|
|
32
32
|
function getSetupInstallState(setupStatus) {
|
|
33
33
|
const hasConfiguredMcp = setupStatus.mcpClients.some((client) => client.configured);
|
|
34
|
-
const hasInstalledCliSkill = setupStatus.skillTargets.some((target) =>
|
|
34
|
+
const hasInstalledCliSkill = setupStatus.skillTargets.some((target) =>
|
|
35
|
+
target.skills.some((skill) => skill.exists)
|
|
36
|
+
);
|
|
35
37
|
return { hasConfiguredMcp, hasInstalledCliSkill };
|
|
36
38
|
}
|
|
37
39
|
|