browser-pilot 0.0.7 → 0.0.9
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 +61 -1
- package/dist/actions.cjs +485 -9
- package/dist/actions.d.cts +24 -5
- package/dist/actions.d.ts +24 -5
- package/dist/actions.mjs +5 -3
- package/dist/browser.cjs +1761 -102
- package/dist/browser.d.cts +8 -4
- package/dist/browser.d.ts +8 -4
- package/dist/browser.mjs +6 -5
- package/dist/{chunk-PCNEJAJ7.mjs → chunk-7OSR2CAE.mjs} +1756 -46
- package/dist/chunk-KKW2SZLV.mjs +741 -0
- package/dist/cli.mjs +7576 -265
- package/dist/index.cjs +2434 -108
- package/dist/index.d.cts +142 -6
- package/dist/index.d.ts +142 -6
- package/dist/index.mjs +360 -13
- package/dist/providers.d.cts +2 -2
- package/dist/providers.d.ts +2 -2
- package/dist/{types-D_uDqh0Z.d.cts → types--wXNHUwt.d.cts} +1 -1
- package/dist/{types-D_uDqh0Z.d.ts → types--wXNHUwt.d.ts} +1 -1
- package/dist/{types-TVlTA7nH.d.cts → types-CYw-7vx1.d.cts} +280 -3
- package/dist/{types-CbdmaocU.d.ts → types-DOGsEYQa.d.ts} +280 -3
- package/package.json +3 -3
- package/dist/chunk-6RB3GKQP.mjs +0 -251
- package/dist/chunk-ZIQA4JOT.mjs +0 -226
- package/dist/cli.cjs +0 -4792
- package/dist/cli.d.cts +0 -25
- package/dist/cli.d.ts +0 -25
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
disableTracing,
|
|
5
|
-
enableTracing,
|
|
6
|
-
getTracer
|
|
7
|
-
} from "./chunk-ZIQA4JOT.mjs";
|
|
8
|
-
import {
|
|
2
|
+
AudioInput,
|
|
3
|
+
AudioOutput,
|
|
9
4
|
Browser,
|
|
10
|
-
ElementNotFoundError,
|
|
11
|
-
NavigationError,
|
|
12
5
|
Page,
|
|
13
6
|
RequestInterceptor,
|
|
14
|
-
|
|
7
|
+
bufferToBase64,
|
|
8
|
+
calculateRMS,
|
|
15
9
|
connect,
|
|
10
|
+
generateSilence,
|
|
11
|
+
generateTone,
|
|
12
|
+
grantAudioPermissions,
|
|
13
|
+
parseWavHeader,
|
|
14
|
+
pcmToWav,
|
|
16
15
|
waitForAnyElement,
|
|
17
16
|
waitForElement,
|
|
18
17
|
waitForNavigation,
|
|
19
18
|
waitForNetworkIdle
|
|
20
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-7OSR2CAE.mjs";
|
|
21
20
|
import {
|
|
22
21
|
CDPError,
|
|
23
22
|
createCDPClient
|
|
@@ -32,9 +31,346 @@ import {
|
|
|
32
31
|
} from "./chunk-R3PS4PCM.mjs";
|
|
33
32
|
import {
|
|
34
33
|
BatchExecutor,
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
ElementNotFoundError,
|
|
35
|
+
NavigationError,
|
|
36
|
+
TimeoutError,
|
|
37
|
+
addBatchToPage,
|
|
38
|
+
validateSteps
|
|
39
|
+
} from "./chunk-KKW2SZLV.mjs";
|
|
40
|
+
|
|
41
|
+
// src/audio/flags.ts
|
|
42
|
+
function getAudioChromeFlags(options) {
|
|
43
|
+
const flags = [
|
|
44
|
+
"--use-fake-device-for-media-stream",
|
|
45
|
+
"--use-fake-ui-for-media-stream",
|
|
46
|
+
"--autoplay-policy=no-user-gesture-required"
|
|
47
|
+
];
|
|
48
|
+
if (options?.inputWavPath) {
|
|
49
|
+
let path = options.inputWavPath;
|
|
50
|
+
if (options.noLoop) {
|
|
51
|
+
path += "%noloop";
|
|
52
|
+
}
|
|
53
|
+
flags.push(`--use-file-for-fake-audio-capture=${path}`);
|
|
54
|
+
}
|
|
55
|
+
return flags;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/audio/transcribe.ts
|
|
59
|
+
async function transcribe(audio, options) {
|
|
60
|
+
const apiKey = options?.apiKey ?? getEnvVar("OPENAI_API_KEY");
|
|
61
|
+
if (!apiKey) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
"OpenAI API key required for transcription. Set OPENAI_API_KEY environment variable or pass apiKey option."
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (audio.left.length === 0) {
|
|
67
|
+
return { text: "", audioDurationMs: 0, apiDurationMs: 0 };
|
|
68
|
+
}
|
|
69
|
+
const model = options?.model ?? "whisper-1";
|
|
70
|
+
const responseFormat = options?.responseFormat ?? "text";
|
|
71
|
+
const wavBuffer = pcmToWav({
|
|
72
|
+
left: audio.left,
|
|
73
|
+
right: audio.right.length > 0 ? audio.right : void 0,
|
|
74
|
+
sampleRate: audio.sampleRate
|
|
75
|
+
});
|
|
76
|
+
const boundary = `----bpAudio${Date.now()}`;
|
|
77
|
+
const parts = [];
|
|
78
|
+
appendFormField(parts, boundary, "file", new Uint8Array(wavBuffer), "audio.wav", "audio/wav");
|
|
79
|
+
appendFormTextField(parts, boundary, "model", model);
|
|
80
|
+
appendFormTextField(parts, boundary, "response_format", responseFormat);
|
|
81
|
+
if (options?.language) {
|
|
82
|
+
appendFormTextField(parts, boundary, "language", options.language);
|
|
83
|
+
}
|
|
84
|
+
if (options?.prompt) {
|
|
85
|
+
appendFormTextField(parts, boundary, "prompt", options.prompt);
|
|
86
|
+
}
|
|
87
|
+
const closing = new TextEncoder().encode(`\r
|
|
88
|
+
--${boundary}--\r
|
|
89
|
+
`);
|
|
90
|
+
parts.push(closing);
|
|
91
|
+
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
92
|
+
const body = new Uint8Array(totalLength);
|
|
93
|
+
let offset = 0;
|
|
94
|
+
for (const part of parts) {
|
|
95
|
+
body.set(part, offset);
|
|
96
|
+
offset += part.length;
|
|
97
|
+
}
|
|
98
|
+
const start = Date.now();
|
|
99
|
+
const response = await fetch("https://api.openai.com/v1/audio/transcriptions", {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: {
|
|
102
|
+
Authorization: `Bearer ${apiKey}`,
|
|
103
|
+
"Content-Type": `multipart/form-data; boundary=${boundary}`
|
|
104
|
+
},
|
|
105
|
+
body
|
|
106
|
+
});
|
|
107
|
+
const apiDurationMs = Date.now() - start;
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
const errorBody = await response.text().catch(() => "");
|
|
110
|
+
throw new Error(`Whisper API error (${response.status}): ${errorBody}`);
|
|
111
|
+
}
|
|
112
|
+
let text;
|
|
113
|
+
if (responseFormat === "text") {
|
|
114
|
+
text = (await response.text()).trim();
|
|
115
|
+
} else {
|
|
116
|
+
const json = await response.json();
|
|
117
|
+
text = json.text ?? "";
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
text,
|
|
121
|
+
audioDurationMs: audio.durationMs,
|
|
122
|
+
apiDurationMs
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function isTranscriptionAvailable() {
|
|
126
|
+
return !!getEnvVar("OPENAI_API_KEY");
|
|
127
|
+
}
|
|
128
|
+
function getEnvVar(name) {
|
|
129
|
+
if (typeof globalThis.process !== "undefined" && globalThis.process.env) {
|
|
130
|
+
return globalThis.process.env[name];
|
|
131
|
+
}
|
|
132
|
+
return void 0;
|
|
133
|
+
}
|
|
134
|
+
function appendFormTextField(parts, boundary, name, value) {
|
|
135
|
+
const text = `\r
|
|
136
|
+
--${boundary}\r
|
|
137
|
+
Content-Disposition: form-data; name="${name}"\r
|
|
138
|
+
\r
|
|
139
|
+
${value}`;
|
|
140
|
+
parts.push(new TextEncoder().encode(text));
|
|
141
|
+
}
|
|
142
|
+
function appendFormField(parts, boundary, name, data, filename, contentType) {
|
|
143
|
+
const header = `\r
|
|
144
|
+
--${boundary}\r
|
|
145
|
+
Content-Disposition: form-data; name="${name}"; filename="${filename}"\r
|
|
146
|
+
Content-Type: ${contentType}\r
|
|
147
|
+
\r
|
|
148
|
+
`;
|
|
149
|
+
parts.push(new TextEncoder().encode(header));
|
|
150
|
+
parts.push(data);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/emulation/devices.ts
|
|
154
|
+
var devices = {
|
|
155
|
+
"iPhone 14": {
|
|
156
|
+
name: "iPhone 14",
|
|
157
|
+
viewport: {
|
|
158
|
+
width: 390,
|
|
159
|
+
height: 844,
|
|
160
|
+
deviceScaleFactor: 3,
|
|
161
|
+
isMobile: true,
|
|
162
|
+
hasTouch: true
|
|
163
|
+
},
|
|
164
|
+
userAgent: {
|
|
165
|
+
userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
|
166
|
+
platform: "iPhone",
|
|
167
|
+
userAgentMetadata: {
|
|
168
|
+
mobile: true,
|
|
169
|
+
platform: "iOS",
|
|
170
|
+
platformVersion: "16.0"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"iPhone 14 Pro Max": {
|
|
175
|
+
name: "iPhone 14 Pro Max",
|
|
176
|
+
viewport: {
|
|
177
|
+
width: 430,
|
|
178
|
+
height: 932,
|
|
179
|
+
deviceScaleFactor: 3,
|
|
180
|
+
isMobile: true,
|
|
181
|
+
hasTouch: true
|
|
182
|
+
},
|
|
183
|
+
userAgent: {
|
|
184
|
+
userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
|
185
|
+
platform: "iPhone"
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"Pixel 7": {
|
|
189
|
+
name: "Pixel 7",
|
|
190
|
+
viewport: {
|
|
191
|
+
width: 412,
|
|
192
|
+
height: 915,
|
|
193
|
+
deviceScaleFactor: 2.625,
|
|
194
|
+
isMobile: true,
|
|
195
|
+
hasTouch: true
|
|
196
|
+
},
|
|
197
|
+
userAgent: {
|
|
198
|
+
userAgent: "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
|
|
199
|
+
platform: "Linux armv8l",
|
|
200
|
+
userAgentMetadata: {
|
|
201
|
+
mobile: true,
|
|
202
|
+
platform: "Android",
|
|
203
|
+
platformVersion: "13",
|
|
204
|
+
model: "Pixel 7"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"iPad Pro 11": {
|
|
209
|
+
name: "iPad Pro 11",
|
|
210
|
+
viewport: {
|
|
211
|
+
width: 834,
|
|
212
|
+
height: 1194,
|
|
213
|
+
deviceScaleFactor: 2,
|
|
214
|
+
isMobile: true,
|
|
215
|
+
hasTouch: true
|
|
216
|
+
},
|
|
217
|
+
userAgent: {
|
|
218
|
+
userAgent: "Mozilla/5.0 (iPad; CPU OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
|
219
|
+
platform: "iPad"
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"Desktop Chrome": {
|
|
223
|
+
name: "Desktop Chrome",
|
|
224
|
+
viewport: {
|
|
225
|
+
width: 1920,
|
|
226
|
+
height: 1080,
|
|
227
|
+
deviceScaleFactor: 1,
|
|
228
|
+
isMobile: false,
|
|
229
|
+
hasTouch: false
|
|
230
|
+
},
|
|
231
|
+
userAgent: {
|
|
232
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
233
|
+
platform: "Win32",
|
|
234
|
+
userAgentMetadata: {
|
|
235
|
+
brands: [
|
|
236
|
+
{ brand: "Not_A Brand", version: "8" },
|
|
237
|
+
{ brand: "Chromium", version: "120" },
|
|
238
|
+
{ brand: "Google Chrome", version: "120" }
|
|
239
|
+
],
|
|
240
|
+
platform: "Windows",
|
|
241
|
+
platformVersion: "10.0.0",
|
|
242
|
+
architecture: "x86",
|
|
243
|
+
bitness: "64",
|
|
244
|
+
mobile: false
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"Desktop Firefox": {
|
|
249
|
+
name: "Desktop Firefox",
|
|
250
|
+
viewport: {
|
|
251
|
+
width: 1920,
|
|
252
|
+
height: 1080,
|
|
253
|
+
deviceScaleFactor: 1,
|
|
254
|
+
isMobile: false,
|
|
255
|
+
hasTouch: false
|
|
256
|
+
},
|
|
257
|
+
userAgent: {
|
|
258
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
|
|
259
|
+
platform: "Win32"
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// src/trace/tracer.ts
|
|
265
|
+
var LEVEL_ORDER = {
|
|
266
|
+
debug: 0,
|
|
267
|
+
info: 1,
|
|
268
|
+
warn: 2,
|
|
269
|
+
error: 3
|
|
270
|
+
};
|
|
271
|
+
var Tracer = class _Tracer {
|
|
272
|
+
options;
|
|
273
|
+
constructor(options = {}) {
|
|
274
|
+
this.options = {
|
|
275
|
+
enabled: options.enabled ?? false,
|
|
276
|
+
output: options.output ?? "console",
|
|
277
|
+
callback: options.callback,
|
|
278
|
+
level: options.level ?? "info",
|
|
279
|
+
includeTimings: options.includeTimings ?? true
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Emit a trace event
|
|
284
|
+
*/
|
|
285
|
+
emit(event) {
|
|
286
|
+
if (!this.options.enabled) return;
|
|
287
|
+
if (LEVEL_ORDER[event.level] < LEVEL_ORDER[this.options.level]) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const fullEvent = {
|
|
291
|
+
...event,
|
|
292
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
293
|
+
};
|
|
294
|
+
switch (this.options.output) {
|
|
295
|
+
case "console":
|
|
296
|
+
this.logToConsole(fullEvent);
|
|
297
|
+
break;
|
|
298
|
+
case "callback":
|
|
299
|
+
this.options.callback?.(fullEvent);
|
|
300
|
+
break;
|
|
301
|
+
case "silent":
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Log event to console
|
|
307
|
+
*/
|
|
308
|
+
logToConsole(event) {
|
|
309
|
+
const { level, category, action, selectorUsed, success, durationMs, error } = event;
|
|
310
|
+
const icon = success === true ? "\u2713" : success === false ? "\u2717" : "\u25CB";
|
|
311
|
+
const timing = this.options.includeTimings && durationMs !== void 0 ? ` (${durationMs}ms)` : "";
|
|
312
|
+
const selector = selectorUsed ? ` ${selectorUsed}` : "";
|
|
313
|
+
const errorStr = error ? ` - ${error}` : "";
|
|
314
|
+
const message = `[${level.toUpperCase()}] [${category}] ${icon} ${action}${selector}${timing}${errorStr}`;
|
|
315
|
+
switch (level) {
|
|
316
|
+
case "debug":
|
|
317
|
+
console.debug(message);
|
|
318
|
+
break;
|
|
319
|
+
case "info":
|
|
320
|
+
console.info(message);
|
|
321
|
+
break;
|
|
322
|
+
case "warn":
|
|
323
|
+
console.warn(message);
|
|
324
|
+
break;
|
|
325
|
+
case "error":
|
|
326
|
+
console.error(message);
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Create a child tracer with modified options
|
|
332
|
+
*/
|
|
333
|
+
child(options) {
|
|
334
|
+
return new _Tracer({ ...this.options, ...options });
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Enable tracing
|
|
338
|
+
*/
|
|
339
|
+
enable() {
|
|
340
|
+
this.options.enabled = true;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Disable tracing
|
|
344
|
+
*/
|
|
345
|
+
disable() {
|
|
346
|
+
this.options.enabled = false;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Check if tracing is enabled
|
|
350
|
+
*/
|
|
351
|
+
get isEnabled() {
|
|
352
|
+
return this.options.enabled;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
var globalTracer = null;
|
|
356
|
+
function getTracer() {
|
|
357
|
+
if (!globalTracer) {
|
|
358
|
+
globalTracer = new Tracer({ enabled: false });
|
|
359
|
+
}
|
|
360
|
+
return globalTracer;
|
|
361
|
+
}
|
|
362
|
+
function enableTracing(options = {}) {
|
|
363
|
+
globalTracer = new Tracer({ ...options, enabled: true });
|
|
364
|
+
return globalTracer;
|
|
365
|
+
}
|
|
366
|
+
function disableTracing() {
|
|
367
|
+
if (globalTracer) {
|
|
368
|
+
globalTracer.disable();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
37
371
|
export {
|
|
372
|
+
AudioInput,
|
|
373
|
+
AudioOutput,
|
|
38
374
|
BatchExecutor,
|
|
39
375
|
Browser,
|
|
40
376
|
BrowserBaseProvider,
|
|
@@ -48,6 +384,8 @@ export {
|
|
|
48
384
|
TimeoutError,
|
|
49
385
|
Tracer,
|
|
50
386
|
addBatchToPage,
|
|
387
|
+
bufferToBase64,
|
|
388
|
+
calculateRMS,
|
|
51
389
|
connect,
|
|
52
390
|
createCDPClient,
|
|
53
391
|
createProvider,
|
|
@@ -55,8 +393,17 @@ export {
|
|
|
55
393
|
disableTracing,
|
|
56
394
|
discoverTargets,
|
|
57
395
|
enableTracing,
|
|
396
|
+
generateSilence,
|
|
397
|
+
generateTone,
|
|
398
|
+
getAudioChromeFlags,
|
|
58
399
|
getBrowserWebSocketUrl,
|
|
59
400
|
getTracer,
|
|
401
|
+
grantAudioPermissions,
|
|
402
|
+
isTranscriptionAvailable,
|
|
403
|
+
parseWavHeader,
|
|
404
|
+
pcmToWav,
|
|
405
|
+
transcribe,
|
|
406
|
+
validateSteps,
|
|
60
407
|
waitForAnyElement,
|
|
61
408
|
waitForElement,
|
|
62
409
|
waitForNavigation,
|
package/dist/providers.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as Provider,
|
|
2
|
-
export { c as ProxyConfig } from './types
|
|
1
|
+
import { P as Provider, C as CreateSessionOptions, a as ProviderSession, b as ConnectOptions } from './types--wXNHUwt.cjs';
|
|
2
|
+
export { c as ProxyConfig } from './types--wXNHUwt.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* BrowserBase provider implementation
|
package/dist/providers.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as Provider,
|
|
2
|
-
export { c as ProxyConfig } from './types
|
|
1
|
+
import { P as Provider, C as CreateSessionOptions, a as ProviderSession, b as ConnectOptions } from './types--wXNHUwt.js';
|
|
2
|
+
export { c as ProxyConfig } from './types--wXNHUwt.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* BrowserBase provider implementation
|
|
@@ -53,4 +53,4 @@ interface ConnectOptions {
|
|
|
53
53
|
timeout?: number;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export type {
|
|
56
|
+
export type { CreateSessionOptions as C, Provider as P, ProviderSession as a, ConnectOptions as b, ProxyConfig as c };
|
|
@@ -53,4 +53,4 @@ interface ConnectOptions {
|
|
|
53
53
|
timeout?: number;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export type {
|
|
56
|
+
export type { CreateSessionOptions as C, Provider as P, ProviderSession as a, ConnectOptions as b, ProxyConfig as c };
|