@canaryai/cli 0.2.12 → 0.2.14

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.
Files changed (73) hide show
  1. package/dist/{chunk-CEW4BDXD.js → chunk-4A4G5KTC.js} +14 -6
  2. package/dist/chunk-4A4G5KTC.js.map +1 -0
  3. package/dist/{chunk-MSMC6UXW.js → chunk-6IAPGYZQ.js} +1016 -245
  4. package/dist/chunk-6IAPGYZQ.js.map +1 -0
  5. package/dist/{chunk-PWWQGYFG.js → chunk-ACRIE2YR.js} +5 -2
  6. package/dist/chunk-ACRIE2YR.js.map +1 -0
  7. package/dist/{chunk-ERSNYLMZ.js → chunk-BOS2YLKH.js} +12 -8
  8. package/dist/chunk-BOS2YLKH.js.map +1 -0
  9. package/dist/{chunk-A44B2PEA.js → chunk-SYPQF57S.js} +40 -8
  10. package/dist/chunk-SYPQF57S.js.map +1 -0
  11. package/dist/{chunk-Q7WFBG5C.js → chunk-ZQF72UTG.js} +19 -5
  12. package/dist/chunk-ZQF72UTG.js.map +1 -0
  13. package/dist/{debug-workflow-53ULOFJC.js → debug-workflow-DIQZDFMN.js} +10 -12
  14. package/dist/debug-workflow-DIQZDFMN.js.map +1 -0
  15. package/dist/{docs-BEE3LOCO.js → docs-CSVSGIGW.js} +63 -15
  16. package/dist/docs-CSVSGIGW.js.map +1 -0
  17. package/dist/{feature-flag-CYTDV4ZB.js → feature-flag-BIPFVVNC.js} +3 -3
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.js +36 -30
  20. package/dist/index.js.map +1 -1
  21. package/dist/{init-M6I3MG3D.js → init-BTDX5N6P.js} +4 -4
  22. package/dist/{issues-NLM72HLU.js → issues-EWVB52CA.js} +37 -18
  23. package/dist/issues-EWVB52CA.js.map +1 -0
  24. package/dist/{knobs-O35GAU5M.js → knobs-VYABZESR.js} +3 -3
  25. package/dist/{list-4K4EIGAT.js → list-RCPYLS36.js} +3 -3
  26. package/dist/list-RCPYLS36.js.map +1 -0
  27. package/dist/{local-NHXXPHZ3.js → local-ZPVM4BXX.js} +6 -6
  28. package/dist/{local-browser-VAZORCO3.js → local-browser-WV4IH2DU.js} +4 -4
  29. package/dist/{login-ZLP64YQP.js → login-W4GXV3VA.js} +4 -4
  30. package/dist/{mcp-ZF5G5DCB.js → mcp-YER5GQG7.js} +7 -10
  31. package/dist/mcp-YER5GQG7.js.map +1 -0
  32. package/dist/{psql-2YPIRMDY.js → psql-XO5BB5L5.js} +2 -2
  33. package/dist/{record-V6QKFFH3.js → record-KRS2PHMW.js} +7 -7
  34. package/dist/record-KRS2PHMW.js.map +1 -0
  35. package/dist/{redis-A7GWM23E.js → redis-CQTBPZ6F.js} +2 -2
  36. package/dist/{release-7TI7EIGD.js → release-DW7RPQSQ.js} +2 -2
  37. package/dist/runner/preload.js +1 -1
  38. package/dist/{session-UGNJXRUW.js → session-CLWAVJ2K.js} +33 -12
  39. package/dist/{session-UGNJXRUW.js.map → session-CLWAVJ2K.js.map} +1 -1
  40. package/dist/{skill-ORWAPBDW.js → skill-2TXI3IKP.js} +1 -1
  41. package/dist/skill-2TXI3IKP.js.map +1 -0
  42. package/dist/{src-4VIDSK4A.js → src-WLOHOI6P.js} +8 -2
  43. package/dist/{start-E532F3BU.js → start-CNNQUP5I.js} +4 -4
  44. package/dist/test.js +1 -1
  45. package/dist/test.js.map +1 -1
  46. package/dist/{workflow-HXIUXRFI.js → workflow-XXL4H5R4.js} +23 -11
  47. package/dist/workflow-XXL4H5R4.js.map +1 -0
  48. package/package.json +1 -2
  49. package/dist/chunk-A44B2PEA.js.map +0 -1
  50. package/dist/chunk-CEW4BDXD.js.map +0 -1
  51. package/dist/chunk-ERSNYLMZ.js.map +0 -1
  52. package/dist/chunk-MSMC6UXW.js.map +0 -1
  53. package/dist/chunk-PWWQGYFG.js.map +0 -1
  54. package/dist/chunk-Q7WFBG5C.js.map +0 -1
  55. package/dist/debug-workflow-53ULOFJC.js.map +0 -1
  56. package/dist/docs-BEE3LOCO.js.map +0 -1
  57. package/dist/issues-NLM72HLU.js.map +0 -1
  58. package/dist/list-4K4EIGAT.js.map +0 -1
  59. package/dist/mcp-ZF5G5DCB.js.map +0 -1
  60. package/dist/record-V6QKFFH3.js.map +0 -1
  61. package/dist/skill-ORWAPBDW.js.map +0 -1
  62. package/dist/workflow-HXIUXRFI.js.map +0 -1
  63. /package/dist/{feature-flag-CYTDV4ZB.js.map → feature-flag-BIPFVVNC.js.map} +0 -0
  64. /package/dist/{init-M6I3MG3D.js.map → init-BTDX5N6P.js.map} +0 -0
  65. /package/dist/{knobs-O35GAU5M.js.map → knobs-VYABZESR.js.map} +0 -0
  66. /package/dist/{local-NHXXPHZ3.js.map → local-ZPVM4BXX.js.map} +0 -0
  67. /package/dist/{local-browser-VAZORCO3.js.map → local-browser-WV4IH2DU.js.map} +0 -0
  68. /package/dist/{login-ZLP64YQP.js.map → login-W4GXV3VA.js.map} +0 -0
  69. /package/dist/{psql-2YPIRMDY.js.map → psql-XO5BB5L5.js.map} +0 -0
  70. /package/dist/{redis-A7GWM23E.js.map → redis-CQTBPZ6F.js.map} +0 -0
  71. /package/dist/{release-7TI7EIGD.js.map → release-DW7RPQSQ.js.map} +0 -0
  72. /package/dist/{src-4VIDSK4A.js.map → src-WLOHOI6P.js.map} +0 -0
  73. /package/dist/{start-E532F3BU.js.map → start-CNNQUP5I.js.map} +0 -0
@@ -38199,7 +38199,7 @@ function setSnapshotAnalyzerLogger(l) {
38199
38199
  logger = l;
38200
38200
  }
