@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.
@@ -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 MAIN world to bypass extension CSP runs as if typed in devtools console
296
- const [result] = await chrome.scripting.executeScript({
297
- target: { tabId: tab.id },
298
- world: 'MAIN',
299
- func: (c) => {
300
- try {
301
- const r = new Function(c)();
302
- return String(r ?? '(no result)');
303
- } catch (err) {
304
- return `Error: ${err.message || String(err)}`;
305
- }
306
- },
307
- args: [code],
308
- });
309
- return result?.result ?? '(no result)';
339
+ // Use Chrome Debugger API to evaluate JSbypasses 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 }) {
@@ -8,7 +8,8 @@
8
8
  "scripting",
9
9
  "activeTab",
10
10
  "storage",
11
- "alarms"
11
+ "alarms",
12
+ "debugger"
12
13
  ],
13
14
  "host_permissions": [
14
15
  "http://127.0.0.1/*",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cereworker/browser",
3
- "version": "26.325.23",
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.23",
24
- "@cereworker/config": "26.325.23"
23
+ "@cereworker/core": "26.325.25",
24
+ "@cereworker/config": "26.325.25"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/ws": "^8.5.14",