@cereworker/browser 26.325.23 → 26.325.25
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/extension/background.js +70 -25
- package/extension/manifest.json +2 -1
- package/package.json +3 -3
package/extension/background.js
CHANGED
|
@@ -255,22 +255,66 @@ async function cmdClickByText({ text, role }) {
|
|
|
255
255
|
async function cmdType({ selector, text }) {
|
|
256
256
|
if (!selector || text === undefined) throw new Error('selector and text are required');
|
|
257
257
|
const tab = await getActiveTab();
|
|
258
|
+
|
|
259
|
+
// First check if element exists and focus it
|
|
260
|
+
const [check] = await chrome.scripting.executeScript({
|
|
261
|
+
target: { tabId: tab.id },
|
|
262
|
+
func: (sel) => {
|
|
263
|
+
const el = document.querySelector(sel);
|
|
264
|
+
if (!el) return { found: false };
|
|
265
|
+
el.focus();
|
|
266
|
+
// Click to ensure cursor is inside the element
|
|
267
|
+
el.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
268
|
+
const isEditable = el.isContentEditable || el.getAttribute('contenteditable') !== null;
|
|
269
|
+
const isInput = el.tagName === 'INPUT' || el.tagName === 'TEXTAREA';
|
|
270
|
+
return { found: true, isEditable, isInput };
|
|
271
|
+
},
|
|
272
|
+
args: [selector],
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (!check?.result?.found) return `Element not found: ${selector}`;
|
|
276
|
+
|
|
277
|
+
if (check.result.isEditable) {
|
|
278
|
+
// Use Chrome Debugger API for contentEditable — most reliable method for React editors
|
|
279
|
+
try {
|
|
280
|
+
await chrome.debugger.attach({ tabId: tab.id }, '1.3');
|
|
281
|
+
// Clear existing content first
|
|
282
|
+
await chrome.debugger.sendCommand({ tabId: tab.id }, 'Input.dispatchKeyEvent', {
|
|
283
|
+
type: 'keyDown', key: 'a', code: 'KeyA', windowsVirtualKeyCode: 65, modifiers: 4, // Ctrl+A
|
|
284
|
+
});
|
|
285
|
+
await chrome.debugger.sendCommand({ tabId: tab.id }, 'Input.dispatchKeyEvent', {
|
|
286
|
+
type: 'keyUp', key: 'a', code: 'KeyA', windowsVirtualKeyCode: 65,
|
|
287
|
+
});
|
|
288
|
+
// Insert text
|
|
289
|
+
await chrome.debugger.sendCommand({ tabId: tab.id }, 'Input.insertText', { text });
|
|
290
|
+
await chrome.debugger.detach({ tabId: tab.id });
|
|
291
|
+
return `Typed into: ${selector}`;
|
|
292
|
+
} catch (debugErr) {
|
|
293
|
+
// Fallback to execCommand if debugger fails
|
|
294
|
+
try { await chrome.debugger.detach({ tabId: tab.id }); } catch { /* ignore */ }
|
|
295
|
+
const [fallback] = await chrome.scripting.executeScript({
|
|
296
|
+
target: { tabId: tab.id },
|
|
297
|
+
func: (sel, txt) => {
|
|
298
|
+
const el = document.querySelector(sel);
|
|
299
|
+
if (!el) return `Element not found: ${sel}`;
|
|
300
|
+
el.focus();
|
|
301
|
+
document.execCommand('selectAll', false, null);
|
|
302
|
+
document.execCommand('insertText', false, txt);
|
|
303
|
+
return `Typed into: ${sel}`;
|
|
304
|
+
},
|
|
305
|
+
args: [selector, text],
|
|
306
|
+
});
|
|
307
|
+
return fallback?.result ?? `Element not found: ${selector}`;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Standard input/textarea elements
|
|
258
312
|
const [result] = await chrome.scripting.executeScript({
|
|
259
313
|
target: { tabId: tab.id },
|
|
260
314
|
func: (sel, txt) => {
|
|
261
315
|
const el = document.querySelector(sel);
|
|
262
316
|
if (!el) return `Element not found: ${sel}`;
|
|
263
317
|
el.focus();
|
|
264
|
-
|
|
265
|
-
// contentEditable elements (React editors like X's tweet box)
|
|
266
|
-
if (el.isContentEditable || el.getAttribute('contenteditable') !== null) {
|
|
267
|
-
// Clear existing content and insert via execCommand for React compatibility
|
|
268
|
-
document.execCommand('selectAll', false, null);
|
|
269
|
-
document.execCommand('insertText', false, txt);
|
|
270
|
-
return `Typed into: ${sel}`;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Standard input/textarea elements
|
|
274
318
|
const nativeSet = Object.getOwnPropertyDescriptor(
|
|
275
319
|
el.tagName === 'TEXTAREA' ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype,
|
|
276
320
|
'value'
|
|
@@ -292,21 +336,22 @@ async function cmdType({ selector, text }) {
|
|
|
292
336
|
async function cmdEvaluate({ code }) {
|
|
293
337
|
if (!code) throw new Error('code is required');
|
|
294
338
|
const tab = await getActiveTab();
|
|
295
|
-
// Use
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
339
|
+
// Use Chrome Debugger API to evaluate JS — bypasses all CSP restrictions
|
|
340
|
+
try {
|
|
341
|
+
await chrome.debugger.attach({ tabId: tab.id }, '1.3');
|
|
342
|
+
const evalResult = await chrome.debugger.sendCommand(
|
|
343
|
+
{ tabId: tab.id }, 'Runtime.evaluate',
|
|
344
|
+
{ expression: code, returnByValue: true },
|
|
345
|
+
);
|
|
346
|
+
await chrome.debugger.detach({ tabId: tab.id });
|
|
347
|
+
if (evalResult.exceptionDetails) {
|
|
348
|
+
return `Error: ${evalResult.exceptionDetails.text || evalResult.exceptionDetails.exception?.description || 'Unknown error'}`;
|
|
349
|
+
}
|
|
350
|
+
return String(evalResult.result?.value ?? '(no result)');
|
|
351
|
+
} catch (err) {
|
|
352
|
+
try { await chrome.debugger.detach({ tabId: tab.id }); } catch { /* ignore */ }
|
|
353
|
+
return `Error: ${err.message || String(err)}`;
|
|
354
|
+
}
|
|
310
355
|
}
|
|
311
356
|
|
|
312
357
|
async function cmdWaitForSelector({ selector, timeout = 5000 }) {
|
package/extension/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cereworker/browser",
|
|
3
|
-
"version": "26.325.
|
|
3
|
+
"version": "26.325.25",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"puppeteer": "^24.0.0",
|
|
21
21
|
"ws": "^8.18.0",
|
|
22
22
|
"zod": "^3.24.0",
|
|
23
|
-
"@cereworker/core": "26.325.
|
|
24
|
-
"@cereworker/config": "26.325.
|
|
23
|
+
"@cereworker/core": "26.325.25",
|
|
24
|
+
"@cereworker/config": "26.325.25"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/ws": "^8.5.14",
|