@quanta-intellect/vessel-browser 0.1.78 → 0.1.80

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/out/main/index.js CHANGED
@@ -441,7 +441,7 @@ class Tab {
441
441
  if (!input.control && !input.meta) return;
442
442
  if (input.type !== "keyDown") return;
443
443
  const key = input.key.toLowerCase();
444
- const wc2 = this.view.webContents;
444
+ const wc = this.view.webContents;
445
445
  if (key === "+" || key === "=") {
446
446
  this.zoomIn();
447
447
  event.preventDefault();
@@ -457,10 +457,10 @@ class Tab {
457
457
  event.preventDefault();
458
458
  return;
459
459
  }
460
- if (key === "c") wc2.copy();
461
- else if (key === "v") wc2.paste();
462
- else if (key === "x") wc2.cut();
463
- else if (key === "a") wc2.selectAll();
460
+ if (key === "c") wc.copy();
461
+ else if (key === "v") wc.paste();
462
+ else if (key === "x") wc.cut();
463
+ else if (key === "a") wc.selectAll();
464
464
  });
465
465
  this.setupListeners();
466
466
  if (url) {
@@ -473,8 +473,8 @@ class Tab {
473
473
  }
474
474
  }
475
475
  setupListeners() {
476
- const wc2 = this.view.webContents;
477
- wc2.setWindowOpenHandler(({ url, disposition }) => {
476
+ const wc = this.view.webContents;
477
+ wc.setWindowOpenHandler(({ url, disposition }) => {
478
478
  const error = this.getNavigationBlockReason(url);
479
479
  if (error) {
480
480
  logger$j.warn(error);
@@ -493,21 +493,21 @@ class Tab {
493
493
  event.preventDefault();
494
494
  logger$j.warn(`${context}: ${error}`);
495
495
  };
496
- wc2.on("will-navigate", (event, url) => {
496
+ wc.on("will-navigate", (event, url) => {
497
497
  blockNavigation(event, url, "Blocked top-level navigation");
498
498
  });
499
- wc2.on("will-redirect", (event, url) => {
499
+ wc.on("will-redirect", (event, url) => {
500
500
  blockNavigation(event, url, "Blocked redirect");
501
501
  });
502
502
  const syncNavigationState = () => {
503
- this._state.title = wc2.getTitle() || this._state.title || "New Tab";
504
- this._state.url = wc2.getURL() || this._state.url;
503
+ this._state.title = wc.getTitle() || this._state.title || "New Tab";
504
+ this._state.url = wc.getURL() || this._state.url;
505
505
  this._state.canGoBack = this.urlHistory.length > 0;
506
506
  this._state.canGoForward = this.urlForwardStack.length > 0;
507
507
  this.onChange();
508
508
  };
509
509
  const updateSecurityState = () => {
510
- const url = wc2.getURL();
510
+ const url = wc.getURL();
511
511
  let status = "none";
512
512
  if (url.startsWith("https:")) {
513
513
  status = "secure";
@@ -536,40 +536,40 @@ class Tab {
536
536
  this.lastCommittedUrl = url;
537
537
  syncNavigationState();
538
538
  };
539
- wc2.on("did-navigate", (_event, url) => {
539
+ wc.on("did-navigate", (_event, url) => {
540
540
  recordNavigation(url);
541
541
  updateSecurityState();
542
542
  });
543
- wc2.on("page-title-updated", (_, title) => {
543
+ wc.on("page-title-updated", (_, title) => {
544
544
  this._state.title = title;
545
545
  this.onChange();
546
546
  });
547
- wc2.on("did-start-loading", () => {
547
+ wc.on("did-start-loading", () => {
548
548
  this._state.isLoading = true;
549
549
  this.onChange();
550
550
  });
551
- wc2.on("did-stop-loading", () => {
551
+ wc.on("did-stop-loading", () => {
552
552
  this._state.isLoading = false;
553
553
  syncNavigationState();
554
554
  });
555
- wc2.on("did-navigate-in-page", (_event, url, isMainFrame) => {
555
+ wc.on("did-navigate-in-page", (_event, url, isMainFrame) => {
556
556
  if (!isMainFrame) return;
557
557
  recordNavigation(url);
558
- this.onPageLoad?.(wc2.getURL(), wc2);
558
+ this.onPageLoad?.(wc.getURL(), wc);
559
559
  updateSecurityState();
560
560
  });
561
- wc2.on("certificate-error", (event, url, error) => {
561
+ wc.on("certificate-error", (event, url, error) => {
562
562
  event.preventDefault();
563
563
  this._securityState = { status: "error", url, errorMessage: error, canProceed: true };
564
564
  this.onChange();
565
565
  });
566
- wc2.on("did-finish-load", () => {
566
+ wc.on("did-finish-load", () => {
567
567
  syncNavigationState();
568
- this.onPageLoad?.(wc2.getURL(), wc2);
568
+ this.onPageLoad?.(wc.getURL(), wc);
569
569
  });
570
- wc2.on("dom-ready", () => {
570
+ wc.on("dom-ready", () => {
571
571
  syncNavigationState();
572
- wc2.insertCSS(`
572
+ wc.insertCSS(`
573
573
  ::-webkit-scrollbar { width: 6px; height: 6px; }
574
574
  ::-webkit-scrollbar-track { background: transparent; }
575
575
  ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 999px; }
@@ -577,27 +577,27 @@ class Tab {
577
577
  ::-webkit-scrollbar-corner { background: transparent; }
578
578
  `).catch((err) => logger$j.warn("Failed to inject scrollbar CSS:", err));
579
579
  });
580
- wc2.on("page-favicon-updated", (_, favicons) => {
580
+ wc.on("page-favicon-updated", (_, favicons) => {
581
581
  this._state.favicon = favicons[0] || "";
582
582
  this.onChange();
583
583
  });
584
- wc2.on("media-started-playing", () => {
584
+ wc.on("media-started-playing", () => {
585
585
  this._state.isAudible = true;
586
- this._state.isMuted = wc2.isAudioMuted();
586
+ this._state.isMuted = wc.isAudioMuted();
587
587
  this.onChange();
588
588
  });
589
- wc2.on("media-paused", () => {
589
+ wc.on("media-paused", () => {
590
590
  setTimeout(() => {
591
- if (wc2.isDestroyed()) return;
592
- this._state.isAudible = wc2.isCurrentlyAudible();
593
- this._state.isMuted = wc2.isAudioMuted();
591
+ if (wc.isDestroyed()) return;
592
+ this._state.isAudible = wc.isCurrentlyAudible();
593
+ this._state.isMuted = wc.isAudioMuted();
594
594
  this.onChange();
595
595
  }, 250);
596
596
  });
597
- wc2.on("context-menu", (_event, params) => {
597
+ wc.on("context-menu", (_event, params) => {
598
598
  const x = params.x;
599
599
  const y = params.y;
600
- void wc2.executeJavaScript(
600
+ void wc.executeJavaScript(
601
601
  `(function() {
602
602
  var el = document.elementFromPoint(${x}, ${y});
603
603
  while (el) {
@@ -609,14 +609,14 @@ class Tab {
609
609
  return '';
610
610
  })()`
611
611
  ).then((highlightedText) => {
612
- this.buildContextMenu(wc2, params, highlightedText.trim());
612
+ this.buildContextMenu(wc, params, highlightedText.trim());
613
613
  }).catch((err) => {
614
614
  logger$j.warn("Failed to inspect highlighted text for context menu:", err);
615
- this.buildContextMenu(wc2, params, "");
615
+ this.buildContextMenu(wc, params, "");
616
616
  });
617
617
  });
618
618
  }
619
- buildContextMenu(wc2, params, highlightedText) {
619
+ buildContextMenu(wc, params, highlightedText) {
620
620
  const menu = new electron.Menu();
621
621
  const colors = [
622
622
  "yellow",
@@ -635,7 +635,7 @@ class Tab {
635
635
  orange: "Orange"
636
636
  };
637
637
  if (highlightedText) {
638
- const url = wc2.getURL();
638
+ const url = wc.getURL();
639
639
  menu.append(
640
640
  new electron.MenuItem({
641
641
  label: "Remove Highlight",
@@ -665,7 +665,7 @@ class Tab {
665
665
  menu.append(
666
666
  new electron.MenuItem({
667
667
  label: "Highlight Selection",
668
- click: () => this.onHighlightSelection?.(wc2)
668
+ click: () => this.onHighlightSelection?.(wc)
669
669
  })
670
670
  );
671
671
  }
@@ -792,14 +792,14 @@ class Tab {
792
792
  this.view.webContents.reload();
793
793
  }
794
794
  zoomIn() {
795
- const wc2 = this.view.webContents;
796
- const level = wc2.getZoomLevel();
797
- wc2.setZoomLevel(level + 0.5);
795
+ const wc = this.view.webContents;
796
+ const level = wc.getZoomLevel();
797
+ wc.setZoomLevel(level + 0.5);
798
798
  }
799
799
  zoomOut() {
800
- const wc2 = this.view.webContents;
801
- const level = wc2.getZoomLevel();
802
- wc2.setZoomLevel(level - 0.5);
800
+ const wc = this.view.webContents;
801
+ const level = wc.getZoomLevel();
802
+ wc.setZoomLevel(level - 0.5);
803
803
  }
804
804
  zoomReset() {
805
805
  this.view.webContents.setZoomLevel(0);
@@ -849,10 +849,10 @@ class Tab {
849
849
  this.onChange();
850
850
  }
851
851
  setMuted(muted) {
852
- const wc2 = this.view.webContents;
853
- wc2.setAudioMuted(muted);
854
- this._state.isMuted = wc2.isAudioMuted();
855
- this._state.isAudible = wc2.isCurrentlyAudible();
852
+ const wc = this.view.webContents;
853
+ wc.setAudioMuted(muted);
854
+ this._state.isMuted = wc.isAudioMuted();
855
+ this._state.isAudible = wc.isCurrentlyAudible();
856
856
  this.onChange();
857
857
  }
858
858
  toggleMuted() {
@@ -877,10 +877,10 @@ class Tab {
877
877
  setHighlightMode(enabled) {
878
878
  if (this._highlightModeActive === enabled) return;
879
879
  this._highlightModeActive = enabled;
880
- const wc2 = this.view.webContents;
881
- if (wc2.isDestroyed()) return;
880
+ const wc = this.view.webContents;
881
+ if (wc.isDestroyed()) return;
882
882
  if (enabled) {
883
- void wc2.executeJavaScript(`
883
+ void wc.executeJavaScript(`
884
884
  (function() {
885
885
  // Ensure highlight CSS is present
886
886
  if (!document.getElementById('__vessel-highlight-styles')) {
@@ -940,7 +940,7 @@ class Tab {
940
940
  })()
941
941
  `).catch((err) => logger$j.warn("Failed to inject highlight listener:", err));
942
942
  } else {
943
- void wc2.executeJavaScript(`
943
+ void wc.executeJavaScript(`
944
944
  (function() {
945
945
  var s = document.getElementById('__vessel-highlight-mode-style');
946
946
  if (s) s.remove();
@@ -1285,9 +1285,9 @@ const VESSEL_HIGHLIGHT_CSS = `
1285
1285
  opacity: 1;
1286
1286
  }
1287
1287
  `;
1288
- async function highlightOnPage(wc2, resolvedSelector, text, label, durationMs, color) {
1288
+ async function highlightOnPage(wc, resolvedSelector, text, label, durationMs, color) {
1289
1289
  const c = resolveColor(color);
1290
- await wc2.executeJavaScript(`
1290
+ await wc.executeJavaScript(`
1291
1291
  (function() {
1292
1292
  if (!document.getElementById('__vessel-highlight-styles')) {
1293
1293
  var s = document.createElement('style');
@@ -1381,7 +1381,7 @@ async function highlightOnPage(wc2, resolvedSelector, text, label, durationMs, c
1381
1381
  })()
1382
1382
  `);
1383
1383
  if (resolvedSelector) {
1384
- return wc2.executeJavaScript(`
1384
+ return wc.executeJavaScript(`
1385
1385
  (function() {
1386
1386
  var el = document.querySelector(${JSON.stringify(resolvedSelector)});
1387
1387
  if (!el) return 'Element not found';
@@ -1421,7 +1421,7 @@ async function highlightOnPage(wc2, resolvedSelector, text, label, durationMs, c
1421
1421
  `);
1422
1422
  }
1423
1423
  if (text) {
1424
- return wc2.executeJavaScript(`
1424
+ return wc.executeJavaScript(`
1425
1425
  (function() {
1426
1426
  var searchText = (${JSON.stringify(text)} || '').trim();
1427
1427
  var foldedSearchText = searchText.toLowerCase();
@@ -1529,7 +1529,7 @@ async function highlightOnPage(wc2, resolvedSelector, text, label, durationMs, c
1529
1529
  }
1530
1530
  return "Error: No element or text to highlight";
1531
1531
  }
1532
- async function highlightBatchOnPage(wc2, entries) {
1532
+ async function highlightBatchOnPage(wc, entries) {
1533
1533
  if (entries.length === 0) return;
1534
1534
  const serialized = entries.filter((e) => e.selector || e.text).map((e) => ({
1535
1535
  selector: e.selector ?? null,
@@ -1538,7 +1538,7 @@ async function highlightBatchOnPage(wc2, entries) {
1538
1538
  color: resolveColor(e.color)
1539
1539
  }));
1540
1540
  if (serialized.length === 0) return;
1541
- await wc2.executeJavaScript(`
1541
+ await wc.executeJavaScript(`
1542
1542
  (function() {
1543
1543
  if (!document.getElementById('__vessel-highlight-styles')) {
1544
1544
  var s = document.createElement('style');
@@ -1621,18 +1621,18 @@ async function highlightBatchOnPage(wc2, entries) {
1621
1621
  `);
1622
1622
  }
1623
1623
  const HIGHLIGHT_SELECTOR = "'.__vessel-highlight, .__vessel-highlight-text'";
1624
- async function getHighlightCount(wc2) {
1625
- if (wc2.isDestroyed()) return 0;
1626
- if (wc2.isLoading()) return 0;
1627
- const currentUrl = wc2.getURL();
1624
+ async function getHighlightCount(wc) {
1625
+ if (wc.isDestroyed()) return 0;
1626
+ if (wc.isLoading()) return 0;
1627
+ const currentUrl = wc.getURL();
1628
1628
  if (!currentUrl || currentUrl === "about:blank") return 0;
1629
- return wc2.executeJavaScript(
1629
+ return wc.executeJavaScript(
1630
1630
  `document.querySelectorAll(${HIGHLIGHT_SELECTOR}).length`
1631
1631
  );
1632
1632
  }
1633
- async function scrollToHighlight(wc2, index) {
1633
+ async function scrollToHighlight(wc, index) {
1634
1634
  const safeIndex = Math.floor(Number(index));
1635
- return wc2.executeJavaScript(`
1635
+ return wc.executeJavaScript(`
1636
1636
  (function() {
1637
1637
  var highlights = document.querySelectorAll(${HIGHLIGHT_SELECTOR});
1638
1638
  if (${safeIndex} < 0 || ${safeIndex} >= highlights.length) return false;
@@ -1645,9 +1645,9 @@ async function scrollToHighlight(wc2, index) {
1645
1645
  })()
1646
1646
  `);
1647
1647
  }
1648
- async function removeHighlightAtIndex(wc2, index) {
1648
+ async function removeHighlightAtIndex(wc, index) {
1649
1649
  const safeIndex = Math.floor(Number(index));
1650
- return wc2.executeJavaScript(`
1650
+ return wc.executeJavaScript(`
1651
1651
  (function() {
1652
1652
  var highlights = document.querySelectorAll(${HIGHLIGHT_SELECTOR});
1653
1653
  if (${safeIndex} < 0 || ${safeIndex} >= highlights.length) return false;
@@ -1672,8 +1672,8 @@ async function removeHighlightAtIndex(wc2, index) {
1672
1672
  })()
1673
1673
  `);
1674
1674
  }
1675
- async function clearAllHighlightElements(wc2) {
1676
- return wc2.executeJavaScript(`
1675
+ async function clearAllHighlightElements(wc) {
1676
+ return wc.executeJavaScript(`
1677
1677
  (function() {
1678
1678
  document.querySelectorAll('.__vessel-highlight-label[data-vessel-highlight]').forEach(function(b) { b.remove(); });
1679
1679
  document.querySelectorAll('.__vessel-highlight-text').forEach(function(mark) {
@@ -1694,8 +1694,8 @@ async function clearAllHighlightElements(wc2) {
1694
1694
  })()
1695
1695
  `);
1696
1696
  }
1697
- async function clearHighlights(wc2) {
1698
- return wc2.executeJavaScript(`
1697
+ async function clearHighlights(wc) {
1698
+ return wc.executeJavaScript(`
1699
1699
  (function() {
1700
1700
  var count = 0;
1701
1701
  document.querySelectorAll('.__vessel-highlight').forEach(function(el) {
@@ -1719,15 +1719,15 @@ async function clearHighlights(wc2) {
1719
1719
  `);
1720
1720
  }
1721
1721
  const MAX_HIGHLIGHT_TEXT = 5e3;
1722
- async function captureSelectionHighlight(wc2) {
1723
- if (wc2.isDestroyed()) {
1722
+ async function captureSelectionHighlight(wc) {
1723
+ if (wc.isDestroyed()) {
1724
1724
  return { success: false, message: "Tab is not available" };
1725
1725
  }
1726
- const url = wc2.getURL();
1726
+ const url = wc.getURL();
1727
1727
  if (!url || url === "about:blank") {
1728
1728
  return { success: false, message: "No page loaded" };
1729
1729
  }
1730
- const selectedText = await wc2.executeJavaScript(`
1730
+ const selectedText = await wc.executeJavaScript(`
1731
1731
  (function() {
1732
1732
  var sel = window.getSelection();
1733
1733
  return sel ? sel.toString().trim() : '';
@@ -1738,11 +1738,11 @@ async function captureSelectionHighlight(wc2) {
1738
1738
  }
1739
1739
  return persistHighlight(url, selectedText);
1740
1740
  }
1741
- async function persistAndMarkHighlight(wc2, text) {
1742
- if (wc2.isDestroyed()) {
1741
+ async function persistAndMarkHighlight(wc, text) {
1742
+ if (wc.isDestroyed()) {
1743
1743
  return { success: false, message: "Tab is not available" };
1744
1744
  }
1745
- const url = wc2.getURL();
1745
+ const url = wc.getURL();
1746
1746
  if (!url || url === "about:blank") {
1747
1747
  return { success: false, message: "No page loaded" };
1748
1748
  }
@@ -1845,6 +1845,35 @@ function clearAll$1() {
1845
1845
  save$1();
1846
1846
  emit$1();
1847
1847
  }
1848
+ function clearByTimeRange(timeRange) {
1849
+ load$3();
1850
+ if (timeRange === "all") {
1851
+ clearAll$1();
1852
+ return;
1853
+ }
1854
+ const now = Date.now();
1855
+ const cutoff = new Date(now - timeRangeToMs(timeRange));
1856
+ state$3.entries = state$3.entries.filter((entry) => {
1857
+ const visitedAt = new Date(entry.visitedAt).getTime();
1858
+ return Number.isNaN(visitedAt) || visitedAt < cutoff.getTime();
1859
+ });
1860
+ save$1();
1861
+ emit$1();
1862
+ }
1863
+ function timeRangeToMs(range) {
1864
+ switch (range) {
1865
+ case "hour":
1866
+ return 60 * 60 * 1e3;
1867
+ case "day":
1868
+ return 24 * 60 * 60 * 1e3;
1869
+ case "week":
1870
+ return 7 * 24 * 60 * 60 * 1e3;
1871
+ case "month":
1872
+ return 30 * 24 * 60 * 60 * 1e3;
1873
+ case "all":
1874
+ return Infinity;
1875
+ }
1876
+ }
1848
1877
  function exportHistoryHtml() {
1849
1878
  const current = getState$1();
1850
1879
  const lines = [
@@ -1956,9 +1985,9 @@ const MAX_NETWORK_ENTRIES = 200;
1956
1985
  const MAX_ERROR_ENTRIES = 200;
1957
1986
  const MAX_PENDING_REQUESTS = 500;
1958
1987
  class DevToolsSession {
1959
- constructor(tabId, wc2) {
1988
+ constructor(tabId, wc) {
1960
1989
  this.tabId = tabId;
1961
- this.wc = wc2;
1990
+ this.wc = wc;
1962
1991
  }
1963
1992
  attached = false;
1964
1993
  attachingPromise = null;
@@ -2698,14 +2727,14 @@ class TabManager {
2698
2727
  onOpenUrl: ({ url: requestedUrl, background: background2, adBlockingEnabled }) => {
2699
2728
  this.createTab(requestedUrl, { background: background2, adBlockingEnabled });
2700
2729
  },
2701
- onPageLoad: (pageUrl, wc2) => {
2702
- this.reapplyHighlights(pageUrl, wc2);
2730
+ onPageLoad: (pageUrl, wc) => {
2731
+ this.reapplyHighlights(pageUrl, wc);
2703
2732
  if (!this.isPrivate) {
2704
- addEntry$1(pageUrl, wc2.getTitle());
2733
+ addEntry$1(pageUrl, wc.getTitle());
2705
2734
  }
2706
- this.pageLoadCallback?.(pageUrl, wc2);
2735
+ this.pageLoadCallback?.(pageUrl, wc);
2707
2736
  },
2708
- onHighlightSelection: (wc2) => this.captureHighlightFromPage(wc2),
2737
+ onHighlightSelection: (wc) => this.captureHighlightFromPage(wc),
2709
2738
  onHighlightRemove: (url2, text) => this.removeHighlightByText(url2, text),
2710
2739
  onHighlightRecolor: (url2, text, color) => this.recolorHighlightByText(url2, text, color),
2711
2740
  onSavePage: () => {
@@ -3032,8 +3061,8 @@ class TabManager {
3032
3061
  this.broadcastState();
3033
3062
  }
3034
3063
  lastReapply = /* @__PURE__ */ new Map();
3035
- reapplyHighlights(url, wc2) {
3036
- const wcId = wc2.id;
3064
+ reapplyHighlights(url, wc) {
3065
+ const wcId = wc.id;
3037
3066
  const now = Date.now();
3038
3067
  const last = this.lastReapply.get(wcId);
3039
3068
  const normalized = normalizeUrl$1(url);
@@ -3047,7 +3076,7 @@ class TabManager {
3047
3076
  color: h.color
3048
3077
  }));
3049
3078
  if (entries.length > 0) {
3050
- void highlightBatchOnPage(wc2, entries).catch(
3079
+ void highlightBatchOnPage(wc, entries).catch(
3051
3080
  (err) => logger$h.warn("Failed to batch highlight:", err)
3052
3081
  );
3053
3082
  }
@@ -3060,16 +3089,16 @@ class TabManager {
3060
3089
  if (!activeTab) {
3061
3090
  return { success: false, message: "No active tab" };
3062
3091
  }
3063
- const wc2 = activeTab.view.webContents;
3064
- this.captureHighlightFromPage(wc2);
3092
+ const wc = activeTab.view.webContents;
3093
+ this.captureHighlightFromPage(wc);
3065
3094
  return null;
3066
3095
  }
3067
- captureHighlightFromPage(wc2) {
3096
+ captureHighlightFromPage(wc) {
3068
3097
  void (async () => {
3069
3098
  try {
3070
- const result = await captureSelectionHighlight(wc2);
3099
+ const result = await captureSelectionHighlight(wc);
3071
3100
  if (result.success && result.text) {
3072
- await highlightOnPage(wc2, null, result.text, void 0, void 0, "yellow").catch(
3101
+ await highlightOnPage(wc, null, result.text, void 0, void 0, "yellow").catch(
3073
3102
  (err) => logger$h.warn("Failed to capture highlight:", err)
3074
3103
  );
3075
3104
  }
@@ -3092,12 +3121,12 @@ class TabManager {
3092
3121
  for (const id of this.order) {
3093
3122
  const tab = this.tabs.get(id);
3094
3123
  if (!tab) continue;
3095
- const wc2 = tab.view.webContents;
3096
- if (wc2.isDestroyed()) continue;
3124
+ const wc = tab.view.webContents;
3125
+ if (wc.isDestroyed()) continue;
3097
3126
  try {
3098
- const tabUrl = normalizeUrl$1(wc2.getURL());
3127
+ const tabUrl = normalizeUrl$1(wc.getURL());
3099
3128
  if (tabUrl === normalized) {
3100
- void this.removeHighlightMarksForText(wc2, text);
3129
+ void this.removeHighlightMarksForText(wc, text);
3101
3130
  }
3102
3131
  } catch (err) {
3103
3132
  logger$h.warn("Failed to remove highlight from matching tab:", err);
@@ -3117,14 +3146,14 @@ class TabManager {
3117
3146
  for (const id of this.order) {
3118
3147
  const tab = this.tabs.get(id);
3119
3148
  if (!tab) continue;
3120
- const wc2 = tab.view.webContents;
3121
- if (wc2.isDestroyed()) continue;
3149
+ const wc = tab.view.webContents;
3150
+ if (wc.isDestroyed()) continue;
3122
3151
  try {
3123
- const tabUrl = normalizeUrl$1(wc2.getURL());
3152
+ const tabUrl = normalizeUrl$1(wc.getURL());
3124
3153
  if (tabUrl === normalized) {
3125
- void this.removeHighlightMarksForText(wc2, text).then(() => {
3154
+ void this.removeHighlightMarksForText(wc, text).then(() => {
3126
3155
  void highlightOnPage(
3127
- wc2,
3156
+ wc,
3128
3157
  null,
3129
3158
  text,
3130
3159
  void 0,
@@ -3162,8 +3191,8 @@ class TabManager {
3162
3191
  }
3163
3192
  this.tabGroups.delete(groupId);
3164
3193
  }
3165
- async removeHighlightMarksForText(wc2, text) {
3166
- await wc2.executeJavaScript(
3194
+ async removeHighlightMarksForText(wc, text) {
3195
+ await wc.executeJavaScript(
3167
3196
  `(function() {
3168
3197
  var marks = document.querySelectorAll('mark.__vessel-highlight-text[data-vessel-highlight]');
3169
3198
  marks.forEach(function(m) {
@@ -4326,7 +4355,7 @@ function okResult(value) {
4326
4355
  ...value ?? {}
4327
4356
  };
4328
4357
  }
4329
- function errorResult$1(error, value) {
4358
+ function errorResult(error, value) {
4330
4359
  return {
4331
4360
  ok: false,
4332
4361
  error,
@@ -4425,16 +4454,16 @@ async function getCheckoutUrl(email) {
4425
4454
  });
4426
4455
  if (!res.ok) {
4427
4456
  const body = await res.text();
4428
- return errorResult$1(body || `HTTP ${res.status}`);
4457
+ return errorResult(body || `HTTP ${res.status}`);
4429
4458
  }
4430
4459
  const { url } = await res.json();
4431
4460
  return okResult({ url });
4432
4461
  } catch (err) {
4433
- return errorResult$1(getErrorMessage(err, "Failed to create checkout"));
4462
+ return errorResult(getErrorMessage(err, "Failed to create checkout"));
4434
4463
  }
4435
4464
  }
4436
4465
  async function getPortalUrl() {
4437
- return errorResult$1(
4466
+ return errorResult(
4438
4467
  "Billing portal access is temporarily disabled until authenticated customer access is implemented."
4439
4468
  );
4440
4469
  }
@@ -4478,7 +4507,7 @@ async function verifySubscription$1(identifier) {
4478
4507
  async function requestActivationCode(email) {
4479
4508
  const normalizedEmail = email.trim().toLowerCase();
4480
4509
  if (!normalizedEmail) {
4481
- return errorResult$1("Email is required");
4510
+ return errorResult("Email is required");
4482
4511
  }
4483
4512
  try {
4484
4513
  const res = await fetch(`${VERIFICATION_API}/activate/start`, {
@@ -4488,27 +4517,27 @@ async function requestActivationCode(email) {
4488
4517
  });
4489
4518
  const data = await res.json().catch(() => ({}));
4490
4519
  if (!res.ok || !data.challengeToken) {
4491
- return errorResult$1(data.error || `HTTP ${res.status}`);
4520
+ return errorResult(data.error || `HTTP ${res.status}`);
4492
4521
  }
4493
4522
  return okResult({
4494
4523
  email: normalizedEmail,
4495
4524
  challengeToken: data.challengeToken
4496
4525
  });
4497
4526
  } catch (err) {
4498
- return errorResult$1(getErrorMessage(err, "Failed to send code"));
4527
+ return errorResult(getErrorMessage(err, "Failed to send code"));
4499
4528
  }
4500
4529
  }
4501
4530
  async function verifyActivationCode(email, code, challengeToken) {
4502
4531
  const normalizedEmail = email.trim().toLowerCase();
4503
4532
  const trimmedCode = code.trim();
4504
4533
  if (!normalizedEmail) {
4505
- return errorResult$1("Email is required", { state: getPremiumState() });
4534
+ return errorResult("Email is required", { state: getPremiumState() });
4506
4535
  }
4507
4536
  if (!trimmedCode) {
4508
- return errorResult$1("Code is required", { state: getPremiumState() });
4537
+ return errorResult("Code is required", { state: getPremiumState() });
4509
4538
  }
4510
4539
  if (!challengeToken.trim()) {
4511
- return errorResult$1("Request a new activation code and try again.", {
4540
+ return errorResult("Request a new activation code and try again.", {
4512
4541
  state: getPremiumState()
4513
4542
  });
4514
4543
  }
@@ -4524,7 +4553,7 @@ async function verifyActivationCode(email, code, challengeToken) {
4524
4553
  });
4525
4554
  const data = await res.json().catch(() => ({}));
4526
4555
  if (!res.ok) {
4527
- return errorResult$1(data.error || `HTTP ${res.status}`, {
4556
+ return errorResult(data.error || `HTTP ${res.status}`, {
4528
4557
  state: getPremiumState()
4529
4558
  });
4530
4559
  }
@@ -4537,9 +4566,9 @@ async function verifyActivationCode(email, code, challengeToken) {
4537
4566
  expiresAt: data.expiresAt || ""
4538
4567
  };
4539
4568
  setSetting("premium", updated);
4540
- return isPremiumActiveState(updated) ? okResult({ state: updated }) : errorResult$1("Subscription is not active.", { state: updated });
4569
+ return isPremiumActiveState(updated) ? okResult({ state: updated }) : errorResult("Subscription is not active.", { state: updated });
4541
4570
  } catch (err) {
4542
- return errorResult$1(getErrorMessage(err, "Failed to verify code"), {
4571
+ return errorResult(getErrorMessage(err, "Failed to verify code"), {
4543
4572
  state: getPremiumState()
4544
4573
  });
4545
4574
  }
@@ -6012,11 +6041,11 @@ function cleanupTimersForWcId(wcId) {
6012
6041
  lastMutationSnapshotAt.delete(wcId);
6013
6042
  lastMutationActivityAt.delete(wcId);
6014
6043
  }
6015
- function attachDestroyCleanup(wc2) {
6016
- if (destroyListenerAttached.has(wc2)) return;
6017
- destroyListenerAttached.add(wc2);
6018
- wc2.once("destroyed", () => {
6019
- cleanupTimersForWcId(wc2.id);
6044
+ function attachDestroyCleanup(wc) {
6045
+ if (destroyListenerAttached.has(wc)) return;
6046
+ destroyListenerAttached.add(wc);
6047
+ wc.once("destroyed", () => {
6048
+ cleanupTimersForWcId(wc.id);
6020
6049
  });
6021
6050
  }
6022
6051
  const MAX_PERSISTED_DIFF_BURSTS = 50;
@@ -6121,12 +6150,12 @@ function enrichWithBurstHistory(key, diff) {
6121
6150
  recentBursts: recentBursts.slice().reverse()
6122
6151
  };
6123
6152
  }
6124
- async function capturePageSnapshot(url, wc2, sendToRendererViews) {
6153
+ async function capturePageSnapshot(url, wc, sendToRendererViews) {
6125
6154
  try {
6126
6155
  if (!shouldTrackSnapshotUrl(url)) return;
6127
6156
  const key = normalizeUrl(url);
6128
6157
  const oldSnap = getSnapshot(key);
6129
- const content = await extractContent(wc2);
6158
+ const content = await extractContent(wc);
6130
6159
  const textContent = content.content || "";
6131
6160
  const title = content.title || "";
6132
6161
  const headings = content.headings || [];
@@ -6154,59 +6183,59 @@ function computeNextSnapshotDueAt(wcId, now, delayMs) {
6154
6183
  const stableAfterActivityAt = lastActivityAt ? lastActivityAt + MUTATION_SETTLE_AFTER_MS : 0;
6155
6184
  return Math.max(now + delayMs, earliestAllowedAt, stableAfterActivityAt);
6156
6185
  }
6157
- function scheduleTimerAt(wc2, sendToRendererViews, dueAt) {
6158
- attachDestroyCleanup(wc2);
6159
- const wcId = wc2.id;
6186
+ function scheduleTimerAt(wc, sendToRendererViews, dueAt) {
6187
+ attachDestroyCleanup(wc);
6188
+ const wcId = wc.id;
6160
6189
  const existing = pendingPageSnapshotTimers.get(wcId);
6161
6190
  if (existing) clearTimeout(existing);
6162
6191
  const timer = setTimeout(() => {
6163
6192
  cleanupTimersForWcId(wcId);
6164
- if (wc2.isDestroyed()) return;
6193
+ if (wc.isDestroyed()) return;
6165
6194
  lastMutationSnapshotAt.set(wcId, Date.now());
6166
- void capturePageSnapshot(wc2.getURL(), wc2, sendToRendererViews);
6195
+ void capturePageSnapshot(wc.getURL(), wc, sendToRendererViews);
6167
6196
  }, Math.max(0, dueAt - Date.now()));
6168
6197
  pendingPageSnapshotTimers.set(wcId, timer);
6169
6198
  pendingPageSnapshotDueAt.set(wcId, dueAt);
6170
6199
  }
6171
- function notePageMutationActivity(wc2, sendToRendererViews) {
6172
- if (wc2.isDestroyed()) return;
6173
- const wcId = wc2.id;
6200
+ function notePageMutationActivity(wc, sendToRendererViews) {
6201
+ if (wc.isDestroyed()) return;
6202
+ const wcId = wc.id;
6174
6203
  const now = Date.now();
6175
6204
  lastMutationActivityAt.set(wcId, now);
6176
6205
  const existingDueAt = pendingPageSnapshotDueAt.get(wcId);
6177
6206
  if (existingDueAt == null) return;
6178
6207
  const nextDueAt = computeNextSnapshotDueAt(wcId, now, 0);
6179
6208
  if (nextDueAt <= existingDueAt) return;
6180
- scheduleTimerAt(wc2, sendToRendererViews, nextDueAt);
6209
+ scheduleTimerAt(wc, sendToRendererViews, nextDueAt);
6181
6210
  }
6182
- function schedulePageSnapshotCapture(wc2, sendToRendererViews, delayMs = 0) {
6183
- if (wc2.isDestroyed()) return;
6184
- const wcId = wc2.id;
6211
+ function schedulePageSnapshotCapture(wc, sendToRendererViews, delayMs = 0) {
6212
+ if (wc.isDestroyed()) return;
6213
+ const wcId = wc.id;
6185
6214
  const now = Date.now();
6186
6215
  const nextDueAt = computeNextSnapshotDueAt(wcId, now, delayMs);
6187
6216
  const existingDueAt = pendingPageSnapshotDueAt.get(wcId);
6188
6217
  if (existingDueAt != null && existingDueAt >= nextDueAt) {
6189
6218
  return;
6190
6219
  }
6191
- scheduleTimerAt(wc2, sendToRendererViews, nextDueAt);
6220
+ scheduleTimerAt(wc, sendToRendererViews, nextDueAt);
6192
6221
  }
6193
6222
  function enableClipboardShortcuts(view) {
6194
6223
  view.webContents.on("before-input-event", (event, input) => {
6195
6224
  if (!input.control && !input.meta) return;
6196
6225
  const key = input.key.toLowerCase();
6197
- const wc2 = view.webContents;
6226
+ const wc = view.webContents;
6198
6227
  if (input.type === "keyDown") {
6199
6228
  if (key === "c") {
6200
- wc2.copy();
6229
+ wc.copy();
6201
6230
  event.preventDefault();
6202
6231
  } else if (key === "v") {
6203
- wc2.paste();
6232
+ wc.paste();
6204
6233
  event.preventDefault();
6205
6234
  } else if (key === "x") {
6206
- wc2.cut();
6235
+ wc.cut();
6207
6236
  event.preventDefault();
6208
6237
  } else if (key === "a") {
6209
- wc2.selectAll();
6238
+ wc.selectAll();
6210
6239
  event.preventDefault();
6211
6240
  }
6212
6241
  }
@@ -6403,8 +6432,8 @@ function createMainWindow(onTabStateChange) {
6403
6432
  chromeView.webContents.send(channel, ...args);
6404
6433
  sidebarView.webContents.send(channel, ...args);
6405
6434
  };
6406
- tabManager.onPageLoad((url, wc2) => {
6407
- void capturePageSnapshot(url, wc2, sendToRendererViews);
6435
+ tabManager.onPageLoad((url, wc) => {
6436
+ void capturePageSnapshot(url, wc, sendToRendererViews);
6408
6437
  });
6409
6438
  const state2 = {
6410
6439
  mainWindow,
@@ -11413,7 +11442,7 @@ function pruneToolsForContext(tools, pageType, query = "", options = {}) {
11413
11442
  function trimText(value) {
11414
11443
  return typeof value === "string" ? value.trim() : "";
11415
11444
  }
11416
- async function resolveBookmarkSourceDraft(wc2, options) {
11445
+ async function resolveBookmarkSourceDraft(wc, options) {
11417
11446
  const explicitUrl = trimText(options.explicitUrl);
11418
11447
  const explicitTitle = trimText(options.explicitTitle);
11419
11448
  if (explicitUrl) {
@@ -11423,8 +11452,8 @@ async function resolveBookmarkSourceDraft(wc2, options) {
11423
11452
  source: "explicit"
11424
11453
  };
11425
11454
  }
11426
- if (wc2 && options.resolvedSelector) {
11427
- const result = await wc2.executeJavaScript(`
11455
+ if (wc && options.resolvedSelector) {
11456
+ const result = await wc.executeJavaScript(`
11428
11457
  (function() {
11429
11458
  const el = document.querySelector(${JSON.stringify(options.resolvedSelector)});
11430
11459
  if (!el) return { error: "Element not found" };
@@ -11475,11 +11504,11 @@ async function resolveBookmarkSourceDraft(wc2, options) {
11475
11504
  source: "link"
11476
11505
  };
11477
11506
  }
11478
- const currentUrl = wc2?.getURL().trim() || "";
11507
+ const currentUrl = wc?.getURL().trim() || "";
11479
11508
  if (!currentUrl) {
11480
11509
  return { error: "No URL provided and no active page to save" };
11481
11510
  }
11482
- const currentTitle = wc2?.getTitle().trim() || currentUrl;
11511
+ const currentTitle = wc?.getTitle().trim() || currentUrl;
11483
11512
  return {
11484
11513
  url: currentUrl,
11485
11514
  title: explicitTitle || currentTitle || currentUrl,
@@ -12134,15 +12163,15 @@ function importBookmarksFromJson(content) {
12134
12163
  function normalizeText(text) {
12135
12164
  return text?.trim() ?? "";
12136
12165
  }
12137
- async function captureLiveHighlightSnapshot(wc2, savedHighlights = []) {
12138
- if (wc2.isDestroyed()) {
12166
+ async function captureLiveHighlightSnapshot(wc, savedHighlights = []) {
12167
+ if (wc.isDestroyed()) {
12139
12168
  return { pageHighlights: [] };
12140
12169
  }
12141
12170
  const savedTexts = new Set(
12142
12171
  savedHighlights.map((highlight) => normalizeText(highlight.text)).filter(Boolean)
12143
12172
  );
12144
12173
  try {
12145
- const snapshot = await wc2.executeJavaScript(`(() => {
12174
+ const snapshot = await wc.executeJavaScript(`(() => {
12146
12175
  const selection = window.getSelection?.()?.toString().trim() || "";
12147
12176
  const pageHighlights = Array.from(
12148
12177
  document.querySelectorAll("mark.__vessel-highlight-text[data-vessel-highlight]")
@@ -12203,13 +12232,13 @@ ${lines.join("\n")}`);
12203
12232
  function sleep(ms) {
12204
12233
  return new Promise((resolve) => setTimeout(resolve, ms));
12205
12234
  }
12206
- function waitForLoad(wc2, timeout = 5e3) {
12235
+ function waitForLoad(wc, timeout = 5e3) {
12207
12236
  return new Promise((resolve) => {
12208
12237
  let finished = false;
12209
12238
  const cleanup = () => {
12210
- wc2.removeListener("did-finish-load", onLoadEvent);
12211
- wc2.removeListener("did-stop-loading", onLoadEvent);
12212
- wc2.removeListener("did-fail-load", onLoadEvent);
12239
+ wc.removeListener("did-finish-load", onLoadEvent);
12240
+ wc.removeListener("did-stop-loading", onLoadEvent);
12241
+ wc.removeListener("did-fail-load", onLoadEvent);
12213
12242
  };
12214
12243
  const finish = () => {
12215
12244
  if (finished) return;
@@ -12219,50 +12248,50 @@ function waitForLoad(wc2, timeout = 5e3) {
12219
12248
  resolve();
12220
12249
  };
12221
12250
  const onLoadEvent = () => {
12222
- const loading = wc2.isLoading();
12251
+ const loading = wc.isLoading();
12223
12252
  if (!loading) {
12224
12253
  finish();
12225
12254
  }
12226
12255
  };
12227
12256
  const timer = setTimeout(() => finish(), timeout);
12228
- if (!wc2.isLoading()) {
12257
+ if (!wc.isLoading()) {
12229
12258
  finish();
12230
12259
  return;
12231
12260
  }
12232
- wc2.once("did-finish-load", onLoadEvent);
12233
- wc2.once("did-stop-loading", onLoadEvent);
12234
- wc2.once("did-fail-load", onLoadEvent);
12261
+ wc.once("did-finish-load", onLoadEvent);
12262
+ wc.once("did-stop-loading", onLoadEvent);
12263
+ wc.once("did-fail-load", onLoadEvent);
12235
12264
  });
12236
12265
  }
12237
12266
  const QUIET_NAVIGATION_WINDOW_MS = 1200;
12238
- function waitForPotentialNavigation$1(wc2, beforeUrl, timeout = 4e3, quietWindowMs) {
12267
+ function waitForPotentialNavigation$1(wc, beforeUrl, timeout = 4e3, quietWindowMs) {
12239
12268
  return new Promise((resolve) => {
12240
12269
  let done = false;
12241
12270
  let waitingForLoad = false;
12242
- const beforeTitle = wc2.getTitle();
12271
+ const beforeTitle = wc.getTitle();
12243
12272
  const finish = () => {
12244
12273
  if (done) return;
12245
12274
  done = true;
12246
12275
  clearTimeout(timer);
12247
12276
  clearInterval(poller);
12248
- wc2.removeListener("did-start-loading", onStart);
12249
- wc2.removeListener("did-navigate", onNavigate);
12250
- wc2.removeListener("did-navigate-in-page", onNavigateInPage);
12251
- wc2.removeListener("did-stop-loading", onNativeChange);
12252
- wc2.removeListener("page-title-updated", onNativeChange);
12277
+ wc.removeListener("did-start-loading", onStart);
12278
+ wc.removeListener("did-navigate", onNavigate);
12279
+ wc.removeListener("did-navigate-in-page", onNavigateInPage);
12280
+ wc.removeListener("did-stop-loading", onNativeChange);
12281
+ wc.removeListener("page-title-updated", onNativeChange);
12253
12282
  resolve();
12254
12283
  };
12255
12284
  const finishAfterLoad = () => {
12256
12285
  if (waitingForLoad) return;
12257
12286
  waitingForLoad = true;
12258
- void waitForLoad(wc2, timeout).then(finish);
12287
+ void waitForLoad(wc, timeout).then(finish);
12259
12288
  };
12260
12289
  const onNativeChange = () => {
12261
- if (wc2.isLoading()) {
12290
+ if (wc.isLoading()) {
12262
12291
  finishAfterLoad();
12263
12292
  return;
12264
12293
  }
12265
- if (wc2.getURL() !== beforeUrl || wc2.getTitle() !== beforeTitle) {
12294
+ if (wc.getURL() !== beforeUrl || wc.getTitle() !== beforeTitle) {
12266
12295
  finish();
12267
12296
  }
12268
12297
  };
@@ -12278,15 +12307,15 @@ function waitForPotentialNavigation$1(wc2, beforeUrl, timeout = 4e3, quietWindow
12278
12307
  quietWindowMs != null ? Math.min(timeout, quietWindowMs) : timeout
12279
12308
  );
12280
12309
  const poller = setInterval(onNativeChange, 100);
12281
- if (wc2.getURL() !== beforeUrl || wc2.getTitle() !== beforeTitle || wc2.isLoading()) {
12310
+ if (wc.getURL() !== beforeUrl || wc.getTitle() !== beforeTitle || wc.isLoading()) {
12282
12311
  onNativeChange();
12283
12312
  return;
12284
12313
  }
12285
- wc2.once("did-start-loading", onStart);
12286
- wc2.once("did-navigate", onNavigate);
12287
- wc2.once("did-navigate-in-page", onNavigateInPage);
12288
- wc2.once("did-stop-loading", onNativeChange);
12289
- wc2.once("page-title-updated", onNativeChange);
12314
+ wc.once("did-start-loading", onStart);
12315
+ wc.once("did-navigate", onNavigate);
12316
+ wc.once("did-navigate-in-page", onNavigateInPage);
12317
+ wc.once("did-stop-loading", onNativeChange);
12318
+ wc.once("page-title-updated", onNativeChange);
12290
12319
  });
12291
12320
  }
12292
12321
  function selectorFromElement(element, index) {
@@ -12309,10 +12338,10 @@ function findSelectorByIndex(page, index) {
12309
12338
  }
12310
12339
  return null;
12311
12340
  }
12312
- async function resolveSelector(wc2, index, selector) {
12341
+ async function resolveSelector(wc, index, selector) {
12313
12342
  if (selector) return selector;
12314
12343
  if (index == null) return null;
12315
- const authoritativeSelector = await wc2.executeJavaScript(
12344
+ const authoritativeSelector = await wc.executeJavaScript(
12316
12345
  `
12317
12346
  (function() {
12318
12347
  return window.__vessel?.getElementSelector
@@ -12323,19 +12352,19 @@ async function resolveSelector(wc2, index, selector) {
12323
12352
  );
12324
12353
  if (typeof authoritativeSelector === "string" && authoritativeSelector) {
12325
12354
  if (authoritativeSelector.includes(" >>> ")) {
12326
- const resolves2 = await wc2.executeJavaScript(
12355
+ const resolves2 = await wc.executeJavaScript(
12327
12356
  `!!window.__vessel?.resolveShadowSelector?.(${JSON.stringify(authoritativeSelector)})`
12328
12357
  );
12329
12358
  if (resolves2) return authoritativeSelector;
12330
12359
  return `__vessel_idx:${index}`;
12331
12360
  }
12332
- const resolves = await wc2.executeJavaScript(
12361
+ const resolves = await wc.executeJavaScript(
12333
12362
  `!!document.querySelector(${JSON.stringify(authoritativeSelector)})`
12334
12363
  );
12335
12364
  if (resolves) return authoritativeSelector;
12336
12365
  return `__vessel_idx:${index}`;
12337
12366
  }
12338
- const fallbackSelector = await wc2.executeJavaScript(
12367
+ const fallbackSelector = await wc.executeJavaScript(
12339
12368
  `
12340
12369
  (function() {
12341
12370
  ${selectorHelpersJS(["data-testid", "name", "form", "aria-label"])}
@@ -12363,7 +12392,7 @@ async function resolveSelector(wc2, index, selector) {
12363
12392
  if (typeof fallbackSelector === "string" && fallbackSelector) {
12364
12393
  return fallbackSelector;
12365
12394
  }
12366
- const page = await extractContent(wc2);
12395
+ const page = await extractContent(wc);
12367
12396
  const extractedSelector = findSelectorByIndex(page, index);
12368
12397
  if (extractedSelector) return extractedSelector;
12369
12398
  return null;
@@ -12456,13 +12485,13 @@ function formatDeadLinkMessage(label, result) {
12456
12485
  const logger$c = createLogger("Screenshot");
12457
12486
  const SCREENSHOT_RETRY_COUNT = 3;
12458
12487
  const SCREENSHOT_RETRY_BASE_DELAY_MS = 120;
12459
- async function captureScreenshot(wc2) {
12488
+ async function captureScreenshot(wc) {
12460
12489
  for (let attempt = 0; attempt < SCREENSHOT_RETRY_COUNT; attempt += 1) {
12461
12490
  await new Promise(
12462
12491
  (resolve) => setTimeout(resolve, SCREENSHOT_RETRY_BASE_DELAY_MS * (attempt + 1))
12463
12492
  );
12464
12493
  try {
12465
- const image = await wc2.capturePage();
12494
+ const image = await wc.capturePage();
12466
12495
  if (!image.isEmpty()) {
12467
12496
  const size = image.getSize();
12468
12497
  const base64 = image.toPNG().toString("base64");
@@ -12481,7 +12510,7 @@ async function captureScreenshot(wc2) {
12481
12510
  );
12482
12511
  }
12483
12512
  }
12484
- return errorResult$1("Page image was empty after 3 attempts");
12513
+ return errorResult("Page image was empty after 3 attempts");
12485
12514
  }
12486
12515
  const SESSION_VERSION = 1;
12487
12516
  function getSessionsDir() {
@@ -13360,17 +13389,17 @@ function getBookmarkMetadataFromArgs(args) {
13360
13389
  }
13361
13390
  const DEFAULT_PAGE_SCRIPT_TIMEOUT_MS = 1500;
13362
13391
  const PAGE_SCRIPT_TIMEOUT = /* @__PURE__ */ Symbol("page-script-timeout");
13363
- async function loadPermittedUrl(wc2, url) {
13392
+ async function loadPermittedUrl(wc, url) {
13364
13393
  assertPermittedNavigationURL(url);
13365
- await wc2.loadURL(url);
13394
+ await wc.loadURL(url);
13366
13395
  }
13367
13396
  function pageBusyError(action) {
13368
13397
  return `Error: Page is still busy; ${action} timed out waiting for page scripts. Retry in a moment.`;
13369
13398
  }
13370
- async function glanceExtract(wc2) {
13399
+ async function glanceExtract(wc) {
13371
13400
  const startMs = Date.now();
13372
13401
  const result = await executePageScript(
13373
- wc2,
13402
+ wc,
13374
13403
  `(function() {
13375
13404
  var vw = window.innerWidth || document.documentElement.clientWidth || 0;
13376
13405
  var vh = window.innerHeight || document.documentElement.clientHeight || 0;
@@ -13463,8 +13492,8 @@ async function glanceExtract(wc2) {
13463
13492
  const elapsed = Date.now() - startMs;
13464
13493
  if (!result || result === PAGE_SCRIPT_TIMEOUT) {
13465
13494
  return [
13466
- `# ${wc2.getTitle() || "(untitled)"}`,
13467
- `URL: ${wc2.getURL()}`,
13495
+ `# ${wc.getTitle() || "(untitled)"}`,
13496
+ `URL: ${wc.getURL()}`,
13468
13497
  "",
13469
13498
  "[read_page mode=glance — page JS thread is completely blocked, no content available]",
13470
13499
  "[Try: click or type_text to interact directly, or wait a few seconds and retry]"
@@ -13515,8 +13544,8 @@ function normalizeReadPageMode(mode, pageContent) {
13515
13544
  }
13516
13545
  return pageContent ? chooseAgentReadMode(pageContent) : "visible_only";
13517
13546
  }
13518
- async function executePageScript(wc2, script, options) {
13519
- if (wc2.isDestroyed()) return null;
13547
+ async function executePageScript(wc, script, options) {
13548
+ if (wc.isDestroyed()) return null;
13520
13549
  const timeoutMs = Math.max(
13521
13550
  150,
13522
13551
  options?.timeoutMs ?? DEFAULT_PAGE_SCRIPT_TIMEOUT_MS
@@ -13524,7 +13553,7 @@ async function executePageScript(wc2, script, options) {
13524
13553
  let timer = null;
13525
13554
  try {
13526
13555
  const result = await Promise.race([
13527
- wc2.executeJavaScript(script, options?.userGesture ?? false),
13556
+ wc.executeJavaScript(script, options?.userGesture ?? false),
13528
13557
  new Promise((resolve) => {
13529
13558
  timer = setTimeout(() => resolve(PAGE_SCRIPT_TIMEOUT), timeoutMs);
13530
13559
  })
@@ -13543,10 +13572,10 @@ async function executePageScript(wc2, script, options) {
13543
13572
  }
13544
13573
  }
13545
13574
  }
13546
- async function waitForJsReady(wc2, timeout = 8e3) {
13575
+ async function waitForJsReady(wc, timeout = 8e3) {
13547
13576
  const start = Date.now();
13548
13577
  while (Date.now() - start < timeout) {
13549
- const ready = await executePageScript(wc2, "1", {
13578
+ const ready = await executePageScript(wc, "1", {
13550
13579
  timeoutMs: 250,
13551
13580
  userGesture: true,
13552
13581
  label: "js-ready probe"
@@ -13555,20 +13584,20 @@ async function waitForJsReady(wc2, timeout = 8e3) {
13555
13584
  await sleep(250);
13556
13585
  }
13557
13586
  }
13558
- function waitForPotentialNavigation(wc2, beforeUrl, timeout = 2500) {
13587
+ function waitForPotentialNavigation(wc, beforeUrl, timeout = 2500) {
13559
13588
  return waitForPotentialNavigation$1(
13560
- wc2,
13589
+ wc,
13561
13590
  beforeUrl,
13562
13591
  timeout,
13563
13592
  QUIET_NAVIGATION_WINDOW_MS
13564
13593
  );
13565
13594
  }
13566
- async function getPostNavSummary(wc2) {
13567
- const title = wc2.getTitle();
13595
+ async function getPostNavSummary(wc) {
13596
+ const title = wc.getTitle();
13568
13597
  const titleLine = title ? `
13569
13598
  Page title: ${title}` : "";
13570
13599
  const overlaySignal = await executePageScript(
13571
- wc2,
13600
+ wc,
13572
13601
  `(function() {
13573
13602
  var signals = [];
13574
13603
  // Body scroll lock is a strong overlay signal
@@ -13620,11 +13649,11 @@ WARNING: Blocking overlay detected (${overlaySignal}). Call clear_overlays or ac
13620
13649
  }
13621
13650
  return titleLine;
13622
13651
  }
13623
- async function getPostSearchSummary(wc2) {
13624
- await waitForLoad(wc2, 2e3);
13652
+ async function getPostSearchSummary(wc) {
13653
+ await waitForLoad(wc, 2e3);
13625
13654
  try {
13626
13655
  const content = await Promise.race([
13627
- extractContent(wc2),
13656
+ extractContent(wc),
13628
13657
  new Promise((resolve) => setTimeout(() => resolve(null), 2500))
13629
13658
  ]);
13630
13659
  if (content && content.content.length > 0) {
@@ -13638,15 +13667,15 @@ ${truncated}`;
13638
13667
  } catch (err) {
13639
13668
  logger$b.warn("Failed to build post-search summary, falling back to nav summary:", err);
13640
13669
  }
13641
- const fallback = await getPostNavSummary(wc2);
13670
+ const fallback = await getPostNavSummary(wc);
13642
13671
  return fallback ? `${fallback}
13643
13672
  Search results snapshot unavailable. Use read_page(mode="results_only") if needed.` : `
13644
13673
  Search results snapshot unavailable. Use read_page(mode="results_only") if needed.`;
13645
13674
  }
13646
- async function getPostClickNavSummary(wc2, toolProfile) {
13675
+ async function getPostClickNavSummary(wc, toolProfile) {
13647
13676
  try {
13648
13677
  const content = await Promise.race([
13649
- extractContent(wc2),
13678
+ extractContent(wc),
13650
13679
  new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
13651
13680
  ]);
13652
13681
  if (content && content.content.length > 0) {
@@ -13663,10 +13692,10 @@ ${truncated}`;
13663
13692
  }
13664
13693
  return "";
13665
13694
  }
13666
- async function scrollPage(wc2, deltaY) {
13695
+ async function scrollPage(wc, deltaY) {
13667
13696
  const getScrollY = async () => {
13668
13697
  const scrollY = await executePageScript(
13669
- wc2,
13698
+ wc,
13670
13699
  `
13671
13700
  (function() {
13672
13701
  return Math.max(
@@ -13686,7 +13715,7 @@ async function scrollPage(wc2, deltaY) {
13686
13715
  };
13687
13716
  const beforeY = await getScrollY();
13688
13717
  const scrolled = await executePageScript(
13689
- wc2,
13718
+ wc,
13690
13719
  `window.scrollBy(0, ${deltaY})`,
13691
13720
  {
13692
13721
  label: "scroll page"
@@ -13707,9 +13736,9 @@ async function scrollPage(wc2, deltaY) {
13707
13736
  movedY: Math.round(afterY - beforeY)
13708
13737
  };
13709
13738
  }
13710
- async function clickElement(wc2, selector) {
13739
+ async function clickElement(wc, selector) {
13711
13740
  const target = await executePageScript(
13712
- wc2,
13741
+ wc,
13713
13742
  `
13714
13743
  (async function() {
13715
13744
  function matchesTarget(candidate, el) {
@@ -13796,24 +13825,24 @@ async function clickElement(wc2, selector) {
13796
13825
  return "Error: Could not resolve click coordinates";
13797
13826
  }
13798
13827
  if (hiddenWindow) {
13799
- const activationResult = await activateElement(wc2, selector);
13828
+ const activationResult = await activateElement(wc, selector);
13800
13829
  if (activationResult.startsWith("Error:")) {
13801
13830
  return activationResult;
13802
13831
  }
13803
13832
  await sleep(80);
13804
13833
  return "Clicked via DOM activation";
13805
13834
  }
13806
- wc2.sendInputEvent({ type: "mouseMove", x, y });
13835
+ wc.sendInputEvent({ type: "mouseMove", x, y });
13807
13836
  await sleep(16);
13808
- wc2.sendInputEvent({ type: "mouseDown", x, y, button: "left", clickCount: 1 });
13837
+ wc.sendInputEvent({ type: "mouseDown", x, y, button: "left", clickCount: 1 });
13809
13838
  await sleep(24);
13810
- wc2.sendInputEvent({ type: "mouseUp", x, y, button: "left", clickCount: 1 });
13839
+ wc.sendInputEvent({ type: "mouseUp", x, y, button: "left", clickCount: 1 });
13811
13840
  await sleep(80);
13812
13841
  return target.obstructed ? "Clicked via pointer events (target may be partially obstructed)" : "Clicked via pointer events";
13813
13842
  }
13814
- async function activateElement(wc2, selector) {
13843
+ async function activateElement(wc, selector) {
13815
13844
  const activated = await executePageScript(
13816
- wc2,
13845
+ wc,
13817
13846
  `
13818
13847
  (function() {
13819
13848
  const el = document.querySelector(${JSON.stringify(selector)});
@@ -13843,9 +13872,9 @@ async function activateElement(wc2, selector) {
13843
13872
  }
13844
13873
  return "Activated element via DOM click";
13845
13874
  }
13846
- async function describeElementForClick(wc2, selector) {
13875
+ async function describeElementForClick(wc, selector) {
13847
13876
  const result = await executePageScript(
13848
- wc2,
13877
+ wc,
13849
13878
  `
13850
13879
  (function() {
13851
13880
  const el = document.querySelector(${JSON.stringify(selector)});
@@ -13887,9 +13916,9 @@ async function describeElementForClick(wc2, selector) {
13887
13916
  isInteractive: "isInteractive" in result && typeof result.isInteractive === "boolean" ? result.isInteractive : void 0
13888
13917
  };
13889
13918
  }
13890
- async function inspectElement(wc2, selector, limit = 8) {
13919
+ async function inspectElement(wc, selector, limit = 8) {
13891
13920
  const result = await executePageScript(
13892
- wc2,
13921
+ wc,
13893
13922
  `
13894
13923
  (function() {
13895
13924
  function text(value) {
@@ -14099,9 +14128,9 @@ async function inspectElement(wc2, selector, limit = 8) {
14099
14128
  }
14100
14129
  return lines.join("\n");
14101
14130
  }
14102
- async function getLocaleSnapshot(wc2) {
14131
+ async function getLocaleSnapshot(wc) {
14103
14132
  const snapshot = await executePageScript(
14104
- wc2,
14133
+ wc,
14105
14134
  `
14106
14135
  (function() {
14107
14136
  return {
@@ -14124,8 +14153,8 @@ async function getLocaleSnapshot(wc2) {
14124
14153
  }
14125
14154
  return {
14126
14155
  lang: typeof snapshot.lang === "string" ? snapshot.lang.trim() : "",
14127
- url: typeof snapshot.url === "string" ? snapshot.url : wc2.getURL(),
14128
- title: typeof snapshot.title === "string" ? snapshot.title : wc2.getTitle()
14156
+ url: typeof snapshot.url === "string" ? snapshot.url : wc.getURL(),
14157
+ title: typeof snapshot.title === "string" ? snapshot.title : wc.getTitle()
14129
14158
  };
14130
14159
  }
14131
14160
  function primaryLanguageTag(value) {
@@ -14141,13 +14170,13 @@ function localeChanged(before, after) {
14141
14170
  const localeHint = /[?&](lang|locale|language|hl)=|\/(ja|jp|en|fr|de|es|it|ko|zh)(\/|$)/i;
14142
14171
  return before.url !== after.url && localeHint.test(after.url);
14143
14172
  }
14144
- async function restoreLocaleSnapshot(wc2, snapshot) {
14145
- if (!snapshot || wc2.isDestroyed()) return;
14173
+ async function restoreLocaleSnapshot(wc, snapshot) {
14174
+ if (!snapshot || wc.isDestroyed()) return;
14146
14175
  try {
14147
- if (typeof wc2.canGoBack === "function" && wc2.canGoBack()) {
14148
- wc2.goBack();
14149
- await waitForLoad(wc2, 3e3);
14150
- const reverted = await getLocaleSnapshot(wc2);
14176
+ if (typeof wc.canGoBack === "function" && wc.canGoBack()) {
14177
+ wc.goBack();
14178
+ await waitForLoad(wc, 3e3);
14179
+ const reverted = await getLocaleSnapshot(wc);
14151
14180
  if (!localeChanged(snapshot, reverted)) {
14152
14181
  return;
14153
14182
  }
@@ -14155,11 +14184,11 @@ async function restoreLocaleSnapshot(wc2, snapshot) {
14155
14184
  } catch (err) {
14156
14185
  logger$b.warn("Failed to restore locale via history navigation, trying URL reload fallback:", err);
14157
14186
  }
14158
- if (snapshot.url && snapshot.url !== wc2.getURL()) {
14187
+ if (snapshot.url && snapshot.url !== wc.getURL()) {
14159
14188
  try {
14160
14189
  assertSafeURL(snapshot.url);
14161
- await wc2.loadURL(snapshot.url);
14162
- await waitForLoad(wc2, 3e3);
14190
+ await wc.loadURL(snapshot.url);
14191
+ await waitForLoad(wc, 3e3);
14163
14192
  return;
14164
14193
  } catch (err) {
14165
14194
  logger$b.warn("Failed to restore locale via safe URL load, trying page reload fallback:", err);
@@ -14167,8 +14196,8 @@ async function restoreLocaleSnapshot(wc2, snapshot) {
14167
14196
  }
14168
14197
  if (snapshot.url) {
14169
14198
  try {
14170
- await wc2.reload();
14171
- await waitForLoad(wc2, 3e3);
14199
+ await wc.reload();
14200
+ await waitForLoad(wc, 3e3);
14172
14201
  } catch (err) {
14173
14202
  logger$b.warn("Failed to restore locale via page reload:", err);
14174
14203
  }
@@ -14213,10 +14242,10 @@ function isDuplicateCartClick(url, text) {
14213
14242
  }
14214
14243
  return isAddToCartText(text);
14215
14244
  }
14216
- async function getProductPageTitle(wc2) {
14245
+ async function getProductPageTitle(wc) {
14217
14246
  try {
14218
14247
  const heading = await executePageScript(
14219
- wc2,
14248
+ wc,
14220
14249
  `(function() {
14221
14250
  var h1 = document.querySelector('h1');
14222
14251
  if (h1 && h1.textContent.trim().length > 3 && h1.textContent.trim().length < 200) {
@@ -14235,7 +14264,7 @@ async function getProductPageTitle(wc2) {
14235
14264
  }
14236
14265
  } catch {
14237
14266
  }
14238
- return wc2.getTitle() || "";
14267
+ return wc.getTitle() || "";
14239
14268
  }
14240
14269
  function normalizeCartProductKey(url) {
14241
14270
  try {
@@ -14288,11 +14317,11 @@ function clearCartState() {
14288
14317
  clickStreakUrl = null;
14289
14318
  clickStreakCount = 0;
14290
14319
  }
14291
- async function buildCartSuccessSuffix(wc2, productUrl, overlayHint) {
14292
- const productTitle = await getProductPageTitle(wc2);
14320
+ async function buildCartSuccessSuffix(wc, productUrl, overlayHint) {
14321
+ const productTitle = await getProductPageTitle(wc);
14293
14322
  recordProductAddedToCart(productUrl, productTitle);
14294
14323
  const cartSummary = getCartAddedSummary(productUrl);
14295
- const dismissResult = await tryAutoDismissCartDialog(wc2);
14324
+ const dismissResult = await tryAutoDismissCartDialog(wc);
14296
14325
  if (dismissResult) {
14297
14326
  return `
14298
14327
  Item added to cart. ${dismissResult}${cartSummary}
@@ -14301,20 +14330,20 @@ Go back to search results to select the next product.`;
14301
14330
  if (!overlayHint) {
14302
14331
  return cartSummary;
14303
14332
  }
14304
- const dialogActions = await getCartDialogActions(wc2);
14333
+ const dialogActions = await getCartDialogActions(wc);
14305
14334
  const actionsSuffix = dialogActions ? `
14306
14335
  ${dialogActions}
14307
14336
  Click one of these dialog actions. Do NOT click any other element.` : "";
14308
14337
  return `
14309
14338
  ${overlayHint}${actionsSuffix}${cartSummary}`;
14310
14339
  }
14311
- async function clickResolvedSelector(wc2, selector) {
14340
+ async function clickResolvedSelector(wc, selector) {
14312
14341
  if (selector.startsWith("__vessel_idx:")) {
14313
14342
  const idx = Number(selector.slice("__vessel_idx:".length));
14314
- const beforeUrl2 = wc2.getURL();
14343
+ const beforeUrl2 = wc.getURL();
14315
14344
  let idxCartMatch = false;
14316
14345
  const idxLabel = await executePageScript(
14317
- wc2,
14346
+ wc,
14318
14347
  `window.__vessel?.getElementText?.(${idx}) || ""`,
14319
14348
  { label: "shadow element text" }
14320
14349
  );
@@ -14327,7 +14356,7 @@ async function clickResolvedSelector(wc2, selector) {
14327
14356
  Go back and select a different product.`;
14328
14357
  }
14329
14358
  const result = await executePageScript(
14330
- wc2,
14359
+ wc,
14331
14360
  `window.__vessel?.interactByIndex?.(${idx}, "click") || "Error: interactByIndex not available"`,
14332
14361
  {
14333
14362
  label: "shadow click by index"
@@ -14338,24 +14367,24 @@ Go back and select a different product.`;
14338
14367
  if (idxCartMatch) {
14339
14368
  recordCartClick(beforeUrl2, idxLabel);
14340
14369
  }
14341
- await waitForPotentialNavigation(wc2, beforeUrl2);
14342
- const afterUrl2 = wc2.getURL();
14370
+ await waitForPotentialNavigation(wc, beforeUrl2);
14371
+ const afterUrl2 = wc.getURL();
14343
14372
  if (afterUrl2 !== beforeUrl2) return `${result} -> ${afterUrl2}`;
14344
- let idxOverlay = await detectPostClickOverlay(wc2);
14373
+ let idxOverlay = await detectPostClickOverlay(wc);
14345
14374
  if (!idxOverlay && idxCartMatch) {
14346
14375
  await sleep(1200);
14347
- idxOverlay = await detectPostClickOverlay(wc2);
14376
+ idxOverlay = await detectPostClickOverlay(wc);
14348
14377
  }
14349
14378
  if (idxCartMatch) {
14350
- return `${result}${await buildCartSuccessSuffix(wc2, beforeUrl2, idxOverlay)}`;
14379
+ return `${result}${await buildCartSuccessSuffix(wc, beforeUrl2, idxOverlay)}`;
14351
14380
  }
14352
14381
  if (!idxOverlay) {
14353
14382
  const hrefMatch = typeof result === "string" ? result.match(/\nhref: (https?:\/\/\S+)/) : null;
14354
14383
  if (hrefMatch) {
14355
14384
  try {
14356
- await loadPermittedUrl(wc2, hrefMatch[1]);
14357
- await waitForLoad(wc2, 8e3);
14358
- const hrefUrl = wc2.getURL();
14385
+ await loadPermittedUrl(wc, hrefMatch[1]);
14386
+ await waitForLoad(wc, 8e3);
14387
+ const hrefUrl = wc.getURL();
14359
14388
  if (hrefUrl !== beforeUrl2) return `${result.split("\n")[0]} -> ${hrefUrl}`;
14360
14389
  } catch {
14361
14390
  }
@@ -14366,10 +14395,10 @@ ${idxOverlay}` : `${result}
14366
14395
  Note: Page did not change after click.`;
14367
14396
  }
14368
14397
  if (selector.includes(" >>> ")) {
14369
- const beforeUrl2 = wc2.getURL();
14398
+ const beforeUrl2 = wc.getURL();
14370
14399
  let shadowCartMatch = false;
14371
14400
  const shadowLabel = await executePageScript(
14372
- wc2,
14401
+ wc,
14373
14402
  `(function() {
14374
14403
  var el = window.__vessel?.resolveShadowSelector?.(${JSON.stringify(selector)});
14375
14404
  return el ? (el.getAttribute("aria-label") || el.textContent?.trim().slice(0, 60) || "") : "";
@@ -14385,7 +14414,7 @@ Note: Page did not change after click.`;
14385
14414
  Go back and select a different product.`;
14386
14415
  }
14387
14416
  const result = await executePageScript(
14388
- wc2,
14417
+ wc,
14389
14418
  `
14390
14419
  (function() {
14391
14420
  var el = window.__vessel?.resolveShadowSelector?.(${JSON.stringify(selector)});
@@ -14405,24 +14434,24 @@ Go back and select a different product.`;
14405
14434
  if (shadowCartMatch) {
14406
14435
  recordCartClick(beforeUrl2, shadowLabel);
14407
14436
  }
14408
- await waitForPotentialNavigation(wc2, beforeUrl2);
14409
- const afterUrl2 = wc2.getURL();
14437
+ await waitForPotentialNavigation(wc, beforeUrl2);
14438
+ const afterUrl2 = wc.getURL();
14410
14439
  if (afterUrl2 !== beforeUrl2) return `${result} -> ${afterUrl2}`;
14411
- let shadowOverlay = await detectPostClickOverlay(wc2);
14440
+ let shadowOverlay = await detectPostClickOverlay(wc);
14412
14441
  if (!shadowOverlay && shadowCartMatch) {
14413
14442
  await sleep(1200);
14414
- shadowOverlay = await detectPostClickOverlay(wc2);
14443
+ shadowOverlay = await detectPostClickOverlay(wc);
14415
14444
  }
14416
14445
  if (shadowCartMatch) {
14417
- return `${result}${await buildCartSuccessSuffix(wc2, beforeUrl2, shadowOverlay)}`;
14446
+ return `${result}${await buildCartSuccessSuffix(wc, beforeUrl2, shadowOverlay)}`;
14418
14447
  }
14419
14448
  if (!shadowOverlay) {
14420
14449
  const hrefMatch = typeof result === "string" ? result.match(/\nhref: (https?:\/\/\S+)/) : null;
14421
14450
  if (hrefMatch) {
14422
14451
  try {
14423
- await loadPermittedUrl(wc2, hrefMatch[1]);
14424
- await waitForLoad(wc2, 8e3);
14425
- const hrefUrl = wc2.getURL();
14452
+ await loadPermittedUrl(wc, hrefMatch[1]);
14453
+ await waitForLoad(wc, 8e3);
14454
+ const hrefUrl = wc.getURL();
14426
14455
  if (hrefUrl !== beforeUrl2) return `${result.split("\n")[0]} -> ${hrefUrl}`;
14427
14456
  } catch {
14428
14457
  }
@@ -14432,15 +14461,15 @@ Go back and select a different product.`;
14432
14461
  ${shadowOverlay}` : `${result}
14433
14462
  Note: Page did not change after click.`;
14434
14463
  }
14435
- const beforeUrl = wc2.getURL();
14436
- const elInfo = await describeElementForClick(wc2, selector);
14464
+ const beforeUrl = wc.getURL();
14465
+ const elInfo = await describeElementForClick(wc, selector);
14437
14466
  if ("error" in elInfo) return `Error: ${elInfo.error}`;
14438
14467
  const cartMatch = isAddToCartText(elInfo.text);
14439
14468
  if (cartMatch && isDuplicateCartClick(beforeUrl, elInfo.text)) {
14440
14469
  return `Blocked: "${elInfo.text}" was already clicked on this page. The item is in your cart. Call read_page to see available actions (e.g. View Cart, Continue Shopping).`;
14441
14470
  }
14442
14471
  if (!cartMatch && recentCartClicks.has(beforeUrl)) {
14443
- const dialogActions = await getCartDialogActions(wc2);
14472
+ const dialogActions = await getCartDialogActions(wc);
14444
14473
  if (dialogActions) {
14445
14474
  return `Blocked: a cart confirmation dialog is open. Do not click background elements.
14446
14475
  ${dialogActions}
@@ -14463,18 +14492,18 @@ Go back and select a different product.`;
14463
14492
  }
14464
14493
  const tagLabel = elInfo.tag && elInfo.tag !== "a" && elInfo.tag !== "button" ? ` <${elInfo.tag}>` : "";
14465
14494
  const clickText = `Clicked: ${elInfo.text}${tagLabel}`;
14466
- const clickResult = await clickElement(wc2, selector);
14495
+ const clickResult = await clickElement(wc, selector);
14467
14496
  if (clickResult.startsWith("Error:")) return clickResult;
14468
- await waitForPotentialNavigation(wc2, beforeUrl);
14469
- const afterUrl = wc2.getURL();
14497
+ await waitForPotentialNavigation(wc, beforeUrl);
14498
+ const afterUrl = wc.getURL();
14470
14499
  if (afterUrl !== beforeUrl) {
14471
14500
  return `${clickText} -> ${afterUrl}`;
14472
14501
  }
14473
- const overlayHint = await detectPostClickOverlay(wc2);
14502
+ const overlayHint = await detectPostClickOverlay(wc);
14474
14503
  if (overlayHint) {
14475
14504
  if (cartMatch) {
14476
14505
  return `${clickText} (${clickResult})${await buildCartSuccessSuffix(
14477
- wc2,
14506
+ wc,
14478
14507
  beforeUrl,
14479
14508
  overlayHint
14480
14509
  )}`;
@@ -14484,28 +14513,28 @@ ${overlayHint}`;
14484
14513
  }
14485
14514
  if (cartMatch) {
14486
14515
  await sleep(1200);
14487
- const delayedOverlayHint = await detectPostClickOverlay(wc2);
14516
+ const delayedOverlayHint = await detectPostClickOverlay(wc);
14488
14517
  if (delayedOverlayHint) {
14489
14518
  return `${clickText} (${clickResult})${await buildCartSuccessSuffix(
14490
- wc2,
14519
+ wc,
14491
14520
  beforeUrl,
14492
14521
  delayedOverlayHint
14493
14522
  )}`;
14494
14523
  }
14495
14524
  return `${clickText} (${clickResult})${await buildCartSuccessSuffix(
14496
- wc2,
14525
+ wc,
14497
14526
  beforeUrl
14498
14527
  )}`;
14499
14528
  }
14500
- const activationResult = await activateElement(wc2, selector);
14529
+ const activationResult = await activateElement(wc, selector);
14501
14530
  if (!activationResult.startsWith("Error:")) {
14502
- await waitForPotentialNavigation(wc2, beforeUrl);
14503
- const fallbackUrl = wc2.getURL();
14531
+ await waitForPotentialNavigation(wc, beforeUrl);
14532
+ const fallbackUrl = wc.getURL();
14504
14533
  if (fallbackUrl !== beforeUrl) {
14505
14534
  return `${clickText} -> ${fallbackUrl} (recovered via DOM activation)`;
14506
14535
  }
14507
14536
  }
14508
- const postActivationOverlayHint = await detectPostClickOverlay(wc2);
14537
+ const postActivationOverlayHint = await detectPostClickOverlay(wc);
14509
14538
  if (postActivationOverlayHint) {
14510
14539
  return `${clickText} (${clickResult})
14511
14540
  ${postActivationOverlayHint}`;
@@ -14515,9 +14544,9 @@ ${postActivationOverlayHint}`;
14515
14544
  const validation = await validateLinkDestination(elInfo.href);
14516
14545
  if (validation.status !== "dead") {
14517
14546
  try {
14518
- await loadPermittedUrl(wc2, elInfo.href);
14519
- await waitForLoad(wc2, 8e3);
14520
- const hrefFallbackUrl = wc2.getURL();
14547
+ await loadPermittedUrl(wc, elInfo.href);
14548
+ await waitForLoad(wc, 8e3);
14549
+ const hrefFallbackUrl = wc.getURL();
14521
14550
  if (hrefFallbackUrl !== beforeUrl) {
14522
14551
  return `${clickText} -> ${hrefFallbackUrl} (recovered via href fallback)`;
14523
14552
  }
@@ -14531,10 +14560,10 @@ Note: The clicked element (<${elInfo.tag || "unknown"}>) is not a link or button
14531
14560
  Note: Page did not change after click. The element may need a different interaction method. Consider read_page or inspect_element.`;
14532
14561
  return `${clickText} (${clickResult})${nonInteractiveWarning}`;
14533
14562
  }
14534
- async function tryAutoDismissCartDialog(wc2) {
14563
+ async function tryAutoDismissCartDialog(wc) {
14535
14564
  try {
14536
14565
  const result = await executePageScript(
14537
- wc2,
14566
+ wc,
14538
14567
  `
14539
14568
  (function() {
14540
14569
  var dialog = document.querySelector('[role="dialog"], dialog[open], [role="alertdialog"], [aria-modal="true"]');
@@ -14571,9 +14600,9 @@ async function tryAutoDismissCartDialog(wc2) {
14571
14600
  }
14572
14601
  return null;
14573
14602
  }
14574
- async function getCartDialogActions(wc2) {
14603
+ async function getCartDialogActions(wc) {
14575
14604
  const result = await executePageScript(
14576
- wc2,
14605
+ wc,
14577
14606
  `
14578
14607
  (function() {
14579
14608
  var dialog = document.querySelector('[role="dialog"], dialog[open], [role="alertdialog"], [aria-modal="true"]');
@@ -14616,9 +14645,9 @@ async function getCartDialogActions(wc2) {
14616
14645
  return `Available dialog actions:
14617
14646
  ${result.actions.join("\n")}`;
14618
14647
  }
14619
- async function detectPostClickOverlay(wc2) {
14648
+ async function detectPostClickOverlay(wc) {
14620
14649
  const result = await executePageScript(
14621
- wc2,
14650
+ wc,
14622
14651
  `
14623
14652
  (function() {
14624
14653
  var vw = window.innerWidth || document.documentElement.clientWidth;
@@ -14722,8 +14751,8 @@ async function detectPostClickOverlay(wc2) {
14722
14751
  const desc = result.label ? ` ("${result.label}")` : "";
14723
14752
  return `A dialog or overlay appeared${desc}. Call read_page to see available actions.`;
14724
14753
  }
14725
- async function dismissPopup(wc2) {
14726
- const before = await extractContent(wc2);
14754
+ async function dismissPopup(wc) {
14755
+ const before = await extractContent(wc);
14727
14756
  const initialBlocking = before.overlays.filter(
14728
14757
  (overlay) => overlay.blocksInteraction
14729
14758
  ).length;
@@ -14746,7 +14775,7 @@ async function dismissPopup(wc2) {
14746
14775
  ];
14747
14776
  if (cartSignals.some((s) => overlayText.includes(s))) {
14748
14777
  const continueResult = await executePageScript(
14749
- wc2,
14778
+ wc,
14750
14779
  `
14751
14780
  (function() {
14752
14781
  var dialog = document.querySelector('[role="dialog"], dialog[open], [role="alertdialog"], [aria-modal="true"]');
@@ -14775,14 +14804,14 @@ async function dismissPopup(wc2) {
14775
14804
  if (continueResult && continueResult !== PAGE_SCRIPT_TIMEOUT && typeof continueResult === "string" && !continueResult.startsWith("Error")) {
14776
14805
  return `Cart confirmation handled: ${continueResult}. Item was already added to your cart.`;
14777
14806
  }
14778
- const dialogActions = await getCartDialogActions(wc2);
14807
+ const dialogActions = await getCartDialogActions(wc);
14779
14808
  return `Cannot dismiss: this is a cart confirmation dialog. Item is in your cart.${dialogActions ? "\n" + dialogActions + "\nClick one of these instead." : " Use read_page to see dialog actions."}`;
14780
14809
  }
14781
14810
  }
14782
14811
  const initialDormant = before.dormantOverlays.length;
14783
- const initialLocale = await getLocaleSnapshot(wc2);
14812
+ const initialLocale = await getLocaleSnapshot(wc);
14784
14813
  const candidates = await executePageScript(
14785
- wc2,
14814
+ wc,
14786
14815
  `
14787
14816
  (function() {
14788
14817
  function text(value) {
@@ -14935,15 +14964,15 @@ async function dismissPopup(wc2) {
14935
14964
  if (!candidate || typeof candidate !== "object" || typeof candidate.selector !== "string") {
14936
14965
  continue;
14937
14966
  }
14938
- const result = await clickElement(wc2, candidate.selector);
14967
+ const result = await clickElement(wc, candidate.selector);
14939
14968
  if (result.startsWith("Error:")) continue;
14940
14969
  await sleep(250);
14941
- const postClickLocale = await getLocaleSnapshot(wc2);
14970
+ const postClickLocale = await getLocaleSnapshot(wc);
14942
14971
  if (localeChanged(initialLocale, postClickLocale)) {
14943
- await restoreLocaleSnapshot(wc2, initialLocale);
14972
+ await restoreLocaleSnapshot(wc, initialLocale);
14944
14973
  continue;
14945
14974
  }
14946
- const after = await extractContent(wc2);
14975
+ const after = await extractContent(wc);
14947
14976
  const blocking = after.overlays.filter(
14948
14977
  (overlay) => overlay.blocksInteraction
14949
14978
  ).length;
@@ -14953,11 +14982,11 @@ async function dismissPopup(wc2) {
14953
14982
  }
14954
14983
  }
14955
14984
  }
14956
- wc2.sendInputEvent({ type: "keyDown", keyCode: "Escape" });
14985
+ wc.sendInputEvent({ type: "keyDown", keyCode: "Escape" });
14957
14986
  await sleep(16);
14958
- wc2.sendInputEvent({ type: "keyUp", keyCode: "Escape" });
14987
+ wc.sendInputEvent({ type: "keyUp", keyCode: "Escape" });
14959
14988
  await sleep(200);
14960
- const afterEscape = await extractContent(wc2);
14989
+ const afterEscape = await extractContent(wc);
14961
14990
  const escapeBlocking = afterEscape.overlays.filter(
14962
14991
  (overlay) => overlay.blocksInteraction
14963
14992
  ).length;
@@ -14975,15 +15004,15 @@ function describeOverlayState(page) {
14975
15004
  signature: getBlockingOverlaySignature(inventory)
14976
15005
  };
14977
15006
  }
14978
- async function clickOverlayCandidate(wc2, action) {
15007
+ async function clickOverlayCandidate(wc, action) {
14979
15008
  if (!action?.selector) return null;
14980
- const result = await clickResolvedSelector(wc2, action.selector);
15009
+ const result = await clickResolvedSelector(wc, action.selector);
14981
15010
  return `${action.label || action.selector}: ${result}`;
14982
15011
  }
14983
- async function tryDismissConsentIframe(wc2) {
15012
+ async function tryDismissConsentIframe(wc) {
14984
15013
  try {
14985
15014
  const hasSignal = await executePageScript(
14986
- wc2,
15015
+ wc,
14987
15016
  `(function() {
14988
15017
  var bs = window.getComputedStyle(document.body);
14989
15018
  var hs = window.getComputedStyle(document.documentElement);
@@ -14995,9 +15024,9 @@ async function tryDismissConsentIframe(wc2) {
14995
15024
  { timeoutMs: 1e3, label: "iframe-consent-signal" }
14996
15025
  );
14997
15026
  if (!hasSignal || hasSignal === PAGE_SCRIPT_TIMEOUT) return null;
14998
- const frames = wc2.mainFrame.framesInSubtree;
15027
+ const frames = wc.mainFrame.framesInSubtree;
14999
15028
  for (const frame of frames) {
15000
- if (frame === wc2.mainFrame) continue;
15029
+ if (frame === wc.mainFrame) continue;
15001
15030
  try {
15002
15031
  const result = await frame.executeJavaScript(`
15003
15032
  (function() {
@@ -15045,9 +15074,9 @@ async function tryDismissConsentIframe(wc2) {
15045
15074
  }
15046
15075
  return null;
15047
15076
  }
15048
- async function tryAcceptCookiesQuickly(wc2) {
15077
+ async function tryAcceptCookiesQuickly(wc) {
15049
15078
  const dismissed = await executePageScript(
15050
- wc2,
15079
+ wc,
15051
15080
  `
15052
15081
  (function() {
15053
15082
  var selectors = [
@@ -15114,10 +15143,10 @@ async function tryAcceptCookiesQuickly(wc2) {
15114
15143
  }
15115
15144
  );
15116
15145
  if (dismissed) return dismissed;
15117
- return tryDismissConsentIframe(wc2);
15146
+ return tryDismissConsentIframe(wc);
15118
15147
  }
15119
- async function clearOverlays(wc2, strategy = "auto") {
15120
- const quickCookieResult = await tryAcceptCookiesQuickly(wc2);
15148
+ async function clearOverlays(wc, strategy = "auto") {
15149
+ const quickCookieResult = await tryAcceptCookiesQuickly(wc);
15121
15150
  if (quickCookieResult === PAGE_SCRIPT_TIMEOUT) {
15122
15151
  return pageBusyError("clear_overlays");
15123
15152
  }
@@ -15127,19 +15156,19 @@ async function clearOverlays(wc2, strategy = "auto") {
15127
15156
  "Stopped after a lightweight consent pass to keep the page responsive. Re-run only if the banner is still blocking the page."
15128
15157
  ].join("\n");
15129
15158
  }
15130
- await waitForJsReady(wc2, 1500);
15159
+ await waitForJsReady(wc, 1500);
15131
15160
  const steps = [];
15132
15161
  let cleared = 0;
15133
15162
  const maxIterations = 8;
15134
15163
  for (let iteration = 0; iteration < maxIterations; iteration += 1) {
15135
- const before = await extractContent(wc2);
15164
+ const before = await extractContent(wc);
15136
15165
  const beforeState = describeOverlayState(before);
15137
15166
  const blockingOverlays = beforeState.inventory.filter(
15138
15167
  (overlay2) => overlay2.blocksInteraction
15139
15168
  );
15140
15169
  if (blockingOverlays.length === 0) {
15141
15170
  if (cleared === 0) {
15142
- const iframeResult = await tryDismissConsentIframe(wc2);
15171
+ const iframeResult = await tryDismissConsentIframe(wc);
15143
15172
  if (iframeResult) {
15144
15173
  steps.push(`Iframe consent: ${iframeResult}`);
15145
15174
  await sleep(500);
@@ -15155,7 +15184,7 @@ async function clearOverlays(wc2, strategy = "auto") {
15155
15184
  let actionMessage = null;
15156
15185
  if (overlay.kind === "cookie_consent") {
15157
15186
  actionMessage = await clickOverlayCandidate(
15158
- wc2,
15187
+ wc,
15159
15188
  overlay.acceptAction || overlay.dismissAction || overlay.actions[0]
15160
15189
  );
15161
15190
  } else if (overlay.kind === "selection_modal") {
@@ -15170,14 +15199,14 @@ async function clearOverlays(wc2, strategy = "auto") {
15170
15199
  }
15171
15200
  } else {
15172
15201
  const optionResult = await clickOverlayCandidate(
15173
- wc2,
15202
+ wc,
15174
15203
  overlay.correctOption
15175
15204
  );
15176
15205
  if (optionResult) {
15177
15206
  actionMessage = `Selected likely-correct option: ${optionResult}`;
15178
15207
  await sleep(120);
15179
15208
  const submitResult = await clickOverlayCandidate(
15180
- wc2,
15209
+ wc,
15181
15210
  overlay.submitAction || overlay.acceptAction
15182
15211
  );
15183
15212
  if (submitResult) {
@@ -15188,7 +15217,7 @@ Submitted modal: ${submitResult}`;
15188
15217
  }
15189
15218
  }
15190
15219
  if (!actionMessage) {
15191
- actionMessage = `Fallback popup handling: ${await dismissPopup(wc2)}`;
15220
+ actionMessage = `Fallback popup handling: ${await dismissPopup(wc)}`;
15192
15221
  }
15193
15222
  steps.push(actionMessage);
15194
15223
  if (overlay.kind === "cookie_consent") {
@@ -15198,7 +15227,7 @@ Submitted modal: ${submitResult}`;
15198
15227
  return steps.join("\n");
15199
15228
  }
15200
15229
  await sleep(250);
15201
- const after = await extractContent(wc2);
15230
+ const after = await extractContent(wc);
15202
15231
  const afterState = describeOverlayState(after);
15203
15232
  steps.push(`Overlays remaining: ${afterState.total}`);
15204
15233
  steps.push(`Page still blocked: ${afterState.blocking > 0}`);
@@ -15214,12 +15243,12 @@ Submitted modal: ${submitResult}`;
15214
15243
  }
15215
15244
  return steps.join("\n");
15216
15245
  }
15217
- async function resolveTargetByText(wc2, query, mode) {
15246
+ async function resolveTargetByText(wc, query, mode) {
15218
15247
  const trimmed = query.trim();
15219
15248
  if (!trimmed) return null;
15220
15249
  if (isInvalidTextTargetQuery(trimmed)) return null;
15221
15250
  const result = await executePageScript(
15222
- wc2,
15251
+ wc,
15223
15252
  `(${resolveTextTargetInDocument.toString()})(document, ${JSON.stringify(trimmed)}, ${JSON.stringify(mode)})`,
15224
15253
  {
15225
15254
  timeoutMs: 2200,
@@ -15243,15 +15272,15 @@ function describeFillField(field) {
15243
15272
  if (field.placeholder) return `placeholder=${field.placeholder}`;
15244
15273
  return "field";
15245
15274
  }
15246
- async function resolveFieldSelector(wc2, field) {
15247
- const directSelector = await resolveSelector(wc2, field.index, field.selector);
15275
+ async function resolveFieldSelector(wc, field) {
15276
+ const directSelector = await resolveSelector(wc, field.index, field.selector);
15248
15277
  if (directSelector) return directSelector;
15249
15278
  const name = normalizeFieldToken(field.name);
15250
15279
  const label = normalizeFieldToken(field.label);
15251
15280
  const placeholder = normalizeFieldToken(field.placeholder);
15252
15281
  if (!name && !label && !placeholder) return null;
15253
15282
  const selector = await executePageScript(
15254
- wc2,
15283
+ wc,
15255
15284
  `
15256
15285
  (function() {
15257
15286
  function normalize(value) {
@@ -15351,10 +15380,10 @@ async function resolveFieldSelector(wc2, field) {
15351
15380
  );
15352
15381
  return typeof selector === "string" && selector ? selector : null;
15353
15382
  }
15354
- async function fillFormFields(wc2, fields) {
15383
+ async function fillFormFields(wc, fields) {
15355
15384
  const results = [];
15356
15385
  for (const field of fields) {
15357
- const selector = await resolveFieldSelector(wc2, field);
15386
+ const selector = await resolveFieldSelector(wc, field);
15358
15387
  if (!selector) {
15359
15388
  results.push({
15360
15389
  field,
@@ -15364,7 +15393,7 @@ async function fillFormFields(wc2, fields) {
15364
15393
  continue;
15365
15394
  }
15366
15395
  const result = await setElementValue(
15367
- wc2,
15396
+ wc,
15368
15397
  selector,
15369
15398
  String(field.value || "")
15370
15399
  );
@@ -15399,18 +15428,18 @@ function isDangerousAction(name) {
15399
15428
  "paginate"
15400
15429
  ].includes(name);
15401
15430
  }
15402
- async function setElementValue(wc2, selector, value) {
15431
+ async function setElementValue(wc, selector, value) {
15403
15432
  if (selector.startsWith("__vessel_idx:")) {
15404
15433
  const idx = Number(selector.slice("__vessel_idx:".length));
15405
15434
  const result2 = await executePageScript(
15406
- wc2,
15435
+ wc,
15407
15436
  `window.__vessel?.interactByIndex?.(${idx}, "value", ${JSON.stringify(value)}) || "Error: interactByIndex not available"`
15408
15437
  );
15409
15438
  return result2 === PAGE_SCRIPT_TIMEOUT ? pageBusyError("type_text") : result2 || "Error: interactByIndex not available";
15410
15439
  }
15411
15440
  if (selector.includes(" >>> ")) {
15412
15441
  const result2 = await executePageScript(
15413
- wc2,
15442
+ wc,
15414
15443
  `
15415
15444
  (function() {
15416
15445
  var el = window.__vessel?.resolveShadowSelector?.(${JSON.stringify(selector)});
@@ -15446,7 +15475,7 @@ async function setElementValue(wc2, selector, value) {
15446
15475
  return result2 === PAGE_SCRIPT_TIMEOUT ? pageBusyError("type_text") : result2 || "Error: Could not type into element";
15447
15476
  }
15448
15477
  const result = await executePageScript(
15449
- wc2,
15478
+ wc,
15450
15479
  `
15451
15480
  (function() {
15452
15481
  const el = document.querySelector(${JSON.stringify(selector)});
@@ -15503,9 +15532,9 @@ async function setElementValue(wc2, selector, value) {
15503
15532
  );
15504
15533
  return result === PAGE_SCRIPT_TIMEOUT ? pageBusyError("type_text") : result || "Error: Could not type into element";
15505
15534
  }
15506
- async function typeKeystroke(wc2, selector, value) {
15535
+ async function typeKeystroke(wc, selector, value) {
15507
15536
  const result = await executePageScript(
15508
- wc2,
15537
+ wc,
15509
15538
  `
15510
15539
  (async function() {
15511
15540
  const el = document.querySelector(${JSON.stringify(selector)});
@@ -15551,8 +15580,8 @@ async function typeKeystroke(wc2, selector, value) {
15551
15580
  );
15552
15581
  return result === PAGE_SCRIPT_TIMEOUT ? pageBusyError("type_text") : result || "Error: Could not type into element";
15553
15582
  }
15554
- async function hoverElement(wc2, selector) {
15555
- const pos = await wc2.executeJavaScript(`
15583
+ async function hoverElement(wc, selector) {
15584
+ const pos = await wc.executeJavaScript(`
15556
15585
  (function() {
15557
15586
  const el = document.querySelector(${JSON.stringify(selector)});
15558
15587
  if (!el) return { error: 'Error[stale-index]: Element not found — the page may have changed. Call read_page to refresh.' };
@@ -15577,12 +15606,12 @@ async function hoverElement(wc2, selector) {
15577
15606
  const y = typeof pos.y === "number" ? pos.y : null;
15578
15607
  if (x == null || y == null)
15579
15608
  return "Error: Could not resolve hover coordinates";
15580
- wc2.sendInputEvent({ type: "mouseMove", x, y });
15609
+ wc.sendInputEvent({ type: "mouseMove", x, y });
15581
15610
  const label = typeof pos.label === "string" ? pos.label : "element";
15582
15611
  return `Hovered: ${label}`;
15583
15612
  }
15584
- async function focusElement(wc2, selector) {
15585
- return wc2.executeJavaScript(`
15613
+ async function focusElement(wc, selector) {
15614
+ return wc.executeJavaScript(`
15586
15615
  (function() {
15587
15616
  const el = document.querySelector(${JSON.stringify(selector)});
15588
15617
  if (!el) return 'Error[stale-index]: Element not found — the page may have changed. Call read_page to refresh.';
@@ -15595,20 +15624,20 @@ async function focusElement(wc2, selector) {
15595
15624
  })()
15596
15625
  `);
15597
15626
  }
15598
- async function waitForCondition(wc2, args) {
15627
+ async function waitForCondition(wc, args) {
15599
15628
  const timeoutMs = Math.max(250, Number(args.timeoutMs) || 5e3);
15600
15629
  const selector = typeof args.selector === "string" && args.selector.trim() ? args.selector.trim() : "";
15601
15630
  const text = typeof args.text === "string" && args.text.trim() ? args.text.trim() : "";
15602
15631
  if (!selector && !text) {
15603
15632
  return "Error: wait_for requires text or selector";
15604
15633
  }
15605
- if (wc2.isLoading()) {
15606
- await waitForLoad(wc2, Math.min(timeoutMs, 5e3));
15634
+ if (wc.isLoading()) {
15635
+ await waitForLoad(wc, Math.min(timeoutMs, 5e3));
15607
15636
  }
15608
15637
  const startedAt = Date.now();
15609
15638
  while (Date.now() - startedAt < timeoutMs) {
15610
15639
  const result = await executePageScript(
15611
- wc2,
15640
+ wc,
15612
15641
  `
15613
15642
  (function() {
15614
15643
  var selector = ${JSON.stringify(selector)};
@@ -15712,11 +15741,11 @@ function composeFolderAwareResponse(message, createdFolder) {
15712
15741
  return `${prefix}${message}
15713
15742
  ${formatFolderStatus()}`;
15714
15743
  }
15715
- async function selectOption(wc2, args) {
15716
- const selector = await resolveSelector(wc2, args.index, args.selector);
15744
+ async function selectOption(wc, args) {
15745
+ const selector = await resolveSelector(wc, args.index, args.selector);
15717
15746
  if (!selector) return "Error: No select element index or selector provided";
15718
15747
  const result = await executePageScript(
15719
- wc2,
15748
+ wc,
15720
15749
  `
15721
15750
  (function() {
15722
15751
  const el = document.querySelector(${JSON.stringify(selector)});
@@ -15748,12 +15777,12 @@ async function selectOption(wc2, args) {
15748
15777
  );
15749
15778
  return result === PAGE_SCRIPT_TIMEOUT ? pageBusyError("select_option") : result || "Error: Could not select option";
15750
15779
  }
15751
- async function submitForm(wc2, args) {
15752
- const beforeUrl = wc2.getURL();
15753
- let selector = await resolveSelector(wc2, args.index, args.selector);
15780
+ async function submitForm(wc, args) {
15781
+ const beforeUrl = wc.getURL();
15782
+ let selector = await resolveSelector(wc, args.index, args.selector);
15754
15783
  if (!selector) {
15755
15784
  const discoveredSelector = await executePageScript(
15756
- wc2,
15785
+ wc,
15757
15786
  `
15758
15787
  (function() {
15759
15788
  var forms = document.querySelectorAll('form');
@@ -15776,7 +15805,7 @@ async function submitForm(wc2, args) {
15776
15805
  if (!selector) return "Error: No form found on the page";
15777
15806
  }
15778
15807
  const formInfo = await executePageScript(
15779
- wc2,
15808
+ wc,
15780
15809
  `
15781
15810
  (function() {
15782
15811
  const target = document.querySelector(${JSON.stringify(selector)});
@@ -15889,19 +15918,19 @@ async function submitForm(wc2, args) {
15889
15918
  if (formInfo.params) {
15890
15919
  url.search = formInfo.params;
15891
15920
  }
15892
- await loadPermittedUrl(wc2, url.toString());
15893
- await waitForPotentialNavigation(wc2, beforeUrl);
15894
- const afterUrl = wc2.getURL();
15921
+ await loadPermittedUrl(wc, url.toString());
15922
+ await waitForPotentialNavigation(wc, beforeUrl);
15923
+ const afterUrl = wc.getURL();
15895
15924
  return afterUrl !== beforeUrl ? `Submitted form via GET -> ${afterUrl}` : "Submitted form via GET";
15896
15925
  }
15897
15926
  if (formInfo.submitted) {
15898
- await waitForPotentialNavigation(wc2, beforeUrl);
15899
- const afterUrl = wc2.getURL();
15927
+ await waitForPotentialNavigation(wc, beforeUrl);
15928
+ const afterUrl = wc.getURL();
15900
15929
  if (afterUrl !== beforeUrl) {
15901
15930
  return `Submitted form via ${formInfo.method} -> ${afterUrl}`;
15902
15931
  }
15903
15932
  await executePageScript(
15904
- wc2,
15933
+ wc,
15905
15934
  `
15906
15935
  (function() {
15907
15936
  var active = document.activeElement;
@@ -15922,29 +15951,29 @@ async function submitForm(wc2, args) {
15922
15951
  label: "submit form enter fallback"
15923
15952
  }
15924
15953
  );
15925
- wc2.sendInputEvent({ type: "keyDown", keyCode: "Return" });
15954
+ wc.sendInputEvent({ type: "keyDown", keyCode: "Return" });
15926
15955
  await new Promise((r) => setTimeout(r, 50));
15927
- wc2.sendInputEvent({ type: "keyUp", keyCode: "Return" });
15928
- await waitForPotentialNavigation(wc2, beforeUrl, 3e3);
15929
- const finalUrl = wc2.getURL();
15956
+ wc.sendInputEvent({ type: "keyUp", keyCode: "Return" });
15957
+ await waitForPotentialNavigation(wc, beforeUrl, 3e3);
15958
+ const finalUrl = wc.getURL();
15930
15959
  return finalUrl !== beforeUrl ? `Submitted form (Enter fallback) -> ${finalUrl}` : `Submitted form via ${formInfo.method} (page may have updated dynamically)`;
15931
15960
  }
15932
15961
  return "Submitted form";
15933
15962
  }
15934
- async function pressKeyDirect(wc2, key, index, selector) {
15935
- return pressKey(wc2, { key, index, selector });
15963
+ async function pressKeyDirect(wc, key, index, selector) {
15964
+ return pressKey(wc, { key, index, selector });
15936
15965
  }
15937
- async function submitFormDirect(wc2, index, selector) {
15938
- return submitForm(wc2, { index, selector });
15966
+ async function submitFormDirect(wc, index, selector) {
15967
+ return submitForm(wc, { index, selector });
15939
15968
  }
15940
- async function selectOptionDirect(wc2, index, selector, label, value) {
15941
- return selectOption(wc2, { index, selector, label, value });
15969
+ async function selectOptionDirect(wc, index, selector, label, value) {
15970
+ return selectOption(wc, { index, selector, label, value });
15942
15971
  }
15943
- async function waitForConditionDirect(wc2, text, selector, timeoutMs) {
15944
- return waitForCondition(wc2, { text, selector, timeoutMs });
15972
+ async function waitForConditionDirect(wc, text, selector, timeoutMs) {
15973
+ return waitForCondition(wc, { text, selector, timeoutMs });
15945
15974
  }
15946
- async function clickElementBySelector(wc2, selector) {
15947
- return clickResolvedSelector(wc2, selector);
15975
+ async function clickElementBySelector(wc, selector) {
15976
+ return clickResolvedSelector(wc, selector);
15948
15977
  }
15949
15978
  function normalizeSearchQuery(query) {
15950
15979
  return query.replace(/\s+/g, " ").trim();
@@ -16016,12 +16045,12 @@ function buildDefaultEngineShortcut(rawQuery) {
16016
16045
  appliedFilters: []
16017
16046
  };
16018
16047
  }
16019
- async function locateSearchTarget(wc2, explicitSelector) {
16048
+ async function locateSearchTarget(wc, explicitSelector) {
16020
16049
  if (explicitSelector) {
16021
16050
  return { selector: explicitSelector, submitSelector: null };
16022
16051
  }
16023
16052
  return executePageScript(
16024
- wc2,
16053
+ wc,
16025
16054
  `
16026
16055
  (function() {
16027
16056
  function text(value) {
@@ -16200,7 +16229,7 @@ async function locateSearchTarget(wc2, explicitSelector) {
16200
16229
  }
16201
16230
  );
16202
16231
  }
16203
- async function searchPage(wc2, args) {
16232
+ async function searchPage(wc, args) {
16204
16233
  const query = String(args.query || "");
16205
16234
  if (!query) return "Error: No search query provided.";
16206
16235
  const queryLower = query.toLowerCase().trim();
@@ -16233,26 +16262,26 @@ async function searchPage(wc2, args) {
16233
16262
  if (buttonLikePatterns.some((p) => queryLower.includes(p))) {
16234
16263
  return `Error: "${query}" looks like a button label, not a search query. Use the click tool to interact with this element instead.`;
16235
16264
  }
16236
- if (looksLikeCurrentSiteNameQuery(query, wc2.getURL(), wc2.getTitle() || "")) {
16237
- return `Error: "${query}" looks like the current site's name, not a product query. You are already on ${wc2.getURL()}. Open a section like staff picks/new releases or search for actual book titles, authors, or genres instead.`;
16265
+ if (looksLikeCurrentSiteNameQuery(query, wc.getURL(), wc.getTitle() || "")) {
16266
+ return `Error: "${query}" looks like the current site's name, not a product query. You are already on ${wc.getURL()}. Open a section like staff picks/new releases or search for actual book titles, authors, or genres instead.`;
16238
16267
  }
16239
16268
  const runShortcut = async (shortcut) => {
16240
- const beforeUrl2 = wc2.getURL();
16241
- await loadPermittedUrl(wc2, shortcut.url);
16242
- await waitForPotentialNavigation(wc2, beforeUrl2, 4e3);
16243
- const afterUrl2 = wc2.getURL();
16269
+ const beforeUrl2 = wc.getURL();
16270
+ await loadPermittedUrl(wc, shortcut.url);
16271
+ await waitForPotentialNavigation(wc, beforeUrl2, 4e3);
16272
+ const afterUrl2 = wc.getURL();
16244
16273
  const applied = shortcut.appliedFilters.length > 0 ? ` (${shortcut.appliedFilters.join(", ")})` : "";
16245
16274
  const destination = shortcut.section ? ` ${shortcut.section}` : "";
16246
- return `Searched "${query}" via ${shortcut.source}${destination} shortcut${applied} → ${afterUrl2}${await getPostSearchSummary(wc2)}`;
16275
+ return `Searched "${query}" via ${shortcut.source}${destination} shortcut${applied} → ${afterUrl2}${await getPostSearchSummary(wc)}`;
16247
16276
  };
16248
16277
  if (typeof args.selector !== "string") {
16249
- const shortcut = buildHuggingFaceSearchShortcut(wc2.getURL(), query) ?? buildCommonSearchUrlShortcut(wc2.getURL(), query);
16278
+ const shortcut = buildHuggingFaceSearchShortcut(wc.getURL(), query) ?? buildCommonSearchUrlShortcut(wc.getURL(), query);
16250
16279
  if (shortcut) {
16251
16280
  return runShortcut(shortcut);
16252
16281
  }
16253
16282
  }
16254
16283
  const searchInfo = await locateSearchTarget(
16255
- wc2,
16284
+ wc,
16256
16285
  typeof args.selector === "string" ? args.selector : void 0
16257
16286
  );
16258
16287
  if (searchInfo === PAGE_SCRIPT_TIMEOUT) {
@@ -16267,42 +16296,42 @@ async function searchPage(wc2, args) {
16267
16296
  }
16268
16297
  return 'Error: Could not find a visible search input. Try read_page(mode="visible_only") or provide a selector.';
16269
16298
  }
16270
- const fillResult = await setElementValue(wc2, searchInfo.selector, query);
16299
+ const fillResult = await setElementValue(wc, searchInfo.selector, query);
16271
16300
  if (fillResult.startsWith("Error:")) {
16272
16301
  return fillResult;
16273
16302
  }
16274
16303
  await sleep(100);
16275
- const beforeUrl = wc2.getURL();
16276
- const keyResult = await pressKey(wc2, {
16304
+ const beforeUrl = wc.getURL();
16305
+ const keyResult = await pressKey(wc, {
16277
16306
  key: "Enter",
16278
16307
  selector: searchInfo.selector
16279
16308
  });
16280
16309
  if (keyResult.startsWith("Error:")) {
16281
16310
  return keyResult;
16282
16311
  }
16283
- await waitForPotentialNavigation(wc2, beforeUrl, 3e3);
16284
- let afterUrl = wc2.getURL();
16312
+ await waitForPotentialNavigation(wc, beforeUrl, 3e3);
16313
+ let afterUrl = wc.getURL();
16285
16314
  if (afterUrl !== beforeUrl) {
16286
- return `Searched "${query}" → ${afterUrl}${await getPostSearchSummary(wc2)}`;
16315
+ return `Searched "${query}" → ${afterUrl}${await getPostSearchSummary(wc)}`;
16287
16316
  }
16288
16317
  if (searchInfo.submitSelector) {
16289
- const clickResult = await clickElementBySelector(wc2, searchInfo.submitSelector);
16318
+ const clickResult = await clickElementBySelector(wc, searchInfo.submitSelector);
16290
16319
  if (!clickResult.startsWith("Error:")) {
16291
- await waitForPotentialNavigation(wc2, beforeUrl, 3e3);
16292
- afterUrl = wc2.getURL();
16320
+ await waitForPotentialNavigation(wc, beforeUrl, 3e3);
16321
+ afterUrl = wc.getURL();
16293
16322
  if (afterUrl !== beforeUrl) {
16294
- return `Searched "${query}" (via search button) → ${afterUrl}${await getPostSearchSummary(wc2)}`;
16323
+ return `Searched "${query}" (via search button) → ${afterUrl}${await getPostSearchSummary(wc)}`;
16295
16324
  }
16296
16325
  }
16297
16326
  }
16298
- return `Searched "${query}" (same page — results may have loaded dynamically)${await getPostSearchSummary(wc2)}`;
16327
+ return `Searched "${query}" (same page — results may have loaded dynamically)${await getPostSearchSummary(wc)}`;
16299
16328
  }
16300
- async function pressKey(wc2, args) {
16329
+ async function pressKey(wc, args) {
16301
16330
  const key = typeof args.key === "string" ? args.key.trim() : "";
16302
16331
  if (!key) return "Error: No key provided";
16303
- const selector = await resolveSelector(wc2, args.index, args.selector);
16332
+ const selector = await resolveSelector(wc, args.index, args.selector);
16304
16333
  const focusResult = await executePageScript(
16305
- wc2,
16334
+ wc,
16306
16335
  `
16307
16336
  (function() {
16308
16337
  const selector = ${JSON.stringify(selector)};
@@ -16336,22 +16365,22 @@ async function pressKey(wc2, args) {
16336
16365
  if ("error" in focusResult && typeof focusResult.error === "string") {
16337
16366
  return focusResult.error;
16338
16367
  }
16339
- wc2.focus();
16368
+ wc.focus();
16340
16369
  const normalizedKey = key.length === 1 ? key : key[0].toUpperCase() + key.slice(1);
16341
16370
  const electronKeyCode = normalizedKey === "Enter" ? "Return" : normalizedKey === "ArrowUp" ? "Up" : normalizedKey === "ArrowDown" ? "Down" : normalizedKey === "ArrowLeft" ? "Left" : normalizedKey === "ArrowRight" ? "Right" : normalizedKey;
16342
- wc2.sendInputEvent({ type: "keyDown", keyCode: electronKeyCode });
16371
+ wc.sendInputEvent({ type: "keyDown", keyCode: electronKeyCode });
16343
16372
  if (key.length === 1) {
16344
- wc2.sendInputEvent({ type: "char", keyCode: key });
16373
+ wc.sendInputEvent({ type: "char", keyCode: key });
16345
16374
  }
16346
16375
  await sleep(16);
16347
- wc2.sendInputEvent({ type: "keyUp", keyCode: electronKeyCode });
16376
+ wc.sendInputEvent({ type: "keyUp", keyCode: electronKeyCode });
16348
16377
  const label = "label" in focusResult && typeof focusResult.label === "string" ? focusResult.label : null;
16349
16378
  return label ? `Pressed key: ${key} on ${label}` : `Pressed key: ${key}`;
16350
16379
  }
16351
16380
  async function getPostActionState$1(ctx, name) {
16352
16381
  const tab = ctx.tabManager.getActiveTab();
16353
16382
  if (!tab) return "";
16354
- const wc2 = tab.view.webContents;
16383
+ const wc = tab.view.webContents;
16355
16384
  const navActions = [
16356
16385
  "navigate",
16357
16386
  "open_bookmark",
@@ -16381,10 +16410,10 @@ async function getPostActionState$1(ctx, name) {
16381
16410
  "load_session"
16382
16411
  ];
16383
16412
  if (navActions.includes(name)) {
16384
- if (wc2.isLoading()) {
16385
- await waitForLoad(wc2);
16413
+ if (wc.isLoading()) {
16414
+ await waitForLoad(wc);
16386
16415
  }
16387
- const currentUrl = wc2.getURL();
16416
+ const currentUrl = wc.getURL();
16388
16417
  let warnings = "";
16389
16418
  if (isProductAlreadyInCart(currentUrl)) {
16390
16419
  warnings += `
@@ -16419,12 +16448,12 @@ WARNING: The clicked link appears to be a filter or sort control, not a product.
16419
16448
  }
16420
16449
  }
16421
16450
  return `
16422
- [state: url=${currentUrl}, title=${JSON.stringify(wc2.getTitle() || "")}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=${wc2.isLoading()}]${warnings}`;
16451
+ [state: url=${currentUrl}, title=${JSON.stringify(wc.getTitle() || "")}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=${wc.isLoading()}]${warnings}`;
16423
16452
  }
16424
- if (name === "click" && !wc2.isLoading()) {
16453
+ if (name === "click" && !wc.isLoading()) {
16425
16454
  try {
16426
16455
  const emptyPage = await executePageScript(
16427
- wc2,
16456
+ wc,
16428
16457
  `(function() {
16429
16458
  var body = (document.body.textContent || '').toLowerCase();
16430
16459
  return /\b(no results|no items found|nothing matched|0 results|zero results|no products|your search.*did not match|no books found)\b/.test(body)
@@ -16434,7 +16463,7 @@ WARNING: The clicked link appears to be a filter or sort control, not a product.
16434
16463
  );
16435
16464
  if (emptyPage && emptyPage !== PAGE_SCRIPT_TIMEOUT) {
16436
16465
  return `
16437
- [state: url=${wc2.getURL()}, title=${JSON.stringify(wc2.getTitle() || "")}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=false]
16466
+ [state: url=${wc.getURL()}, title=${JSON.stringify(wc.getTitle() || "")}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=false]
16438
16467
  WARNING: This page shows no results. You likely clicked a filter or category link instead of a product. Call go_back to return to the search results.`;
16439
16468
  }
16440
16469
  } catch {
@@ -16442,7 +16471,7 @@ WARNING: This page shows no results. You likely clicked a filter or category lin
16442
16471
  }
16443
16472
  if (interactActions.includes(name)) {
16444
16473
  return `
16445
- [state: url=${wc2.getURL()}, title=${JSON.stringify(wc2.getTitle() || "")}, tabId=${ctx.tabManager.getActiveTabId()}]`;
16474
+ [state: url=${wc.getURL()}, title=${JSON.stringify(wc.getTitle() || "")}, tabId=${ctx.tabManager.getActiveTabId()}]`;
16446
16475
  }
16447
16476
  if (tabActions.includes(name)) {
16448
16477
  const activeId = ctx.tabManager.getActiveTabId();
@@ -16553,7 +16582,7 @@ async function executeAction(name, args, ctx) {
16553
16582
  if (isToolGated(name)) {
16554
16583
  return `This tool (${name}) requires Vessel Premium. Upgrade at Settings > Premium to unlock screenshot, session management, workflow tracking, and more.`;
16555
16584
  }
16556
- const wc2 = tab?.view.webContents;
16585
+ const wc = tab?.view.webContents;
16557
16586
  const result = await ctx.runtime.runControlledAction({
16558
16587
  source: "ai",
16559
16588
  name,
@@ -16563,13 +16592,13 @@ async function executeAction(name, args, ctx) {
16563
16592
  executor: async () => {
16564
16593
  switch (name) {
16565
16594
  case "screenshot": {
16566
- if (!wc2) return "Error: No active tab";
16595
+ if (!wc) return "Error: No active tab";
16567
16596
  const screenshotStart = Date.now();
16568
- const shot = await captureScreenshot(wc2);
16597
+ const shot = await captureScreenshot(wc);
16569
16598
  if (!shot.ok) return `Error: ${shot.error}`;
16570
16599
  const screenshotMs = Date.now() - screenshotStart;
16571
- const title = wc2.getTitle() || "(untitled)";
16572
- const url = wc2.getURL();
16600
+ const title = wc.getTitle() || "(untitled)";
16601
+ const url = wc.getURL();
16573
16602
  return makeImageResult(
16574
16603
  shot.base64,
16575
16604
  `Screenshot of "${title}" (${url}) — ${shot.width}x${shot.height}, captured in ${screenshotMs}ms. Analyze the image to understand the current visual state of the page.`
@@ -16626,7 +16655,7 @@ async function executeAction(name, args, ctx) {
16626
16655
  return `Created tab ${createdId}`;
16627
16656
  }
16628
16657
  case "navigate": {
16629
- if (!wc2 || !tabId) return "Error: No active tab";
16658
+ if (!wc || !tabId) return "Error: No active tab";
16630
16659
  const taskGoal = ctx.runtime.getState().taskTracker?.goal;
16631
16660
  if (taskGoal && typeof args.url === "string") {
16632
16661
  const domainDrift = shouldBlockOffGoalDomainNavigation(
@@ -16637,8 +16666,8 @@ async function executeAction(name, args, ctx) {
16637
16666
  return `Navigation blocked: ${args.url} drifts away from the requested site ${domainDrift.requestedDomain}. Stay on the requested domain and continue the original task there.`;
16638
16667
  }
16639
16668
  }
16640
- if (typeof args.url === "string" && !args.postBody && isRedundantNavigateTarget(wc2.getURL(), args.url)) {
16641
- return `Already on ${wc2.getURL()}. Do not navigate to the same URL again. Use click, inspect_element, read_page, or search for actual book terms instead.`;
16669
+ if (typeof args.url === "string" && !args.postBody && isRedundantNavigateTarget(wc.getURL(), args.url)) {
16670
+ return `Already on ${wc.getURL()}. Do not navigate to the same URL again. Use click, inspect_element, read_page, or search for actual book terms instead.`;
16642
16671
  }
16643
16672
  const navValidation = await validateLinkDestination(args.url);
16644
16673
  if (navValidation.status === "dead") {
@@ -16646,74 +16675,74 @@ async function executeAction(name, args, ctx) {
16646
16675
  }
16647
16676
  const navError = ctx.tabManager.navigateTab(tabId, args.url, args.postBody);
16648
16677
  if (navError) return navError;
16649
- await waitForLoad(wc2);
16650
- return `Navigated to ${wc2.getURL()}${await getPostNavSummary(wc2)}`;
16678
+ await waitForLoad(wc);
16679
+ return `Navigated to ${wc.getURL()}${await getPostNavSummary(wc)}`;
16651
16680
  }
16652
16681
  case "go_back": {
16653
- if (!tab || !wc2 || !tabId) return "Error: No active tab";
16682
+ if (!tab || !wc || !tabId) return "Error: No active tab";
16654
16683
  if (!tab.canGoBack()) {
16655
16684
  return "No previous page in history";
16656
16685
  }
16657
- const beforeUrl = wc2.getURL();
16686
+ const beforeUrl = wc.getURL();
16658
16687
  ctx.tabManager.goBack(tabId);
16659
- await waitForLoad(wc2);
16660
- const afterUrl = wc2.getURL();
16661
- return afterUrl !== beforeUrl ? `Went back to ${afterUrl}${await getPostNavSummary(wc2)}` : `Back action completed but page stayed on ${afterUrl}`;
16688
+ await waitForLoad(wc);
16689
+ const afterUrl = wc.getURL();
16690
+ return afterUrl !== beforeUrl ? `Went back to ${afterUrl}${await getPostNavSummary(wc)}` : `Back action completed but page stayed on ${afterUrl}`;
16662
16691
  }
16663
16692
  case "go_forward": {
16664
- if (!tab || !wc2 || !tabId) return "Error: No active tab";
16693
+ if (!tab || !wc || !tabId) return "Error: No active tab";
16665
16694
  if (!tab.canGoForward()) {
16666
16695
  return "No forward page in history";
16667
16696
  }
16668
- const beforeUrl = wc2.getURL();
16697
+ const beforeUrl = wc.getURL();
16669
16698
  ctx.tabManager.goForward(tabId);
16670
- await waitForLoad(wc2);
16671
- const afterUrl = wc2.getURL();
16672
- return afterUrl !== beforeUrl ? `Went forward to ${afterUrl}${await getPostNavSummary(wc2)}` : `Forward action completed but page stayed on ${afterUrl}`;
16699
+ await waitForLoad(wc);
16700
+ const afterUrl = wc.getURL();
16701
+ return afterUrl !== beforeUrl ? `Went forward to ${afterUrl}${await getPostNavSummary(wc)}` : `Forward action completed but page stayed on ${afterUrl}`;
16673
16702
  }
16674
16703
  case "reload": {
16675
- if (!wc2 || !tabId) return "Error: No active tab";
16704
+ if (!wc || !tabId) return "Error: No active tab";
16676
16705
  ctx.tabManager.reloadTab(tabId);
16677
- await waitForLoad(wc2);
16678
- return `Reloaded ${wc2.getURL()}`;
16706
+ await waitForLoad(wc);
16707
+ return `Reloaded ${wc.getURL()}`;
16679
16708
  }
16680
16709
  case "click": {
16681
- if (!wc2) return "Error: No active tab";
16710
+ if (!wc) return "Error: No active tab";
16682
16711
  let selector = null;
16683
16712
  const textTarget = typeof args.text === "string" && args.text.trim() ? args.text.trim() : "";
16684
16713
  if (typeof args.selector === "string" && args.selector.trim()) {
16685
- selector = await resolveSelector(wc2, void 0, args.selector);
16714
+ selector = await resolveSelector(wc, void 0, args.selector);
16686
16715
  } else if (textTarget) {
16687
16716
  if (isInvalidTextTargetQuery(textTarget)) {
16688
16717
  return `Error: "${textTarget}" looks like HTML or markup, not a visible page label. Use a book title, button text, or element index instead.`;
16689
16718
  }
16690
- selector = await resolveTargetByText(wc2, textTarget, "interactive");
16719
+ selector = await resolveTargetByText(wc, textTarget, "interactive");
16691
16720
  if (!selector && typeof args.index === "number") {
16692
16721
  selector = `__vessel_idx:${args.index}`;
16693
16722
  }
16694
16723
  } else if (typeof args.index === "number") {
16695
- selector = await resolveSelector(wc2, args.index);
16724
+ selector = await resolveSelector(wc, args.index);
16696
16725
  if (!selector) selector = `__vessel_idx:${args.index}`;
16697
16726
  } else {
16698
- selector = await resolveSelector(wc2, args.index, args.selector);
16727
+ selector = await resolveSelector(wc, args.index, args.selector);
16699
16728
  }
16700
16729
  if (selector === PAGE_SCRIPT_TIMEOUT) return pageBusyError("click");
16701
16730
  if (!selector) {
16702
16731
  return "Error: No element index, selector, or visible text provided";
16703
16732
  }
16704
- return clickResolvedSelector(wc2, selector);
16733
+ return clickResolvedSelector(wc, selector);
16705
16734
  }
16706
16735
  case "inspect_element": {
16707
- if (!wc2) return "Error: No active tab";
16736
+ if (!wc) return "Error: No active tab";
16708
16737
  let selector = null;
16709
16738
  const textTarget = typeof args.text === "string" && args.text.trim() ? args.text.trim() : "";
16710
16739
  if (textTarget) {
16711
16740
  if (isInvalidTextTargetQuery(textTarget)) {
16712
16741
  return `Error: "${textTarget}" looks like HTML or markup, not visible page text. Use a section title, book title, or element index instead.`;
16713
16742
  }
16714
- selector = await resolveTargetByText(wc2, textTarget, "context");
16743
+ selector = await resolveTargetByText(wc, textTarget, "context");
16715
16744
  } else {
16716
- selector = await resolveSelector(wc2, args.index, args.selector);
16745
+ selector = await resolveSelector(wc, args.index, args.selector);
16717
16746
  }
16718
16747
  if (selector === PAGE_SCRIPT_TIMEOUT) {
16719
16748
  return pageBusyError("inspect_element");
@@ -16722,44 +16751,44 @@ async function executeAction(name, args, ctx) {
16722
16751
  return "Error: No element index, selector, or visible text provided";
16723
16752
  }
16724
16753
  return inspectElement(
16725
- wc2,
16754
+ wc,
16726
16755
  selector,
16727
16756
  typeof args.limit === "number" ? args.limit : 8
16728
16757
  );
16729
16758
  }
16730
16759
  case "type_text": {
16731
- if (!wc2) return "Error: No active tab";
16732
- const selector = await resolveSelector(wc2, args.index, args.selector);
16760
+ if (!wc) return "Error: No active tab";
16761
+ const selector = await resolveSelector(wc, args.index, args.selector);
16733
16762
  if (!selector) return "Error: No element index or selector provided";
16734
16763
  const mode = typeof args.mode === "string" ? args.mode : "default";
16735
16764
  if (mode === "keystroke") {
16736
- return typeKeystroke(wc2, selector, String(args.text || ""));
16765
+ return typeKeystroke(wc, selector, String(args.text || ""));
16737
16766
  }
16738
- return setElementValue(wc2, selector, String(args.text || ""));
16767
+ return setElementValue(wc, selector, String(args.text || ""));
16739
16768
  }
16740
16769
  case "select_option": {
16741
- if (!wc2) return "Error: No active tab";
16742
- return selectOption(wc2, args);
16770
+ if (!wc) return "Error: No active tab";
16771
+ return selectOption(wc, args);
16743
16772
  }
16744
16773
  case "submit_form": {
16745
- if (!wc2) return "Error: No active tab";
16746
- const beforeUrl = wc2.getURL();
16747
- const result2 = await submitForm(wc2, args);
16774
+ if (!wc) return "Error: No active tab";
16775
+ const beforeUrl = wc.getURL();
16776
+ const result2 = await submitForm(wc, args);
16748
16777
  if (result2.startsWith("Error") || result2.startsWith("Target") || result2.startsWith("No parent") || result2.startsWith("Submit control")) {
16749
16778
  return result2;
16750
16779
  }
16751
- await waitForPotentialNavigation(wc2, beforeUrl);
16752
- const afterUrl = wc2.getURL();
16780
+ await waitForPotentialNavigation(wc, beforeUrl);
16781
+ const afterUrl = wc.getURL();
16753
16782
  return afterUrl !== beforeUrl ? `${result2} -> ${afterUrl}` : result2;
16754
16783
  }
16755
16784
  case "press_key": {
16756
- if (!wc2) return "Error: No active tab";
16757
- const beforeUrl = wc2.getURL();
16758
- const result2 = await pressKey(wc2, args);
16785
+ if (!wc) return "Error: No active tab";
16786
+ const beforeUrl = wc.getURL();
16787
+ const result2 = await pressKey(wc, args);
16759
16788
  const key = typeof args.key === "string" ? args.key.trim() : "";
16760
16789
  if (key === "Enter") {
16761
- await waitForPotentialNavigation(wc2, beforeUrl, 3e3);
16762
- const afterUrl = wc2.getURL();
16790
+ await waitForPotentialNavigation(wc, beforeUrl, 3e3);
16791
+ const afterUrl = wc.getURL();
16763
16792
  if (afterUrl !== beforeUrl) {
16764
16793
  return `${result2} -> ${afterUrl}`;
16765
16794
  }
@@ -16769,23 +16798,23 @@ async function executeAction(name, args, ctx) {
16769
16798
  return result2;
16770
16799
  }
16771
16800
  case "scroll": {
16772
- if (!wc2) return "Error: No active tab";
16801
+ if (!wc) return "Error: No active tab";
16773
16802
  const pixels = coerceOptionalNumber(args.amount) ?? 500;
16774
16803
  const dir = args.direction === "up" ? -pixels : pixels;
16775
- const result2 = await scrollPage(wc2, dir);
16804
+ const result2 = await scrollPage(wc, dir);
16776
16805
  return `Scrolled ${args.direction} by ${pixels}px (moved ${Math.abs(result2.movedY)}px, now at y=${Math.round(result2.afterY)})`;
16777
16806
  }
16778
16807
  case "hover": {
16779
- if (!wc2) return "Error: No active tab";
16780
- const selector = await resolveSelector(wc2, args.index, args.selector);
16808
+ if (!wc) return "Error: No active tab";
16809
+ const selector = await resolveSelector(wc, args.index, args.selector);
16781
16810
  if (!selector) return "Error: No element index or selector provided";
16782
- return hoverElement(wc2, selector);
16811
+ return hoverElement(wc, selector);
16783
16812
  }
16784
16813
  case "focus": {
16785
- if (!wc2) return "Error: No active tab";
16786
- const selector = await resolveSelector(wc2, args.index, args.selector);
16814
+ if (!wc) return "Error: No active tab";
16815
+ const selector = await resolveSelector(wc, args.index, args.selector);
16787
16816
  if (!selector) return "Error: No element index or selector provided";
16788
- return focusElement(wc2, selector);
16817
+ return focusElement(wc, selector);
16789
16818
  }
16790
16819
  case "set_ad_blocking": {
16791
16820
  const enabled = typeof args.enabled === "boolean" ? args.enabled : null;
@@ -16812,24 +16841,24 @@ async function executeAction(name, args, ctx) {
16812
16841
  return `${enabled ? "Enabled" : "Disabled"} ad blocking for "${state2.title}"${shouldReload ? " and reloaded the tab" : ""}`;
16813
16842
  }
16814
16843
  case "dismiss_popup": {
16815
- if (!wc2) return "Error: No active tab";
16816
- return dismissPopup(wc2);
16844
+ if (!wc) return "Error: No active tab";
16845
+ return dismissPopup(wc);
16817
16846
  }
16818
16847
  case "clear_overlays": {
16819
- if (!wc2) return "Error: No active tab";
16848
+ if (!wc) return "Error: No active tab";
16820
16849
  const strategy = args.strategy === "interactive" ? "interactive" : "auto";
16821
- return clearOverlays(wc2, strategy);
16850
+ return clearOverlays(wc, strategy);
16822
16851
  }
16823
16852
  case "read_page": {
16824
- if (!wc2) return "Error: No active tab";
16853
+ if (!wc) return "Error: No active tab";
16825
16854
  const requestedGlance = typeof args.mode === "string" && args.mode.trim().toLowerCase() === "glance";
16826
16855
  if (requestedGlance) {
16827
- return glanceExtract(wc2);
16856
+ return glanceExtract(wc);
16828
16857
  }
16829
16858
  let content = null;
16830
16859
  try {
16831
16860
  content = await Promise.race([
16832
- extractContent(wc2),
16861
+ extractContent(wc),
16833
16862
  new Promise(
16834
16863
  (resolve) => setTimeout(() => {
16835
16864
  resolve(null);
@@ -16843,14 +16872,14 @@ async function executeAction(name, args, ctx) {
16843
16872
  if (!content || content.content.length === 0) {
16844
16873
  try {
16845
16874
  const iframeResult = await Promise.race([
16846
- tryDismissConsentIframe(wc2),
16875
+ tryDismissConsentIframe(wc),
16847
16876
  new Promise((resolve) => setTimeout(() => resolve(null), 2e3))
16848
16877
  ]);
16849
16878
  if (iframeResult) {
16850
16879
  await sleep(500);
16851
16880
  try {
16852
16881
  content = await Promise.race([
16853
- extractContent(wc2),
16882
+ extractContent(wc),
16854
16883
  new Promise((resolve) => setTimeout(() => resolve(null), 3e3))
16855
16884
  ]);
16856
16885
  } catch (err) {
@@ -16865,7 +16894,7 @@ async function executeAction(name, args, ctx) {
16865
16894
  if (content && content.content.length > 0) {
16866
16895
  const liveSelectionSection = formatLiveSelectionSection(
16867
16896
  await captureLiveHighlightSnapshot(
16868
- wc2,
16897
+ wc,
16869
16898
  getHighlightsForUrl(content.url)
16870
16899
  )
16871
16900
  );
@@ -16895,20 +16924,20 @@ ${truncated}`;
16895
16924
  `Need more detail? Escalate with read_page(mode="debug") only if the narrow modes are insufficient.`
16896
16925
  ].filter(Boolean).join("\n\n");
16897
16926
  }
16898
- return glanceExtract(wc2);
16927
+ return glanceExtract(wc);
16899
16928
  }
16900
16929
  case "wait_for": {
16901
- if (!wc2) return "Error: No active tab";
16902
- return waitForCondition(wc2, args);
16930
+ if (!wc) return "Error: No active tab";
16931
+ return waitForCondition(wc, args);
16903
16932
  }
16904
16933
  case "wait_for_navigation": {
16905
- if (!wc2) return "Error: No active tab";
16934
+ if (!wc) return "Error: No active tab";
16906
16935
  const timeout = typeof args.timeoutMs === "number" ? args.timeoutMs : 1e4;
16907
- const beforeUrl = wc2.getURL();
16908
- if (wc2.isLoading()) {
16936
+ const beforeUrl = wc.getURL();
16937
+ if (wc.isLoading()) {
16909
16938
  await new Promise((resolve) => {
16910
16939
  const timer = setTimeout(resolve, timeout);
16911
- wc2.once("did-stop-loading", () => {
16940
+ wc.once("did-stop-loading", () => {
16912
16941
  clearTimeout(timer);
16913
16942
  resolve();
16914
16943
  });
@@ -16922,19 +16951,19 @@ ${truncated}`;
16922
16951
  },
16923
16952
  Math.min(timeout, 2e3)
16924
16953
  );
16925
- wc2.once("did-start-loading", () => {
16954
+ wc.once("did-start-loading", () => {
16926
16955
  navigated = true;
16927
16956
  clearTimeout(timer);
16928
16957
  const loadTimer = setTimeout(resolve, timeout);
16929
- wc2.once("did-stop-loading", () => {
16958
+ wc.once("did-stop-loading", () => {
16930
16959
  clearTimeout(loadTimer);
16931
16960
  resolve();
16932
16961
  });
16933
16962
  });
16934
16963
  });
16935
16964
  }
16936
- const afterUrl = wc2.getURL();
16937
- const title = wc2.getTitle();
16965
+ const afterUrl = wc.getURL();
16966
+ const title = wc.getTitle();
16938
16967
  if (afterUrl !== beforeUrl) {
16939
16968
  return `Navigation complete: ${title} (${afterUrl})`;
16940
16969
  }
@@ -17052,8 +17081,8 @@ ${truncated}`;
17052
17081
  );
17053
17082
  }
17054
17083
  case "save_bookmark": {
17055
- const resolvedSelector = wc2 && (typeof args.index === "number" || typeof args.selector === "string") ? await resolveSelector(wc2, args.index, args.selector) : null;
17056
- const source = await resolveBookmarkSourceDraft(wc2, {
17084
+ const resolvedSelector = wc && (typeof args.index === "number" || typeof args.selector === "string") ? await resolveSelector(wc, args.index, args.selector) : null;
17085
+ const source = await resolveBookmarkSourceDraft(wc, {
17057
17086
  explicitUrl: args.url,
17058
17087
  explicitTitle: args.title,
17059
17088
  resolvedSelector
@@ -17096,8 +17125,8 @@ ${truncated}`;
17096
17125
  if (target.error) return target.error;
17097
17126
  const bookmarkId = typeof args.bookmarkId === "string" ? args.bookmarkId.trim() : "";
17098
17127
  const note = typeof args.note === "string" && args.note.trim() ? args.note.trim() : void 0;
17099
- const resolvedSelector = wc2 && (typeof args.index === "number" || typeof args.selector === "string") ? await resolveSelector(wc2, args.index, args.selector) : null;
17100
- const source = await resolveBookmarkSourceDraft(wc2, {
17128
+ const resolvedSelector = wc && (typeof args.index === "number" || typeof args.selector === "string") ? await resolveSelector(wc, args.index, args.selector) : null;
17129
+ const source = await resolveBookmarkSourceDraft(wc, {
17101
17130
  explicitUrl: args.url,
17102
17131
  explicitTitle: args.title,
17103
17132
  resolvedSelector
@@ -17144,8 +17173,8 @@ ${truncated}`;
17144
17173
  if (target.error) return target.error;
17145
17174
  const bookmarkId = typeof args.bookmarkId === "string" ? args.bookmarkId.trim() : "";
17146
17175
  const note = typeof args.note === "string" && args.note.trim() ? args.note.trim() : void 0;
17147
- const resolvedSelector = wc2 && (typeof args.index === "number" || typeof args.selector === "string") ? await resolveSelector(wc2, args.index, args.selector) : null;
17148
- const source = await resolveBookmarkSourceDraft(wc2, {
17176
+ const resolvedSelector = wc && (typeof args.index === "number" || typeof args.selector === "string") ? await resolveSelector(wc, args.index, args.selector) : null;
17177
+ const source = await resolveBookmarkSourceDraft(wc, {
17149
17178
  explicitUrl: args.url,
17150
17179
  explicitTitle: args.title,
17151
17180
  resolvedSelector
@@ -17194,7 +17223,7 @@ ${truncated}`;
17194
17223
  return formatDeadLinkMessage(bookmark.title, validation);
17195
17224
  }
17196
17225
  const openInNewTab = Boolean(args.newTab);
17197
- if (openInNewTab || !tabId || !wc2) {
17226
+ if (openInNewTab || !tabId || !wc) {
17198
17227
  const createdId = ctx.tabManager.createTab(bookmark.url);
17199
17228
  const created = ctx.tabManager.getActiveTab();
17200
17229
  if (created) {
@@ -17203,15 +17232,15 @@ ${truncated}`;
17203
17232
  return `Opened bookmark "${bookmark.title}" in new tab ${createdId}`;
17204
17233
  }
17205
17234
  ctx.tabManager.navigateTab(tabId, bookmark.url);
17206
- await waitForLoad(wc2);
17235
+ await waitForLoad(wc);
17207
17236
  return `Opened bookmark "${bookmark.title}" in current tab`;
17208
17237
  }
17209
17238
  case "highlight": {
17210
- if (!wc2) return "Error: No active tab";
17211
- const selector = await resolveSelector(wc2, args.index, args.selector);
17239
+ if (!wc) return "Error: No active tab";
17240
+ const selector = await resolveSelector(wc, args.index, args.selector);
17212
17241
  const highlightColor = args.color || "yellow";
17213
17242
  const highlightText = normalizeLooseString(args.text);
17214
- const url = wc2.getURL();
17243
+ const url = wc.getURL();
17215
17244
  if (url && url !== "about:blank") {
17216
17245
  addHighlight(
17217
17246
  url,
@@ -17223,7 +17252,7 @@ ${truncated}`;
17223
17252
  );
17224
17253
  }
17225
17254
  return highlightOnPage(
17226
- wc2,
17255
+ wc,
17227
17256
  selector,
17228
17257
  highlightText,
17229
17258
  args.label,
@@ -17232,8 +17261,8 @@ ${truncated}`;
17232
17261
  );
17233
17262
  }
17234
17263
  case "clear_highlights": {
17235
- if (!wc2) return "Error: No active tab";
17236
- return clearHighlights(wc2);
17264
+ if (!wc) return "Error: No active tab";
17265
+ return clearHighlights(wc);
17237
17266
  }
17238
17267
  // --- Speedee System ---
17239
17268
  case "flow_start": {
@@ -17241,7 +17270,7 @@ ${truncated}`;
17241
17270
  const steps = coerceStringArray(args.steps) ?? [];
17242
17271
  if (!goal || steps.length === 0)
17243
17272
  return "Error: goal and steps are required";
17244
- const flow = ctx.runtime.startFlow(goal, steps, wc2?.getURL());
17273
+ const flow = ctx.runtime.startFlow(goal, steps, wc?.getURL());
17245
17274
  return `Flow started: ${flow.goal}
17246
17275
  ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`;
17247
17276
  }
@@ -17267,10 +17296,10 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
17267
17296
  return `Undid action: ${undone}. Browser restored to state before that action.`;
17268
17297
  }
17269
17298
  case "suggest": {
17270
- if (!wc2) return "No active tab. Use navigate to open a page.";
17299
+ if (!wc) return "No active tab. Use navigate to open a page.";
17271
17300
  let page;
17272
17301
  try {
17273
- page = await extractContent(wc2);
17302
+ page = await extractContent(wc);
17274
17303
  } catch (err) {
17275
17304
  logger$b.warn("Failed to extract content for suggest:", err);
17276
17305
  return "Could not read page. Try navigate to a working URL.";
@@ -17368,18 +17397,18 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
17368
17397
  return suggestions.join("\n");
17369
17398
  }
17370
17399
  case "fill_form": {
17371
- if (!wc2) return "Error: No active tab";
17400
+ if (!wc) return "Error: No active tab";
17372
17401
  const fields = Array.isArray(args.fields) ? args.fields : [];
17373
17402
  if (fields.length === 0) return "Error: No fields provided";
17374
- const fillResults = await fillFormFields(wc2, fields);
17403
+ const fillResults = await fillFormFields(wc, fields);
17375
17404
  const results = fillResults.map((item) => item.result);
17376
17405
  if (args.submit) {
17377
17406
  const firstSel = fillResults.find((item) => item.selector)?.selector ?? null;
17378
17407
  if (firstSel) {
17379
- const beforeUrl = wc2.getURL();
17380
- const submitResult = await submitForm(wc2, { selector: firstSel });
17381
- await waitForPotentialNavigation(wc2, beforeUrl);
17382
- const afterUrl = wc2.getURL();
17408
+ const beforeUrl = wc.getURL();
17409
+ const submitResult = await submitForm(wc, { selector: firstSel });
17410
+ await waitForPotentialNavigation(wc, beforeUrl);
17411
+ const afterUrl = wc.getURL();
17383
17412
  results.push(
17384
17413
  afterUrl !== beforeUrl ? `Submitted → ${afterUrl}` : submitResult
17385
17414
  );
@@ -17389,16 +17418,16 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
17389
17418
  ${results.join("\n")}`;
17390
17419
  }
17391
17420
  case "login": {
17392
- if (!wc2) return "Error: No active tab";
17421
+ if (!wc) return "Error: No active tab";
17393
17422
  const steps = [];
17394
17423
  if (typeof args.url === "string" && args.url.trim()) {
17395
17424
  const id = ctx.tabManager.getActiveTabId();
17396
17425
  ctx.tabManager.navigateTab(id, args.url);
17397
- await waitForLoad(wc2);
17398
- steps.push(`Navigated to ${wc2.getURL()}`);
17426
+ await waitForLoad(wc);
17427
+ steps.push(`Navigated to ${wc.getURL()}`);
17399
17428
  }
17400
17429
  const userSel = args.username_selector || await executePageScript(
17401
- wc2,
17430
+ wc,
17402
17431
  `
17403
17432
  (function() {
17404
17433
  var el = document.querySelector('input[type="email"], input[name="email"], input[name="username"], input[name="user"], input[autocomplete="username"], input[autocomplete="email"], input[type="text"]:not([name="search"]):not([name="q"])');
@@ -17412,7 +17441,7 @@ ${results.join("\n")}`;
17412
17441
  if (!userSel)
17413
17442
  return "Error: Could not find username/email field. Try providing username_selector.";
17414
17443
  const passSel = args.password_selector || await executePageScript(
17415
- wc2,
17444
+ wc,
17416
17445
  `
17417
17446
  (function() {
17418
17447
  var el = document.querySelector('input[type="password"]');
@@ -17426,23 +17455,23 @@ ${results.join("\n")}`;
17426
17455
  if (!passSel)
17427
17456
  return "Error: Could not find password field. Try providing password_selector.";
17428
17457
  const userResult = await setElementValue(
17429
- wc2,
17458
+ wc,
17430
17459
  userSel,
17431
17460
  String(args.username || "")
17432
17461
  );
17433
17462
  steps.push(userResult);
17434
17463
  const passResult = await setElementValue(
17435
- wc2,
17464
+ wc,
17436
17465
  passSel,
17437
17466
  String(args.password || "")
17438
17467
  );
17439
17468
  steps.push(passResult);
17440
- const beforeUrl = wc2.getURL();
17469
+ const beforeUrl = wc.getURL();
17441
17470
  if (args.submit_selector) {
17442
- await clickResolvedSelector(wc2, args.submit_selector);
17471
+ await clickResolvedSelector(wc, args.submit_selector);
17443
17472
  } else {
17444
17473
  const clicked = await executePageScript(
17445
- wc2,
17474
+ wc,
17446
17475
  `
17447
17476
  (function() {
17448
17477
  var btn = document.querySelector('button[type="submit"], input[type="submit"], form button:not([type="button"])');
@@ -17462,8 +17491,8 @@ ${results.join("\n")}`;
17462
17491
  if (!clicked)
17463
17492
  return steps.join("\n") + "\nWarning: Could not find submit button. Credentials filled but form not submitted.";
17464
17493
  }
17465
- await waitForPotentialNavigation(wc2, beforeUrl);
17466
- const afterUrl = wc2.getURL();
17494
+ await waitForPotentialNavigation(wc, beforeUrl);
17495
+ const afterUrl = wc.getURL();
17467
17496
  steps.push(
17468
17497
  afterUrl !== beforeUrl ? `Submitted → ${afterUrl}` : "Form submitted (same page)"
17469
17498
  );
@@ -17471,18 +17500,18 @@ ${results.join("\n")}`;
17471
17500
  ${steps.join("\n")}`;
17472
17501
  }
17473
17502
  case "search": {
17474
- if (!wc2) return "Error: No active tab";
17475
- return searchPage(wc2, args);
17503
+ if (!wc) return "Error: No active tab";
17504
+ return searchPage(wc, args);
17476
17505
  }
17477
17506
  case "paginate": {
17478
- if (!wc2) return "Error: No active tab";
17479
- const beforeUrl = wc2.getURL();
17507
+ if (!wc) return "Error: No active tab";
17508
+ const beforeUrl = wc.getURL();
17480
17509
  if (args.selector) {
17481
- return clickResolvedSelector(wc2, args.selector);
17510
+ return clickResolvedSelector(wc, args.selector);
17482
17511
  }
17483
17512
  const isNext = args.direction === "next";
17484
17513
  const clicked = await executePageScript(
17485
- wc2,
17514
+ wc,
17486
17515
  `
17487
17516
  (function() {
17488
17517
  var patterns = ${isNext ? '["next", "Next", "›", "»", "→", ">", "Next Page", "Load More"]' : '["prev", "Prev", "Previous", "‹", "«", "←", "<", "Previous Page"]'};
@@ -17512,13 +17541,13 @@ ${steps.join("\n")}`;
17512
17541
  }
17513
17542
  if (!clicked)
17514
17543
  return `Error: Could not find ${args.direction} pagination control. Try providing a selector.`;
17515
- await waitForPotentialNavigation(wc2, beforeUrl);
17516
- const afterUrl = wc2.getURL();
17544
+ await waitForPotentialNavigation(wc, beforeUrl);
17545
+ const afterUrl = wc.getURL();
17517
17546
  return afterUrl !== beforeUrl ? `Paginated ${args.direction} → ${afterUrl}` : `Clicked ${args.direction} (page may have updated dynamically)`;
17518
17547
  }
17519
17548
  case "accept_cookies": {
17520
- if (!wc2) return "Error: No active tab";
17521
- const dismissed = await tryAcceptCookiesQuickly(wc2);
17549
+ if (!wc) return "Error: No active tab";
17550
+ const dismissed = await tryAcceptCookiesQuickly(wc);
17522
17551
  if (dismissed === PAGE_SCRIPT_TIMEOUT) {
17523
17552
  return pageBusyError("accept_cookies");
17524
17553
  }
@@ -17526,9 +17555,9 @@ ${steps.join("\n")}`;
17526
17555
  return "No cookie consent banner detected. Try dismiss_popup for other overlays.";
17527
17556
  }
17528
17557
  case "extract_table": {
17529
- if (!wc2) return "Error: No active tab";
17530
- const selector = args.selector ? args.selector : args.index != null ? await resolveSelector(wc2, args.index, void 0) : null;
17531
- const tableJson = await wc2.executeJavaScript(`
17558
+ if (!wc) return "Error: No active tab";
17559
+ const selector = args.selector ? args.selector : args.index != null ? await resolveSelector(wc, args.index, void 0) : null;
17560
+ const tableJson = await wc.executeJavaScript(`
17532
17561
  (function() {
17533
17562
  var table = ${selector ? `document.querySelector(${JSON.stringify(selector)})` : "document.querySelector('table')"};
17534
17563
  if (!table) return null;
@@ -17577,16 +17606,16 @@ ${JSON.stringify(tableJson, null, 2)}`;
17577
17606
  return lines.join("\n");
17578
17607
  }
17579
17608
  case "scroll_to_element": {
17580
- if (!wc2) return "Error: No active tab";
17609
+ if (!wc) return "Error: No active tab";
17581
17610
  let sel = null;
17582
17611
  const textTarget = typeof args.text === "string" && args.text.trim() ? args.text.trim() : "";
17583
17612
  if (textTarget) {
17584
17613
  if (isInvalidTextTargetQuery(textTarget)) {
17585
17614
  return `Error: "${textTarget}" looks like HTML or markup, not visible page text. Use a section title or element index instead.`;
17586
17615
  }
17587
- sel = await resolveTargetByText(wc2, textTarget, "context");
17616
+ sel = await resolveTargetByText(wc, textTarget, "context");
17588
17617
  } else {
17589
- sel = await resolveSelector(wc2, args.index, args.selector);
17618
+ sel = await resolveSelector(wc, args.index, args.selector);
17590
17619
  }
17591
17620
  if (sel === PAGE_SCRIPT_TIMEOUT) return pageBusyError("scroll_to_element");
17592
17621
  if (!sel) {
@@ -17595,7 +17624,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
17595
17624
  const block = args.position === "top" ? "start" : args.position === "bottom" ? "end" : "center";
17596
17625
  if (sel.startsWith("__vessel_idx:")) {
17597
17626
  const idx = Number(sel.slice("__vessel_idx:".length));
17598
- return wc2.executeJavaScript(`
17627
+ return wc.executeJavaScript(`
17599
17628
  (function() {
17600
17629
  var el = window.__vessel?.interactByIndex && Object.values(window.__vessel)[2];
17601
17630
  var ref = (function() { try { return document.querySelector('[data-vessel-idx="${idx}"]'); } catch(e) { return null; } })();
@@ -17606,7 +17635,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
17606
17635
  `);
17607
17636
  }
17608
17637
  if (sel.includes(" >>> ")) {
17609
- return wc2.executeJavaScript(`
17638
+ return wc.executeJavaScript(`
17610
17639
  (function() {
17611
17640
  var el = window.__vessel?.resolveShadowSelector?.(${JSON.stringify(sel)});
17612
17641
  if (!el) return "Error: Shadow DOM element not found";
@@ -17615,7 +17644,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
17615
17644
  })()
17616
17645
  `);
17617
17646
  }
17618
- return wc2.executeJavaScript(`
17647
+ return wc.executeJavaScript(`
17619
17648
  (function() {
17620
17649
  var el = document.querySelector(${JSON.stringify(sel)});
17621
17650
  if (!el) return "Error: Element not found";
@@ -19162,7 +19191,7 @@ function getActiveTabSummary(tabManager) {
19162
19191
  async function getPostActionState(tabManager, name) {
19163
19192
  const tab = tabManager.getActiveTab();
19164
19193
  if (!tab) return "";
19165
- const wc2 = tab.view.webContents;
19194
+ const wc = tab.view.webContents;
19166
19195
  const navActions = [
19167
19196
  "navigate",
19168
19197
  "go_back",
@@ -19183,10 +19212,10 @@ async function getPostActionState(tabManager, name) {
19183
19212
  if (navActions.includes(name)) {
19184
19213
  let warning = "";
19185
19214
  try {
19186
- const page = await extractContent(wc2);
19215
+ const page = await extractContent(wc);
19187
19216
  const issue = getRecoverableAccessIssue(page);
19188
19217
  if (issue) {
19189
- const blockedUrl = wc2.getURL();
19218
+ const blockedUrl = wc.getURL();
19190
19219
  const canRecover = [
19191
19220
  "navigate",
19192
19221
  "open_bookmark",
@@ -19196,9 +19225,9 @@ async function getPostActionState(tabManager, name) {
19196
19225
  "press_key"
19197
19226
  ].includes(name) && tab.canGoBack();
19198
19227
  if (canRecover && tab.goBack()) {
19199
- await waitForLoad(wc2);
19228
+ await waitForLoad(wc);
19200
19229
  warning = `
19201
- [warning: ${issue.summary} ${issue.recommendation ?? ""} Automatically returned to ${wc2.getURL()} after landing on ${blockedUrl}.]`;
19230
+ [warning: ${issue.summary} ${issue.recommendation ?? ""} Automatically returned to ${wc.getURL()} after landing on ${blockedUrl}.]`;
19202
19231
  } else {
19203
19232
  warning = `
19204
19233
  [warning: ${issue.summary} ${issue.recommendation ?? ""}${tab.canGoBack() ? "" : " No previous page was available for automatic recovery."}]`;
@@ -19208,11 +19237,11 @@ async function getPostActionState(tabManager, name) {
19208
19237
  logger$8.warn("Failed to compute post-action state warning:", err);
19209
19238
  }
19210
19239
  return `${warning}
19211
- [state: url=${wc2.getURL()}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=${wc2.isLoading()}]`;
19240
+ [state: url=${wc.getURL()}, canGoBack=${tab.canGoBack()}, canGoForward=${tab.canGoForward()}, loading=${wc.isLoading()}]`;
19212
19241
  }
19213
19242
  if (interactActions.includes(name)) {
19214
19243
  return `
19215
- [state: url=${wc2.getURL()}, title=${JSON.stringify(wc2.getTitle() || "")}, tabId=${tabManager.getActiveTabId()}]`;
19244
+ [state: url=${wc.getURL()}, title=${JSON.stringify(wc.getTitle() || "")}, tabId=${tabManager.getActiveTabId()}]`;
19216
19245
  }
19217
19246
  if (tabActions.includes(name)) {
19218
19247
  const activeId = tabManager.getActiveTabId();
@@ -19240,13 +19269,13 @@ async function withAction(runtime2, tabManager, name, args, executor) {
19240
19269
  return asErrorTextResponse(getErrorMessage(error));
19241
19270
  }
19242
19271
  }
19243
- async function waitForConditionMcp(wc2, text, selector, timeoutMs) {
19272
+ async function waitForConditionMcp(wc, text, selector, timeoutMs) {
19244
19273
  const effectiveTimeout = Math.max(250, timeoutMs || 5e3);
19245
19274
  const expectedText = (text || "").trim();
19246
19275
  const expectedSelector = (selector || "").trim();
19247
19276
  const startedAt = Date.now();
19248
19277
  const result = await waitForConditionDirect(
19249
- wc2,
19278
+ wc,
19250
19279
  expectedText,
19251
19280
  expectedSelector,
19252
19281
  effectiveTimeout
@@ -19297,7 +19326,7 @@ async function waitForConditionMcp(wc2, text, selector, timeoutMs) {
19297
19326
  timeout_ms: effectiveTimeout
19298
19327
  };
19299
19328
  if (expectedSelector) {
19300
- const diagnostic = await wc2.executeJavaScript(`
19329
+ const diagnostic = await wc.executeJavaScript(`
19301
19330
  (function() {
19302
19331
  try {
19303
19332
  var count = document.querySelectorAll(${JSON.stringify(expectedSelector)}).length;
@@ -19388,10 +19417,10 @@ function registerTools(server, tabManager, runtime2) {
19388
19417
  let pageTitle = "";
19389
19418
  if (activeTab) {
19390
19419
  try {
19391
- const wc2 = activeTab.view.webContents;
19392
- pageUrl = wc2.getURL();
19393
- pageTitle = wc2.getTitle();
19394
- const page = await extractContent(wc2);
19420
+ const wc = activeTab.view.webContents;
19421
+ pageUrl = wc.getURL();
19422
+ pageTitle = wc.getTitle();
19423
+ const page = await extractContent(wc);
19395
19424
  pageType = detectPageType(page);
19396
19425
  } catch (err) {
19397
19426
  logger$8.warn("Failed to detect page type for tool scoring, falling back to GENERAL:", err);
@@ -19511,13 +19540,13 @@ function registerTools(server, tabManager, runtime2) {
19511
19540
  "visible_only",
19512
19541
  "results_only"
19513
19542
  ];
19514
- async function buildExtractResponse(pageContent, mode, adBlockingEnabled, wc2) {
19543
+ async function buildExtractResponse(pageContent, mode, adBlockingEnabled, wc) {
19515
19544
  const adBlockLine = `**Ad Blocking:** ${adBlockingEnabled ? "On" : "Off"}`;
19516
19545
  const savedHighlights = getHighlightsForUrl(
19517
19546
  pageContent.url
19518
19547
  );
19519
- const liveSelectionSection = wc2 ? formatLiveSelectionSection(
19520
- await captureLiveHighlightSnapshot(wc2, savedHighlights)
19548
+ const liveSelectionSection = wc ? formatLiveSelectionSection(
19549
+ await captureLiveHighlightSnapshot(wc, savedHighlights)
19521
19550
  ) : null;
19522
19551
  const livePrefix = liveSelectionSection ? `
19523
19552
 
@@ -19838,12 +19867,12 @@ ${buildScopedContext(pageContent, mode)}`;
19838
19867
  "click",
19839
19868
  { index, selector },
19840
19869
  async () => {
19841
- const wc2 = tab.view.webContents;
19842
- const resolvedSelector = typeof selector === "string" && selector.trim() ? await resolveSelector(wc2, void 0, selector) : typeof index === "number" ? `__vessel_idx:${index}` : await resolveSelector(wc2, index, selector);
19870
+ const wc = tab.view.webContents;
19871
+ const resolvedSelector = typeof selector === "string" && selector.trim() ? await resolveSelector(wc, void 0, selector) : typeof index === "number" ? `__vessel_idx:${index}` : await resolveSelector(wc, index, selector);
19843
19872
  if (!resolvedSelector) {
19844
19873
  return "Error: No index or selector provided";
19845
19874
  }
19846
- return clickResolvedSelector(wc2, resolvedSelector);
19875
+ return clickResolvedSelector(wc, resolvedSelector);
19847
19876
  }
19848
19877
  );
19849
19878
  }
@@ -19867,12 +19896,12 @@ ${buildScopedContext(pageContent, mode)}`;
19867
19896
  "hover",
19868
19897
  { index, selector },
19869
19898
  async () => {
19870
- const wc2 = tab.view.webContents;
19871
- const resolvedSelector = await resolveSelector(wc2, index, selector);
19899
+ const wc = tab.view.webContents;
19900
+ const resolvedSelector = await resolveSelector(wc, index, selector);
19872
19901
  if (!resolvedSelector) {
19873
19902
  return "Error: No index or selector provided";
19874
19903
  }
19875
- return hoverElement(wc2, resolvedSelector);
19904
+ return hoverElement(wc, resolvedSelector);
19876
19905
  }
19877
19906
  );
19878
19907
  }
@@ -19896,12 +19925,12 @@ ${buildScopedContext(pageContent, mode)}`;
19896
19925
  "focus",
19897
19926
  { index, selector },
19898
19927
  async () => {
19899
- const wc2 = tab.view.webContents;
19900
- const resolvedSelector = await resolveSelector(wc2, index, selector);
19928
+ const wc = tab.view.webContents;
19929
+ const resolvedSelector = await resolveSelector(wc, index, selector);
19901
19930
  if (!resolvedSelector) {
19902
19931
  return "Error: No index or selector provided";
19903
19932
  }
19904
- return focusElement(wc2, resolvedSelector);
19933
+ return focusElement(wc, resolvedSelector);
19905
19934
  }
19906
19935
  );
19907
19936
  }
@@ -19919,12 +19948,12 @@ ${buildScopedContext(pageContent, mode)}`;
19919
19948
  async ({ index, selector }) => {
19920
19949
  const tab = tabManager.getActiveTab();
19921
19950
  if (!tab) return asNoActiveTabResponse();
19922
- const wc2 = tab.view.webContents;
19923
- const resolvedSelector = await resolveSelector(wc2, index, selector);
19951
+ const wc = tab.view.webContents;
19952
+ const resolvedSelector = await resolveSelector(wc, index, selector);
19924
19953
  if (!resolvedSelector) {
19925
19954
  return asErrorTextResponse("No index or selector provided");
19926
19955
  }
19927
- const result = await wc2.executeJavaScript(`
19956
+ const result = await wc.executeJavaScript(`
19928
19957
  (function() {
19929
19958
  try {
19930
19959
  const el = document.querySelector(${JSON.stringify(resolvedSelector)});
@@ -20131,12 +20160,12 @@ ${buildScopedContext(pageContent, mode)}`;
20131
20160
  "press_key",
20132
20161
  { key, index, selector },
20133
20162
  async () => {
20134
- const wc2 = tab.view.webContents;
20135
- const beforeUrl = wc2.getURL();
20136
- const result = await pressKeyDirect(wc2, key, index, selector);
20163
+ const wc = tab.view.webContents;
20164
+ const beforeUrl = wc.getURL();
20165
+ const result = await pressKeyDirect(wc, key, index, selector);
20137
20166
  if (key === "Enter") {
20138
- await waitForPotentialNavigation$1(wc2, beforeUrl, 3e3);
20139
- const afterUrl = wc2.getURL();
20167
+ await waitForPotentialNavigation$1(wc, beforeUrl, 3e3);
20168
+ const afterUrl = wc.getURL();
20140
20169
  if (afterUrl !== beforeUrl) {
20141
20170
  return `${result} -> ${afterUrl}`;
20142
20171
  }
@@ -20618,10 +20647,10 @@ To analyze visually, call vision_analyze with image_url="${screenshotPath}"`
20618
20647
  color
20619
20648
  },
20620
20649
  async () => {
20621
- const wc2 = tab.view.webContents;
20622
- const resolvedSelector = await resolveSelector(wc2, index, selector);
20650
+ const wc = tab.view.webContents;
20651
+ const resolvedSelector = await resolveSelector(wc, index, selector);
20623
20652
  const result = await highlightOnPage(
20624
- wc2,
20653
+ wc,
20625
20654
  resolvedSelector,
20626
20655
  normalizedText,
20627
20656
  label,
@@ -20629,7 +20658,7 @@ To analyze visually, call vision_analyze with image_url="${screenshotPath}"`
20629
20658
  color
20630
20659
  );
20631
20660
  if (persist && !durationMs && !result.startsWith("Error") && !result.includes("not found")) {
20632
- const url = normalizeUrl$1(wc2.getURL());
20661
+ const url = normalizeUrl$1(wc.getURL());
20633
20662
  addHighlight(
20634
20663
  url,
20635
20664
  resolvedSelector ?? void 0,
@@ -20659,10 +20688,10 @@ To analyze visually, call vision_analyze with image_url="${screenshotPath}"`
20659
20688
  "clear_highlights",
20660
20689
  {},
20661
20690
  async () => {
20662
- const wc2 = tab.view.webContents;
20663
- const url = normalizeUrl$1(wc2.getURL());
20691
+ const wc = tab.view.webContents;
20692
+ const url = normalizeUrl$1(wc.getURL());
20664
20693
  clearHighlightsForUrl(url);
20665
- return clearHighlights(wc2);
20694
+ return clearHighlights(wc);
20666
20695
  }
20667
20696
  );
20668
20697
  }
@@ -20780,12 +20809,12 @@ ${JSON.stringify(otherHighlights, null, 2)}`
20780
20809
  }
20781
20810
  const tab = tabManager.getTab(tabState.id);
20782
20811
  if (!tab) continue;
20783
- const wc2 = tab.view.webContents;
20784
- await clearHighlights(wc2);
20812
+ const wc = tab.view.webContents;
20813
+ await clearHighlights(wc);
20785
20814
  for (const h of remaining) {
20786
20815
  if (!h.selector && !h.text) continue;
20787
20816
  void highlightOnPage(
20788
- wc2,
20817
+ wc,
20789
20818
  h.selector ?? null,
20790
20819
  h.text,
20791
20820
  h.label,
@@ -21635,10 +21664,10 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
21635
21664
  return asTextResponse(
21636
21665
  "No active tab. Use navigate to open a page."
21637
21666
  );
21638
- const wc2 = tab.view.webContents;
21667
+ const wc = tab.view.webContents;
21639
21668
  let page;
21640
21669
  try {
21641
- page = await extractContent(wc2);
21670
+ page = await extractContent(wc);
21642
21671
  } catch (err) {
21643
21672
  logger$8.warn("Failed to extract page while generating suggestions:", err);
21644
21673
  return asTextResponse(
@@ -21754,16 +21783,16 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
21754
21783
  "fill_form",
21755
21784
  { fieldCount: fields.length, submit },
21756
21785
  async () => {
21757
- const wc2 = tab.view.webContents;
21758
- const fillResults = await fillFormFields(wc2, fields);
21786
+ const wc = tab.view.webContents;
21787
+ const fillResults = await fillFormFields(wc, fields);
21759
21788
  const results = fillResults.map((item) => item.result);
21760
21789
  if (submit) {
21761
21790
  const firstSel = fillResults.find((item) => item.selector)?.selector ?? null;
21762
21791
  if (firstSel) {
21763
- const beforeUrl = wc2.getURL();
21764
- const submitResult = await submitFormDirect(wc2, void 0, firstSel);
21765
- await waitForPotentialNavigation$1(wc2, beforeUrl);
21766
- const afterUrl = wc2.getURL();
21792
+ const beforeUrl = wc.getURL();
21793
+ const submitResult = await submitFormDirect(wc, void 0, firstSel);
21794
+ await waitForPotentialNavigation$1(wc, beforeUrl);
21795
+ const afterUrl = wc.getURL();
21767
21796
  results.push(
21768
21797
  afterUrl !== beforeUrl ? `Submitted → ${afterUrl}` : submitResult
21769
21798
  );
@@ -21811,15 +21840,15 @@ ${results.join("\n")}`;
21811
21840
  "login",
21812
21841
  { url, username: username.slice(0, 3) + "***" },
21813
21842
  async () => {
21814
- const wc2 = tab.view.webContents;
21843
+ const wc = tab.view.webContents;
21815
21844
  const steps = [];
21816
21845
  if (url) {
21817
21846
  const id = tabManager.getActiveTabId();
21818
21847
  tabManager.navigateTab(id, url);
21819
- await waitForLoad(wc2);
21820
- steps.push(`Navigated to ${wc2.getURL()}`);
21848
+ await waitForLoad(wc);
21849
+ steps.push(`Navigated to ${wc.getURL()}`);
21821
21850
  }
21822
- const userSel = username_selector || await wc2.executeJavaScript(`
21851
+ const userSel = username_selector || await wc.executeJavaScript(`
21823
21852
  (function() {
21824
21853
  var el = document.querySelector('input[type="email"], input[name="email"], input[name="username"], input[name="user"], input[autocomplete="username"], input[autocomplete="email"], input[type="text"]:not([name="search"]):not([name="q"])');
21825
21854
  return el ? (el.id ? '#' + CSS.escape(el.id) : el.name ? 'input[name="' + el.name + '"]' : null) : null;
@@ -21827,7 +21856,7 @@ ${results.join("\n")}`;
21827
21856
  `);
21828
21857
  if (!userSel)
21829
21858
  return "Error: Could not find username/email field. Try providing username_selector.";
21830
- const passSel = password_selector || await wc2.executeJavaScript(`
21859
+ const passSel = password_selector || await wc.executeJavaScript(`
21831
21860
  (function() {
21832
21861
  var el = document.querySelector('input[type="password"]');
21833
21862
  return el ? (el.id ? '#' + CSS.escape(el.id) : el.name ? 'input[name="' + el.name + '"]' : null) : null;
@@ -21835,15 +21864,15 @@ ${results.join("\n")}`;
21835
21864
  `);
21836
21865
  if (!passSel)
21837
21866
  return "Error: Could not find password field. Try providing password_selector.";
21838
- const userResult = await setElementValue(wc2, userSel, username);
21867
+ const userResult = await setElementValue(wc, userSel, username);
21839
21868
  steps.push(userResult);
21840
- const passResult = await setElementValue(wc2, passSel, password);
21869
+ const passResult = await setElementValue(wc, passSel, password);
21841
21870
  steps.push(passResult);
21842
- const beforeUrl = wc2.getURL();
21871
+ const beforeUrl = wc.getURL();
21843
21872
  if (submit_selector) {
21844
- await clickResolvedSelector(wc2, submit_selector);
21873
+ await clickResolvedSelector(wc, submit_selector);
21845
21874
  } else {
21846
- const clicked = await wc2.executeJavaScript(`
21875
+ const clicked = await wc.executeJavaScript(`
21847
21876
  (function() {
21848
21877
  var btn = document.querySelector('button[type="submit"], input[type="submit"], form button:not([type="button"])');
21849
21878
  if (btn) { btn.click(); return true; }
@@ -21855,8 +21884,8 @@ ${results.join("\n")}`;
21855
21884
  if (!clicked)
21856
21885
  return steps.join("\n") + "\nWarning: Could not find submit button. Credentials filled but form not submitted.";
21857
21886
  }
21858
- await waitForPotentialNavigation$1(wc2, beforeUrl);
21859
- const afterUrl = wc2.getURL();
21887
+ await waitForPotentialNavigation$1(wc, beforeUrl);
21888
+ const afterUrl = wc.getURL();
21860
21889
  steps.push(
21861
21890
  afterUrl !== beforeUrl ? `Submitted → ${afterUrl}` : "Form submitted (same page)"
21862
21891
  );
@@ -21912,8 +21941,8 @@ ${steps.join("\n")}`;
21912
21941
  );
21913
21942
  }
21914
21943
  return withAction(runtime2, tabManager, "search", { query }, async () => {
21915
- const wc2 = tab.view.webContents;
21916
- const searchSel = selector || await wc2.executeJavaScript(`
21944
+ const wc = tab.view.webContents;
21945
+ const searchSel = selector || await wc.executeJavaScript(`
21917
21946
  (function() {
21918
21947
  var el = document.querySelector('input[type="search"], input[name="q"], input[name="query"], input[name="search"], input[role="searchbox"], input[aria-label*="search" i], input[placeholder*="search" i]');
21919
21948
  if (!el) {
@@ -21931,20 +21960,20 @@ ${steps.join("\n")}`;
21931
21960
  `);
21932
21961
  if (!searchSel)
21933
21962
  return "Error: Could not find search input. Try providing a selector.";
21934
- await setElementValue(wc2, searchSel, query);
21935
- await wc2.executeJavaScript(`
21963
+ await setElementValue(wc, searchSel, query);
21964
+ await wc.executeJavaScript(`
21936
21965
  (function() {
21937
21966
  var el = document.querySelector(${JSON.stringify(searchSel)});
21938
21967
  if (el) el.focus();
21939
21968
  })()
21940
21969
  `);
21941
21970
  await new Promise((r) => setTimeout(r, 50));
21942
- const beforeUrl = wc2.getURL();
21943
- wc2.sendInputEvent({ type: "keyDown", keyCode: "Return" });
21971
+ const beforeUrl = wc.getURL();
21972
+ wc.sendInputEvent({ type: "keyDown", keyCode: "Return" });
21944
21973
  await new Promise((r) => setTimeout(r, 16));
21945
- wc2.sendInputEvent({ type: "keyUp", keyCode: "Return" });
21946
- await waitForPotentialNavigation$1(wc2, beforeUrl);
21947
- const afterUrl = wc2.getURL();
21974
+ wc.sendInputEvent({ type: "keyUp", keyCode: "Return" });
21975
+ await waitForPotentialNavigation$1(wc, beforeUrl);
21976
+ const afterUrl = wc.getURL();
21948
21977
  return afterUrl !== beforeUrl ? `Searched "${query}" → ${afterUrl}` : `Searched "${query}" (same page — results may have loaded dynamically)`;
21949
21978
  });
21950
21979
  }
@@ -21970,13 +21999,13 @@ ${steps.join("\n")}`;
21970
21999
  "paginate",
21971
22000
  { direction },
21972
22001
  async () => {
21973
- const wc2 = tab.view.webContents;
21974
- const beforeUrl = wc2.getURL();
22002
+ const wc = tab.view.webContents;
22003
+ const beforeUrl = wc.getURL();
21975
22004
  if (selector) {
21976
- return clickResolvedSelector(wc2, selector);
22005
+ return clickResolvedSelector(wc, selector);
21977
22006
  }
21978
22007
  const isNext = direction === "next";
21979
- const clicked = await wc2.executeJavaScript(`
22008
+ const clicked = await wc.executeJavaScript(`
21980
22009
  (function() {
21981
22010
  var patterns = ${isNext ? '["next", "Next", "›", "»", "→", ">", "Next Page", "Load More"]' : '["prev", "Prev", "Previous", "‹", "«", "←", "<", "Previous Page"]'};
21982
22011
  var links = document.querySelectorAll('a, button');
@@ -21998,8 +22027,8 @@ ${steps.join("\n")}`;
21998
22027
  `);
21999
22028
  if (!clicked)
22000
22029
  return `Error: Could not find ${direction} pagination control. Try providing a selector.`;
22001
- await waitForPotentialNavigation$1(wc2, beforeUrl);
22002
- const afterUrl = wc2.getURL();
22030
+ await waitForPotentialNavigation$1(wc, beforeUrl);
22031
+ const afterUrl = wc.getURL();
22003
22032
  return afterUrl !== beforeUrl ? `Paginated ${direction} → ${afterUrl}` : `Clicked ${direction} (page may have updated dynamically)`;
22004
22033
  }
22005
22034
  );
@@ -22021,8 +22050,8 @@ ${steps.join("\n")}`;
22021
22050
  "accept_cookies",
22022
22051
  {},
22023
22052
  async () => {
22024
- const wc2 = tab.view.webContents;
22025
- const dismissed = await wc2.executeJavaScript(`
22053
+ const wc = tab.view.webContents;
22054
+ const dismissed = await wc.executeJavaScript(`
22026
22055
  (function() {
22027
22056
  var selectors = [
22028
22057
  '#onetrust-accept-btn-handler',
@@ -22079,9 +22108,9 @@ ${steps.join("\n")}`;
22079
22108
  "extract_table",
22080
22109
  { index, selector: rawSelector },
22081
22110
  async () => {
22082
- const wc2 = tab.view.webContents;
22083
- const sel = rawSelector || (index != null ? await resolveSelector(wc2, index) : null);
22084
- const tableJson = await wc2.executeJavaScript(`
22111
+ const wc = tab.view.webContents;
22112
+ const sel = rawSelector || (index != null ? await resolveSelector(wc, index) : null);
22113
+ const tableJson = await wc.executeJavaScript(`
22085
22114
  (function() {
22086
22115
  var table = ${sel ? `document.querySelector(${JSON.stringify(sel)})` : "document.querySelector('table')"};
22087
22116
  if (!table) return null;
@@ -22134,13 +22163,13 @@ ${JSON.stringify(tableJson, null, 2)}`;
22134
22163
  "scroll_to_element",
22135
22164
  { index, selector: rawSelector, position },
22136
22165
  async () => {
22137
- const wc2 = tab.view.webContents;
22138
- const sel = rawSelector || (index != null ? await resolveSelector(wc2, index) : null);
22166
+ const wc = tab.view.webContents;
22167
+ const sel = rawSelector || (index != null ? await resolveSelector(wc, index) : null);
22139
22168
  if (!sel) return "Error: Provide an index or selector.";
22140
22169
  const block = position === "top" ? "start" : position === "bottom" ? "end" : "center";
22141
22170
  if (sel.startsWith("__vessel_idx:")) {
22142
22171
  const idx = Number(sel.slice("__vessel_idx:".length));
22143
- return wc2.executeJavaScript(`
22172
+ return wc.executeJavaScript(`
22144
22173
  (function() {
22145
22174
  var refs = window.__vessel;
22146
22175
  if (!refs || !refs.interactByIndex) return "Error: __vessel not available";
@@ -22153,7 +22182,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
22153
22182
  `);
22154
22183
  }
22155
22184
  if (sel.includes(" >>> ")) {
22156
- return wc2.executeJavaScript(`
22185
+ return wc.executeJavaScript(`
22157
22186
  (function() {
22158
22187
  var el = window.__vessel?.resolveShadowSelector?.(${JSON.stringify(sel)});
22159
22188
  if (!el) return "Error: Shadow DOM element not found";
@@ -22162,7 +22191,7 @@ ${JSON.stringify(tableJson, null, 2)}`;
22162
22191
  })()
22163
22192
  `);
22164
22193
  }
22165
- return wc2.executeJavaScript(`
22194
+ return wc.executeJavaScript(`
22166
22195
  (function() {
22167
22196
  var el = document.querySelector(${JSON.stringify(sel)});
22168
22197
  if (!el) return "Error: Element not found";
@@ -22192,13 +22221,13 @@ ${JSON.stringify(tableJson, null, 2)}`;
22192
22221
  "wait_for_navigation",
22193
22222
  { timeoutMs },
22194
22223
  async () => {
22195
- const wc2 = tab.view.webContents;
22224
+ const wc = tab.view.webContents;
22196
22225
  const timeout = timeoutMs || 1e4;
22197
- const beforeUrl = wc2.getURL();
22198
- if (wc2.isLoading()) {
22226
+ const beforeUrl = wc.getURL();
22227
+ if (wc.isLoading()) {
22199
22228
  await new Promise((resolve) => {
22200
22229
  const timer = setTimeout(resolve, timeout);
22201
- wc2.once("did-stop-loading", () => {
22230
+ wc.once("did-stop-loading", () => {
22202
22231
  clearTimeout(timer);
22203
22232
  resolve();
22204
22233
  });
@@ -22212,19 +22241,19 @@ ${JSON.stringify(tableJson, null, 2)}`;
22212
22241
  },
22213
22242
  Math.min(timeout, 2e3)
22214
22243
  );
22215
- wc2.once("did-start-loading", () => {
22244
+ wc.once("did-start-loading", () => {
22216
22245
  navigated = true;
22217
22246
  clearTimeout(timer);
22218
22247
  const loadTimer = setTimeout(resolve, timeout);
22219
- wc2.once("did-stop-loading", () => {
22248
+ wc.once("did-stop-loading", () => {
22220
22249
  clearTimeout(loadTimer);
22221
22250
  resolve();
22222
22251
  });
22223
22252
  });
22224
22253
  });
22225
22254
  }
22226
- const afterUrl = wc2.getURL();
22227
- const title = wc2.getTitle();
22255
+ const afterUrl = wc.getURL();
22256
+ const title = wc.getTitle();
22228
22257
  return afterUrl !== beforeUrl ? `Navigation complete: ${title} (${afterUrl})` : `Page loaded: ${title} (${afterUrl})`;
22229
22258
  }
22230
22259
  );
@@ -22310,7 +22339,7 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22310
22339
  }) => {
22311
22340
  const tab = tabManager.getActiveTab();
22312
22341
  if (!tab) return asNoActiveTabResponse();
22313
- const wc2 = tab.view.webContents;
22342
+ const wc = tab.view.webContents;
22314
22343
  let hostname;
22315
22344
  try {
22316
22345
  hostname = new URL(tab.state.url).hostname;
@@ -22356,13 +22385,13 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22356
22385
  }
22357
22386
  const results = [];
22358
22387
  if (username_index != null) {
22359
- const usernameResult = await wc2.executeJavaScript(
22388
+ const usernameResult = await wc.executeJavaScript(
22360
22389
  `window.__vessel?.interactByIndex?.(${username_index}, "value", ${JSON.stringify(creds.username)}) || "Error: interactByIndex not available"`
22361
22390
  );
22362
22391
  results.push(`Username: ${usernameResult}`);
22363
22392
  }
22364
22393
  if (password_index != null) {
22365
- const passwordResult = await wc2.executeJavaScript(
22394
+ const passwordResult = await wc.executeJavaScript(
22366
22395
  `window.__vessel?.interactByIndex?.(${password_index}, "value", ${JSON.stringify(creds.password)}) || "Error: interactByIndex not available"`
22367
22396
  );
22368
22397
  results.push(`Password: ${passwordResult.replace(/Typed into:.*/, "Typed into: [password field]")}`);
@@ -22370,7 +22399,7 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22370
22399
  recordUsage$1(match.id);
22371
22400
  trackVaultAction("login_fill");
22372
22401
  if (submit_after && submit_index != null) {
22373
- const submitResult = await wc2.executeJavaScript(
22402
+ const submitResult = await wc.executeJavaScript(
22374
22403
  `window.__vessel?.interactByIndex?.(${submit_index}, "click") || "Error: interactByIndex not available"`
22375
22404
  );
22376
22405
  results.push(`Submit: ${submitResult}`);
@@ -22404,7 +22433,7 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22404
22433
  async ({ credential_label, code_index, submit_after, submit_index }) => {
22405
22434
  const tab = tabManager.getActiveTab();
22406
22435
  if (!tab) return asNoActiveTabResponse();
22407
- const wc2 = tab.view.webContents;
22436
+ const wc = tab.view.webContents;
22408
22437
  let hostname;
22409
22438
  try {
22410
22439
  hostname = new URL(tab.state.url).hostname;
@@ -22449,14 +22478,14 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22449
22478
  );
22450
22479
  }
22451
22480
  const code = generateTotpCode(secret);
22452
- const fillResult = await wc2.executeJavaScript(
22481
+ const fillResult = await wc.executeJavaScript(
22453
22482
  `window.__vessel?.interactByIndex?.(${code_index}, "value", ${JSON.stringify(code)}) || "Error: interactByIndex not available"`
22454
22483
  );
22455
22484
  recordUsage$1(match.id);
22456
22485
  trackVaultAction("totp_fill");
22457
22486
  const results = [`2FA code filled: ${fillResult.replace(/Typed into:.*/, "Typed into: [2FA field]")}`];
22458
22487
  if (submit_after && submit_index != null) {
22459
- const submitResult = await wc2.executeJavaScript(
22488
+ const submitResult = await wc.executeJavaScript(
22460
22489
  `window.__vessel?.interactByIndex?.(${submit_index}, "click") || "Error: interactByIndex not available"`
22461
22490
  );
22462
22491
  results.push(`Submit: ${submitResult}`);
@@ -22582,22 +22611,22 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22582
22611
  if (!decrypted) {
22583
22612
  return asErrorTextResponse("Failed to decrypt password.");
22584
22613
  }
22585
- const wc2 = tab.view.webContents;
22614
+ const wc = tab.view.webContents;
22586
22615
  const results = [];
22587
22616
  if (username_index != null) {
22588
- const usernameResult = await wc2.executeJavaScript(
22617
+ const usernameResult = await wc.executeJavaScript(
22589
22618
  `window.__vessel?.interactByIndex?.(${username_index}, "value", ${JSON.stringify(entry.username)}) || "Error: interactByIndex not available"`
22590
22619
  );
22591
22620
  results.push(`Username filled: ${usernameResult.replace(/Typed into:.*/, "Typed into: [username field]")}`);
22592
22621
  }
22593
22622
  if (password_index != null) {
22594
- const passwordResult = await wc2.executeJavaScript(
22623
+ const passwordResult = await wc.executeJavaScript(
22595
22624
  `window.__vessel?.interactByIndex?.(${password_index}, "value", ${JSON.stringify(decrypted.password)}) || "Error: interactByIndex not available"`
22596
22625
  );
22597
22626
  results.push(`Password filled: ${passwordResult.replace(/Typed into:.*/, "Typed into: [password field]")}`);
22598
22627
  }
22599
22628
  if (submit_after && submit_index != null) {
22600
- const submitResult = await wc2.executeJavaScript(
22629
+ const submitResult = await wc.executeJavaScript(
22601
22630
  `window.__vessel?.interactByIndex?.(${submit_index}, "click") || "Error: interactByIndex not available"`
22602
22631
  );
22603
22632
  results.push(`Submit: ${submitResult}`);
@@ -22666,23 +22695,23 @@ Use vault_login to fill the login form. Credentials are filled directly — you
22666
22695
  }
22667
22696
  );
22668
22697
  }
22669
- function waitForLoadWithStatus(wc2, timeout = 1e4) {
22698
+ function waitForLoadWithStatus(wc, timeout = 1e4) {
22670
22699
  return new Promise((resolve) => {
22671
22700
  let httpStatus = null;
22672
22701
  const onNavigate = (_, _url, code) => {
22673
22702
  if (code > 0) httpStatus = code;
22674
22703
  };
22675
- wc2.on("did-navigate", onNavigate);
22704
+ wc.on("did-navigate", onNavigate);
22676
22705
  const finish = () => {
22677
- wc2.removeListener("did-navigate", onNavigate);
22706
+ wc.removeListener("did-navigate", onNavigate);
22678
22707
  resolve({ httpStatus });
22679
22708
  };
22680
- if (!wc2.isLoading()) {
22709
+ if (!wc.isLoading()) {
22681
22710
  finish();
22682
22711
  return;
22683
22712
  }
22684
22713
  const timer = setTimeout(finish, timeout);
22685
- wc2.once("did-stop-loading", () => {
22714
+ wc.once("did-stop-loading", () => {
22686
22715
  clearTimeout(timer);
22687
22716
  finish();
22688
22717
  });
@@ -22780,7 +22809,7 @@ function startMcpServer(tabManager, runtime2, port) {
22780
22809
  if (httpServer === server) {
22781
22810
  httpServer = null;
22782
22811
  }
22783
- finish(errorResult$1(message, {
22812
+ finish(errorResult(message, {
22784
22813
  configuredPort: port,
22785
22814
  activePort: null,
22786
22815
  endpoint: null,
@@ -22913,64 +22942,64 @@ async function installKitFromFile() {
22913
22942
  properties: ["openFile"]
22914
22943
  });
22915
22944
  if (canceled || filePaths.length === 0) {
22916
- return errorResult$1("canceled");
22945
+ return errorResult("canceled");
22917
22946
  }
22918
22947
  let raw;
22919
22948
  try {
22920
22949
  raw = fs$1.readFileSync(filePaths[0], "utf-8");
22921
22950
  } catch {
22922
- return errorResult$1("Could not read the selected file.");
22951
+ return errorResult("Could not read the selected file.");
22923
22952
  }
22924
22953
  let parsed;
22925
22954
  try {
22926
22955
  parsed = JSON.parse(raw);
22927
22956
  } catch {
22928
- return errorResult$1("File is not valid JSON.");
22957
+ return errorResult("File is not valid JSON.");
22929
22958
  }
22930
22959
  if (!isValidKit(parsed)) {
22931
- return errorResult$1(
22960
+ return errorResult(
22932
22961
  "File is not a valid automation kit. Required fields: id, name, description, icon, inputs, promptTemplate."
22933
22962
  );
22934
22963
  }
22935
22964
  if (BUNDLED_KIT_IDS.has(parsed.id)) {
22936
- return errorResult$1(
22965
+ return errorResult(
22937
22966
  `Kit id "${parsed.id}" conflicts with a built-in kit and cannot be overwritten.`
22938
22967
  );
22939
22968
  }
22940
22969
  ensureKitsDir();
22941
22970
  const dest = getKitFilePath(parsed.id);
22942
22971
  if (!dest) {
22943
- return errorResult$1("Kit id contains unsupported characters.");
22972
+ return errorResult("Kit id contains unsupported characters.");
22944
22973
  }
22945
22974
  try {
22946
22975
  fs$1.writeFileSync(dest, JSON.stringify(parsed, null, 2), "utf-8");
22947
22976
  } catch {
22948
- return errorResult$1("Failed to save the kit file.");
22977
+ return errorResult("Failed to save the kit file.");
22949
22978
  }
22950
22979
  return okResult({ kit: parsed });
22951
22980
  }
22952
22981
  function uninstallKit(id, scheduledKitIds) {
22953
22982
  if (BUNDLED_KIT_IDS.has(id)) {
22954
- return errorResult$1("Built-in kits cannot be removed.");
22983
+ return errorResult("Built-in kits cannot be removed.");
22955
22984
  }
22956
22985
  if (scheduledKitIds?.has(id)) {
22957
- return errorResult$1(
22986
+ return errorResult(
22958
22987
  "This kit has active scheduled jobs. Delete or reassign them first."
22959
22988
  );
22960
22989
  }
22961
22990
  ensureKitsDir();
22962
22991
  const target = getKitFilePath(id);
22963
22992
  if (!target) {
22964
- return errorResult$1("Kit id contains unsupported characters.");
22993
+ return errorResult("Kit id contains unsupported characters.");
22965
22994
  }
22966
22995
  if (!fs$1.existsSync(target)) {
22967
- return errorResult$1("Kit not found.");
22996
+ return errorResult("Kit not found.");
22968
22997
  }
22969
22998
  try {
22970
22999
  fs$1.unlinkSync(target);
22971
23000
  return okResult();
22972
23001
  } catch {
22973
- return errorResult$1("Failed to remove the kit file.");
23002
+ return errorResult("Failed to remove the kit file.");
22974
23003
  }
22975
23004
  }
22976
23005
  const logger$6 = createLogger("Scheduler");
@@ -23274,9 +23303,9 @@ function isValidEmail(value) {
23274
23303
  function getActiveTabInfo(tabManager) {
23275
23304
  const tab = tabManager.getActiveTab();
23276
23305
  if (!tab) return null;
23277
- const wc2 = tab.view.webContents;
23278
- if (wc2.isDestroyed()) return null;
23279
- return { tab, wc: wc2 };
23306
+ const wc = tab.view.webContents;
23307
+ if (wc.isDestroyed()) return null;
23308
+ return { tab, wc };
23280
23309
  }
23281
23310
  const SAVE_DEBOUNCE_MS = 250;
23282
23311
  const PROFILE_FIELDS = [
@@ -23639,9 +23668,9 @@ function registerAutofillHandlers(windowState) {
23639
23668
  const profile = getProfile(profileId);
23640
23669
  if (!profile) throw new Error("Profile not found");
23641
23670
  const activeTab = windowState.tabManager.getActiveTab();
23642
- const wc2 = activeTab?.view.webContents;
23643
- if (!wc2) throw new Error("No active tab");
23644
- const content = await extractContent(wc2);
23671
+ const wc = activeTab?.view.webContents;
23672
+ if (!wc) throw new Error("No active tab");
23673
+ const content = await extractContent(wc);
23645
23674
  const elements = content.interactiveElements || [];
23646
23675
  const matches = matchFields(elements, profile);
23647
23676
  if (matches.length === 0) {
@@ -23652,7 +23681,7 @@ function registerAutofillHandlers(windowState) {
23652
23681
  selector: match.selector,
23653
23682
  value: match.value
23654
23683
  }));
23655
- const results = await fillFormFields(wc2, fields);
23684
+ const results = await fillFormFields(wc, fields);
23656
23685
  const filled = results.filter(
23657
23686
  (result) => result.result.startsWith("Typed into:") || result.result.startsWith("Selected:")
23658
23687
  ).length;
@@ -23671,9 +23700,9 @@ function registerAutofillHandlers(windowState) {
23671
23700
  function registerPageDiffHandlers(windowState, sendToRendererViews) {
23672
23701
  electron.ipcMain.handle(Channels.PAGE_DIFF_GET, () => {
23673
23702
  const activeTab = windowState.tabManager.getActiveTab();
23674
- const wc2 = activeTab?.view.webContents;
23675
- if (!wc2) return null;
23676
- return getLatestPageDiff(wc2.getURL());
23703
+ const wc = activeTab?.view.webContents;
23704
+ if (!wc) return null;
23705
+ return getLatestPageDiff(wc.getURL());
23677
23706
  });
23678
23707
  electron.ipcMain.handle(Channels.PAGE_DIFF_HISTORY, () => {
23679
23708
  try {
@@ -23681,22 +23710,22 @@ function registerPageDiffHandlers(windowState, sendToRendererViews) {
23681
23710
  return { error: "Premium required" };
23682
23711
  }
23683
23712
  const activeTab = windowState.tabManager.getActiveTab();
23684
- const wc2 = activeTab?.view.webContents;
23685
- if (!wc2) return [];
23686
- return getPageDiffBursts(wc2.getURL());
23713
+ const wc = activeTab?.view.webContents;
23714
+ if (!wc) return [];
23715
+ return getPageDiffBursts(wc.getURL());
23687
23716
  } catch {
23688
23717
  return [];
23689
23718
  }
23690
23719
  });
23691
23720
  electron.ipcMain.on(Channels.PAGE_DIFF_ACTIVITY, (event) => {
23692
- const wc2 = event.sender;
23693
- if (!wc2 || wc2.isDestroyed()) return;
23694
- notePageMutationActivity(wc2, sendToRendererViews);
23721
+ const wc = event.sender;
23722
+ if (!wc || wc.isDestroyed()) return;
23723
+ notePageMutationActivity(wc, sendToRendererViews);
23695
23724
  });
23696
23725
  electron.ipcMain.on(Channels.PAGE_DIFF_DIRTY, (event) => {
23697
- const wc2 = event.sender;
23698
- if (!wc2 || wc2.isDestroyed()) return;
23699
- schedulePageSnapshotCapture(wc2, sendToRendererViews);
23726
+ const wc = event.sender;
23727
+ if (!wc || wc.isDestroyed()) return;
23728
+ schedulePageSnapshotCapture(wc, sendToRendererViews);
23700
23729
  });
23701
23730
  }
23702
23731
  function registerVaultHandlers() {
@@ -24228,8 +24257,8 @@ function showGroupContextMenu(tabManager, groupId, parentWindow) {
24228
24257
  function createFindInPageBridge(tabManager, chromeView) {
24229
24258
  let wiredWcId = null;
24230
24259
  let findResultListener = null;
24231
- function wireFindEvents(wc2) {
24232
- if (wiredWcId === wc2.id && findResultListener) return;
24260
+ function wireFindEvents(wc) {
24261
+ if (wiredWcId === wc.id && findResultListener) return;
24233
24262
  if (wiredWcId !== null && findResultListener) {
24234
24263
  const prev = tabManager.findTabByWebContentsId(wiredWcId);
24235
24264
  const prevWc = prev?.view.webContents;
@@ -24237,17 +24266,17 @@ function createFindInPageBridge(tabManager, chromeView) {
24237
24266
  prevWc.removeListener("found-in-page", findResultListener);
24238
24267
  }
24239
24268
  }
24240
- wiredWcId = wc2.id;
24241
- if (wc2.isDestroyed()) return;
24269
+ wiredWcId = wc.id;
24270
+ if (wc.isDestroyed()) return;
24242
24271
  const listener = (_event, result) => {
24243
24272
  if (!chromeView.webContents.isDestroyed()) {
24244
24273
  chromeView.webContents.send(Channels.FIND_IN_PAGE_RESULT, result);
24245
24274
  }
24246
24275
  };
24247
24276
  findResultListener = listener;
24248
- wc2.on("found-in-page", listener);
24249
- const capturedWcId = wc2.id;
24250
- wc2.once("destroyed", () => {
24277
+ wc.on("found-in-page", listener);
24278
+ const capturedWcId = wc.id;
24279
+ wc.once("destroyed", () => {
24251
24280
  if (wiredWcId === capturedWcId) {
24252
24281
  wiredWcId = null;
24253
24282
  findResultListener = null;
@@ -24258,10 +24287,10 @@ function createFindInPageBridge(tabManager, chromeView) {
24258
24287
  start(text, options) {
24259
24288
  const tab = tabManager.getActiveTab();
24260
24289
  if (!tab) return null;
24261
- const wc2 = tab.view.webContents;
24262
- if (wc2.isDestroyed()) return null;
24263
- wireFindEvents(wc2);
24264
- return wc2.findInPage(text, {
24290
+ const wc = tab.view.webContents;
24291
+ if (wc.isDestroyed()) return null;
24292
+ wireFindEvents(wc);
24293
+ return wc.findInPage(text, {
24265
24294
  forward: options?.forward ?? true,
24266
24295
  findNext: options?.findNext ?? false
24267
24296
  });
@@ -24269,17 +24298,17 @@ function createFindInPageBridge(tabManager, chromeView) {
24269
24298
  next(forward) {
24270
24299
  const tab = tabManager.getActiveTab();
24271
24300
  if (!tab) return null;
24272
- const wc2 = tab.view.webContents;
24273
- if (wc2.isDestroyed()) return null;
24274
- wireFindEvents(wc2);
24275
- return wc2.findInPage("", { forward: forward ?? true, findNext: true });
24301
+ const wc = tab.view.webContents;
24302
+ if (wc.isDestroyed()) return null;
24303
+ wireFindEvents(wc);
24304
+ return wc.findInPage("", { forward: forward ?? true, findNext: true });
24276
24305
  },
24277
24306
  stop(action) {
24278
24307
  const tab = tabManager.getActiveTab();
24279
24308
  if (!tab) return;
24280
- const wc2 = tab.view.webContents;
24281
- if (wc2.isDestroyed()) return;
24282
- wc2.stopFindInPage(action ?? "clearSelection");
24309
+ const wc = tab.view.webContents;
24310
+ if (wc.isDestroyed()) return;
24311
+ wc.stopFindInPage(action ?? "clearSelection");
24283
24312
  }
24284
24313
  };
24285
24314
  }
@@ -24890,13 +24919,13 @@ const premiumApiOrigin = process.env.VESSEL_PREMIUM_API ? new URL(process.env.VE
24890
24919
  function registerPremiumHandlers(tabManager, sendToRendererViews) {
24891
24920
  const watchPremiumCheckoutTab = (tabId) => {
24892
24921
  const tab = tabManager.getTab(tabId);
24893
- const wc2 = tab?.view.webContents;
24894
- if (!wc2) return;
24922
+ const wc = tab?.view.webContents;
24923
+ if (!wc) return;
24895
24924
  let completed = false;
24896
24925
  const cleanup = () => {
24897
- wc2.removeListener("did-navigate", onNavigate);
24898
- wc2.removeListener("did-navigate-in-page", onNavigateInPage);
24899
- wc2.removeListener("destroyed", cleanup);
24926
+ wc.removeListener("did-navigate", onNavigate);
24927
+ wc.removeListener("did-navigate-in-page", onNavigateInPage);
24928
+ wc.removeListener("destroyed", cleanup);
24900
24929
  };
24901
24930
  const handleUrl = async (rawUrl) => {
24902
24931
  if (completed) return;
@@ -24945,10 +24974,10 @@ function registerPremiumHandlers(tabManager, sendToRendererViews) {
24945
24974
  if (!isMainFrame) return;
24946
24975
  void handleUrl(url);
24947
24976
  };
24948
- wc2.on("did-navigate", onNavigate);
24949
- wc2.on("did-navigate-in-page", onNavigateInPage);
24950
- wc2.on("destroyed", cleanup);
24951
- const currentUrl = wc2.getURL();
24977
+ wc.on("did-navigate", onNavigate);
24978
+ wc.on("did-navigate-in-page", onNavigateInPage);
24979
+ wc.on("destroyed", cleanup);
24980
+ const currentUrl = wc.getURL();
24952
24981
  if (currentUrl) {
24953
24982
  void handleUrl(currentUrl);
24954
24983
  }
@@ -24959,7 +24988,7 @@ function registerPremiumHandlers(tabManager, sendToRendererViews) {
24959
24988
  electron.ipcMain.handle(Channels.PREMIUM_ACTIVATION_START, async (_, email) => {
24960
24989
  assertString(email, "email");
24961
24990
  if (!isValidEmail(email)) {
24962
- return errorResult$1("Invalid email format");
24991
+ return errorResult("Invalid email format");
24963
24992
  }
24964
24993
  trackPremiumFunnel("activation_attempted");
24965
24994
  const result = await requestActivationCode(email);
@@ -24975,7 +25004,7 @@ function registerPremiumHandlers(tabManager, sendToRendererViews) {
24975
25004
  assertString(code, "code");
24976
25005
  assertString(challengeToken, "challengeToken");
24977
25006
  if (!isValidEmail(email)) {
24978
- return errorResult$1("Invalid email format", {
25007
+ return errorResult("Invalid email format", {
24979
25008
  state: getPremiumState()
24980
25009
  });
24981
25010
  }
@@ -25109,9 +25138,9 @@ const VALID_APPROVAL_MODES = ["auto", "confirm-dangerous", "manual"];
25109
25138
  async function togglePictureInPicture(tabManager) {
25110
25139
  const info = getActiveTabInfo(tabManager);
25111
25140
  if (!info) return false;
25112
- const { wc: wc2 } = info;
25141
+ const { wc } = info;
25113
25142
  try {
25114
- return await wc2.executeJavaScript(`
25143
+ return await wc.executeJavaScript(`
25115
25144
  (async function() {
25116
25145
  const video = document.querySelector('video');
25117
25146
  if (!video) return false;
@@ -25449,7 +25478,7 @@ function registerIpcHandlers(windowState, runtime2) {
25449
25478
  sidebarResizeActive = true;
25450
25479
  clearSidebarResizeRecoveryTimer();
25451
25480
  const [width, height] = windowState.mainWindow.getContentSize();
25452
- const chromeHeight = windowState.uiState.focusMode ? 0 : 110;
25481
+ const chromeHeight = windowState.uiState.focusMode ? 0 : CHROME_HEIGHT;
25453
25482
  const sidebarWidth = windowState.uiState.sidebarWidth;
25454
25483
  const resizeHandleOverlap = 6;
25455
25484
  windowState.sidebarView.setBounds({
@@ -25569,10 +25598,10 @@ function registerIpcHandlers(windowState, runtime2) {
25569
25598
  if (!activeTab) {
25570
25599
  return { success: false, message: "No active tab" };
25571
25600
  }
25572
- const wc2 = activeTab.view.webContents;
25573
- const result = await captureSelectionHighlight(wc2);
25601
+ const wc = activeTab.view.webContents;
25602
+ const result = await captureSelectionHighlight(wc);
25574
25603
  if (result.success && result.text) {
25575
- await highlightOnPage(wc2, null, result.text, void 0, void 0, "yellow").catch(
25604
+ await highlightOnPage(wc, null, result.text, void 0, void 0, "yellow").catch(
25576
25605
  (err) => logger$4.warn("Failed to highlight captured selection:", err)
25577
25606
  );
25578
25607
  await emitHighlightCount();
@@ -25593,11 +25622,11 @@ function registerIpcHandlers(windowState, runtime2) {
25593
25622
  });
25594
25623
  electron.ipcMain.on(Channels.HIGHLIGHT_SELECTION, (event, text) => {
25595
25624
  try {
25596
- const wc2 = event.sender;
25597
- if (wc2.isDestroyed()) return;
25598
- const tab = tabManager.findTabByWebContentsId(wc2.id);
25625
+ const wc = event.sender;
25626
+ if (wc.isDestroyed()) return;
25627
+ const tab = tabManager.findTabByWebContentsId(wc.id);
25599
25628
  if (!tab || !tab.highlightModeActive) return;
25600
- void persistAndMarkHighlight(wc2, text).then((result) => {
25629
+ void persistAndMarkHighlight(wc, text).then((result) => {
25601
25630
  if (result.success && !chromeView.webContents.isDestroyed()) {
25602
25631
  void emitHighlightCount();
25603
25632
  chromeView.webContents.send(Channels.HIGHLIGHT_CAPTURE_RESULT, result);
@@ -25638,7 +25667,7 @@ function registerIpcHandlers(windowState, runtime2) {
25638
25667
  const info = getActiveTabInfo(tabManager);
25639
25668
  if (!info) return false;
25640
25669
  try {
25641
- const cleared = await clearAllHighlightElements(wc);
25670
+ const cleared = await clearAllHighlightElements(info.wc);
25642
25671
  if (cleared) {
25643
25672
  await emitHighlightCount();
25644
25673
  }
@@ -25701,7 +25730,7 @@ function registerIpcHandlers(windowState, runtime2) {
25701
25730
  await electron.session.defaultSession.clearStorageData({ storages });
25702
25731
  }
25703
25732
  if (history) {
25704
- historyManager.clearByTimeRange(timeRange);
25733
+ clearByTimeRange(timeRange);
25705
25734
  }
25706
25735
  });
25707
25736
  electron.ipcMain.handle(Channels.TAB_TOGGLE_PIP, async () => {
@@ -27017,11 +27046,11 @@ async function bootstrap() {
27017
27046
  }
27018
27047
  const syncActiveHighlightCount = async (state2) => {
27019
27048
  const activeTab = state2.tabManager.getActiveTab();
27020
- const wc2 = activeTab?.view.webContents;
27049
+ const wc = activeTab?.view.webContents;
27021
27050
  let count = 0;
27022
- if (wc2 && !wc2.isDestroyed()) {
27051
+ if (wc && !wc.isDestroyed()) {
27023
27052
  try {
27024
- count = await getHighlightCount(wc2) ?? 0;
27053
+ count = await getHighlightCount(wc) ?? 0;
27025
27054
  } catch {
27026
27055
  count = 0;
27027
27056
  }