38201
38201
  function extractSnapshotYaml(mcpResponse) {
38202
- const text = typeof mcpResponse === "string" ? mcpResponse : mcpResponse != null && typeof mcpResponse === "object" && "text" in mcpResponse && typeof mcpResponse.text === "string" ? mcpResponse.text : String(mcpResponse);
38202
+ const text = typeof mcpResponse === "string" ? mcpResponse : mcpResponse !== null && mcpResponse !== void 0 && typeof mcpResponse === "object" && "text" in mcpResponse && typeof mcpResponse.text === "string" ? mcpResponse.text : String(mcpResponse);
38203
38203
  const yamlMatch = text.match(/Page Snapshot:\s*```yaml\s*([\s\S]*?)```/);
38204
38204
  if (yamlMatch) {
38205
38205
  return yamlMatch[1].trim();
@@ -38568,9 +38568,18 @@ var INTERACTIVE_LEAF_ROLES = /* @__PURE__ */ new Set([
38568
38568
  "switch",
38569
38569
  "svg-shape"
38570
38570
  ]);
38571
- var FORM_INPUT_ROLES = /* @__PURE__ */ new Set(["combobox", "textbox", "searchbox", "spinbutton", "slider"]);
38571
+ var FORM_INPUT_ROLES = /* @__PURE__ */ new Set([
38572
+ "combobox",
38573
+ "textbox",
38574
+ "searchbox",
38575
+ "spinbutton",
38576
+ "slider"
38577
+ ]);
38572
38578
  var INTERACTIVE_CONTAINER_ROLES = /* @__PURE__ */ new Set(["menu", "menubar", "tablist", "listbox"]);
38573
- var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([...INTERACTIVE_LEAF_ROLES, ...INTERACTIVE_CONTAINER_ROLES]);
38579
+ var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
38580
+ ...INTERACTIVE_LEAF_ROLES,
38581
+ ...INTERACTIVE_CONTAINER_ROLES
38582
+ ]);
38574
38583
  var STRUCTURAL_ROLES = /* @__PURE__ */ new Set([
38575
38584
  "banner",
38576
38585
  "navigation",
@@ -38596,15 +38605,16 @@ var TEXT_CARRYING_ROLES = /* @__PURE__ */ new Set([
38596
38605
  "caption"
38597
38606
  ]);
38598
38607
  var VISUAL_HEADING_MAX_LENGTH = 60;
38599
- var STATUS_WORDS = /* @__PURE__ */ new Set(["favorable", "unfavorable", "success", "error", "warning", "pending"]);
38600
- var BLANK_PATTERNS = [
38601
- /\s*\(Blank\)\s*/gi,
38602
- /\s*\(blank\)\s*/gi
38603
- ];
38604
- var MENU_TRIGGER_PATTERNS = [
38605
- /^Open menu for /i,
38606
- /^Show more options$/i
38607
- ];
38608
+ var STATUS_WORDS = /* @__PURE__ */ new Set([
38609
+ "favorable",
38610
+ "unfavorable",
38611
+ "success",
38612
+ "error",
38613
+ "warning",
38614
+ "pending"
38615
+ ]);
38616
+ var BLANK_PATTERNS = [/\s*\(Blank\)\s*/gi, /\s*\(blank\)\s*/gi];
38617
+ var MENU_TRIGGER_PATTERNS = [/^Open menu for /i, /^Show more options$/i];
38608
38618
  var SECTION_BOUNDARY_ROLES = /* @__PURE__ */ new Set([
38609
38619
  "dialog",
38610
38620
  "alertdialog",
@@ -38617,7 +38627,7 @@ var SECTION_BOUNDARY_ROLES = /* @__PURE__ */ new Set([
38617
38627
  ]);
38618
38628
  var FRAMEWORK_NOISE_RE = /^(ng-binding|ng-scope|ng-pristine|ng-dirty|ng-valid|ng-invalid|ng-untouched|ng-touched|v-enter|v-leave)$/;
38619
38629
  function normalizeSearchText(text) {
38620
- return text.toLowerCase().replace(/[-_.,;:!?'"()\[\]{}\/\\@#$%^&*+=<>~`|]/g, "").replace(/\s+/g, " ").trim();
38630
+ return text.toLowerCase().replace(/[-_.,;:!?'"()[\]{}/\\@#$%^&*+=<>~`|]/g, "").replace(/\s+/g, " ").trim();
38621
38631
  }
38622
38632
  function isActiveElement(element) {
38623
38633
  return element.attributes["active"] !== void 0 || element.rawLine.includes("[active]");
@@ -38694,7 +38704,8 @@ function getDisplayText(element, options) {
38694
38704
  return normalizeIconLabelText(element.role, rawTextSource);
38695
38705
  }
38696
38706
  function hasInteractiveDescendants(element) {
38697
- if (element.ref && (INTERACTIVE_ROLES.has(element.role) || isClickableByAttribute(element))) return true;
38707
+ if (element.ref && (INTERACTIVE_ROLES.has(element.role) || isClickableByAttribute(element)))
38708
+ return true;
38698
38709
  for (const child of element.children) {
38699
38710
  if (hasInteractiveDescendants(child)) return true;
38700
38711
  }
@@ -39621,7 +39632,8 @@ function shouldCollapse(section) {
39621
39632
  if (section.hasSearchMatch) return false;
39622
39633
  if (section.isBackground) return true;
39623
39634
  if (section.role === "dialog" || section.role === "alertdialog") return false;
39624
- if (section.role === "navigation" || section.role === "menubar" || section.role === "menu") return false;
39635
+ if (section.role === "navigation" || section.role === "menubar" || section.role === "menu")
39636
+ return false;
39625
39637
  if (section.role === "banner") return false;
39626
39638
  if (section.role === "form") return false;
39627
39639
  if (section.elementCount >= MIN_ELEMENTS_TO_COLLAPSE) return true;
@@ -39674,7 +39686,12 @@ function collectInteractiveElements(element, elements, subsections, depth, inher
39674
39686
  if ((INTERACTIVE_LEAF_ROLES.has(element.role) || isClickableByAttribute(element)) && element.ref) {
39675
39687
  const effectiveFieldLabel = shouldDropInheritedFieldLabel(element, inheritedFieldLabel) ? void 0 : inheritedFieldLabel;
39676
39688
  if (INTERACTIVE_LEAF_ROLES.has(element.role) && isExpandedWithActionableChildren(element)) {
39677
- elements.push(formatElement(element, { overrideLabel: composeTriggerLabel(element), fieldLabel: effectiveFieldLabel }));
39689
+ elements.push(
39690
+ formatElement(element, {
39691
+ overrideLabel: composeTriggerLabel(element),
39692
+ fieldLabel: effectiveFieldLabel
39693
+ })
39694
+ );
39678
39695
  collectExpandedChildren(element, elements);
39679
39696
  return;
39680
39697
  }
@@ -39730,7 +39747,9 @@ function collectInteractiveElements(element, elements, subsections, depth, inher
39730
39747
  const fieldLabel = shouldDropInheritedFieldLabel(child, rawFieldLabel) ? void 0 : rawFieldLabel;
39731
39748
  if (!isMenuTriggerNoise(child)) {
39732
39749
  if (INTERACTIVE_LEAF_ROLES.has(child.role) && isExpandedWithActionableChildren(child)) {
39733
- elements.push(formatElement(child, { overrideLabel: composeTriggerLabel(child), fieldLabel }));
39750
+ elements.push(
39751
+ formatElement(child, { overrideLabel: composeTriggerLabel(child), fieldLabel })
39752
+ );
39734
39753
  collectExpandedChildren(child, elements);
39735
39754
  } else {
39736
39755
  elements.push(formatElement(child, { fieldLabel }));
@@ -39803,7 +39822,9 @@ function buildSection(element, depth) {
39803
39822
  } else if ((INTERACTIVE_LEAF_ROLES.has(child.role) || isClickableByAttribute(child)) && child.ref) {
39804
39823
  const fieldLabel = findFieldLabelInContext(child, children2, ci);
39805
39824
  if (INTERACTIVE_LEAF_ROLES.has(child.role) && isExpandedWithActionableChildren(child)) {
39806
- interactiveElements.push(formatElement(child, { overrideLabel: composeTriggerLabel(child), fieldLabel }));
39825
+ interactiveElements.push(
39826
+ formatElement(child, { overrideLabel: composeTriggerLabel(child), fieldLabel })
39827
+ );
39807
39828
  collectExpandedChildren(child, interactiveElements);
39808
39829
  } else {
39809
39830
  if (!isMenuTriggerNoise(child)) {
@@ -39811,13 +39832,25 @@ function buildSection(element, depth) {
39811
39832
  }
39812
39833
  if (!INTERACTIVE_LEAF_ROLES.has(child.role) && isClickableByAttribute(child)) {
39813
39834
  for (const grandchild of child.children) {
39814
- collectInteractiveElements(grandchild, interactiveElements, subsections, depth + 1, fieldLabel);
39835
+ collectInteractiveElements(
39836
+ grandchild,
39837
+ interactiveElements,
39838
+ subsections,
39839
+ depth + 1,
39840
+ fieldLabel
39841
+ );
39815
39842
  }
39816
39843
  }
39817
39844
  }
39818
39845
  } else {
39819
39846
  const containerLabel = resolveContainerFieldLabel(child) ?? findFieldLabelFromSiblings(children2, ci);
39820
- collectInteractiveElements(child, interactiveElements, subsections, depth + 1, containerLabel);
39847
+ collectInteractiveElements(
39848
+ child,
39849
+ interactiveElements,
39850
+ subsections,
39851
+ depth + 1,
39852
+ containerLabel
39853
+ );
39821
39854
  }
39822
39855
  }
39823
39856
  if (isClickableByAttribute(element) && element.ref && !INTERACTIVE_ROLES.has(element.role)) {
@@ -40070,11 +40103,15 @@ function formatSectionOutput(section, indent, showCollapsed) {
40070
40103
  const focusedPart = section.isFocused ? " [FOCUSED]" : "";
40071
40104
  const backgroundPart = section.isBackground ? " [BACKGROUND]" : "";
40072
40105
  const activePart = section.containsActive && !section.isFocused ? " \u2190 ACTIVE" : "";
40073
- lines.push(`${indentStr}${headingPrefix}${section.heading}${refPart}${focusedPart}${backgroundPart}${activePart}`);
40106
+ lines.push(
40107
+ `${indentStr}${headingPrefix}${section.heading}${refPart}${focusedPart}${backgroundPart}${activePart}`
40108
+ );
40074
40109
  if (section.collapsed && !showCollapsed) {
40075
40110
  if (section.isBackground) {
40076
40111
  if (section.ref) {
40077
- lines.push(`${indentStr} (${section.elementCount} elements - use expand="${section.ref}" to see content)`);
40112
+ lines.push(
40113
+ `${indentStr} (${section.elementCount} elements - use expand="${section.ref}" to see content)`
40114
+ );
40078
40115
  } else {
40079
40116
  lines.push(`${indentStr} (${section.elementCount} elements)`);
40080
40117
  }
@@ -40453,7 +40490,7 @@ function gridInfoToRows(grid) {
40453
40490
  }
40454
40491
  const rows = [];
40455
40492
  for (const row of grid.rows) {
40456
- const values = new Array(columns.length).fill("");
40493
+ const values = Array.from({ length: columns.length }).fill("");
40457
40494
  for (const cell of row.cells) {
40458
40495
  const idx = columnIndex.get(cell.column);
40459
40496
  if (idx !== void 0) {
@@ -41412,9 +41449,14 @@ var BrowserToolExecutor = class {
41412
41449
  this.autoSnapshotAfterAction = options?.autoSnapshotAfterAction !== false;
41413
41450
  this.includeScreenshotWithSnapshot = options?.includeScreenshotWithSnapshot !== false;
41414
41451
  if (!options?.workspaceDir && !options?.tmpBaseDir) {
41415
- options?.logger?.debug?.("[BrowserToolExecutor] No tmpBaseDir provided, using flat canary dir (not org-scoped)");
41452
+ options?.logger?.debug?.(
41453
+ "[BrowserToolExecutor] No tmpBaseDir provided, using flat canary dir (not org-scoped)"
41454
+ );
41416
41455
  }
41417
- this.workspaceDir = options?.workspaceDir ?? path2.join(options?.tmpBaseDir ?? getCanaryTmpDir(), `browser-workspace-${Date.now()}-${crypto2.randomUUID().slice(0, 8)}`);
41456
+ this.workspaceDir = options?.workspaceDir ?? path2.join(
41457
+ options?.tmpBaseDir ?? getCanaryTmpDir(),
41458
+ `browser-workspace-${Date.now()}-${crypto2.randomUUID().slice(0, 8)}`
41459
+ );
41418
41460
  this.logger = options?.logger;
41419
41461
  fs2.mkdir(this.workspaceDir, { recursive: true }).catch(() => {
41420
41462
  });
@@ -41482,10 +41524,14 @@ Viewport: ${viewportSize.width}x${viewportSize.height} | Image: ~${imgWidth}x${i
41482
41524
  ` + buildResolutionNote(viewportSize, maxImageDim, this.logger) + `
41483
41525
  ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from grid labels.\n" : ""}Click coordinates should be in viewport space (0-${viewportSize.width}, 0-${viewportSize.height}).
41484
41526
  `;
41485
- return withRecoveryNoticeMCP(this.client, {
41486
- text: scaleInfo + (rawTextContent || ""),
41487
- images: result.images
41488
- }, this.logger);
41527
+ return withRecoveryNoticeMCP(
41528
+ this.client,
41529
+ {
41530
+ text: scaleInfo + (rawTextContent || ""),
41531
+ images: result.images
41532
+ },
41533
+ this.logger
41534
+ );
41489
41535
  }
41490
41536
  return withRecoveryNoticeMCP(this.client, rawTextContent, this.logger);
41491
41537
  }
@@ -41498,10 +41544,14 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41498
41544
  this.maxImageDimension,
41499
41545
  this.logger
41500
41546
  );
41501
- return withRecoveryNoticeMCP(this.client, {
41502
- text: resolutionNote + "\n" + semanticText2,
41503
- images: result.images
41504
- }, this.logger);
41547
+ return withRecoveryNoticeMCP(
41548
+ this.client,
41549
+ {
41550
+ text: resolutionNote + "\n" + semanticText2,
41551
+ images: result.images
41552
+ },
41553
+ this.logger
41554
+ );
41505
41555
  }
41506
41556
  return withRecoveryNoticeMCP(this.client, semanticText2, this.logger);
41507
41557
  }
@@ -41551,7 +41601,9 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41551
41601
  let probeResult;
41552
41602
  if (opts.probeAt && searchTerms.length === 0 && this.client.probeAtCoordinates) {
41553
41603
  try {
41554
- const probe = await this.client.probeAtCoordinates(opts.probeAt.x, opts.probeAt.y, { signal: this.signal });
41604
+ const probe = await this.client.probeAtCoordinates(opts.probeAt.x, opts.probeAt.y, {
41605
+ signal: this.signal
41606
+ });
41555
41607
  if (probe) {
41556
41608
  probeResult = probe;
41557
41609
  if (hasImages && probe.boundingBox) {
@@ -41635,10 +41687,14 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41635
41687
  this.maxImageDimension,
41636
41688
  this.logger
41637
41689
  );
41638
- return withRecoveryNoticeMCP(this.client, {
41639
- text: resolutionNote + "\n" + semanticText,
41640
- images: result.images
41641
- }, this.logger);
41690
+ return withRecoveryNoticeMCP(
41691
+ this.client,
41692
+ {
41693
+ text: resolutionNote + "\n" + semanticText,
41694
+ images: result.images
41695
+ },
41696
+ this.logger
41697
+ );
41642
41698
  }
41643
41699
  return withRecoveryNoticeMCP(this.client, semanticText, this.logger);
41644
41700
  }
@@ -41657,10 +41713,7 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41657
41713
  if (img) {
41658
41714
  const base64Match = img.match(/^data:image\/(png|jpeg);base64,(.+)$/);
41659
41715
  if (base64Match) {
41660
- const downsampledBase64 = await downsampleImage(
41661
- base64Match[2],
41662
- this.maxImageDimension
41663
- );
41716
+ const downsampledBase64 = await downsampleImage(base64Match[2], this.maxImageDimension);
41664
41717
  return {
41665
41718
  text: `Screenshot captured${opts?.label ? ` (${opts.label})` : ""}`,
41666
41719
  images: [{ data: downsampledBase64, mimeType: "image/jpeg" }]
@@ -41721,18 +41774,32 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41721
41774
  if (dialogMsg) {
41722
41775
  result = result + "\n\n" + dialogMsg;
41723
41776
  }
41724
- return withRecoveryNoticeMCP(this.client, composeActionResult(result, autoSnapshot), this.logger);
41777
+ return withRecoveryNoticeMCP(
41778
+ this.client,
41779
+ composeActionResult(result, autoSnapshot),
41780
+ this.logger
41781
+ );
41725
41782
  }
41726
41783
  async type(opts) {
41727
41784
  const submitNote = opts.submit ? " and submitted" : "";
41728
41785
  const actionDesc = `Typed "${opts.text}" into "${opts.element}"${submitNote}`;
41729
41786
  if (opts.submit) {
41730
41787
  const { diffText, autoSnapshot } = await this.withSemanticDiff(actionDesc, async () => {
41731
- await this.client.type(opts.ref, opts.text, opts.element, opts.submit, { delay: opts.delay, signal: this.signal });
41788
+ await this.client.type(opts.ref, opts.text, opts.element, opts.submit, {
41789
+ delay: opts.delay,
41790
+ signal: this.signal
41791
+ });
41732
41792
  });
41733
- return withRecoveryNoticeMCP(this.client, composeActionResult(diffText, autoSnapshot), this.logger);
41793
+ return withRecoveryNoticeMCP(
41794
+ this.client,
41795
+ composeActionResult(diffText, autoSnapshot),
41796
+ this.logger
41797
+ );
41734
41798
  }
41735
- await this.client.type(opts.ref, opts.text, opts.element, opts.submit, { delay: opts.delay, signal: this.signal });
41799
+ await this.client.type(opts.ref, opts.text, opts.element, opts.submit, {
41800
+ delay: opts.delay,
41801
+ signal: this.signal
41802
+ });
41736
41803
  return withRecoveryNotice(this.client, actionDesc, this.logger);
41737
41804
  }
41738
41805
  async hover(opts) {
@@ -41753,9 +41820,18 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41753
41820
  const actionDesc = useCoordinates ? `Dragged from (${opts.startX}, ${opts.startY}) to (${opts.endX}, ${opts.endY})` : `Dragged "${opts.startElement}" to "${opts.endElement}"`;
41754
41821
  const { diffText, autoSnapshot } = await this.withSemanticDiff(actionDesc, async () => {
41755
41822
  if (useCoordinates) {
41756
- await this.client.dragCoordinates(opts.startX, opts.startY, opts.endX, opts.endY, opts.startElement, { signal: this.signal });
41823
+ await this.client.dragCoordinates(
41824
+ opts.startX,
41825
+ opts.startY,
41826
+ opts.endX,
41827
+ opts.endY,
41828
+ opts.startElement,
41829
+ { signal: this.signal }
41830
+ );
41757
41831
  } else {
41758
- await this.client.drag(opts.startRef, opts.startElement, opts.endRef, opts.endElement, { signal: this.signal });
41832
+ await this.client.drag(opts.startRef, opts.startElement, opts.endRef, opts.endElement, {
41833
+ signal: this.signal
41834
+ });
41759
41835
  }
41760
41836
  });
41761
41837
  return composeActionResult(diffText, autoSnapshot);
@@ -41766,7 +41842,11 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41766
41842
  const { diffText, autoSnapshot } = await this.withSemanticDiff(`Pressed ${key}`, async () => {
41767
41843
  await this.client.pressKey(key, { signal: this.signal });
41768
41844
  });
41769
- return withRecoveryNoticeMCP(this.client, composeActionResult(diffText, autoSnapshot), this.logger);
41845
+ return withRecoveryNoticeMCP(
41846
+ this.client,
41847
+ composeActionResult(diffText, autoSnapshot),
41848
+ this.logger
41849
+ );
41770
41850
  }
41771
41851
  await this.client.pressKey(key, { signal: this.signal });
41772
41852
  return withRecoveryNotice(this.client, `Pressed ${key}`, this.logger);
@@ -41796,7 +41876,13 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41796
41876
  // ==================== Scroll ====================
41797
41877
  async scroll(opts) {
41798
41878
  if (opts.toRef) {
41799
- const result2 = await this.client.scroll(opts.direction, opts.amount, opts.withinRef, opts.toRef, { signal: this.signal });
41879
+ const result2 = await this.client.scroll(
41880
+ opts.direction,
41881
+ opts.amount,
41882
+ opts.withinRef,
41883
+ opts.toRef,
41884
+ { signal: this.signal }
41885
+ );
41800
41886
  const scrollDesc2 = `Scrolled to element ${opts.toRef}`;
41801
41887
  if (isMCPContentWithImages(result2)) {
41802
41888
  return {
@@ -41807,7 +41893,13 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41807
41893
  return scrollDesc2;
41808
41894
  }
41809
41895
  if (opts.x !== void 0 && opts.y !== void 0) {
41810
- const result2 = await this.client.scrollAtCoordinates(opts.x, opts.y, opts.direction, opts.amount, { signal: this.signal });
41896
+ const result2 = await this.client.scrollAtCoordinates(
41897
+ opts.x,
41898
+ opts.y,
41899
+ opts.direction,
41900
+ opts.amount,
41901
+ { signal: this.signal }
41902
+ );
41811
41903
  const scrollDesc2 = `Scrolled ${opts.direction} at (${opts.x}, ${opts.y})${opts.amount ? ` (intensity ${opts.amount})` : ""}`;
41812
41904
  if (isMCPContentWithImages(result2)) {
41813
41905
  return {
@@ -41817,7 +41909,13 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41817
41909
  }
41818
41910
  return scrollDesc2;
41819
41911
  }
41820
- const result = await this.client.scroll(opts.direction, opts.amount, opts.withinRef, void 0, { signal: this.signal });
41912
+ const result = await this.client.scroll(
41913
+ opts.direction,
41914
+ opts.amount,
41915
+ opts.withinRef,
41916
+ void 0,
41917
+ { signal: this.signal }
41918
+ );
41821
41919
  const scrollDesc = `Scrolled ${opts.direction}${opts.amount ? ` (intensity ${opts.amount})` : ""}`;
41822
41920
  if (isMCPContentWithImages(result)) {
41823
41921
  return {
@@ -41829,7 +41927,9 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41829
41927
  }
41830
41928
  // ==================== Dialogs ====================
41831
41929
  async handleDialog(opts) {
41832
- const result = await this.client.handleDialog(opts.action, opts.promptText, { signal: this.signal });
41930
+ const result = await this.client.handleDialog(opts.action, opts.promptText, {
41931
+ signal: this.signal
41932
+ });
41833
41933
  return typeof result === "string" ? result : `Dialog ${opts.action}ed`;
41834
41934
  }
41835
41935
  async dismissOverlay(opts) {
@@ -41859,7 +41959,9 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41859
41959
  break;
41860
41960
  }
41861
41961
  case "backdrop":
41862
- await this.client.clickAtCoordinates(10, 10, "backdrop/outside modal", { signal: this.signal });
41962
+ await this.client.clickAtCoordinates(10, 10, "backdrop/outside modal", {
41963
+ signal: this.signal
41964
+ });
41863
41965
  break;
41864
41966
  }
41865
41967
  await this.client.waitFor({ timeSec: 0.5, signal: this.signal });
@@ -41870,7 +41972,12 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41870
41972
  if (!afterModal) {
41871
41973
  const afterState2 = captureSnapshotState(afterUrl2, afterYaml2);
41872
41974
  const diff3 = compareSnapshots(beforeState, afterState2);
41873
- return formatSemanticDiff(diff3, `Dismissed overlay using ${strategy}`, void 0, (/* @__PURE__ */ new Date()).toISOString());
41975
+ return formatSemanticDiff(
41976
+ diff3,
41977
+ `Dismissed overlay using ${strategy}`,
41978
+ void 0,
41979
+ (/* @__PURE__ */ new Date()).toISOString()
41980
+ );
41874
41981
  }
41875
41982
  } catch (err) {
41876
41983
  this.logger?.debug?.(`[BrowserTools] Dismiss strategy ${strategy} failed`, {
@@ -41886,7 +41993,12 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41886
41993
  const diff2 = compareSnapshots(beforeState, afterState);
41887
41994
  return `Could not dismiss overlay with strategies: ${strategies.join(", ")}. Modal may require specific interaction.
41888
41995
 
41889
- ` + formatSemanticDiff(diff2, "Dismiss overlay attempted (failed)", void 0, (/* @__PURE__ */ new Date()).toISOString());
41996
+ ` + formatSemanticDiff(
41997
+ diff2,
41998
+ "Dismiss overlay attempted (failed)",
41999
+ void 0,
42000
+ (/* @__PURE__ */ new Date()).toISOString()
42001
+ );
41890
42002
  }
41891
42003
  // ==================== Waiting ====================
41892
42004
  async waitFor(opts) {
@@ -41925,7 +42037,7 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
41925
42037
  `Size: ${result.sizeBytes} bytes`,
41926
42038
  `Type: ${result.mimeType}`
41927
42039
  ];
41928
- if (result.textContent != null) {
42040
+ if (result.textContent !== null && result.textContent !== void 0) {
41929
42041
  lines.push("", "--- Content ---", result.textContent);
41930
42042
  } else {
41931
42043
  lines.push("", "[Binary file \u2014 content cannot be displayed as text]");
@@ -42015,7 +42127,11 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
42015
42127
  await fs2.writeFile(snapshotFilePath, afterYaml, "utf-8");
42016
42128
  } catch {
42017
42129
  }
42018
- const semanticText = formatSemanticSnapshot(afterYaml, { snapshotFilePath, currentTime: now, capturedToasts: this.client.getCapturedToasts?.() ?? [] });
42130
+ const semanticText = formatSemanticSnapshot(afterYaml, {
42131
+ snapshotFilePath,
42132
+ currentTime: now,
42133
+ capturedToasts: this.client.getCapturedToasts?.() ?? []
42134
+ });
42019
42135
  const afterImages = isMCPContentWithImages(afterResult) ? afterResult.images : void 0;
42020
42136
  if (afterImages?.length && this.onScreenshot) {
42021
42137
  const img = afterImages[0];
@@ -42056,7 +42172,11 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
42056
42172
  await fs2.writeFile(snapshotFilePath, yaml, "utf-8");
42057
42173
  } catch {
42058
42174
  }
42059
- const semanticText = formatSemanticSnapshot(yaml, { snapshotFilePath, currentTime: (/* @__PURE__ */ new Date()).toISOString(), capturedToasts: this.client.getCapturedToasts?.() ?? [] });
42175
+ const semanticText = formatSemanticSnapshot(yaml, {
42176
+ snapshotFilePath,
42177
+ currentTime: (/* @__PURE__ */ new Date()).toISOString(),
42178
+ capturedToasts: this.client.getCapturedToasts?.() ?? []
42179
+ });
42060
42180
  const yamlBlockPattern = /- Page Snapshot:\n```yaml\n[\s\S]*?```/;
42061
42181
  if (yamlBlockPattern.test(result)) {
42062
42182
  return result.replace(yamlBlockPattern, `- Page Snapshot (semantic):
@@ -42176,52 +42296,624 @@ function getBrowserToolDefinitions() {
42176
42296
  }
42177
42297
  },
42178
42298
  {
42179
- name: "browser_network_requests",
42180
- description: "Get network requests made by the page",
42299
+ name: "browser_network_requests",
42300
+ description: "Get network requests made by the page",
42301
+ inputSchema: {
42302
+ type: "object",
42303
+ properties: {}
42304
+ }
42305
+ },
42306
+ {
42307
+ name: "browser_click",
42308
+ description: "Click an element on the page. Provide EITHER a ref from the snapshot OR coordinates (x, y).\n- **ref**: Uses Playwright locator - handles scrolling into view and actionability checks automatically.\n- **coordinates**: Clicks at exact pixel position - useful when ref-based clicking fails due to overlays.\nAlways describe what you are clicking in the element parameter.",
42309
+ inputSchema: {
42310
+ type: "object",
42311
+ properties: {
42312
+ ref: {
42313
+ type: "string",
42314
+ description: "Element reference from snapshot (optional if x/y coordinates provided)"
42315
+ },
42316
+ x: { type: "number", description: "X coordinate on the page (use with y)" },
42317
+ y: { type: "number", description: "Y coordinate on the page (use with x)" },
42318
+ element: { type: "string", description: "Description of what you are clicking" },
42319
+ doubleClick: { type: "boolean", description: "Perform a double click" },
42320
+ button: {
42321
+ type: "string",
42322
+ description: "Mouse button to click: left, right, middle"
42323
+ },
42324
+ modifiers: {
42325
+ type: "array",
42326
+ items: { type: "string" },
42327
+ description: "Keyboard modifiers: Alt, Control, Meta, Shift"
42328
+ }
42329
+ },
42330
+ required: ["element"]
42331
+ }
42332
+ },
42333
+ {
42334
+ name: "browser_hover",
42335
+ description: "Hover over an element to reveal hidden content (dropdowns, tooltips, submenus). This does NOT click - use browser_click after hovering to interact with revealed items.",
42336
+ inputSchema: {
42337
+ type: "object",
42338
+ properties: {
42339
+ ref: { type: "string", description: "The element reference from snapshot" },
42340
+ element: { type: "string", description: "Description of what you are hovering over" }
42341
+ },
42342
+ required: ["ref", "element"]
42343
+ }
42344
+ },
42345
+ {
42346
+ name: "browser_drag",
42347
+ description: "Drag between two points. Provide EITHER refs OR coordinates.\n- **refs**: startRef + endRef \u2014 uses Playwright locators for drag-and-drop.\n- **coordinates**: startX, startY, endX, endY \u2014 drags between exact pixel positions.",
42348
+ inputSchema: {
42349
+ type: "object",
42350
+ properties: {
42351
+ startRef: { type: "string", description: "Starting element reference" },
42352
+ startElement: { type: "string", description: "Description of starting element" },
42353
+ endRef: { type: "string", description: "Target element reference" },
42354
+ endElement: { type: "string", description: "Description of target element" },
42355
+ startX: { type: "number", description: "Start X coordinate" },
42356
+ startY: { type: "number", description: "Start Y coordinate" },
42357
+ endX: { type: "number", description: "End X coordinate" },
42358
+ endY: { type: "number", description: "End Y coordinate" }
42359
+ },
42360
+ required: ["startElement", "endElement"]
42361
+ }
42362
+ },
42363
+ {
42364
+ name: "browser_type",
42365
+ description: 'Type text into an input field and optionally submit the form. WARNING: For date inputs (type="date"), use ISO format (YYYY-MM-DD) with browser_fill_form instead.',
42366
+ inputSchema: {
42367
+ type: "object",
42368
+ properties: {
42369
+ ref: { type: "string", description: "The element reference from snapshot" },
42370
+ text: { type: "string", description: "The text to type" },
42371
+ element: { type: "string", description: "Description of the input field" },
42372
+ submit: { type: "boolean", description: "Whether to submit the form after typing" },
42373
+ delay: { type: "number", description: "Delay between keystrokes in milliseconds" }
42374
+ },
42375
+ required: ["ref", "text", "element"]
42376
+ }
42377
+ },
42378
+ {
42379
+ name: "browser_press_key",
42380
+ description: "Press a keyboard key",
42381
+ inputSchema: {
42382
+ type: "object",
42383
+ properties: {
42384
+ key: {
42385
+ type: "string",
42386
+ description: 'Key to press (e.g., "Enter", "Escape", "ArrowDown")'
42387
+ }
42388
+ },
42389
+ required: ["key"]
42390
+ }
42391
+ },
42392
+ {
42393
+ name: "browser_fill_form",
42394
+ description: "Fill multiple form fields at once",
42395
+ inputSchema: {
42396
+ type: "object",
42397
+ properties: {
42398
+ fields: {
42399
+ type: "array",
42400
+ items: {
42401
+ type: "object",
42402
+ properties: {
42403
+ ref: { type: "string", description: "Element reference" },
42404
+ element: { type: "string", description: "Element description" },
42405
+ value: { type: "string", description: "Value to fill" }
42406
+ },
42407
+ required: ["ref", "value"]
42408
+ },
42409
+ description: "Array of form fields to fill"
42410
+ }
42411
+ },
42412
+ required: ["fields"]
42413
+ }
42414
+ },
42415
+ {
42416
+ name: "browser_select_option",
42417
+ description: "Select an option from a dropdown",
42418
+ inputSchema: {
42419
+ type: "object",
42420
+ properties: {
42421
+ ref: { type: "string", description: "Select element reference" },
42422
+ value: { type: "string", description: "Option value to select" },
42423
+ element: { type: "string", description: "Description of the dropdown" }
42424
+ },
42425
+ required: ["ref", "value", "element"]
42426
+ }
42427
+ },
42428
+ {
42429
+ name: "browser_file_upload",
42430
+ description: "Upload one or multiple files",
42431
+ inputSchema: {
42432
+ type: "object",
42433
+ properties: {
42434
+ paths: {
42435
+ type: "array",
42436
+ items: { type: "string" },
42437
+ description: "Array of file paths to upload"
42438
+ }
42439
+ },
42440
+ required: ["paths"]
42441
+ }
42442
+ },
42443
+ {
42444
+ name: "browser_scroll",
42445
+ description: "Scroll the page. Returns a screenshot showing the new viewport. Three modes:\n1. **Scroll at coordinates**: Use x + y to scroll at a specific point\n2. **Scroll by amount**: Use direction + amount to scroll up/down/left/right\n3. **Scroll to element**: Use toRef to scroll so that element is centered in the viewport",
42446
+ inputSchema: {
42447
+ type: "object",
42448
+ properties: {
42449
+ direction: {
42450
+ type: "string",
42451
+ enum: ["up", "down", "left", "right"],
42452
+ description: "Direction to scroll (ignored if toRef is provided)"
42453
+ },
42454
+ amount: {
42455
+ type: "number",
42456
+ description: "Scroll intensity from 1-10 (default 3). Ignored if toRef is provided."
42457
+ },
42458
+ withinRef: {
42459
+ type: "string",
42460
+ description: "Scroll within this scrollable element instead of the page"
42461
+ },
42462
+ toRef: {
42463
+ type: "string",
42464
+ description: "Scroll the page so this element is centered in the viewport. Handles both vertical and horizontal scrolling automatically \u2014 works for grid columns that are horizontally off-screen."
42465
+ },
42466
+ x: {
42467
+ type: "number",
42468
+ description: "X coordinate for visual scroll origin."
42469
+ },
42470
+ y: {
42471
+ type: "number",
42472
+ description: "Y coordinate for visual scroll origin."
42473
+ }
42474
+ },
42475
+ required: ["direction"]
42476
+ }
42477
+ },
42478
+ {
42479
+ name: "browser_handle_dialog",
42480
+ description: 'Pre-register how to handle the next browser dialog (alert, confirm, prompt). Call this with action "accept" BEFORE re-clicking the button that triggered the dialog.',
42481
+ inputSchema: {
42482
+ type: "object",
42483
+ properties: {
42484
+ action: {
42485
+ type: "string",
42486
+ enum: ["accept", "dismiss"],
42487
+ description: "Action to take on the dialog"
42488
+ },
42489
+ promptText: { type: "string", description: "Text to enter in prompt dialog" }
42490
+ },
42491
+ required: ["action"]
42492
+ }
42493
+ },
42494
+ {
42495
+ name: "browser_dismiss_overlay",
42496
+ description: "Systematically attempt to dismiss any modal, overlay, or dialog blocking the page. Tries multiple strategies: Escape key, close button, backdrop click.",
42497
+ inputSchema: {
42498
+ type: "object",
42499
+ properties: {
42500
+ preferredStrategy: {
42501
+ type: "string",
42502
+ enum: ["escape", "close_button", "backdrop", "auto"],
42503
+ description: 'Preferred dismissal method. "auto" (default) tries all strategies.'
42504
+ }
42505
+ }
42506
+ }
42507
+ },
42508
+ {
42509
+ name: "browser_wait_for",
42510
+ description: "Wait for a condition or time period",
42511
+ inputSchema: {
42512
+ type: "object",
42513
+ properties: {
42514
+ time: { type: "number", description: "Time to wait in seconds" },
42515
+ text: { type: "string", description: "Text to wait for to appear" },
42516
+ textGone: { type: "string", description: "Text to wait for to disappear" },
42517
+ selector: { type: "string", description: "CSS selector to wait for" },
42518
+ state: {
42519
+ type: "string",
42520
+ description: "State to wait for (visible, hidden, attached, detached)"
42521
+ },
42522
+ timeout: { type: "number", description: "Maximum wait time in milliseconds" }
42523
+ }
42524
+ }
42525
+ },
42526
+ {
42527
+ name: "browser_close",
42528
+ description: "Close the current page",
42529
+ inputSchema: {
42530
+ type: "object",
42531
+ properties: {}
42532
+ }
42533
+ },
42534
+ {
42535
+ name: "browser_resize",
42536
+ description: "Resize the browser viewport",
42537
+ inputSchema: {
42538
+ type: "object",
42539
+ properties: {
42540
+ width: { type: "number", description: "Viewport width in pixels" },
42541
+ height: { type: "number", description: "Viewport height in pixels" }
42542
+ },
42543
+ required: ["width", "height"]
42544
+ }
42545
+ },
42546
+ {
42547
+ name: "browser_tabs",
42548
+ description: "List, create, close, or select a browser tab",
42549
+ inputSchema: {
42550
+ type: "object",
42551
+ properties: {
42552
+ action: {
42553
+ type: "string",
42554
+ enum: ["list", "new", "close", "select"],
42555
+ description: "Operation to perform"
42556
+ },
42557
+ index: {
42558
+ type: "number",
42559
+ description: "Tab index for close/select operations"
42560
+ }
42561
+ },
42562
+ required: ["action"]
42563
+ }
42564
+ },
42565
+ {
42566
+ name: "browser_list_downloads",
42567
+ description: "List all files downloaded during this browser session.",
42568
+ inputSchema: {
42569
+ type: "object",
42570
+ properties: {}
42571
+ }
42572
+ },
42573
+ {
42574
+ name: "browser_read_download",
42575
+ description: "Read the content of a downloaded file. For PDFs, extracts text. For text formats, reads as text. Binary files return metadata only.",
42576
+ inputSchema: {
42577
+ type: "object",
42578
+ properties: {
42579
+ downloadId: {
42580
+ type: "number",
42581
+ description: "ID of the download to read. Defaults to most recent."
42582
+ }
42583
+ }
42584
+ }
42585
+ },
42586
+ {
42587
+ name: "browser_pdf_read",
42588
+ description: "Fetch a PDF from a URL and extract its text content using the browser's authenticated session.",
42589
+ inputSchema: {
42590
+ type: "object",
42591
+ properties: {
42592
+ url: {
42593
+ type: "string",
42594
+ description: "The URL of the PDF to fetch and extract text from"
42595
+ }
42596
+ },
42597
+ required: ["url"]
42598
+ }
42599
+ }
42600
+ ];
42601
+ }
42602
+ var BROWSER_LIFECYCLE_TOOLS = ["browser_start", "browser_stop"];
42603
+ function getBrowserToolDefinitionsWithLifecycle() {
42604
+ return [
42605
+ {
42606
+ name: "browser_start",
42607
+ description: "Launch a local browser for direct automation. Returns when browser is ready. The browser opens in headed mode so you can watch it.",
42608
+ inputSchema: {
42609
+ type: "object",
42610
+ properties: {
42611
+ headless: {
42612
+ type: "boolean",
42613
+ description: "Run browser headless (default: false \u2014 headed so you can watch)"
42614
+ },
42615
+ storageStatePath: {
42616
+ type: "string",
42617
+ description: "Path to Playwright storage state JSON for pre-authenticated sessions"
42618
+ }
42619
+ }
42620
+ }
42621
+ },
42622
+ {
42623
+ name: "browser_stop",
42624
+ description: "Stop the local browser and clean up resources.",
42625
+ inputSchema: {
42626
+ type: "object",
42627
+ properties: {}
42628
+ }
42629
+ },
42630
+ ...getBrowserToolDefinitions()
42631
+ ];
42632
+ }
42633
+
42634
+ // ../browser-core/src/tools/dispatcher.ts
42635
+ async function dispatchBrowserTool(executor, toolName, args) {
42636
+ switch (toolName) {
42637
+ case "browser_navigate":
42638
+ return executor.navigate(args.url);
42639
+ case "browser_navigate_back":
42640
+ return executor.navigateBack();
42641
+ case "browser_snapshot":
42642
+ return executor.snapshot({
42643
+ mode: args.mode,
42644
+ expand: args.expand,
42645
+ search: args.search,
42646
+ showCoordinateGrid: args.showCoordinateGrid,
42647
+ probeAt: args.probeAt
42648
+ });
42649
+ case "browser_screenshot":
42650
+ return executor.screenshot({
42651
+ fullPage: args.fullPage,
42652
+ element: args.element,
42653
+ ref: args.ref,
42654
+ label: args.label,
42655
+ returnImage: args.returnImage
42656
+ });
42657
+ case "browser_evaluate":
42658
+ return executor.evaluate({
42659
+ expression: args.function,
42660
+ element: args.element,
42661
+ ref: args.ref
42662
+ });
42663
+ case "browser_console_messages":
42664
+ return executor.consoleMessages({
42665
+ onlyErrors: args.onlyErrors
42666
+ });
42667
+ case "browser_network_requests":
42668
+ return executor.networkRequests();
42669
+ case "browser_click":
42670
+ return executor.click({
42671
+ ref: args.ref,
42672
+ x: args.x,
42673
+ y: args.y,
42674
+ element: args.element,
42675
+ doubleClick: args.doubleClick,
42676
+ button: args.button,
42677
+ modifiers: args.modifiers
42678
+ });
42679
+ case "browser_hover":
42680
+ return executor.hover({
42681
+ ref: args.ref,
42682
+ element: args.element
42683
+ });
42684
+ case "browser_drag":
42685
+ return executor.drag({
42686
+ startRef: args.startRef,
42687
+ endRef: args.endRef,
42688
+ startElement: args.startElement,
42689
+ endElement: args.endElement,
42690
+ startX: args.startX,
42691
+ startY: args.startY,
42692
+ endX: args.endX,
42693
+ endY: args.endY
42694
+ });
42695
+ case "browser_type":
42696
+ return executor.type({
42697
+ ref: args.ref,
42698
+ text: args.text,
42699
+ element: args.element,
42700
+ submit: args.submit,
42701
+ delay: args.delay
42702
+ });
42703
+ case "browser_press_key":
42704
+ return executor.pressKey(args.key);
42705
+ case "browser_fill_form":
42706
+ return executor.fillForm(
42707
+ args.fields
42708
+ );
42709
+ case "browser_select_option":
42710
+ return executor.selectOption({
42711
+ ref: args.ref,
42712
+ value: args.value,
42713
+ element: args.element
42714
+ });
42715
+ case "browser_file_upload":
42716
+ return executor.fileUpload(args.paths);
42717
+ case "browser_scroll":
42718
+ return executor.scroll({
42719
+ direction: args.direction,
42720
+ amount: args.amount,
42721
+ withinRef: args.withinRef,
42722
+ toRef: args.toRef,
42723
+ x: args.x,
42724
+ y: args.y
42725
+ });
42726
+ case "browser_handle_dialog":
42727
+ return executor.handleDialog({
42728
+ action: args.action,
42729
+ promptText: args.promptText
42730
+ });
42731
+ case "browser_dismiss_overlay":
42732
+ return executor.dismissOverlay({
42733
+ preferredStrategy: args.preferredStrategy
42734
+ });
42735
+ case "browser_wait_for":
42736
+ return executor.waitFor({
42737
+ timeSec: args.time,
42738
+ text: args.text,
42739
+ textGone: args.textGone,
42740
+ selector: args.selector,
42741
+ state: args.state,
42742
+ timeout: args.timeout
42743
+ });
42744
+ case "browser_close":
42745
+ return executor.close();
42746
+ case "browser_resize":
42747
+ return executor.resize(args.width, args.height);
42748
+ case "browser_tabs":
42749
+ return executor.tabs({
42750
+ action: args.action,
42751
+ index: args.index
42752
+ });
42753
+ case "browser_list_downloads":
42754
+ return executor.listDownloads();
42755
+ case "browser_read_download":
42756
+ return executor.readDownload(args.downloadId);
42757
+ case "browser_pdf_read":
42758
+ return executor.fetchPdfText(args.url);
42759
+ default:
42760
+ throw new Error(`Unknown browser tool: ${toolName}`);
42761
+ }
42762
+ }
42763
+
42764
+ // ../browser-core/src/tools/consolidated-definitions.ts
42765
+ function getConsolidatedBrowserToolDefinitions() {
42766
+ return [
42767
+ // --- Navigation ---
42768
+ {
42769
+ name: "browser_navigate",
42770
+ description: 'Navigate to a URL in the browser. Use url "back" to go to the previous page.',
42771
+ inputSchema: {
42772
+ type: "object",
42773
+ properties: {
42774
+ url: {
42775
+ type: "string",
42776
+ description: 'The URL to navigate to. Use "back" to go to the previous page.'
42777
+ }
42778
+ },
42779
+ required: ["url"]
42780
+ }
42781
+ },
42782
+ // --- Page Inspection ---
42783
+ {
42784
+ name: "browser_snapshot",
42785
+ description: 'Get a snapshot of the page accessibility tree. Use search="term" to find elements near your current focus. Search returns ONLY relevant matches within your working context (the dialog, form, or section containing the active element). Results are highlighted in frontmatter with coordinates and on screenshot.',
42786
+ inputSchema: {
42787
+ type: "object",
42788
+ properties: {
42789
+ mode: {
42790
+ type: "string",
42791
+ enum: ["both", "screenshot", "tree"],
42792
+ description: 'What to return: "both" (default) = tree + screenshot, "screenshot" = screenshot only (use coordinate-based clicking), "tree" = tree only'
42793
+ },
42794
+ expand: {
42795
+ type: "string",
42796
+ description: "Ref of a collapsed section to expand and show full details"
42797
+ },
42798
+ search: {
42799
+ type: "string",
42800
+ description: 'Search for 1-2 specific terms to LOCATE elements for your next action. Terms are OR-matched (use "|"), case-insensitive, and ignore punctuation. Results filtered to your current working context (not the whole page). IMPORTANT: Search overlays can obscure subtle UI states. Use search to LOCATE elements, not to VALIDATE visual states. If search results are confusing, take a snapshot without search for a clearer view. Example: "Save" or "Email|Username"'
42801
+ },
42802
+ showCoordinateGrid: {
42803
+ type: "boolean",
42804
+ description: "Overlay a coordinate grid showing pixel positions. Helps estimate click coordinates when using coordinate-based interaction."
42805
+ },
42806
+ probeAt: {
42807
+ type: "object",
42808
+ properties: {
42809
+ x: { type: "number", description: "X coordinate in viewport pixels" },
42810
+ y: { type: "number", description: "Y coordinate in viewport pixels" }
42811
+ },
42812
+ required: ["x", "y"],
42813
+ description: 'RECOMMENDED before any coordinate-based click. Probes what element is at a pixel position. Returns the full tree with a PROBE RESULT in frontmatter showing the ref, role, and label of the element at those coordinates. If the probe returns a ref, prefer browser_action action="click" ref=... over coordinate clicking. Mutually exclusive with search.'
42814
+ }
42815
+ }
42816
+ }
42817
+ },
42818
+ {
42819
+ name: "browser_screenshot",
42820
+ description: "Take a screenshot of the current page or a specific element. Optionally provide a human-readable label to reference this screenshot later.",
42821
+ inputSchema: {
42822
+ type: "object",
42823
+ properties: {
42824
+ fullPage: {
42825
+ type: "boolean",
42826
+ description: "Whether to capture the full page or just viewport"
42827
+ },
42828
+ element: { type: "string", description: "Human-readable element description" },
42829
+ ref: { type: "string", description: "Exact element reference from snapshot" },
42830
+ label: {
42831
+ type: "string",
42832
+ description: "Human-readable label to reference this screenshot later"
42833
+ },
42834
+ returnImage: {
42835
+ type: "boolean",
42836
+ description: "When true, returns the image data so the model can see it. Use sparingly as images consume many tokens."
42837
+ }
42838
+ }
42839
+ }
42840
+ },
42841
+ // --- Code Execution ---
42842
+ {
42843
+ name: "browser_evaluate",
42844
+ description: "Execute JavaScript in the page context and return the result",
42845
+ inputSchema: {
42846
+ type: "object",
42847
+ properties: {
42848
+ function: {
42849
+ type: "string",
42850
+ description: 'JavaScript function to execute (e.g., "() => window.location.href")'
42851
+ },
42852
+ element: {
42853
+ type: "string",
42854
+ description: "Human-readable element description to evaluate on"
42855
+ },
42856
+ ref: { type: "string", description: "Exact element reference to evaluate on" }
42857
+ },
42858
+ required: ["function"]
42859
+ }
42860
+ },
42861
+ {
42862
+ name: "browser_run_code",
42863
+ description: "Execute Playwright Node.js code with `page` object access. Runs in Node.js, NOT in the browser.",
42181
42864
  inputSchema: {
42182
42865
  type: "object",
42183
- properties: {}
42866
+ properties: {
42867
+ code: {
42868
+ type: "string",
42869
+ description: 'Playwright code to run with access to `page` object (e.g., `await page.getByRole("button", { name: "Submit" }).click();`)'
42870
+ }
42871
+ },
42872
+ required: ["code"]
42184
42873
  }
42185
42874
  },
42875
+ // --- Consolidated: browser_action (click + hover + type) ---
42186
42876
  {
42187
- name: "browser_click",
42188
- description: "Click an element on the page. Provide EITHER a ref from the snapshot OR coordinates (x, y).\n- **ref**: Uses Playwright locator - handles scrolling into view and actionability checks automatically.\n- **coordinates**: Clicks at exact pixel position - useful when ref-based clicking fails due to overlays.\nAlways describe what you are clicking in the element parameter.",
42877
+ name: "browser_action",
42878
+ description: 'Interact with a page element. Use action="click" to click, "hover" to reveal dropdowns/tooltips, "type" to enter text.\n- **click**: Provide ref OR coordinates (x, y). Always describe what you are clicking in element.\n- **hover**: Provide ref. Reveals hidden content without clicking.\n- **type**: Provide ref + text. Types into an input field. For date inputs, use browser_fill_form instead.',
42189
42879
  inputSchema: {
42190
42880
  type: "object",
42191
42881
  properties: {
42882
+ action: {
42883
+ type: "string",
42884
+ enum: ["click", "hover", "type"],
42885
+ description: "The interaction to perform"
42886
+ },
42192
42887
  ref: {
42193
42888
  type: "string",
42194
- description: "Element reference from snapshot (optional if x/y coordinates provided)"
42889
+ description: "Element reference from snapshot"
42195
42890
  },
42196
- x: { type: "number", description: "X coordinate on the page (use with y)" },
42197
- y: { type: "number", description: "Y coordinate on the page (use with x)" },
42198
- element: { type: "string", description: "Description of what you are clicking" },
42199
- doubleClick: { type: "boolean", description: "Perform a double click" },
42891
+ element: {
42892
+ type: "string",
42893
+ description: "Description of the element you are interacting with"
42894
+ },
42895
+ // click-specific
42896
+ x: { type: "number", description: "X coordinate on the page (click only, use with y)" },
42897
+ y: { type: "number", description: "Y coordinate on the page (click only, use with x)" },
42898
+ doubleClick: { type: "boolean", description: "Perform a double click (click only)" },
42200
42899
  button: {
42201
42900
  type: "string",
42202
- description: "Mouse button to click: left, right, middle"
42901
+ description: "Mouse button: left, right, middle (click only)"
42203
42902
  },
42204
42903
  modifiers: {
42205
42904
  type: "array",
42206
42905
  items: { type: "string" },
42207
- description: "Keyboard modifiers: Alt, Control, Meta, Shift"
42208
- }
42209
- },
42210
- required: ["element"]
42211
- }
42212
- },
42213
- {
42214
- name: "browser_hover",
42215
- description: "Hover over an element to reveal hidden content (dropdowns, tooltips, submenus). This does NOT click - use browser_click after hovering to interact with revealed items.",
42216
- inputSchema: {
42217
- type: "object",
42218
- properties: {
42219
- ref: { type: "string", description: "The element reference from snapshot" },
42220
- element: { type: "string", description: "Description of what you are hovering over" }
42906
+ description: "Keyboard modifiers: Alt, Control, Meta, Shift (click only)"
42907
+ },
42908
+ // type-specific
42909
+ text: { type: "string", description: "The text to type (type only)" },
42910
+ submit: { type: "boolean", description: "Submit the form after typing (type only)" },
42911
+ delay: { type: "number", description: "Delay between keystrokes in ms (type only)" }
42221
42912
  },
42222
- required: ["ref", "element"]
42913
+ required: ["action", "element"]
42223
42914
  }
42224
42915
  },
42916
+ // --- Kept separate ---
42225
42917
  {
42226
42918
  name: "browser_drag",
42227
42919
  description: "Drag between two points. Provide EITHER refs OR coordinates.\n- **refs**: startRef + endRef \u2014 uses Playwright locators for drag-and-drop.\n- **coordinates**: startX, startY, endX, endY \u2014 drags between exact pixel positions.",
@@ -42240,21 +42932,6 @@ function getBrowserToolDefinitions() {
42240
42932
  required: ["startElement", "endElement"]
42241
42933
  }
42242
42934
  },
42243
- {
42244
- name: "browser_type",
42245
- description: 'Type text into an input field and optionally submit the form. WARNING: For date inputs (type="date"), use ISO format (YYYY-MM-DD) with browser_fill_form instead.',
42246
- inputSchema: {
42247
- type: "object",
42248
- properties: {
42249
- ref: { type: "string", description: "The element reference from snapshot" },
42250
- text: { type: "string", description: "The text to type" },
42251
- element: { type: "string", description: "Description of the input field" },
42252
- submit: { type: "boolean", description: "Whether to submit the form after typing" },
42253
- delay: { type: "number", description: "Delay between keystrokes in milliseconds" }
42254
- },
42255
- required: ["ref", "text", "element"]
42256
- }
42257
- },
42258
42935
  {
42259
42936
  name: "browser_press_key",
42260
42937
  description: "Press a keyboard key",
@@ -42341,50 +43018,14 @@ function getBrowserToolDefinitions() {
42341
43018
  },
42342
43019
  toRef: {
42343
43020
  type: "string",
42344
- description: "Scroll the page so this element is centered in the viewport. Handles both vertical and horizontal scrolling automatically \u2014 works for grid columns that are horizontally off-screen."
43021
+ description: "Scroll the page so this element is centered in the viewport. Handles both vertical and horizontal scrolling automatically."
42345
43022
  },
42346
- x: {
42347
- type: "number",
42348
- description: "X coordinate for visual scroll origin."
42349
- },
42350
- y: {
42351
- type: "number",
42352
- description: "Y coordinate for visual scroll origin."
42353
- }
43023
+ x: { type: "number", description: "X coordinate for visual scroll origin." },
43024
+ y: { type: "number", description: "Y coordinate for visual scroll origin." }
42354
43025
  },
42355
43026
  required: ["direction"]
42356
43027
  }
42357
43028
  },
42358
- {
42359
- name: "browser_handle_dialog",
42360
- description: 'Pre-register how to handle the next browser dialog (alert, confirm, prompt). Call this with action "accept" BEFORE re-clicking the button that triggered the dialog.',
42361
- inputSchema: {
42362
- type: "object",
42363
- properties: {
42364
- action: {
42365
- type: "string",
42366
- enum: ["accept", "dismiss"],
42367
- description: "Action to take on the dialog"
42368
- },
42369
- promptText: { type: "string", description: "Text to enter in prompt dialog" }
42370
- },
42371
- required: ["action"]
42372
- }
42373
- },
42374
- {
42375
- name: "browser_dismiss_overlay",
42376
- description: "Systematically attempt to dismiss any modal, overlay, or dialog blocking the page. Tries multiple strategies: Escape key, close button, backdrop click.",
42377
- inputSchema: {
42378
- type: "object",
42379
- properties: {
42380
- preferredStrategy: {
42381
- type: "string",
42382
- enum: ["escape", "close_button", "backdrop", "auto"],
42383
- description: 'Preferred dismissal method. "auto" (default) tries all strategies.'
42384
- }
42385
- }
42386
- }
42387
- },
42388
43029
  {
42389
43030
  name: "browser_wait_for",
42390
43031
  description: "Wait for a condition or time period",
@@ -42403,14 +43044,6 @@ function getBrowserToolDefinitions() {
42403
43044
  }
42404
43045
  }
42405
43046
  },
42406
- {
42407
- name: "browser_close",
42408
- description: "Close the current page",
42409
- inputSchema: {
42410
- type: "object",
42411
- properties: {}
42412
- }
42413
- },
42414
43047
  {
42415
43048
  name: "browser_resize",
42416
43049
  description: "Resize the browser viewport",
@@ -42442,45 +43075,70 @@ function getBrowserToolDefinitions() {
42442
43075
  required: ["action"]
42443
43076
  }
42444
43077
  },
43078
+ // --- Consolidated: browser_dialog (replaces browser_handle_dialog) ---
42445
43079
  {
42446
- name: "browser_list_downloads",
42447
- description: "List all files downloaded during this browser session.",
43080
+ name: "browser_dialog",
43081
+ description: 'Pre-register how to handle the next browser dialog (alert, confirm, prompt). Call this with action "accept" BEFORE re-clicking the button that triggered the dialog.',
42448
43082
  inputSchema: {
42449
43083
  type: "object",
42450
- properties: {}
43084
+ properties: {
43085
+ action: {
43086
+ type: "string",
43087
+ enum: ["accept", "dismiss"],
43088
+ description: "Action to take on the dialog"
43089
+ },
43090
+ promptText: { type: "string", description: "Text to enter in prompt dialog" }
43091
+ },
43092
+ required: ["action"]
42451
43093
  }
42452
43094
  },
43095
+ // --- Consolidated: browser_devtools (console + network) ---
42453
43096
  {
42454
- name: "browser_read_download",
42455
- description: "Read the content of a downloaded file. For PDFs, extracts text. For text formats, reads as text. Binary files return metadata only.",
43097
+ name: "browser_devtools",
43098
+ description: 'Access browser developer tools data. Use target="console" to get console messages, target="network" to get network requests.',
42456
43099
  inputSchema: {
42457
43100
  type: "object",
42458
43101
  properties: {
42459
- downloadId: {
42460
- type: "number",
42461
- description: "ID of the download to read. Defaults to most recent."
43102
+ target: {
43103
+ type: "string",
43104
+ enum: ["console", "network"],
43105
+ description: 'What to inspect: "console" for console messages, "network" for network requests'
43106
+ },
43107
+ onlyErrors: {
43108
+ type: "boolean",
43109
+ description: "Only return error messages (console target only)"
42462
43110
  }
42463
- }
43111
+ },
43112
+ required: ["target"]
42464
43113
  }
42465
43114
  },
43115
+ // --- Consolidated: browser_download (list + read + pdf) ---
42466
43116
  {
42467
- name: "browser_pdf_read",
42468
- description: "Fetch a PDF from a URL and extract its text content using the browser's authenticated session.",
43117
+ name: "browser_download",
43118
+ description: `Manage downloaded files. Use action="list" to list downloads, "read" to read a download's content, "pdf" to fetch and extract text from a PDF URL using the browser's authenticated session.`,
42469
43119
  inputSchema: {
42470
43120
  type: "object",
42471
43121
  properties: {
43122
+ action: {
43123
+ type: "string",
43124
+ enum: ["list", "read", "pdf"],
43125
+ description: 'Operation: "list" downloads, "read" a download, or fetch a "pdf" from URL'
43126
+ },
43127
+ downloadId: {
43128
+ type: "number",
43129
+ description: 'ID of the download to read (for action="read"). Defaults to most recent.'
43130
+ },
42472
43131
  url: {
42473
43132
  type: "string",
42474
- description: "The URL of the PDF to fetch and extract text from"
43133
+ description: 'URL of the PDF to fetch (for action="pdf")'
42475
43134
  }
42476
43135
  },
42477
- required: ["url"]
43136
+ required: ["action"]
42478
43137
  }
42479
43138
  }
42480
43139
  ];
42481
43140
  }
42482
- var BROWSER_LIFECYCLE_TOOLS = ["browser_start", "browser_stop"];
42483
- function getBrowserToolDefinitionsWithLifecycle() {
43141
+ function getConsolidatedBrowserToolDefinitionsWithLifecycle() {
42484
43142
  return [
42485
43143
  {
42486
43144
  name: "browser_start",
@@ -42507,17 +43165,23 @@ function getBrowserToolDefinitionsWithLifecycle() {
42507
43165
  properties: {}
42508
43166
  }
42509
43167
  },
42510
- ...getBrowserToolDefinitions()
43168
+ ...getConsolidatedBrowserToolDefinitions()
42511
43169
  ];
42512
43170
  }
42513
43171
 
42514
- // ../browser-core/src/tools/dispatcher.ts
42515
- async function dispatchBrowserTool(executor, toolName, args) {
43172
+ // ../browser-core/src/tools/consolidated-dispatcher.ts
43173
+ async function dispatchConsolidatedBrowserTool(executor, toolName, args) {
42516
43174
  switch (toolName) {
43175
+ // --- Navigation ---
42517
43176
  case "browser_navigate":
43177
+ if (args.url === "back") {
43178
+ return executor.navigateBack();
43179
+ }
42518
43180
  return executor.navigate(args.url);
43181
+ // Legacy alias
42519
43182
  case "browser_navigate_back":
42520
43183
  return executor.navigateBack();
43184
+ // --- Page Inspection (unchanged) ---
42521
43185
  case "browser_snapshot":
42522
43186
  return executor.snapshot({
42523
43187
  mode: args.mode,
@@ -42534,18 +43198,45 @@ async function dispatchBrowserTool(executor, toolName, args) {
42534
43198
  label: args.label,
42535
43199
  returnImage: args.returnImage
42536
43200
  });
43201
+ // --- Code Execution (unchanged) ---
42537
43202
  case "browser_evaluate":
42538
43203
  return executor.evaluate({
42539
43204
  expression: args.function,
42540
43205
  element: args.element,
42541
43206
  ref: args.ref
42542
43207
  });
42543
- case "browser_console_messages":
42544
- return executor.consoleMessages({
42545
- onlyErrors: args.onlyErrors
42546
- });
42547
- case "browser_network_requests":
42548
- return executor.networkRequests();
43208
+ // --- Consolidated: browser_action (click + hover + type) ---
43209
+ case "browser_action": {
43210
+ const action = args.action;
43211
+ switch (action) {
43212
+ case "click":
43213
+ return executor.click({
43214
+ ref: args.ref,
43215
+ x: args.x,
43216
+ y: args.y,
43217
+ element: args.element,
43218
+ doubleClick: args.doubleClick,
43219
+ button: args.button,
43220
+ modifiers: args.modifiers
43221
+ });
43222
+ case "hover":
43223
+ return executor.hover({
43224
+ ref: args.ref,
43225
+ element: args.element
43226
+ });
43227
+ case "type":
43228
+ return executor.type({
43229
+ ref: args.ref,
43230
+ text: args.text,
43231
+ element: args.element,
43232
+ submit: args.submit,
43233
+ delay: args.delay
43234
+ });
43235
+ default:
43236
+ throw new Error(`Unknown browser_action action: ${action}`);
43237
+ }
43238
+ }
43239
+ // Legacy aliases for browser_action
42549
43240
  case "browser_click":
42550
43241
  return executor.click({
42551
43242
  ref: args.ref,
@@ -42561,6 +43252,15 @@ async function dispatchBrowserTool(executor, toolName, args) {
42561
43252
  ref: args.ref,
42562
43253
  element: args.element
42563
43254
  });
43255
+ case "browser_type":
43256
+ return executor.type({
43257
+ ref: args.ref,
43258
+ text: args.text,
43259
+ element: args.element,
43260
+ submit: args.submit,
43261
+ delay: args.delay
43262
+ });
43263
+ // --- Kept separate (unchanged) ---
42564
43264
  case "browser_drag":
42565
43265
  return executor.drag({
42566
43266
  startRef: args.startRef,
@@ -42572,14 +43272,6 @@ async function dispatchBrowserTool(executor, toolName, args) {
42572
43272
  endX: args.endX,
42573
43273
  endY: args.endY
42574
43274
  });
42575
- case "browser_type":
42576
- return executor.type({
42577
- ref: args.ref,
42578
- text: args.text,
42579
- element: args.element,
42580
- submit: args.submit,
42581
- delay: args.delay
42582
- });
42583
43275
  case "browser_press_key":
42584
43276
  return executor.pressKey(args.key);
42585
43277
  case "browser_fill_form":
@@ -42603,15 +43295,6 @@ async function dispatchBrowserTool(executor, toolName, args) {
42603
43295
  x: args.x,
42604
43296
  y: args.y
42605
43297
  });
42606
- case "browser_handle_dialog":
42607
- return executor.handleDialog({
42608
- action: args.action,
42609
- promptText: args.promptText
42610
- });
42611
- case "browser_dismiss_overlay":
42612
- return executor.dismissOverlay({
42613
- preferredStrategy: args.preferredStrategy
42614
- });
42615
43298
  case "browser_wait_for":
42616
43299
  return executor.waitFor({
42617
43300
  timeSec: args.time,
@@ -42621,8 +43304,6 @@ async function dispatchBrowserTool(executor, toolName, args) {
42621
43304
  state: args.state,
42622
43305
  timeout: args.timeout
42623
43306
  });
42624
- case "browser_close":
42625
- return executor.close();
42626
43307
  case "browser_resize":
42627
43308
  return executor.resize(args.width, args.height);
42628
43309
  case "browser_tabs":
@@ -42630,12 +43311,64 @@ async function dispatchBrowserTool(executor, toolName, args) {
42630
43311
  action: args.action,
42631
43312
  index: args.index
42632
43313
  });
43314
+ // --- Consolidated: browser_dialog ---
43315
+ case "browser_dialog":
43316
+ return executor.handleDialog({
43317
+ action: args.action,
43318
+ promptText: args.promptText
43319
+ });
43320
+ // Legacy alias
43321
+ case "browser_handle_dialog":
43322
+ return executor.handleDialog({
43323
+ action: args.action,
43324
+ promptText: args.promptText
43325
+ });
43326
+ // --- Consolidated: browser_devtools ---
43327
+ case "browser_devtools": {
43328
+ const target = args.target;
43329
+ if (target === "console") {
43330
+ return executor.consoleMessages({
43331
+ onlyErrors: args.onlyErrors
43332
+ });
43333
+ }
43334
+ return executor.networkRequests();
43335
+ }
43336
+ // Legacy aliases
43337
+ case "browser_console_messages":
43338
+ return executor.consoleMessages({
43339
+ onlyErrors: args.onlyErrors
43340
+ });
43341
+ case "browser_network_requests":
43342
+ return executor.networkRequests();
43343
+ // --- Consolidated: browser_download ---
43344
+ case "browser_download": {
43345
+ const downloadAction = args.action;
43346
+ switch (downloadAction) {
43347
+ case "list":
43348
+ return executor.listDownloads();
43349
+ case "read":
43350
+ return executor.readDownload(args.downloadId);
43351
+ case "pdf":
43352
+ return executor.fetchPdfText(args.url);
43353
+ default:
43354
+ throw new Error(`Unknown browser_download action: ${downloadAction}`);
43355
+ }
43356
+ }
43357
+ // Legacy aliases
42633
43358
  case "browser_list_downloads":
42634
43359
  return executor.listDownloads();
42635
43360
  case "browser_read_download":
42636
43361
  return executor.readDownload(args.downloadId);
42637
43362
  case "browser_pdf_read":
42638
43363
  return executor.fetchPdfText(args.url);
43364
+ // Legacy: browser_close (dropped but kept for compat)
43365
+ case "browser_close":
43366
+ return executor.close();
43367
+ // Legacy: browser_dismiss_overlay (dropped but kept for compat)
43368
+ case "browser_dismiss_overlay":
43369
+ return executor.dismissOverlay({
43370
+ preferredStrategy: args.preferredStrategy
43371
+ });
42639
43372
  default:
42640
43373
  throw new Error(`Unknown browser tool: ${toolName}`);
42641
43374
  }
@@ -44668,7 +45401,9 @@ function formatMcpResponse(input) {
44668
45401
  for (const toast of input.capturedToasts) {
44669
45402
  const remaining = toast.snapshotsRemaining ?? 1;
44670
45403
  const placementHint = toast.placement ? ` [visible at (${toast.placement.x}, ${toast.placement.y}), ${toast.placement.width}\xD7${toast.placement.height}px]` : "";
44671
- lines.push(`- [${toast.role}] ${toast.text}${placementHint} (expires in ${remaining} snapshot${remaining !== 1 ? "s" : ""})`);
45404
+ lines.push(
45405
+ `- [${toast.role}] ${toast.text}${placementHint} (expires in ${remaining} snapshot${remaining !== 1 ? "s" : ""})`
45406
+ );
44672
45407
  }
44673
45408
  lines.push("");
44674
45409
  }
@@ -44678,7 +45413,7 @@ function formatMcpResponse(input) {
44678
45413
  if (completedNew.length > 0) {
44679
45414
  lines.push("### Downloads");
44680
45415
  for (const dl of completedNew) {
44681
- const size = dl.sizeBytes != null ? ` (${formatFileSize(dl.sizeBytes)})` : "";
45416
+ const size = dl.sizeBytes !== null && dl.sizeBytes !== void 0 ? ` (${formatFileSize(dl.sizeBytes)})` : "";
44682
45417
  lines.push(
44683
45418
  `- [${dl.id}] ${dl.suggestedFilename}${size} \u2014 use browser_read_download to view content`
44684
45419
  );
@@ -44892,7 +45627,9 @@ var PlaywrightClient = class _PlaywrightClient {
44892
45627
  this.screencastEncoderFactory = options?.screencastEncoderFactory ?? null;
44893
45628
  this.cursorOverlay = new CursorOverlay({ enabled: false });
44894
45629
  if (!options?.tmpBaseDir) {
44895
- this.logger.debug("[PlaywrightClient] No tmpBaseDir provided, using flat canary dir (not org-scoped)");
45630
+ this.logger.debug(
45631
+ "[PlaywrightClient] No tmpBaseDir provided, using flat canary dir (not org-scoped)"
45632
+ );
44896
45633
  }
44897
45634
  this.tmpBaseDir = options?.tmpBaseDir ?? getCanaryTmpDir();
44898
45635
  }
@@ -44912,10 +45649,7 @@ var PlaywrightClient = class _PlaywrightClient {
44912
45649
  return Promise.race([
44913
45650
  operation,
44914
45651
  new Promise(
44915
- (_, reject2) => setTimeout(
44916
- () => reject2(new Error(`${label} timed out after ${timeoutMs}ms`)),
44917
- timeoutMs
44918
- )
45652
+ (_, reject2) => setTimeout(() => reject2(new Error(`${label} timed out after ${timeoutMs}ms`)), timeoutMs)
44919
45653
  )
44920
45654
  ]);
44921
45655
  }
@@ -45215,8 +45949,8 @@ var PlaywrightClient = class _PlaywrightClient {
45215
45949
  acceptDownloads: true
45216
45950
  };
45217
45951
  const mergedHeaders = {
45218
- ...this.lastConnectOptions?.extraHTTPHeaders ?? {},
45219
- ...options.extraHTTPHeaders ?? {}
45952
+ ...this.lastConnectOptions?.extraHTTPHeaders,
45953
+ ...options.extraHTTPHeaders
45220
45954
  };
45221
45955
  if (Object.keys(mergedHeaders).length > 0) {
45222
45956
  contextOptions.extraHTTPHeaders = mergedHeaders;
@@ -45491,13 +46225,10 @@ var PlaywrightClient = class _PlaywrightClient {
45491
46225
  const candidate = path4.join(cacheDir, dir, relativeBinaryPath);
45492
46226
  try {
45493
46227
  await fs4.access(candidate);
45494
- logger2.warn(
45495
- "[DirectPlaywright] Using fallback Chromium binary (version mismatch)",
45496
- {
45497
- expected: defaultPath,
45498
- using: candidate
45499
- }
45500
- );
46228
+ logger2.warn("[DirectPlaywright] Using fallback Chromium binary (version mismatch)", {
46229
+ expected: defaultPath,
46230
+ using: candidate
46231
+ });
45501
46232
  return candidate;
45502
46233
  } catch {
45503
46234
  continue;
@@ -45679,7 +46410,10 @@ var PlaywrightClient = class _PlaywrightClient {
45679
46410
  });
45680
46411
  this.lastKnownUrl = url;
45681
46412
  await this.stabilize("navigation");
45682
- const [snapshotYaml, title] = await Promise.all([this.captureSnapshotInternal(), page.title()]);
46413
+ const [snapshotYaml, title] = await Promise.all([
46414
+ this.captureSnapshotInternal(),
46415
+ this.getPage().then((p) => p.title())
46416
+ ]);
45683
46417
  return this.formatMCPResponse(
45684
46418
  `Navigated to ${url}`,
45685
46419
  snapshotYaml,
@@ -45695,7 +46429,10 @@ var PlaywrightClient = class _PlaywrightClient {
45695
46429
  this.logger.debug("[DirectPlaywright] Navigating back");
45696
46430
  await page.goBack({ timeout: opts?.timeoutMs ?? TIMEOUTS.NAVIGATE });
45697
46431
  await this.stabilize("navigation");
45698
- const [snapshotYaml, title] = await Promise.all([this.captureSnapshotInternal(), page.title()]);
46432
+ const [snapshotYaml, title] = await Promise.all([
46433
+ this.captureSnapshotInternal(),
46434
+ this.getPage().then((p) => p.title())
46435
+ ]);
45699
46436
  return this.formatMCPResponse("Navigated back", snapshotYaml, "await page.goBack();", title);
45700
46437
  }
45701
46438
  // ================ PAGE INSPECTION ================
@@ -45741,14 +46478,14 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
45741
46478
  }
45742
46479
  const [rawSnapshotYaml, title] = await Promise.all([
45743
46480
  this.captureSnapshotInternal(),
45744
- page.title()
46481
+ this.getPage().then((p) => p.title())
45745
46482
  ]);
45746
46483
  const snapshotYaml = this.filterSnapshot(
45747
46484
  rawSnapshotYaml,
45748
46485
  opts?.depth,
45749
46486
  opts?.filterToInteractive
45750
46487
  );
45751
- let snapshotText = this.formatMCPResponse("", snapshotYaml, void 0, title);
46488
+ const snapshotText = this.formatMCPResponse("", snapshotYaml, void 0, title);
45752
46489
  const DOM_COMPLEXITY_THRESHOLD = 3e4;
45753
46490
  const estimatedTokens = estimateTextTokens(snapshotText);
45754
46491
  const refCount = (snapshotYaml.match(/\[ref=/g) || []).length;
@@ -45924,7 +46661,9 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
45924
46661
  try {
45925
46662
  await page.waitForLoadState("networkidle", { timeout: timeoutMs });
45926
46663
  } catch {
45927
- this.logger.debug("[DirectPlaywright] waitForNetworkIdle timed out, proceeding", { timeoutMs });
46664
+ this.logger.debug("[DirectPlaywright] waitForNetworkIdle timed out, proceeding", {
46665
+ timeoutMs
46666
+ });
45928
46667
  }
45929
46668
  }
45930
46669
  getPendingNetworkInfo() {
@@ -46790,19 +47529,22 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
46790
47529
  async probeAtCoordinates(x2, y2, _opts) {
46791
47530
  try {
46792
47531
  const page = await this.getPage();
46793
- const elementInfo = await page.evaluate(({ px, py }) => {
46794
- const el = document.elementFromPoint(px, py);
46795
- if (!el) return null;
46796
- el.setAttribute("data-probe-target", "true");
46797
- return {
46798
- tagName: el.tagName.toLowerCase(),
46799
- id: el.id || void 0,
46800
- className: typeof el.className === "string" ? el.className || void 0 : void 0,
46801
- ariaLabel: el.getAttribute("aria-label") || void 0,
46802
- textContent: el.textContent?.trim().slice(0, 100) || void 0,
46803
- role: el.getAttribute("role") || void 0
46804
- };
46805
- }, { px: x2, py: y2 });
47532
+ const elementInfo = await page.evaluate(
47533
+ ({ px, py }) => {
47534
+ const el = document.elementFromPoint(px, py);
47535
+ if (!el) return null;
47536
+ el.setAttribute("data-probe-target", "true");
47537
+ return {
47538
+ tagName: el.tagName.toLowerCase(),
47539
+ id: el.id || void 0,
47540
+ className: typeof el.className === "string" ? el.className || void 0 : void 0,
47541
+ ariaLabel: el.getAttribute("aria-label") || void 0,
47542
+ textContent: el.textContent?.trim().slice(0, 100) || void 0,
47543
+ role: el.getAttribute("role") || void 0
47544
+ };
47545
+ },
47546
+ { px: x2, py: y2 }
47547
+ );
46806
47548
  if (!elementInfo) return null;
46807
47549
  let ref;
46808
47550
  let label;
@@ -46981,10 +47723,13 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
46981
47723
  });
46982
47724
  await new Promise((resolve2) => setTimeout(resolve2, 200 * attempt));
46983
47725
  } else {
46984
- this.logger.warn("[DirectPlaywright] All snapshot attempts failed, using empty fallback", {
46985
- attempts: maxRetries,
46986
- error: err instanceof Error ? err.message : String(err)
46987
- });
47726
+ this.logger.warn(
47727
+ "[DirectPlaywright] All snapshot attempts failed, using empty fallback",
47728
+ {
47729
+ attempts: maxRetries,
47730
+ error: err instanceof Error ? err.message : String(err)
47731
+ }
47732
+ );
46988
47733
  }
46989
47734
  }
46990
47735
  }
@@ -47174,7 +47919,10 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
47174
47919
  return;
47175
47920
  }
47176
47921
  if (!this.screencastManager) {
47177
- this.screencastManager = new CdpScreencastManager(options, this.screencastEncoderFactory ?? void 0);
47922
+ this.screencastManager = new CdpScreencastManager(
47923
+ options,
47924
+ this.screencastEncoderFactory ?? void 0
47925
+ );
47178
47926
  }
47179
47927
  this.screencastHandler = onFrame;
47180
47928
  await this.screencastManager.start(this.page, onFrame);
@@ -47707,21 +48455,37 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
47707
48455
  }
47708
48456
  };
47709
48457
  if (this.extensionsEnabled && this.context) {
47710
- this.logger.warn("[DirectPlaywright] Restoring page in existing persistent context", {
47711
- reason
47712
- });
47713
- await this.createPageWithListeners(this.context, reason);
47714
- await this.restoreUrlAfterRecovery(urlToRestore, crashType);
47715
- await restartScreencastIfNeeded();
47716
- return;
48458
+ try {
48459
+ this.logger.warn("[DirectPlaywright] Restoring page in existing persistent context", {
48460
+ reason
48461
+ });
48462
+ await this.createPageWithListeners(this.context, reason);
48463
+ await this.restoreUrlAfterRecovery(urlToRestore, crashType);
48464
+ await restartScreencastIfNeeded();
48465
+ return;
48466
+ } catch (err) {
48467
+ this.logger.warn(
48468
+ "[DirectPlaywright] Persistent context unusable, falling through to full recreation",
48469
+ { reason, error: err instanceof Error ? err.message : String(err) }
48470
+ );
48471
+ this.context = null;
48472
+ }
47717
48473
  }
47718
48474
  const reuseContext = this.browser?.isConnected() && this.context;
47719
48475
  if (reuseContext) {
47720
- this.logger.warn("[DirectPlaywright] Restoring page in existing context", { reason });
47721
- await this.createPageWithListeners(this.context, reason);
47722
- await this.restoreUrlAfterRecovery(urlToRestore, crashType);
47723
- await restartScreencastIfNeeded();
47724
- return;
48476
+ try {
48477
+ this.logger.warn("[DirectPlaywright] Restoring page in existing context", { reason });
48478
+ await this.createPageWithListeners(this.context, reason);
48479
+ await this.restoreUrlAfterRecovery(urlToRestore, crashType);
48480
+ await restartScreencastIfNeeded();
48481
+ return;
48482
+ } catch (err) {
48483
+ this.logger.warn(
48484
+ "[DirectPlaywright] Context unusable despite connected browser, falling through",
48485
+ { reason, error: err instanceof Error ? err.message : String(err) }
48486
+ );
48487
+ this.context = null;
48488
+ }
47725
48489
  }
47726
48490
  if (this.browserLease) {
47727
48491
  this.logger.warn("[DirectPlaywright] Recovering via pool lease", {
@@ -47730,7 +48494,11 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
47730
48494
  });
47731
48495
  const newLease = await this.browserLease.recover();
47732
48496
  this.browserLease = newLease;
47733
- const { storageStatePath: ssp, recordVideo: rv, extraHTTPHeaders: headers } = connectOptions;
48497
+ const {
48498
+ storageStatePath: ssp,
48499
+ recordVideo: rv,
48500
+ extraHTTPHeaders: headers
48501
+ } = connectOptions;
47734
48502
  const videoConfig2 = this.resolveVideoConfig(rv);
47735
48503
  this.videoEnabled = !!videoConfig2;
47736
48504
  this.videoDir = videoConfig2?.dir ?? null;
@@ -48001,7 +48769,7 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
48001
48769
  }
48002
48770
  const lines = [`${this._capturedDownloads.length} download(s):`];
48003
48771
  for (const dl of this._capturedDownloads) {
48004
- const size = dl.sizeBytes != null ? ` (${this.formatFileSize(dl.sizeBytes)})` : "";
48772
+ const size = dl.sizeBytes !== null && dl.sizeBytes !== void 0 ? ` (${this.formatFileSize(dl.sizeBytes)})` : "";
48005
48773
  let status;
48006
48774
  if (dl.completed) {
48007
48775
  status = "completed";
@@ -48018,7 +48786,7 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
48018
48786
  if (this._capturedDownloads.length === 0) {
48019
48787
  throw new Error("No downloads captured during this session.");
48020
48788
  }
48021
- const target = downloadId != null ? this._capturedDownloads.find((d) => d.id === downloadId) : this._capturedDownloads[this._capturedDownloads.length - 1];
48789
+ const target = downloadId !== null && downloadId !== void 0 ? this._capturedDownloads.find((d) => d.id === downloadId) : this._capturedDownloads[this._capturedDownloads.length - 1];
48022
48790
  if (!target) {
48023
48791
  throw new Error(
48024
48792
  `Download #${downloadId} not found. Use browser_list_downloads to see available downloads.`
@@ -48190,6 +48958,9 @@ export {
48190
48958
  BROWSER_LIFECYCLE_TOOLS,
48191
48959
  getBrowserToolDefinitionsWithLifecycle,
48192
48960
  dispatchBrowserTool,
48961
+ getConsolidatedBrowserToolDefinitions,
48962
+ getConsolidatedBrowserToolDefinitionsWithLifecycle,
48963
+ dispatchConsolidatedBrowserTool,
48193
48964
  extractSemanticHint,
48194
48965
  PlaywrightClient
48195
48966
  };
@@ -48472,4 +49243,4 @@ playwright-extra/dist/index.esm.js:
48472
49243
  * @license MIT
48473
49244
  *)
48474
49245
  */
48475
- //# sourceMappingURL=chunk-MSMC6UXW.js.map
49246
+ //# sourceMappingURL=chunk-6IAPGYZQ.js.map