@irsprs/mobwright 0.1.0
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/CHANGELOG.md +50 -0
- package/LICENSE +19 -0
- package/README.md +776 -0
- package/dist/cli/index.cjs +796 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +773 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.cjs +1219 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +546 -0
- package/dist/index.d.ts +546 -0
- package/dist/index.js +1163 -0
- package/dist/index.js.map +1 -0
- package/package.json +100 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import * as _playwright_test from '@playwright/test';
|
|
2
|
+
import { Browser } from 'webdriverio';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Supported mobile platforms.
|
|
6
|
+
*/
|
|
7
|
+
declare enum Platform {
|
|
8
|
+
ANDROID = "android",
|
|
9
|
+
IOS = "ios"
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Where the device comes from.
|
|
13
|
+
* v0.1: emulator (Android) | simulator (iOS)
|
|
14
|
+
* v0.2+: real-device, browserstack, lambdatest, etc.
|
|
15
|
+
*/
|
|
16
|
+
type DeviceProvider = 'emulator' | 'simulator';
|
|
17
|
+
/**
|
|
18
|
+
* Device configuration for a project.
|
|
19
|
+
*/
|
|
20
|
+
interface DeviceConfig {
|
|
21
|
+
provider: DeviceProvider;
|
|
22
|
+
/** Emulator AVD name (Android) or simulator device name (iOS) */
|
|
23
|
+
name: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for a single project (platform + device combo).
|
|
27
|
+
*/
|
|
28
|
+
interface ProjectConfig {
|
|
29
|
+
name: string;
|
|
30
|
+
use: {
|
|
31
|
+
platform: Platform;
|
|
32
|
+
device: DeviceConfig;
|
|
33
|
+
buildPath: string;
|
|
34
|
+
/** Android only: explicit launcher activity */
|
|
35
|
+
appActivity?: string;
|
|
36
|
+
/** Android only: explicit app package */
|
|
37
|
+
appPackage?: string;
|
|
38
|
+
/** iOS only: bundle id (launches installed app without needing buildPath) */
|
|
39
|
+
bundleId?: string;
|
|
40
|
+
/** iOS only: platform version (e.g. "17.4") */
|
|
41
|
+
platformVersion?: string;
|
|
42
|
+
/** iOS only: simulator UDID (faster than deviceName matching) */
|
|
43
|
+
udid?: string;
|
|
44
|
+
actionTimeout?: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* AI provider name. v0.1 supports these three.
|
|
49
|
+
*/
|
|
50
|
+
type AIProviderName = 'anthropic' | 'openai' | 'deepseek';
|
|
51
|
+
/**
|
|
52
|
+
* AI configuration.
|
|
53
|
+
*/
|
|
54
|
+
interface AIConfig {
|
|
55
|
+
provider: AIProviderName;
|
|
56
|
+
model: string;
|
|
57
|
+
apiKey: string;
|
|
58
|
+
/** Optional override of the base URL. */
|
|
59
|
+
baseURL?: string;
|
|
60
|
+
/** Optional timeout in ms. */
|
|
61
|
+
timeout?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Top-level mobwright configuration.
|
|
65
|
+
*/
|
|
66
|
+
interface MobwrightConfig {
|
|
67
|
+
projects: ProjectConfig[];
|
|
68
|
+
ai?: AIConfig;
|
|
69
|
+
/** Default timeout for all locator actions in ms */
|
|
70
|
+
actionTimeout?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface LocatorOptions {
|
|
74
|
+
/** Max time in ms to wait for the element to be actionable. Default 5000. */
|
|
75
|
+
timeout?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A lazy reference to a UI element.
|
|
79
|
+
*
|
|
80
|
+
* Locators don't query the device when created — only when an action runs.
|
|
81
|
+
* Every action auto-waits up to `timeout` (default 5s) for the element to
|
|
82
|
+
* be present + visible + enabled before failing.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* await device.locator('~loginButton').tap();
|
|
86
|
+
* const text = await device.locator('~welcome').getText();
|
|
87
|
+
*/
|
|
88
|
+
declare class Locator {
|
|
89
|
+
readonly selector: string;
|
|
90
|
+
private readonly browser;
|
|
91
|
+
private readonly platform;
|
|
92
|
+
private readonly defaultTimeout;
|
|
93
|
+
constructor(browser: Browser, platform: Platform, selector: string, options?: LocatorOptions);
|
|
94
|
+
/**
|
|
95
|
+
* Wait for the element to be present in the tree AND displayed.
|
|
96
|
+
* Returns the wdio element handle once ready.
|
|
97
|
+
*/
|
|
98
|
+
private waitForElement;
|
|
99
|
+
/**
|
|
100
|
+
* Tap (click) the element. Auto-waits until visible + enabled.
|
|
101
|
+
*/
|
|
102
|
+
tap(): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Type text into the element. Auto-waits until visible.
|
|
105
|
+
* Clears existing content first.
|
|
106
|
+
*/
|
|
107
|
+
fill(text: string): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Get the visible text of the element.
|
|
110
|
+
*/
|
|
111
|
+
getText(): Promise<string>;
|
|
112
|
+
/**
|
|
113
|
+
* Check if the element is currently visible (no waiting).
|
|
114
|
+
* Returns false if not present.
|
|
115
|
+
*/
|
|
116
|
+
isVisible(): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Wait for the element to become visible.
|
|
119
|
+
* Useful for explicit waits without performing an action.
|
|
120
|
+
*/
|
|
121
|
+
waitFor(options?: {
|
|
122
|
+
timeout?: number;
|
|
123
|
+
}): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Press and hold the element for `duration` ms (long-press).
|
|
126
|
+
* Default duration: 1000 ms.
|
|
127
|
+
*/
|
|
128
|
+
tapAndHold(options?: {
|
|
129
|
+
duration?: number;
|
|
130
|
+
}): Promise<void>;
|
|
131
|
+
/** Swipe left within the element bounds. */
|
|
132
|
+
swipeLeft(options?: {
|
|
133
|
+
duration?: number;
|
|
134
|
+
distance?: number;
|
|
135
|
+
}): Promise<void>;
|
|
136
|
+
/** Swipe right within the element bounds. */
|
|
137
|
+
swipeRight(options?: {
|
|
138
|
+
duration?: number;
|
|
139
|
+
distance?: number;
|
|
140
|
+
}): Promise<void>;
|
|
141
|
+
/** Swipe up within the element bounds. */
|
|
142
|
+
swipeUp(options?: {
|
|
143
|
+
duration?: number;
|
|
144
|
+
distance?: number;
|
|
145
|
+
}): Promise<void>;
|
|
146
|
+
/** Swipe down within the element bounds. */
|
|
147
|
+
swipeDown(options?: {
|
|
148
|
+
duration?: number;
|
|
149
|
+
distance?: number;
|
|
150
|
+
}): Promise<void>;
|
|
151
|
+
/**
|
|
152
|
+
* Scroll up inside a scrollable container.
|
|
153
|
+
* Slower and longer than swipeUp — use on lists/pages.
|
|
154
|
+
*/
|
|
155
|
+
scrollUp(options?: {
|
|
156
|
+
duration?: number;
|
|
157
|
+
distance?: number;
|
|
158
|
+
}): Promise<void>;
|
|
159
|
+
/**
|
|
160
|
+
* Scroll down inside a scrollable container.
|
|
161
|
+
* Slower and longer than swipeDown — use on lists/pages.
|
|
162
|
+
*/
|
|
163
|
+
scrollDown(options?: {
|
|
164
|
+
duration?: number;
|
|
165
|
+
distance?: number;
|
|
166
|
+
}): Promise<void>;
|
|
167
|
+
/**
|
|
168
|
+
* Check if the element is currently enabled (not greyed out / disabled).
|
|
169
|
+
* Returns false if not present or not enabled.
|
|
170
|
+
* Does NOT auto-wait — for retry behavior, use expect(locator).toBeEnabled().
|
|
171
|
+
*/
|
|
172
|
+
isEnabled(): Promise<boolean>;
|
|
173
|
+
private _swipe;
|
|
174
|
+
private _scroll;
|
|
175
|
+
private _performSwipeAction;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* What every AI provider must understand for locator resolution.
|
|
180
|
+
*/
|
|
181
|
+
interface ResolveLocatorInput {
|
|
182
|
+
/** Natural-language description of the target element. */
|
|
183
|
+
description: string;
|
|
184
|
+
/** Serialized accessibility tree (XML for Appium). */
|
|
185
|
+
accessibilityTree: string;
|
|
186
|
+
/** Optional screenshot, for providers that support vision. */
|
|
187
|
+
screenshot?: Buffer;
|
|
188
|
+
/** Target platform — affects selector strategy choices. */
|
|
189
|
+
platform: Platform;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* What the provider returns.
|
|
193
|
+
*/
|
|
194
|
+
interface ResolveLocatorResult {
|
|
195
|
+
/** A selector string mobwright can parse: ~foo, #foo, //xpath, or plain text. */
|
|
196
|
+
selector: string;
|
|
197
|
+
/** Which strategy the selector uses. Helps with validation/logging. */
|
|
198
|
+
strategy: SelectorStrategy;
|
|
199
|
+
/** 0..1 — how confident the provider is. <0.5 should be treated as a miss. */
|
|
200
|
+
confidence: number;
|
|
201
|
+
/** Free-text explanation, for debugging. */
|
|
202
|
+
rationale?: string;
|
|
203
|
+
}
|
|
204
|
+
type SelectorStrategy = 'accessibility-id' | 'id' | 'xpath' | 'text';
|
|
205
|
+
/**
|
|
206
|
+
* Provider configuration. Each provider may interpret these differently.
|
|
207
|
+
*/
|
|
208
|
+
interface ProviderConfig {
|
|
209
|
+
apiKey: string;
|
|
210
|
+
model: string;
|
|
211
|
+
/** Override the API base URL. Used for DeepSeek (OpenAI-compatible endpoint). */
|
|
212
|
+
baseURL?: string;
|
|
213
|
+
/** Request timeout in ms. */
|
|
214
|
+
timeout?: number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Common interface for all AI providers.
|
|
219
|
+
*
|
|
220
|
+
* v0.1 only needs resolveLocator. Future versions will add:
|
|
221
|
+
* - analyzeFailure() for AI failure reports
|
|
222
|
+
* - suggestHeal() for self-healing locators
|
|
223
|
+
*/
|
|
224
|
+
interface AIProvider {
|
|
225
|
+
/** Provider name for logging, e.g. 'anthropic', 'openai', 'deepseek'. */
|
|
226
|
+
readonly name: string;
|
|
227
|
+
/** Resolve a natural-language description to a concrete selector. */
|
|
228
|
+
resolveLocator(input: ResolveLocatorInput): Promise<ResolveLocatorResult>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
interface AILocatorOptions extends LocatorOptions {
|
|
232
|
+
/**
|
|
233
|
+
* Minimum confidence the AI must return for us to trust the resolution.
|
|
234
|
+
* Below this, we throw with a clear error rather than silently using a bad selector.
|
|
235
|
+
* Default: 0.5.
|
|
236
|
+
*/
|
|
237
|
+
minConfidence?: number;
|
|
238
|
+
/**
|
|
239
|
+
* Max characters of the accessibility tree to send to the AI.
|
|
240
|
+
* Default: 12,000 (~3000 tokens).
|
|
241
|
+
*/
|
|
242
|
+
treeCharBudget?: number;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* A natural-language locator. Lazily resolves an English description to a
|
|
246
|
+
* concrete selector via the configured AI provider, then delegates to a
|
|
247
|
+
* regular Locator for the actual action.
|
|
248
|
+
*
|
|
249
|
+
* Resolution happens once per AILocator instance. Subsequent actions reuse
|
|
250
|
+
* the cached selector.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* await device.ai('the Continue button').tap();
|
|
254
|
+
* await device.ai('the email input').fill('me@example.com');
|
|
255
|
+
*/
|
|
256
|
+
declare class AILocator {
|
|
257
|
+
readonly description: string;
|
|
258
|
+
private readonly browser;
|
|
259
|
+
private readonly platform;
|
|
260
|
+
private readonly provider;
|
|
261
|
+
private readonly options;
|
|
262
|
+
/** Cached resolution. Populated on first action. */
|
|
263
|
+
private resolved;
|
|
264
|
+
/** Cached underlying Locator. Populated on first action. */
|
|
265
|
+
private locator;
|
|
266
|
+
constructor(browser: Browser, platform: Platform, provider: AIProvider, description: string, options?: AILocatorOptions);
|
|
267
|
+
/**
|
|
268
|
+
* Resolve the description to a Locator. Called automatically on first action.
|
|
269
|
+
* Exposed for advanced use / debugging.
|
|
270
|
+
*/
|
|
271
|
+
resolve(): Promise<Locator>;
|
|
272
|
+
/** Validate the AI's response before trusting it. */
|
|
273
|
+
private validate;
|
|
274
|
+
/** Build a mobwright selector string from the AI's strategy + value. */
|
|
275
|
+
private buildSelectorString;
|
|
276
|
+
/** Tap the resolved element. Resolves on first call. */
|
|
277
|
+
tap(): Promise<void>;
|
|
278
|
+
/** Type text into the resolved element. */
|
|
279
|
+
fill(text: string): Promise<void>;
|
|
280
|
+
/** Get the visible text of the resolved element. */
|
|
281
|
+
getText(): Promise<string>;
|
|
282
|
+
/** Check visibility of the resolved element (snapshot, no waiting). */
|
|
283
|
+
isVisible(): Promise<boolean>;
|
|
284
|
+
/** Wait for the resolved element to be visible. */
|
|
285
|
+
waitFor(options?: {
|
|
286
|
+
timeout?: number;
|
|
287
|
+
}): Promise<void>;
|
|
288
|
+
/** Check if the resolved element is enabled (snapshot, no waiting). */
|
|
289
|
+
isEnabled(): Promise<boolean>;
|
|
290
|
+
/**
|
|
291
|
+
* Inspect the resolved selector. Returns null if not yet resolved.
|
|
292
|
+
* Useful for debugging or "save back to a stable selector" workflows.
|
|
293
|
+
*/
|
|
294
|
+
getResolved(): ResolveLocatorResult | null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
declare class Device {
|
|
298
|
+
readonly stub: false;
|
|
299
|
+
readonly project: string;
|
|
300
|
+
readonly platform: Platform;
|
|
301
|
+
readonly browser: Browser;
|
|
302
|
+
/** Optional AI provider — only set if AI is configured. */
|
|
303
|
+
readonly aiProvider: AIProvider | undefined;
|
|
304
|
+
private readonly defaultTimeout;
|
|
305
|
+
constructor(browser: Browser, project: ProjectConfig, aiProvider?: AIProvider);
|
|
306
|
+
/**
|
|
307
|
+
* Create a lazy reference to a UI element by selector string.
|
|
308
|
+
*
|
|
309
|
+
* Selector syntax:
|
|
310
|
+
* ~foo → accessibility id
|
|
311
|
+
* #foo → resource id (ends-with match; package prefix optional)
|
|
312
|
+
* //... → xpath
|
|
313
|
+
* foo → accessibility id (no prefix)
|
|
314
|
+
*/
|
|
315
|
+
locator(selector: string, options?: LocatorOptions): Locator;
|
|
316
|
+
/**
|
|
317
|
+
* Convenience: locate an element by its visible text or label (exact match).
|
|
318
|
+
*/
|
|
319
|
+
getByText(text: string, options?: LocatorOptions): Locator;
|
|
320
|
+
/**
|
|
321
|
+
* Locate an element whose visible text **contains** the substring.
|
|
322
|
+
* Case-insensitive by default.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* device.getByContainingText('get started'); // matches "Get Started", "GET STARTED", etc.
|
|
326
|
+
* device.getByContainingText('Started', { ignoreCase: false }); // case-sensitive substring
|
|
327
|
+
*/
|
|
328
|
+
getByContainingText(text: string, options?: LocatorOptions & {
|
|
329
|
+
ignoreCase?: boolean;
|
|
330
|
+
}): Locator;
|
|
331
|
+
/**
|
|
332
|
+
* Take a screenshot. Returns raw PNG bytes.
|
|
333
|
+
*/
|
|
334
|
+
screenshot(): Promise<Buffer>;
|
|
335
|
+
/**
|
|
336
|
+
* Get the current accessibility tree as an XML string.
|
|
337
|
+
* Used later by AI locator resolution.
|
|
338
|
+
*/
|
|
339
|
+
getPageSource(): Promise<string>;
|
|
340
|
+
/**
|
|
341
|
+
* Create a natural-language locator. Resolves on first action via AI.
|
|
342
|
+
*
|
|
343
|
+
* Requires AI to be configured (MOBWRIGHT_AI_PROVIDER + MOBWRIGHT_AI_API_KEY).
|
|
344
|
+
* Throws AIError immediately if AI is not configured.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* await device.ai('the blue Continue button at the bottom').tap();
|
|
348
|
+
* await device.ai('the email input field').fill('me@example.com');
|
|
349
|
+
*/
|
|
350
|
+
ai(description: string, options?: AILocatorOptions): AILocator;
|
|
351
|
+
/**
|
|
352
|
+
* Get cumulative token usage from the AI provider (if it tracks tokens).
|
|
353
|
+
* Returns null if AI is not configured or if the provider doesn't support token tracking.
|
|
354
|
+
*/
|
|
355
|
+
getAITokenUsage(): unknown;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
|
|
359
|
+
device: Device;
|
|
360
|
+
}, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Anything our matchers know how to assert on.
|
|
364
|
+
* Both Locator and AILocator have the methods we need.
|
|
365
|
+
*/
|
|
366
|
+
type AssertableLocator = Pick<Locator, 'isVisible' | 'getText' | 'selector'> & {
|
|
367
|
+
isEnabled?: () => Promise<boolean>;
|
|
368
|
+
};
|
|
369
|
+
interface MatcherResult {
|
|
370
|
+
pass: boolean;
|
|
371
|
+
message: () => string;
|
|
372
|
+
name?: string;
|
|
373
|
+
expected?: unknown;
|
|
374
|
+
actual?: unknown;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Match modes for text assertions.
|
|
378
|
+
*/
|
|
379
|
+
type TextMatcher = string | RegExp;
|
|
380
|
+
/**
|
|
381
|
+
* Mobwright's expect — extends Playwright's with mobile-aware matchers.
|
|
382
|
+
*
|
|
383
|
+
* Each matcher auto-retries up to `timeout` ms (default 5000).
|
|
384
|
+
*/
|
|
385
|
+
declare const expect: _playwright_test.Expect<{
|
|
386
|
+
/**
|
|
387
|
+
* Assert the element is currently visible (present + displayed).
|
|
388
|
+
* Auto-retries until visible or timeout.
|
|
389
|
+
*/
|
|
390
|
+
toBeVisible(this: _playwright_test.ExpectMatcherState, received: AssertableLocator, options?: {
|
|
391
|
+
timeout?: number;
|
|
392
|
+
}): Promise<MatcherResult>;
|
|
393
|
+
/**
|
|
394
|
+
* Assert the element's visible text matches.
|
|
395
|
+
* Pass a string for exact match, or a RegExp for pattern match.
|
|
396
|
+
* Auto-retries until match or timeout.
|
|
397
|
+
*/
|
|
398
|
+
toHaveText(this: _playwright_test.ExpectMatcherState, received: AssertableLocator, expected: TextMatcher, options?: {
|
|
399
|
+
timeout?: number;
|
|
400
|
+
}): Promise<MatcherResult>;
|
|
401
|
+
/**
|
|
402
|
+
* Assert the element's visible text **contains** the expected substring.
|
|
403
|
+
* Case-insensitive by default. Pass `ignoreCase: false` for exact-case check.
|
|
404
|
+
* Also accepts a RegExp.
|
|
405
|
+
* Auto-retries until match or timeout.
|
|
406
|
+
*/
|
|
407
|
+
toContainText(this: _playwright_test.ExpectMatcherState, received: AssertableLocator, expected: TextMatcher, options?: {
|
|
408
|
+
timeout?: number;
|
|
409
|
+
ignoreCase?: boolean;
|
|
410
|
+
}): Promise<MatcherResult>;
|
|
411
|
+
/**
|
|
412
|
+
* Assert the element is enabled (interactable).
|
|
413
|
+
* Auto-retries until enabled or timeout.
|
|
414
|
+
*/
|
|
415
|
+
toBeEnabled(this: _playwright_test.ExpectMatcherState, received: AssertableLocator, options?: {
|
|
416
|
+
timeout?: number;
|
|
417
|
+
}): Promise<MatcherResult>;
|
|
418
|
+
}>;
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Define mobwright config with full type inference.
|
|
422
|
+
*
|
|
423
|
+
* @example
|
|
424
|
+
* import { defineConfig, Platform } from 'mobwright';
|
|
425
|
+
*
|
|
426
|
+
* export default defineConfig({
|
|
427
|
+
* projects: [
|
|
428
|
+
* {
|
|
429
|
+
* name: 'android',
|
|
430
|
+
* use: {
|
|
431
|
+
* platform: Platform.ANDROID,
|
|
432
|
+
* device: { provider: 'emulator', name: 'Pixel_6_API_34' },
|
|
433
|
+
* buildPath: './app.apk',
|
|
434
|
+
* },
|
|
435
|
+
* },
|
|
436
|
+
* ],
|
|
437
|
+
* });
|
|
438
|
+
*/
|
|
439
|
+
declare function defineConfig(config: MobwrightConfig): MobwrightConfig;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Base class for all AI-related errors so callers can catch them generically.
|
|
443
|
+
*/
|
|
444
|
+
declare class AIError extends Error {
|
|
445
|
+
readonly cause?: unknown | undefined;
|
|
446
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
447
|
+
}
|
|
448
|
+
/** The provider's HTTP call failed or timed out. */
|
|
449
|
+
declare class AIRequestError extends AIError {
|
|
450
|
+
constructor(message: string, cause?: unknown);
|
|
451
|
+
}
|
|
452
|
+
/** The provider returned a response we couldn't parse. */
|
|
453
|
+
declare class AIResponseError extends AIError {
|
|
454
|
+
readonly raw?: string | undefined;
|
|
455
|
+
constructor(message: string, raw?: string | undefined, cause?: unknown);
|
|
456
|
+
}
|
|
457
|
+
/** The provider's response didn't meet our validation criteria. */
|
|
458
|
+
declare class AIValidationError extends AIError {
|
|
459
|
+
constructor(message: string, cause?: unknown);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
interface OpenAICompatibleProviderOptions extends ProviderConfig {
|
|
463
|
+
/** Override the provider name in logs. Defaults to 'openai'. */
|
|
464
|
+
name?: string;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* OpenAI-compatible provider.
|
|
468
|
+
*
|
|
469
|
+
* Used directly for OpenAI, and as the base for DeepSeek (which exposes
|
|
470
|
+
* an OpenAI-compatible API at a different base URL).
|
|
471
|
+
*/
|
|
472
|
+
declare class OpenAICompatibleProvider implements AIProvider {
|
|
473
|
+
readonly name: string;
|
|
474
|
+
private readonly client;
|
|
475
|
+
private readonly model;
|
|
476
|
+
constructor(config: OpenAICompatibleProviderOptions);
|
|
477
|
+
resolveLocator(input: ResolveLocatorInput): Promise<ResolveLocatorResult>;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* DeepSeek uses an OpenAI-compatible API at a different base URL.
|
|
482
|
+
* This is just a thin wrapper for ergonomics + correct defaults.
|
|
483
|
+
*
|
|
484
|
+
* Default model: deepseek-chat (general purpose, cheap).
|
|
485
|
+
* For reasoning-heavy tasks: deepseek-reasoner.
|
|
486
|
+
*/
|
|
487
|
+
declare class DeepSeekProvider extends OpenAICompatibleProvider {
|
|
488
|
+
constructor(config: ProviderConfig);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
declare class AnthropicProvider implements AIProvider {
|
|
492
|
+
readonly name = "anthropic";
|
|
493
|
+
private readonly client;
|
|
494
|
+
private readonly model;
|
|
495
|
+
private totalInputTokens;
|
|
496
|
+
private totalOutputTokens;
|
|
497
|
+
constructor(config: ProviderConfig);
|
|
498
|
+
resolveLocator(input: ResolveLocatorInput): Promise<ResolveLocatorResult>;
|
|
499
|
+
/** Get cumulative token usage across all requests. */
|
|
500
|
+
getTokenUsage(): {
|
|
501
|
+
inputTokens: number;
|
|
502
|
+
outputTokens: number;
|
|
503
|
+
totalTokens: number;
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Create an AIProvider from a mobwright AIConfig.
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* const provider = createProvider({
|
|
512
|
+
* provider: 'deepseek',
|
|
513
|
+
* model: 'deepseek-chat',
|
|
514
|
+
* apiKey: process.env.MOBWRIGHT_AI_API_KEY!,
|
|
515
|
+
* });
|
|
516
|
+
*/
|
|
517
|
+
declare function createProvider(config: AIConfig): AIProvider;
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Get a cleaned-up accessibility tree for AI consumption.
|
|
521
|
+
*
|
|
522
|
+
* Returns serialized XML with:
|
|
523
|
+
* - Layout/coordinate noise stripped
|
|
524
|
+
* - false-valued boolean attributes removed
|
|
525
|
+
* - empty attributes removed
|
|
526
|
+
*
|
|
527
|
+
* Intent: a much smaller payload that still preserves selector-relevant info
|
|
528
|
+
* (text, content-desc, resource-id, class, name, label, value).
|
|
529
|
+
*/
|
|
530
|
+
declare function getCleanTree(browser: Browser, platform: Platform): Promise<string>;
|
|
531
|
+
/**
|
|
532
|
+
* Pure function — exported for unit testing.
|
|
533
|
+
*/
|
|
534
|
+
declare function cleanTree(raw: string, platform: Platform): string;
|
|
535
|
+
/** Conservative tree budget — leaves room for system prompt + user prompt + response. */
|
|
536
|
+
declare const DEFAULT_TREE_CHAR_BUDGET = 12000;
|
|
537
|
+
/**
|
|
538
|
+
* Truncate a tree to fit within a character budget.
|
|
539
|
+
* Preference: keep the start of the tree (usually contains the main interactive content).
|
|
540
|
+
* Logs a warning if truncation happens.
|
|
541
|
+
*/
|
|
542
|
+
declare function fitTreeToBudget(tree: string, budget?: number): string;
|
|
543
|
+
/** Estimate tokens for a string. Rough but useful for cost forecasting. */
|
|
544
|
+
declare function estimateTokens(text: string): number;
|
|
545
|
+
|
|
546
|
+
export { type AIConfig, AIError, AILocator, type AILocatorOptions, type AIProvider, type AIProviderName, AIRequestError, AIResponseError, AIValidationError, AnthropicProvider, DEFAULT_TREE_CHAR_BUDGET, DeepSeekProvider, Device, type DeviceConfig, type DeviceProvider, Locator, type LocatorOptions, type MobwrightConfig, OpenAICompatibleProvider, Platform, type ProjectConfig, type ProviderConfig, type ResolveLocatorInput, type ResolveLocatorResult, type SelectorStrategy, cleanTree, createProvider, defineConfig, estimateTokens, expect, fitTreeToBudget, getCleanTree, test };
|