@tontoko/fast-playwright-mcp 0.1.0 → 0.1.2
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/README.md +116 -96
- package/lib/diagnostics/page-analyzer.js +2 -1
- package/lib/schemas/expectation.js +5 -5
- package/lib/services/selector-resolver.js +541 -0
- package/lib/tab.js +47 -24
- package/lib/tools/base-tool-handler.js +3 -19
- package/lib/tools/batch-execute.js +1 -1
- package/lib/tools/dialogs.js +4 -4
- package/lib/tools/evaluate.js +14 -10
- package/lib/tools/files.js +3 -3
- package/lib/tools/inspect-html.js +238 -0
- package/lib/tools/keyboard.js +18 -20
- package/lib/tools/mouse.js +10 -10
- package/lib/tools/navigate.js +8 -8
- package/lib/tools/network.js +9 -9
- package/lib/tools/screenshot.js +17 -15
- package/lib/tools/shared-element-utils.js +60 -0
- package/lib/tools/snapshot.js +35 -37
- package/lib/tools/tabs.js +10 -10
- package/lib/tools/wait.js +5 -5
- package/lib/tools.js +2 -0
- package/lib/types/batch.js +2 -2
- package/lib/types/html-inspection.js +106 -0
- package/lib/types/selectors.js +126 -0
- package/lib/utilities/html-inspector.js +514 -0
- package/lib/utilities/index.js +24 -0
- package/lib/utils/tool-patterns.js +3 -30
- package/package.json +1 -1
package/lib/tools/snapshot.js
CHANGED
|
@@ -20,7 +20,13 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
20
20
|
// src/tools/snapshot.ts
|
|
21
21
|
import { z } from "zod";
|
|
22
22
|
import { expectationSchema } from "../schemas/expectation.js";
|
|
23
|
+
import { elementSelectorSchema } from "../types/selectors.js";
|
|
23
24
|
import { formatObject } from "../utils/codegen.js";
|
|
25
|
+
import {
|
|
26
|
+
handleSnapshotExpectation,
|
|
27
|
+
resolveDragElements,
|
|
28
|
+
resolveFirstElement
|
|
29
|
+
} from "./shared-element-utils.js";
|
|
24
30
|
import { defineTabTool, defineTool } from "./tool.js";
|
|
25
31
|
import { generateLocator } from "./utils.js";
|
|
26
32
|
var snapshot = defineTool({
|
|
@@ -28,9 +34,9 @@ var snapshot = defineTool({
|
|
|
28
34
|
schema: {
|
|
29
35
|
name: "browser_snapshot",
|
|
30
36
|
title: "Page snapshot",
|
|
31
|
-
description:
|
|
37
|
+
description: "Capture accessibility snapshot of current page",
|
|
32
38
|
inputSchema: z.object({
|
|
33
|
-
expectation: expectationSchema
|
|
39
|
+
expectation: expectationSchema.describe("Page state config")
|
|
34
40
|
}),
|
|
35
41
|
type: "readOnly"
|
|
36
42
|
},
|
|
@@ -45,26 +51,24 @@ var snapshot = defineTool({
|
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
});
|
|
48
|
-
var
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
button: z.enum(["left", "right", "middle"]).optional().describe("Button to click, defaults to left"),
|
|
55
|
-
expectation: expectationSchema
|
|
54
|
+
var selectorsSchema = z.array(elementSelectorSchema).min(1).max(5).describe("Array of element selectors (max 5). Selectors are tried in order until one succeeds (fallback mechanism). " + "Multiple matches trigger an error with candidate list. " + "Supports: ref (highest priority), CSS (#id, .class, tag), role (button, textbox, etc.), text content. " + 'Example: [{css: "#submit"}, {role: "button", text: "Submit"}] - tries ID first, falls back to role+text');
|
|
55
|
+
var clickSchema = z.object({
|
|
56
|
+
selectors: selectorsSchema,
|
|
57
|
+
doubleClick: z.boolean().optional().describe("Double-click if true"),
|
|
58
|
+
button: z.enum(["left", "right", "middle"]).optional().describe("Mouse button (default: left)"),
|
|
59
|
+
expectation: expectationSchema.describe("Page state capture config. Use batch_execute for multi-clicks")
|
|
56
60
|
});
|
|
57
61
|
var click = defineTabTool({
|
|
58
62
|
capability: "core",
|
|
59
63
|
schema: {
|
|
60
64
|
name: "browser_click",
|
|
61
|
-
title: "
|
|
62
|
-
description:
|
|
65
|
+
title: "Perform click on web page",
|
|
66
|
+
description: "Perform click on web page",
|
|
63
67
|
inputSchema: clickSchema,
|
|
64
68
|
type: "destructive"
|
|
65
69
|
},
|
|
66
70
|
handle: async (tab, params, response) => {
|
|
67
|
-
const locator = await tab.
|
|
71
|
+
const { locator } = await resolveFirstElement(tab, params.selectors, "Failed to resolve any element selectors");
|
|
68
72
|
const button = params.button;
|
|
69
73
|
const buttonAttr = button ? `{ button: '${button}' }` : "";
|
|
70
74
|
if (params.doubleClick) {
|
|
@@ -79,10 +83,7 @@ var click = defineTabTool({
|
|
|
79
83
|
await locator.click({ button });
|
|
80
84
|
}
|
|
81
85
|
});
|
|
82
|
-
|
|
83
|
-
const newSnapshot = await tab.captureSnapshot();
|
|
84
|
-
response.setTabSnapshot(newSnapshot);
|
|
85
|
-
}
|
|
86
|
+
await handleSnapshotExpectation(tab, params.expectation, response);
|
|
86
87
|
}
|
|
87
88
|
});
|
|
88
89
|
var drag = defineTabTool({
|
|
@@ -90,21 +91,16 @@ var drag = defineTabTool({
|
|
|
90
91
|
schema: {
|
|
91
92
|
name: "browser_drag",
|
|
92
93
|
title: "Drag mouse",
|
|
93
|
-
description:
|
|
94
|
+
description: "Perform drag and drop between two elements",
|
|
94
95
|
inputSchema: z.object({
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
endRef: z.string().describe('System-generated target element ID from previous tool results (e.g., "rNODE-45-1"). Never use custom values.'),
|
|
99
|
-
expectation: expectationSchema
|
|
96
|
+
startSelectors: selectorsSchema.describe("Source element selectors for drag start"),
|
|
97
|
+
endSelectors: selectorsSchema.describe("Target element selectors for drag end"),
|
|
98
|
+
expectation: expectationSchema.describe("Page state after drag. Use batch_execute for workflows")
|
|
100
99
|
}),
|
|
101
100
|
type: "destructive"
|
|
102
101
|
},
|
|
103
102
|
handle: async (tab, params, response) => {
|
|
104
|
-
const
|
|
105
|
-
{ ref: params.startRef, element: params.startElement },
|
|
106
|
-
{ ref: params.endRef, element: params.endElement }
|
|
107
|
-
]);
|
|
103
|
+
const { startLocator, endLocator } = await resolveDragElements(tab, params.startSelectors, params.endSelectors);
|
|
108
104
|
await tab.waitForCompletion(async () => {
|
|
109
105
|
await startLocator.dragTo(endLocator);
|
|
110
106
|
});
|
|
@@ -116,35 +112,37 @@ var hover = defineTabTool({
|
|
|
116
112
|
schema: {
|
|
117
113
|
name: "browser_hover",
|
|
118
114
|
title: "Hover mouse",
|
|
119
|
-
description:
|
|
120
|
-
inputSchema:
|
|
121
|
-
|
|
115
|
+
description: "Hover over element on page",
|
|
116
|
+
inputSchema: z.object({
|
|
117
|
+
selectors: selectorsSchema,
|
|
118
|
+
expectation: expectationSchema.describe("Page state after hover. Use batch_execute for hover→click")
|
|
122
119
|
}),
|
|
123
120
|
type: "readOnly"
|
|
124
121
|
},
|
|
125
122
|
handle: async (tab, params, response) => {
|
|
126
|
-
const locator = await tab.
|
|
123
|
+
const { locator } = await resolveFirstElement(tab, params.selectors);
|
|
127
124
|
response.addCode(`await page.${await generateLocator(locator)}.hover();`);
|
|
128
125
|
await tab.waitForCompletion(async () => {
|
|
129
126
|
await locator.hover();
|
|
130
127
|
});
|
|
131
128
|
}
|
|
132
129
|
});
|
|
133
|
-
var selectOptionSchema =
|
|
134
|
-
|
|
135
|
-
|
|
130
|
+
var selectOptionSchema = z.object({
|
|
131
|
+
selectors: selectorsSchema,
|
|
132
|
+
values: z.array(z.string()).describe("Values to select (array)"),
|
|
133
|
+
expectation: expectationSchema.describe("Page state after selection. Use batch_execute for forms")
|
|
136
134
|
});
|
|
137
135
|
var selectOption = defineTabTool({
|
|
138
136
|
capability: "core",
|
|
139
137
|
schema: {
|
|
140
138
|
name: "browser_select_option",
|
|
141
139
|
title: "Select option",
|
|
142
|
-
description:
|
|
140
|
+
description: "Select option in dropdown",
|
|
143
141
|
inputSchema: selectOptionSchema,
|
|
144
142
|
type: "destructive"
|
|
145
143
|
},
|
|
146
144
|
handle: async (tab, params, response) => {
|
|
147
|
-
const locator = await tab.
|
|
145
|
+
const { locator } = await resolveFirstElement(tab, params.selectors);
|
|
148
146
|
response.addCode(`await page.${await generateLocator(locator)}.selectOption(${formatObject(params.values)});`);
|
|
149
147
|
await tab.waitForCompletion(async () => {
|
|
150
148
|
await locator.selectOption(params.values);
|
|
@@ -153,6 +151,6 @@ var selectOption = defineTabTool({
|
|
|
153
151
|
});
|
|
154
152
|
var snapshot_default = [snapshot, click, drag, hover, selectOption];
|
|
155
153
|
export {
|
|
156
|
-
|
|
154
|
+
selectorsSchema,
|
|
157
155
|
snapshot_default as default
|
|
158
156
|
};
|
package/lib/tools/tabs.js
CHANGED
|
@@ -26,9 +26,9 @@ var listTabs = defineTool({
|
|
|
26
26
|
schema: {
|
|
27
27
|
name: "browser_tab_list",
|
|
28
28
|
title: "List tabs",
|
|
29
|
-
description: "List browser tabs
|
|
29
|
+
description: "List browser tabs with titles and URLs",
|
|
30
30
|
inputSchema: z.object({
|
|
31
|
-
expectation: expectationSchema
|
|
31
|
+
expectation: expectationSchema.describe("Page state config")
|
|
32
32
|
}),
|
|
33
33
|
type: "readOnly"
|
|
34
34
|
},
|
|
@@ -42,10 +42,10 @@ var selectTab = defineTool({
|
|
|
42
42
|
schema: {
|
|
43
43
|
name: "browser_tab_select",
|
|
44
44
|
title: "Select a tab",
|
|
45
|
-
description:
|
|
45
|
+
description: "Select a tab by index",
|
|
46
46
|
inputSchema: z.object({
|
|
47
47
|
index: z.number().describe("The index of the tab to select"),
|
|
48
|
-
expectation: expectationSchema
|
|
48
|
+
expectation: expectationSchema.describe("Page state after tab switch")
|
|
49
49
|
}),
|
|
50
50
|
type: "readOnly"
|
|
51
51
|
},
|
|
@@ -59,10 +59,10 @@ var newTab = defineTool({
|
|
|
59
59
|
schema: {
|
|
60
60
|
name: "browser_tab_new",
|
|
61
61
|
title: "Open a new tab",
|
|
62
|
-
description:
|
|
62
|
+
description: "Open a new tab",
|
|
63
63
|
inputSchema: z.object({
|
|
64
|
-
url: z.string().optional().describe("
|
|
65
|
-
expectation: expectationSchema
|
|
64
|
+
url: z.string().optional().describe("URL for new tab (optional)"),
|
|
65
|
+
expectation: expectationSchema.describe("Page state of new tab")
|
|
66
66
|
}),
|
|
67
67
|
type: "readOnly"
|
|
68
68
|
},
|
|
@@ -79,10 +79,10 @@ var closeTab = defineTool({
|
|
|
79
79
|
schema: {
|
|
80
80
|
name: "browser_tab_close",
|
|
81
81
|
title: "Close a tab",
|
|
82
|
-
description: "Close a tab
|
|
82
|
+
description: "Close a tab by index or close current tab",
|
|
83
83
|
inputSchema: z.object({
|
|
84
|
-
index: z.number().optional().describe("
|
|
85
|
-
expectation: expectationSchema
|
|
84
|
+
index: z.number().optional().describe("Tab index to close (omit for current)"),
|
|
85
|
+
expectation: expectationSchema.describe("Page state after close")
|
|
86
86
|
}),
|
|
87
87
|
type: "destructive"
|
|
88
88
|
},
|
package/lib/tools/wait.js
CHANGED
|
@@ -26,12 +26,12 @@ var wait = defineTool({
|
|
|
26
26
|
schema: {
|
|
27
27
|
name: "browser_wait_for",
|
|
28
28
|
title: "Wait for",
|
|
29
|
-
description:
|
|
29
|
+
description: "Wait for text to appear or disappear or a specified time to pass",
|
|
30
30
|
inputSchema: z.object({
|
|
31
|
-
time: z.number().optional().describe("
|
|
32
|
-
text: z.string().optional()
|
|
33
|
-
textGone: z.string().optional()
|
|
34
|
-
expectation: expectationSchema
|
|
31
|
+
time: z.number().optional().describe("Wait time in seconds"),
|
|
32
|
+
text: z.string().optional(),
|
|
33
|
+
textGone: z.string().optional(),
|
|
34
|
+
expectation: expectationSchema.describe("Page state after wait")
|
|
35
35
|
}),
|
|
36
36
|
type: "readOnly"
|
|
37
37
|
},
|
package/lib/tools.js
CHANGED
|
@@ -26,6 +26,7 @@ import dialogs from "./tools/dialogs.js";
|
|
|
26
26
|
import evaluate from "./tools/evaluate.js";
|
|
27
27
|
import files from "./tools/files.js";
|
|
28
28
|
import { browserFindElements } from "./tools/find-elements.js";
|
|
29
|
+
import inspectHtml from "./tools/inspect-html.js";
|
|
29
30
|
import install from "./tools/install.js";
|
|
30
31
|
import keyboard from "./tools/keyboard.js";
|
|
31
32
|
import mouse from "./tools/mouse.js";
|
|
@@ -43,6 +44,7 @@ var allTools = [
|
|
|
43
44
|
...evaluate,
|
|
44
45
|
...files,
|
|
45
46
|
...install,
|
|
47
|
+
...inspectHtml,
|
|
46
48
|
...keyboard,
|
|
47
49
|
...navigate,
|
|
48
50
|
...network,
|
package/lib/types/batch.js
CHANGED
|
@@ -37,9 +37,9 @@ var batchStepSchema = z.object({
|
|
|
37
37
|
expectation: expectationSchema.describe("Expected output configuration for this step")
|
|
38
38
|
});
|
|
39
39
|
var batchExecuteSchema = z.object({
|
|
40
|
-
steps: z.array(batchStepSchema).min(1).describe(
|
|
40
|
+
steps: z.array(batchStepSchema).min(1).describe('Array of steps to execute in sequence. Recommended for form filling (multiple type→click), multi-step navigation, any workflow with 2+ known steps. Saves 90% tokens vs individual calls. Example: [{tool:"browser_navigate",arguments:{url:"https://example.com"}},{tool:"browser_type",arguments:{selectors:[{css:"#user"}],text:"john"}},{tool:"browser_click",arguments:{selectors:[{css:"#btn"}]}}]'),
|
|
41
41
|
stopOnFirstError: z.boolean().optional().default(false).describe("Stop entire batch on first error"),
|
|
42
|
-
globalExpectation: z.preprocess(parseJsonString, expectationSchema).optional().describe(
|
|
42
|
+
globalExpectation: z.preprocess(parseJsonString, expectationSchema).optional().describe('Default expectation for all steps. Recommended: {includeSnapshot:false,snapshotOptions:{selector:"#app"},diffOptions:{enabled:true}}. Per-step override with steps[].expectation')
|
|
43
43
|
});
|
|
44
44
|
export {
|
|
45
45
|
batchStepSchema,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
// src/types/html-inspection.ts
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import { elementSelectorSchema } from "./selectors.js";
|
|
23
|
+
var htmlInspectionOptionsSchema = z.object({
|
|
24
|
+
selectors: z.array(elementSelectorSchema).min(1).describe("Array of element selectors to inspect"),
|
|
25
|
+
depth: z.number().min(1).max(10).optional().default(2).describe("Maximum hierarchy depth to extract"),
|
|
26
|
+
includeStyles: z.boolean().optional().default(false).describe("Include computed CSS styles"),
|
|
27
|
+
maxSize: z.number().min(1024).max(500000).optional().default(50000).describe("Maximum size in bytes (1KB-500KB)"),
|
|
28
|
+
format: z.enum(["html", "aria", "text"]).optional().default("html").describe("Output format"),
|
|
29
|
+
includeAttributes: z.boolean().optional().default(true).describe("Include element attributes"),
|
|
30
|
+
preserveWhitespace: z.boolean().optional().default(false).describe("Preserve whitespace in content"),
|
|
31
|
+
excludeSelector: z.string().optional().describe("CSS selector to exclude elements")
|
|
32
|
+
});
|
|
33
|
+
var HTMLInspectionError = {
|
|
34
|
+
SELECTOR_NOT_FOUND: "SELECTOR_NOT_FOUND",
|
|
35
|
+
SIZE_LIMIT_EXCEEDED: "SIZE_LIMIT_EXCEEDED",
|
|
36
|
+
EXTRACTION_TIMEOUT: "EXTRACTION_TIMEOUT",
|
|
37
|
+
INVALID_SELECTOR: "INVALID_SELECTOR",
|
|
38
|
+
DOM_ACCESS_ERROR: "DOM_ACCESS_ERROR"
|
|
39
|
+
};
|
|
40
|
+
function calculateHtmlSize(html) {
|
|
41
|
+
return new TextEncoder().encode(html).length;
|
|
42
|
+
}
|
|
43
|
+
function truncateHtml(html, maxSize) {
|
|
44
|
+
if (calculateHtmlSize(html) <= maxSize) {
|
|
45
|
+
return { html, truncated: false };
|
|
46
|
+
}
|
|
47
|
+
const truncated = html.substring(0, maxSize - 100);
|
|
48
|
+
const lastTag = truncated.lastIndexOf("<");
|
|
49
|
+
const safeHtml = lastTag > truncated.lastIndexOf(">") ? truncated.substring(0, lastTag) : truncated;
|
|
50
|
+
return { html: `${safeHtml}<!-- TRUNCATED -->`, truncated: true };
|
|
51
|
+
}
|
|
52
|
+
function validateHTMLInspectionOptions(options) {
|
|
53
|
+
return htmlInspectionOptionsSchema.parse(options);
|
|
54
|
+
}
|
|
55
|
+
function generateHTMLInspectionSuggestions(result) {
|
|
56
|
+
const suggestions = [];
|
|
57
|
+
if (result.truncated) {
|
|
58
|
+
suggestions.push("Content was truncated. Consider reducing depth or using more specific selectors.");
|
|
59
|
+
}
|
|
60
|
+
if (result.stats.selectorsNotFound > 0) {
|
|
61
|
+
suggestions.push("Some selectors did not match elements. Try using more specific or alternative selectors.");
|
|
62
|
+
}
|
|
63
|
+
if (result.timing.totalMs > 5000) {
|
|
64
|
+
suggestions.push("Inspection took longer than expected. Consider reducing scope or depth.");
|
|
65
|
+
}
|
|
66
|
+
if (result.stats.averageDepth > 5) {
|
|
67
|
+
suggestions.push("Deep element extraction detected. Consider limiting depth for better performance.");
|
|
68
|
+
}
|
|
69
|
+
return suggestions;
|
|
70
|
+
}
|
|
71
|
+
var HTMLInspectionUtils = {
|
|
72
|
+
calculateHtmlSize,
|
|
73
|
+
truncateHtml,
|
|
74
|
+
validateOptions: validateHTMLInspectionOptions,
|
|
75
|
+
generateSuggestions: generateHTMLInspectionSuggestions
|
|
76
|
+
};
|
|
77
|
+
var HTMLInspectionConstants = {
|
|
78
|
+
DEFAULT_MAX_SIZE: 50000,
|
|
79
|
+
DEFAULT_DEPTH: 2,
|
|
80
|
+
MAX_DEPTH: 10,
|
|
81
|
+
DEFAULT_TIMEOUT_MS: 1e4,
|
|
82
|
+
SIZE_THRESHOLDS: {
|
|
83
|
+
WARNING: 30000,
|
|
84
|
+
CRITICAL: 45000
|
|
85
|
+
},
|
|
86
|
+
COMMON_ARIA_PROPERTIES: [
|
|
87
|
+
"aria-label",
|
|
88
|
+
"aria-describedby",
|
|
89
|
+
"aria-hidden",
|
|
90
|
+
"aria-expanded",
|
|
91
|
+
"aria-selected",
|
|
92
|
+
"aria-checked",
|
|
93
|
+
"aria-disabled",
|
|
94
|
+
"aria-required"
|
|
95
|
+
]
|
|
96
|
+
};
|
|
97
|
+
export {
|
|
98
|
+
validateHTMLInspectionOptions,
|
|
99
|
+
truncateHtml,
|
|
100
|
+
htmlInspectionOptionsSchema,
|
|
101
|
+
generateHTMLInspectionSuggestions,
|
|
102
|
+
calculateHtmlSize,
|
|
103
|
+
HTMLInspectionUtils,
|
|
104
|
+
HTMLInspectionError,
|
|
105
|
+
HTMLInspectionConstants
|
|
106
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
// src/types/selectors.ts
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
var refSelectorSchema = z.object({
|
|
23
|
+
ref: z.string().describe("System-generated element ID from previous tool results")
|
|
24
|
+
});
|
|
25
|
+
var roleSelectorSchema = z.object({
|
|
26
|
+
role: z.string().describe("ARIA role to match (e.g., button, textbox, link)"),
|
|
27
|
+
text: z.string().optional().describe("Optional text content to match within the role")
|
|
28
|
+
});
|
|
29
|
+
var cssSelectorSchema = z.object({
|
|
30
|
+
css: z.string().describe('CSS selector string (e.g., "#id", ".class", "button[type=submit]")')
|
|
31
|
+
});
|
|
32
|
+
var textSelectorSchema = z.object({
|
|
33
|
+
text: z.string().describe("Text content to search for"),
|
|
34
|
+
tag: z.string().optional().describe("Optional HTML tag to limit search scope")
|
|
35
|
+
});
|
|
36
|
+
var elementSelectorSchema = z.union([
|
|
37
|
+
refSelectorSchema,
|
|
38
|
+
roleSelectorSchema,
|
|
39
|
+
cssSelectorSchema,
|
|
40
|
+
textSelectorSchema
|
|
41
|
+
]).describe("Element selector supporting ref, role, CSS, or text-based selection");
|
|
42
|
+
var SelectorConfidence = {
|
|
43
|
+
HIGH: 0.9,
|
|
44
|
+
MEDIUM: 0.7,
|
|
45
|
+
LOW: 0.5,
|
|
46
|
+
VERY_LOW: 0.3
|
|
47
|
+
};
|
|
48
|
+
var ResolutionStrategy = {
|
|
49
|
+
REF: "ref",
|
|
50
|
+
CSS_PARALLEL: "css_parallel",
|
|
51
|
+
ROLE_SEQUENTIAL: "role_sequential",
|
|
52
|
+
TEXT_FALLBACK: "text_fallback"
|
|
53
|
+
};
|
|
54
|
+
function isRefSelector(selector) {
|
|
55
|
+
return "ref" in selector;
|
|
56
|
+
}
|
|
57
|
+
function isRoleSelector(selector) {
|
|
58
|
+
return "role" in selector;
|
|
59
|
+
}
|
|
60
|
+
function isCSSSelector(selector) {
|
|
61
|
+
return "css" in selector;
|
|
62
|
+
}
|
|
63
|
+
function isTextSelector(selector) {
|
|
64
|
+
return "text" in selector && !("role" in selector);
|
|
65
|
+
}
|
|
66
|
+
function validateElementSelector(selector) {
|
|
67
|
+
return elementSelectorSchema.parse(selector);
|
|
68
|
+
}
|
|
69
|
+
function isValidSelector(selector) {
|
|
70
|
+
try {
|
|
71
|
+
elementSelectorSchema.parse(selector);
|
|
72
|
+
return true;
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
var SelectorValidator = {
|
|
78
|
+
validateElementSelector,
|
|
79
|
+
isValidSelector
|
|
80
|
+
};
|
|
81
|
+
var SelectorPatterns = {
|
|
82
|
+
ARIA_ROLES: [
|
|
83
|
+
"button",
|
|
84
|
+
"textbox",
|
|
85
|
+
"link",
|
|
86
|
+
"checkbox",
|
|
87
|
+
"radio",
|
|
88
|
+
"combobox",
|
|
89
|
+
"listbox",
|
|
90
|
+
"option",
|
|
91
|
+
"tab",
|
|
92
|
+
"tabpanel",
|
|
93
|
+
"dialog",
|
|
94
|
+
"alert",
|
|
95
|
+
"menu",
|
|
96
|
+
"menuitem",
|
|
97
|
+
"table",
|
|
98
|
+
"row",
|
|
99
|
+
"cell",
|
|
100
|
+
"heading"
|
|
101
|
+
],
|
|
102
|
+
CSS_PATTERNS: {
|
|
103
|
+
byId: (id) => `#${id}`,
|
|
104
|
+
byClass: (className) => `.${className}`,
|
|
105
|
+
byAttribute: (attr, value) => value ? `[${attr}="${value}"]` : `[${attr}]`,
|
|
106
|
+
byDataTestId: (testId) => `[data-testid="${testId}"]`,
|
|
107
|
+
byRole: (role) => `[role="${role}"]`
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
export {
|
|
111
|
+
validateElementSelector,
|
|
112
|
+
textSelectorSchema,
|
|
113
|
+
roleSelectorSchema,
|
|
114
|
+
refSelectorSchema,
|
|
115
|
+
isValidSelector,
|
|
116
|
+
isTextSelector,
|
|
117
|
+
isRoleSelector,
|
|
118
|
+
isRefSelector,
|
|
119
|
+
isCSSSelector,
|
|
120
|
+
elementSelectorSchema,
|
|
121
|
+
cssSelectorSchema,
|
|
122
|
+
SelectorValidator,
|
|
123
|
+
SelectorPatterns,
|
|
124
|
+
SelectorConfidence,
|
|
125
|
+
ResolutionStrategy
|
|
126
|
+
};
|