@browserflow-ai/exploration 0.0.6

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 (58) hide show
  1. package/dist/adapters/claude-cli.d.ts +57 -0
  2. package/dist/adapters/claude-cli.d.ts.map +1 -0
  3. package/dist/adapters/claude-cli.js +195 -0
  4. package/dist/adapters/claude-cli.js.map +1 -0
  5. package/dist/adapters/claude.d.ts +54 -0
  6. package/dist/adapters/claude.d.ts.map +1 -0
  7. package/dist/adapters/claude.js +160 -0
  8. package/dist/adapters/claude.js.map +1 -0
  9. package/dist/adapters/index.d.ts +6 -0
  10. package/dist/adapters/index.d.ts.map +1 -0
  11. package/dist/adapters/index.js +4 -0
  12. package/dist/adapters/index.js.map +1 -0
  13. package/dist/adapters/types.d.ts +196 -0
  14. package/dist/adapters/types.d.ts.map +1 -0
  15. package/dist/adapters/types.js +3 -0
  16. package/dist/adapters/types.js.map +1 -0
  17. package/dist/agent-browser-session.d.ts +62 -0
  18. package/dist/agent-browser-session.d.ts.map +1 -0
  19. package/dist/agent-browser-session.js +272 -0
  20. package/dist/agent-browser-session.js.map +1 -0
  21. package/dist/evidence.d.ts +111 -0
  22. package/dist/evidence.d.ts.map +1 -0
  23. package/dist/evidence.js +144 -0
  24. package/dist/evidence.js.map +1 -0
  25. package/dist/explorer.d.ts +180 -0
  26. package/dist/explorer.d.ts.map +1 -0
  27. package/dist/explorer.js +393 -0
  28. package/dist/explorer.js.map +1 -0
  29. package/dist/index.d.ts +15 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +15 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/locator-candidates.d.ts +127 -0
  34. package/dist/locator-candidates.d.ts.map +1 -0
  35. package/dist/locator-candidates.js +358 -0
  36. package/dist/locator-candidates.js.map +1 -0
  37. package/dist/step-executor.d.ts +99 -0
  38. package/dist/step-executor.d.ts.map +1 -0
  39. package/dist/step-executor.js +646 -0
  40. package/dist/step-executor.js.map +1 -0
  41. package/package.json +34 -0
  42. package/src/adapters/claude-cli.test.ts +134 -0
  43. package/src/adapters/claude-cli.ts +240 -0
  44. package/src/adapters/claude.test.ts +195 -0
  45. package/src/adapters/claude.ts +190 -0
  46. package/src/adapters/index.ts +21 -0
  47. package/src/adapters/types.ts +207 -0
  48. package/src/agent-browser-session.test.ts +369 -0
  49. package/src/agent-browser-session.ts +349 -0
  50. package/src/evidence.test.ts +239 -0
  51. package/src/evidence.ts +203 -0
  52. package/src/explorer.test.ts +321 -0
  53. package/src/explorer.ts +565 -0
  54. package/src/index.ts +51 -0
  55. package/src/locator-candidates.test.ts +602 -0
  56. package/src/locator-candidates.ts +441 -0
  57. package/src/step-executor.test.ts +696 -0
  58. package/src/step-executor.ts +783 -0
