channel-worker 1.0.26 → 1.0.28

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.
@@ -550,7 +550,7 @@ class CommandPoller {
550
550
  }
551
551
 
552
552
  async handleTypeText(command) {
553
- const { text, profile_id, url_match, focus_selector } = command.payload || {};
553
+ const { text, profile_id, url_match, focus_selector, press_enter } = command.payload || {};
554
554
  console.log(`[commands] Typing text (${text?.length} chars) for profile: ${profile_id}`);
555
555
  try {
556
556
  const WebSocket = require('ws');
@@ -588,22 +588,25 @@ class CommandPoller {
588
588
  try {
589
589
  await send('DOM.enable');
590
590
  // Focus target element via CDP
591
- const sel = (focus_selector || '').replace(/'/g, "\\'");
591
+ const rawSel = (focus_selector || '');
592
+ const isXpath = rawSel.startsWith('xpath:');
593
+ const sel = rawSel.replace('xpath:', '').replace(/'/g, "\\'").replace(/"/g, '\\"');
592
594
  const focusResult = await send('Runtime.evaluate', {
593
595
  expression: `
594
596
  (function() {
595
- // Use specific selector if provided
596
- if ('${sel}') {
597
- const el = document.querySelector('${sel}');
598
- if (el) { el.focus(); el.click(); return 'focused_selector: ${sel}'; }
597
+ let el = null;
598
+ if (${isXpath} && '${sel}') {
599
+ el = document.evaluate("${sel}", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
600
+ } else if ('${sel}') {
601
+ el = document.querySelector('${sel}');
599
602
  }
600
- // Try dialog editor
603
+ if (el) { el.focus(); el.click(); return 'focused: ' + (el.tagName || '') + ' ' + (el.getAttribute('aria-label') || '').substring(0, 30); }
604
+ // Fallback: dialog editor
601
605
  const dialog = document.querySelector('[role="dialog"]');
602
606
  if (dialog) {
603
607
  const editor = dialog.querySelector('[contenteditable="true"], [role="textbox"]');
604
608
  if (editor) { editor.focus(); editor.click(); return 'focused_dialog'; }
605
609
  }
606
- // Fallback
607
610
  const editors = document.querySelectorAll('[contenteditable="true"], [role="textbox"]');
608
611
  for (const e of editors) {
609
612
  if (e.offsetHeight >= 15) { e.focus(); e.click(); return 'focused_fallback'; }
@@ -617,6 +620,11 @@ class CommandPoller {
617
620
  await new Promise(r => setTimeout(r, 300));
618
621
  // Type text
619
622
  await send('Input.insertText', { text });
623
+ // Press Enter if requested
624
+ if (press_enter) {
625
+ await send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 });
626
+ await send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 });
627
+ }
620
628
  ws.close();
621
629
  resolve({ success: true, length: text.length });
622
630
  } catch (e) { ws.close(); resolve({ success: false, error: e.message }); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "channel-worker",
3
- "version": "1.0.26",
3
+ "version": "1.0.28",
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": {