channel-worker 1.0.30 → 1.0.32

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.
@@ -587,11 +587,13 @@ class CommandPoller {
587
587
  ws.on('open', async () => {
588
588
  try {
589
589
  await send('DOM.enable');
590
- // Focus target element via CDP
590
+ // Focus target element via CDP mouse click (trusted event)
591
591
  const rawSel = (focus_selector || '');
592
592
  const isXpath = rawSel.startsWith('xpath:');
593
593
  const sel = rawSel.replace('xpath:', '').replace(/'/g, "\\'").replace(/"/g, '\\"');
594
- const focusResult = await send('Runtime.evaluate', {
594
+
595
+ // Get element bounding box
596
+ const posResult = await send('Runtime.evaluate', {
595
597
  expression: `
596
598
  (function() {
597
599
  let el = null;
@@ -600,36 +602,44 @@ class CommandPoller {
600
602
  } else if ('${sel}') {
601
603
  el = document.querySelector('${sel}');
602
604
  }
603
- if (el) { el.focus(); el.click(); return 'focused: ' + (el.tagName || '') + ' ' + (el.getAttribute('aria-label') || '').substring(0, 30); }
604
- // Fallback: dialog editor
605
- const dialog = document.querySelector('[role="dialog"]');
606
- if (dialog) {
607
- const editor = dialog.querySelector('[contenteditable="true"], [role="textbox"]');
608
- if (editor) { editor.focus(); editor.click(); return 'focused_dialog'; }
609
- }
610
- const editors = document.querySelectorAll('[contenteditable="true"], [role="textbox"]');
611
- for (const e of editors) {
612
- if (e.offsetHeight >= 15) { e.focus(); e.click(); return 'focused_fallback'; }
605
+ if (!el) {
606
+ const dialog = document.querySelector('[role="dialog"]');
607
+ if (dialog) el = dialog.querySelector('[contenteditable="true"], [role="textbox"]');
608
+ if (!el) {
609
+ const editors = document.querySelectorAll('[contenteditable="true"], [role="textbox"]');
610
+ for (const e of editors) { if (e.offsetHeight >= 15) { el = e; break; } }
611
+ }
613
612
  }
614
- return 'no_editor';
613
+ if (!el) return null;
614
+ const rect = el.getBoundingClientRect();
615
+ return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2, tag: el.tagName, aria: (el.getAttribute('aria-label') || '').substring(0, 30) };
615
616
  })()
616
617
  `,
618
+ returnByValue: true,
617
619
  });
618
- console.log('[commands] Focus result:', focusResult?.result?.value);
620
+
621
+ const pos = posResult?.result?.value;
622
+ console.log('[commands] Element position:', JSON.stringify(pos));
623
+
624
+ if (pos && pos.x && pos.y) {
625
+ // Click with real mouse events (trusted)
626
+ await send('Input.dispatchMouseEvent', { type: 'mousePressed', x: pos.x, y: pos.y, button: 'left', clickCount: 1 });
627
+ await send('Input.dispatchMouseEvent', { type: 'mouseReleased', x: pos.x, y: pos.y, button: 'left', clickCount: 1 });
628
+ console.log(`[commands] Mouse clicked at (${pos.x}, ${pos.y}) — ${pos.tag} ${pos.aria}`);
629
+ } else {
630
+ console.log('[commands] No element found to focus');
631
+ }
619
632
  // Small delay for focus to take effect
620
633
  await new Promise(r => setTimeout(r, 300));
621
- // Type text
622
- await send('Input.insertText', { text });
623
- // Press Enter/Tab to confirm (e.g. Facebook tags)
634
+ // Type text — use char-by-char for inputs that need keystroke events (press_enter mode)
624
635
  if (press_enter) {
625
- await new Promise(r => setTimeout(r, 500));
626
- // Try Enter first
627
- await send('Input.dispatchKeyEvent', { type: 'rawKeyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, nativeVirtualKeyCode: 13 });
628
- await send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, nativeVirtualKeyCode: 13 });
629
- await new Promise(r => setTimeout(r, 500));
630
- // Also try Tab (some inputs confirm on Tab)
631
- await send('Input.dispatchKeyEvent', { type: 'rawKeyDown', key: 'Tab', code: 'Tab', windowsVirtualKeyCode: 9, nativeVirtualKeyCode: 9 });
632
- await send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Tab', code: 'Tab', windowsVirtualKeyCode: 9, nativeVirtualKeyCode: 9 });
636
+ // Type each character individually so React detects keystrokes
637
+ for (const char of text) {
638
+ await send('Input.dispatchKeyEvent', { type: 'keyDown', key: char, text: char });
639
+ await send('Input.dispatchKeyEvent', { type: 'keyUp', key: char });
640
+ }
641
+ } else {
642
+ await send('Input.insertText', { text });
633
643
  }
634
644
  ws.close();
635
645
  resolve({ success: true, length: text.length });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "1.0.30",
3
+ "version": "1.0.32",
4
4
  "description": "Channel Manager worker daemon — runs on remote machines to execute video pipeline jobs",
5
5
  "main": "lib/daemon.js",
6
6
  "bin": {