@@ -0,0 +1,358 @@
1
+ // @browserflow-ai/exploration - Locator candidate generation
2
+ /**
3
+ * Implicit ARIA roles for common HTML elements
4
+ */
5
+ const IMPLICIT_ROLES = {
6
+ a: 'link',
7
+ button: 'button',
8
+ input: 'textbox',
9
+ select: 'combobox',
10
+ textarea: 'textbox',
11
+ img: 'img',
12
+ nav: 'navigation',
13
+ main: 'main',
14
+ header: 'banner',
15
+ footer: 'contentinfo',
16
+ aside: 'complementary',
17
+ article: 'article',
18
+ section: 'region',
19
+ form: 'form',
20
+ table: 'table',
21
+ ul: 'list',
22
+ ol: 'list',
23
+ li: 'listitem',
24
+ dialog: 'dialog',
25
+ menu: 'menu',
26
+ option: 'option',
27
+ progress: 'progressbar',
28
+ meter: 'meter',
29
+ h1: 'heading',
30
+ h2: 'heading',
31
+ h3: 'heading',
32
+ h4: 'heading',
33
+ h5: 'heading',
34
+ h6: 'heading',
35
+ };
36
+ /**
37
+ * Maximum text length for text-based locators
38
+ */
39
+ const MAX_TEXT_LENGTH = 50;
40
+ /**
41
+ * LocatorCandidateGenerator - Generates ranked locator options for elements
42
+ *
43
+ * Uses multiple strategies to find elements:
44
+ * - Element refs from agent-browser snapshots
45
+ * - Test IDs (data-testid, data-test, etc.)
46
+ * - ARIA roles and labels
47
+ * - Text content matching
48
+ * - CSS selectors
49
+ * - XPath expressions
50
+ */
51
+ export class LocatorCandidateGenerator {
52
+ preferredStrategies;
53
+ maxCandidates;
54
+ constructor(config = {}) {
55
+ this.preferredStrategies = config.preferredStrategies ?? [
56
+ 'ref',
57
+ 'testid',
58
+ 'role',
59
+ 'text',
60
+ 'css',
61
+ ];
62
+ this.maxCandidates = config.maxCandidates ?? 5;
63
+ }
64
+ /**
65
+ * Generate locator candidates for an element based on natural language query
66
+ *
67
+ * @param query - Natural language description (e.g., "Submit button in the form")
68
+ * @param snapshot - Browser snapshot containing element refs
69
+ * @returns Promise resolving to ranked list of locator strings
70
+ */
71
+ async generateCandidates(query, snapshot) {
72
+ const candidates = await this.findCandidates(query, snapshot);
73
+ return candidates.slice(0, this.maxCandidates).map((c) => c.locator);
74
+ }
75
+ /**
76
+ * Generate detailed locator candidates with metadata
77
+ *
78
+ * @param query - Natural language description
79
+ * @param snapshot - Browser snapshot
80
+ * @returns Promise resolving to ranked list of candidates with scores
81
+ */
82
+ async generateDetailedCandidates(query, snapshot) {
83
+ const candidates = await this.findCandidates(query, snapshot);
84
+ return candidates.slice(0, this.maxCandidates);
85
+ }
86
+ /**
87
+ * Generate all applicable locator candidates for a known element
88
+ *
89
+ * @param element - Element information
90
+ * @returns Promise resolving to ranked list of candidates
91
+ */
92
+ async generateCandidatesForElement(element) {
93
+ const candidates = [];
94
+ // 1. Ref locator (highest confidence - direct reference)
95
+ candidates.push(this.generateRefLocator(element.ref));
96
+ // 2. Test ID locator (if present)
97
+ const testId = element.testId || element.attributes?.['data-testid'] || element.attributes?.['data-test'];
98
+ if (testId) {
99
+ candidates.push(this.generateTestIdLocator(testId));
100
+ }
101
+ // 3. Role locator (explicit or implicit)
102
+ const role = element.role || IMPLICIT_ROLES[element.tag];
103
+ if (role) {
104
+ const name = element.ariaLabel || (element.text && element.text.length <= MAX_TEXT_LENGTH ? element.text : undefined);
105
+ candidates.push(this.generateRoleLocator(role, name));
106
+ }
107
+ // 4. Text locator (if text is short enough)
108
+ if (element.text && element.text.length > 0 && element.text.length <= MAX_TEXT_LENGTH) {
109
+ // Use exact match for shorter text
110
+ const exact = element.text.length <= 30;
111
+ candidates.push(this.generateTextLocator(element.text, exact));
112
+ }
113
+ // 5. CSS selector (always as fallback)
114
+ const cssSelector = this.generateCssSelectorForElement(element);
115
+ candidates.push({
116
+ locator: cssSelector,
117
+ type: 'css',
118
+ confidence: this.calculateCssConfidence(element),
119
+ description: 'CSS selector',
120
+ });
121
+ // Sort by confidence (highest first)
122
+ return candidates.sort((a, b) => b.confidence - a.confidence);
123
+ }
124
+ /**
125
+ * Find candidate locators matching a query
126
+ */
127
+ async findCandidates(query, snapshot) {
128
+ // Handle empty query
129
+ if (!query || query.trim() === '') {
130
+ return [];
131
+ }
132
+ const normalizedQuery = query.toLowerCase().trim();
133
+ const refs = (snapshot.refs || {});
134
+ // Handle empty snapshot
135
+ if (Object.keys(refs).length === 0) {
136
+ return [];
137
+ }
138
+ // Find matching elements
139
+ const matchedElements = [];
140
+ for (const [ref, refData] of Object.entries(refs)) {
141
+ const element = this.parseElementFromRef(ref, refData);
142
+ const matchScore = this.calculateMatchScore(element, normalizedQuery);
143
+ if (matchScore > 0) {
144
+ matchedElements.push({ element, score: matchScore });
145
+ }
146
+ }
147
+ // Sort by match score (best match first)
148
+ matchedElements.sort((a, b) => b.score - a.score);
149
+ // Take the best matching element and generate candidates for it
150
+ if (matchedElements.length === 0) {
151
+ return [];
152
+ }
153
+ const bestMatch = matchedElements[0];
154
+ return this.generateCandidatesForElement(bestMatch.element);
155
+ }
156
+ /**
157
+ * Parse element info from snapshot ref data
158
+ */
159
+ parseElementFromRef(ref, refData) {
160
+ return {
161
+ ref,
162
+ tag: refData.tag || 'div',
163
+ role: refData.role,
164
+ text: refData.text,
165
+ ariaLabel: refData.ariaLabel,
166
+ testId: refData.testId,
167
+ className: refData.className,
168
+ id: refData.id,
169
+ attributes: refData.attributes,
170
+ };
171
+ }
172
+ /**
173
+ * Calculate how well an element matches the query
174
+ * Returns a score from 0 (no match) to 1 (perfect match)
175
+ */
176
+ calculateMatchScore(element, normalizedQuery) {
177
+ let score = 0;
178
+ const queryTerms = normalizedQuery.split(/\s+/);
179
+ // Match by text content
180
+ if (element.text) {
181
+ const normalizedText = element.text.toLowerCase();
182
+ if (normalizedText === normalizedQuery) {
183
+ score += 1.0; // Exact match
184
+ }
185
+ else if (normalizedText.includes(normalizedQuery)) {
186
+ score += 0.8; // Contains query
187
+ }
188
+ else {
189
+ // Check if all query terms are in the text
190
+ const matchedTerms = queryTerms.filter((term) => normalizedText.includes(term));
191
+ score += (matchedTerms.length / queryTerms.length) * 0.6;
192
+ }
193
+ }
194
+ // Match by aria-label
195
+ if (element.ariaLabel) {
196
+ const normalizedLabel = element.ariaLabel.toLowerCase();
197
+ if (normalizedLabel === normalizedQuery) {
198
+ score += 0.9;
199
+ }
200
+ else if (normalizedLabel.includes(normalizedQuery)) {
201
+ score += 0.7;
202
+ }
203
+ else {
204
+ const matchedTerms = queryTerms.filter((term) => normalizedLabel.includes(term));
205
+ score += (matchedTerms.length / queryTerms.length) * 0.5;
206
+ }
207
+ }
208
+ // Match by tag name
209
+ const normalizedTag = element.tag.toLowerCase();
210
+ if (queryTerms.includes(normalizedTag)) {
211
+ score += 0.4;
212
+ }
213
+ // Match by role
214
+ if (element.role) {
215
+ const normalizedRole = element.role.toLowerCase();
216
+ if (queryTerms.includes(normalizedRole)) {
217
+ score += 0.5;
218
+ }
219
+ }
220
+ else {
221
+ // Check implicit role
222
+ const implicitRole = IMPLICIT_ROLES[element.tag];
223
+ if (implicitRole && queryTerms.includes(implicitRole)) {
224
+ score += 0.4;
225
+ }
226
+ }
227
+ // Match by test ID
228
+ if (element.testId) {
229
+ const normalizedTestId = element.testId.toLowerCase().replace(/[-_]/g, ' ');
230
+ const matchedTerms = queryTerms.filter((term) => normalizedTestId.includes(term));
231
+ score += (matchedTerms.length / queryTerms.length) * 0.3;
232
+ }
233
+ // Match by class name
234
+ if (element.className) {
235
+ const normalizedClasses = element.className.toLowerCase().replace(/[-_]/g, ' ');
236
+ const matchedTerms = queryTerms.filter((term) => normalizedClasses.includes(term));
237
+ score += (matchedTerms.length / queryTerms.length) * 0.2;
238
+ }
239
+ return Math.min(score, 1.0); // Cap at 1.0
240
+ }
241
+ /**
242
+ * Generate a CSS selector for an element
243
+ */
244
+ generateCssSelectorForElement(element) {
245
+ // Prefer ID if available (most specific)
246
+ if (element.id) {
247
+ return `#${this.escapeCssSelector(element.id)}`;
248
+ }
249
+ // Build selector from tag and classes
250
+ let selector = element.tag;
251
+ if (element.className) {
252
+ const classes = element.className.split(/\s+/).filter((c) => c.length > 0);
253
+ if (classes.length > 0) {
254
+ // Use first 2 classes for specificity without being too brittle
255
+ const selectedClasses = classes.slice(0, 2);
256
+ selector += selectedClasses.map((c) => `.${this.escapeCssSelector(c)}`).join('');
257
+ }
258
+ }
259
+ return selector;
260
+ }
261
+ /**
262
+ * Escape special characters in CSS selectors
263
+ */
264
+ escapeCssSelector(value) {
265
+ return value.replace(/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, '\\$1');
266
+ }
267
+ /**
268
+ * Calculate CSS selector confidence based on element attributes
269
+ */
270
+ calculateCssConfidence(element) {
271
+ // ID-based selectors are more stable
272
+ if (element.id) {
273
+ return 0.75;
274
+ }
275
+ // Class-based selectors are moderately stable
276
+ if (element.className) {
277
+ return 0.6;
278
+ }
279
+ // Tag-only selectors are least stable
280
+ return 0.4;
281
+ }
282
+ /**
283
+ * Generate a locator from element ref
284
+ */
285
+ generateRefLocator(ref) {
286
+ return {
287
+ locator: `@${ref}`,
288
+ type: 'ref',
289
+ confidence: 1.0,
290
+ description: 'Element reference from snapshot',
291
+ };
292
+ }
293
+ /**
294
+ * Generate a locator from test ID
295
+ */
296
+ generateTestIdLocator(testId) {
297
+ return {
298
+ locator: `[data-testid="${testId}"]`,
299
+ type: 'testid',
300
+ confidence: 0.95,
301
+ description: 'Test ID selector',
302
+ };
303
+ }
304
+ /**
305
+ * Generate a locator from ARIA role
306
+ */
307
+ generateRoleLocator(role, name) {
308
+ const locator = name ? `role=${role}[name="${name}"]` : `role=${role}`;
309
+ return {
310
+ locator,
311
+ type: 'role',
312
+ confidence: name ? 0.9 : 0.85,
313
+ description: `ARIA role: ${role}${name ? ` with name "${name}"` : ''}`,
314
+ };
315
+ }
316
+ /**
317
+ * Generate a locator from text content
318
+ */
319
+ generateTextLocator(text, exact = false) {
320
+ const locator = exact ? `text="${text}"` : `text~="${text}"`;
321
+ return {
322
+ locator,
323
+ type: 'text',
324
+ confidence: exact ? 0.85 : 0.7,
325
+ description: `Text content${exact ? ' (exact)' : ' (partial)'}`,
326
+ };
327
+ }
328
+ /**
329
+ * Generate a CSS selector locator
330
+ */
331
+ generateCssLocator(selector) {
332
+ return {
333
+ locator: selector,
334
+ type: 'css',
335
+ confidence: 0.8,
336
+ description: 'CSS selector',
337
+ };
338
+ }
339
+ /**
340
+ * Get the maximum number of candidates to return
341
+ */
342
+ getMaxCandidates() {
343
+ return this.maxCandidates;
344
+ }
345
+ /**
346
+ * Set the maximum number of candidates to return
347
+ */
348
+ setMaxCandidates(max) {
349
+ this.maxCandidates = max;
350
+ }
351
+ /**
352
+ * Get the preferred strategies in order
353
+ */
354
+ getPreferredStrategies() {
355
+ return [...this.preferredStrategies];
356
+ }
357
+ }
358
+ //# sourceMappingURL=locator-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locator-candidates.js","sourceRoot":"","sources":["../src/locator-candidates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import type { BrowserSession } from './explorer';
2
+ import type { SpecStep, StepResult, StepExecution, AIAdapter } from './adapters/types';
3
+ /**
4
+ * Configuration for step execution
5
+ */
6
+ export interface StepExecutorConfig {
7
+ browser?: BrowserSession;
8
+ adapter?: AIAdapter;
9
+ baseUrl?: string;
10
+ defaultTimeout?: number;
11
+ screenshotDir?: string;
12
+ captureBeforeScreenshots?: boolean;
13
+ captureAfterScreenshots?: boolean;
14
+ customActionHandlers?: Record<string, (step: SpecStep, browser: BrowserSession) => Promise<StepExecution>>;
15
+ }
16
+ /**
17
+ * StepExecutor - Executes individual spec steps against a browser session
18
+ *
19
+ * Handles:
20
+ * - Navigation: navigate, back, forward, refresh
21
+ * - Interaction: click, fill, type, select, check, press
22
+ * - Waiting: wait for element, text, url, time
23
+ * - Assertions: verify_state with various checks
24
+ * - Capture: screenshot, scroll
25
+ */
26
+ export declare class StepExecutor {
27
+ private browser?;
28
+ private adapter?;
29
+ private baseUrl;
30
+ private defaultTimeout;
31
+ private screenshotDir;
32
+ private captureBeforeScreenshots;
33
+ private captureAfterScreenshots;
34
+ private customActionHandlers;
35
+ constructor(config?: StepExecutorConfig);
36
+ /**
37
+ * Configure the executor with browser and adapter (for lazy initialization)
38
+ */
39
+ configure(config: {
40
+ browser?: BrowserSession;
41
+ adapter?: AIAdapter;
42
+ baseUrl?: string;
43
+ }): void;
44
+ /**
45
+ * Check if executor is properly configured
46
+ */
47
+ isConfigured(): boolean;
48
+ /**
49
+ * Execute a single step
50
+ *
51
+ * @param step - The step definition from the spec
52
+ * @param stepIndex - Index of this step in the spec
53
+ * @returns Promise resolving to step result
54
+ */
55
+ execute(step: SpecStep, stepIndex?: number): Promise<StepResult>;
56
+ /**
57
+ * Execute a single action based on step type
58
+ */
59
+ private executeAction;
60
+ private executeNavigate;
61
+ private executeBack;
62
+ private executeForward;
63
+ private executeRefresh;
64
+ private executeClick;
65
+ private executeFill;
66
+ private executeType;
67
+ private executeSelect;
68
+ private executeCheck;
69
+ private executePress;
70
+ private executeWait;
71
+ private executeVerifyState;
72
+ private executeScreenshot;
73
+ private executeScroll;
74
+ private executeScrollIntoView;
75
+ private executeIdentifyElement;
76
+ private executeAIVerify;
77
+ private executeCustom;
78
+ /**
79
+ * Resolve target to element ref
80
+ */
81
+ private resolveTarget;
82
+ /**
83
+ * Find element in snapshot by selector/query
84
+ */
85
+ private findElementInSnapshot;
86
+ /**
87
+ * Capture a screenshot
88
+ */
89
+ private captureScreenshot;
90
+ /**
91
+ * Get the default timeout value
92
+ */
93
+ getDefaultTimeout(): number;
94
+ /**
95
+ * Get the screenshot directory
96
+ */
97
+ getScreenshotDir(): string;
98
+ }
99
+ //# sourceMappingURL=step-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-executor.d.ts","sourceRoot":"","sources":["../src/step-executor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,SAAS,EAGV,MAAM,kBAAkB,CAAC;AAe1B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAC3B,MAAM,EACN,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,aAAa,CAAC,CACpE,CAAC;CACH;AAUD;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAC,CAAiB;IACjC,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,wBAAwB,CAAU;IAC1C,OAAO,CAAC,uBAAuB,CAAU;IACzC,OAAO,CAAC,oBAAoB,CAG1B;gBAEU,MAAM,GAAE,kBAAuB;IAW3C;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,cAAc,CAAC;QAAC,OAAO,CAAC,EAAE,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAM5F;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAE,MAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAwEzE;;OAEG;YACW,aAAa;YAiEb,eAAe;YAsBf,WAAW;YAWX,cAAc;YAWd,cAAc;YAad,YAAY;YAyBZ,WAAW;YA0BX,WAAW;YA0BX,aAAa;YA0Bb,YAAY;YA0BZ,YAAY;YAwBZ,WAAW;YAiDX,kBAAkB;YA8ElB,iBAAiB;YASjB,aAAa;YAeb,qBAAqB;YA0BrB,sBAAsB;YA8BtB,eAAe;YAYf,aAAa;IAgB3B;;OAEG;YACW,aAAa;IA0B3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyB7B;;OAEG;YACW,iBAAiB;IAgB/B;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,gBAAgB,IAAI,MAAM;CAG3B"}