@btraut/browser-bridge 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/dist/index.js ADDED
@@ -0,0 +1,2087 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // packages/cli/src/index.ts
27
+ var import_commander = require("commander");
28
+
29
+ // packages/shared/src/errors.ts
30
+ var import_zod = require("zod");
31
+ var ErrorCodeSchema = import_zod.z.enum([
32
+ "UNKNOWN",
33
+ "INVALID_ARGUMENT",
34
+ "NOT_FOUND",
35
+ "ALREADY_EXISTS",
36
+ "FAILED_PRECONDITION",
37
+ "UNAUTHORIZED",
38
+ "FORBIDDEN",
39
+ "CONFLICT",
40
+ "TIMEOUT",
41
+ "CANCELLED",
42
+ "UNAVAILABLE",
43
+ "RATE_LIMITED",
44
+ "NOT_IMPLEMENTED",
45
+ "INTERNAL",
46
+ "SESSION_NOT_FOUND",
47
+ "SESSION_CLOSED",
48
+ "SESSION_BROKEN",
49
+ "DRIVE_UNAVAILABLE",
50
+ "INSPECT_UNAVAILABLE",
51
+ "EXTENSION_DISCONNECTED",
52
+ "DEBUGGER_IN_USE",
53
+ "ATTACH_DENIED",
54
+ "TAB_NOT_FOUND",
55
+ "NOT_SUPPORTED",
56
+ "LOCATOR_NOT_FOUND",
57
+ "NAVIGATION_FAILED",
58
+ "EVALUATION_FAILED",
59
+ "ARTIFACT_IO_ERROR"
60
+ ]);
61
+ var ErrorInfoSchema = import_zod.z.object({
62
+ code: ErrorCodeSchema,
63
+ message: import_zod.z.string(),
64
+ retryable: import_zod.z.boolean(),
65
+ details: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
66
+ });
67
+ var ErrorEnvelopeSchema = import_zod.z.object({
68
+ ok: import_zod.z.literal(false),
69
+ error: ErrorInfoSchema
70
+ });
71
+ var successEnvelopeSchema = (result) => import_zod.z.object({
72
+ ok: import_zod.z.literal(true),
73
+ result
74
+ });
75
+ var apiEnvelopeSchema = (result) => import_zod.z.union([successEnvelopeSchema(result), ErrorEnvelopeSchema]);
76
+
77
+ // packages/shared/src/schemas.ts
78
+ var import_zod2 = require("zod");
79
+ var LocatorRoleSchema = import_zod2.z.object({
80
+ name: import_zod2.z.string(),
81
+ value: import_zod2.z.string().optional()
82
+ });
83
+ var LocatorSchema = import_zod2.z.object({
84
+ ref: import_zod2.z.string().min(1).optional(),
85
+ testid: import_zod2.z.string().min(1).optional(),
86
+ css: import_zod2.z.string().min(1).optional(),
87
+ text: import_zod2.z.string().min(1).optional(),
88
+ role: LocatorRoleSchema.optional()
89
+ }).refine(
90
+ (value) => Boolean(
91
+ value.ref || value.testid || value.css || value.text || value.role
92
+ ),
93
+ {
94
+ message: "Locator must include at least one selector."
95
+ }
96
+ );
97
+ var OpResultSchema = import_zod2.z.object({
98
+ ok: import_zod2.z.literal(true),
99
+ message: import_zod2.z.string().optional(),
100
+ warnings: import_zod2.z.array(import_zod2.z.string()).optional()
101
+ });
102
+ var SessionStateSchema = import_zod2.z.enum([
103
+ "INIT",
104
+ "DRIVE_READY",
105
+ "INSPECT_READY",
106
+ "READY",
107
+ "DEGRADED_DRIVE",
108
+ "DEGRADED_INSPECT",
109
+ "BROKEN",
110
+ "CLOSED"
111
+ ]);
112
+ var SessionInfoSchema = import_zod2.z.object({
113
+ session_id: import_zod2.z.string(),
114
+ state: SessionStateSchema,
115
+ created_at: import_zod2.z.string().datetime().optional()
116
+ });
117
+ var SessionPlaneStatusSchema = import_zod2.z.object({
118
+ connected: import_zod2.z.boolean(),
119
+ last_seen_at: import_zod2.z.string().datetime().optional(),
120
+ error: ErrorInfoSchema.optional()
121
+ });
122
+ var SessionStatusSchema = import_zod2.z.object({
123
+ session_id: import_zod2.z.string(),
124
+ state: SessionStateSchema,
125
+ drive: SessionPlaneStatusSchema.optional(),
126
+ inspect: SessionPlaneStatusSchema.optional(),
127
+ updated_at: import_zod2.z.string().datetime().optional()
128
+ });
129
+ var RecoverResultSchema = import_zod2.z.object({
130
+ session_id: import_zod2.z.string(),
131
+ recovered: import_zod2.z.boolean(),
132
+ state: SessionStateSchema,
133
+ message: import_zod2.z.string().optional()
134
+ });
135
+ var DiagnosticCheckSchema = import_zod2.z.object({
136
+ name: import_zod2.z.string(),
137
+ ok: import_zod2.z.boolean(),
138
+ message: import_zod2.z.string().optional(),
139
+ details: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional()
140
+ });
141
+ var DiagnosticReportSchema = import_zod2.z.object({
142
+ ok: import_zod2.z.boolean(),
143
+ session_id: import_zod2.z.string().optional(),
144
+ checks: import_zod2.z.array(DiagnosticCheckSchema).optional(),
145
+ extension: import_zod2.z.object({
146
+ connected: import_zod2.z.boolean().optional(),
147
+ version: import_zod2.z.string().optional(),
148
+ last_seen_at: import_zod2.z.string().datetime().optional()
149
+ }).optional(),
150
+ debugger: import_zod2.z.object({
151
+ attached: import_zod2.z.boolean().optional(),
152
+ idle_timeout_ms: import_zod2.z.number().finite().optional(),
153
+ console_buffer_size: import_zod2.z.number().finite().optional(),
154
+ network_buffer_size: import_zod2.z.number().finite().optional(),
155
+ last_error: ErrorInfoSchema.optional()
156
+ }).optional(),
157
+ artifacts: import_zod2.z.object({
158
+ root_dir: import_zod2.z.string().optional()
159
+ }).optional(),
160
+ recovery: import_zod2.z.object({
161
+ last_attempt: import_zod2.z.object({
162
+ session_id: import_zod2.z.string(),
163
+ recovered: import_zod2.z.boolean(),
164
+ state: SessionStateSchema,
165
+ message: import_zod2.z.string().optional(),
166
+ at: import_zod2.z.string()
167
+ }).optional(),
168
+ attempts: import_zod2.z.array(
169
+ import_zod2.z.object({
170
+ session_id: import_zod2.z.string(),
171
+ recovered: import_zod2.z.boolean(),
172
+ state: SessionStateSchema,
173
+ message: import_zod2.z.string().optional(),
174
+ at: import_zod2.z.string()
175
+ })
176
+ ).optional(),
177
+ success_count: import_zod2.z.number().finite().optional(),
178
+ failure_count: import_zod2.z.number().finite().optional(),
179
+ success_rate: import_zod2.z.number().finite().optional(),
180
+ recent_failure_count: import_zod2.z.number().finite().optional(),
181
+ loop_detected: import_zod2.z.boolean().optional()
182
+ }).optional(),
183
+ warnings: import_zod2.z.array(import_zod2.z.string()).optional(),
184
+ notes: import_zod2.z.array(import_zod2.z.string()).optional()
185
+ });
186
+ var SessionIdSchema = import_zod2.z.object({
187
+ session_id: import_zod2.z.string().min(1)
188
+ });
189
+ var SessionCreateInputSchema = import_zod2.z.object({}).strict().default({});
190
+ var SessionCreateOutputSchema = SessionInfoSchema;
191
+ var SessionStatusInputSchema = SessionIdSchema;
192
+ var SessionStatusOutputSchema = SessionStatusSchema;
193
+ var SessionRecoverInputSchema = SessionIdSchema;
194
+ var SessionRecoverOutputSchema = RecoverResultSchema;
195
+ var SessionCloseInputSchema = SessionIdSchema;
196
+ var SessionCloseOutputSchema = import_zod2.z.object({
197
+ ok: import_zod2.z.boolean()
198
+ });
199
+ var DriveWaitConditionSchema = import_zod2.z.object({
200
+ kind: import_zod2.z.enum(["locator_visible", "text_present", "url_matches"]),
201
+ value: import_zod2.z.string().min(1)
202
+ });
203
+ var DriveNavigateInputSchema = import_zod2.z.object({
204
+ session_id: import_zod2.z.string().min(1),
205
+ url: import_zod2.z.string().min(1),
206
+ tab_id: import_zod2.z.number().finite().optional(),
207
+ wait: import_zod2.z.enum(["none", "domcontentloaded"]).default("domcontentloaded")
208
+ });
209
+ var DriveNavigateOutputSchema = OpResultSchema;
210
+ var DriveGoBackInputSchema = import_zod2.z.object({
211
+ session_id: import_zod2.z.string().min(1),
212
+ tab_id: import_zod2.z.number().finite().optional()
213
+ });
214
+ var DriveGoBackOutputSchema = OpResultSchema;
215
+ var DriveGoForwardInputSchema = import_zod2.z.object({
216
+ session_id: import_zod2.z.string().min(1),
217
+ tab_id: import_zod2.z.number().finite().optional()
218
+ });
219
+ var DriveGoForwardOutputSchema = OpResultSchema;
220
+ var DriveBackInputSchema = DriveGoBackInputSchema;
221
+ var DriveBackOutputSchema = OpResultSchema;
222
+ var DriveForwardInputSchema = DriveGoForwardInputSchema;
223
+ var DriveForwardOutputSchema = OpResultSchema;
224
+ var DriveClickInputSchema = import_zod2.z.object({
225
+ session_id: import_zod2.z.string().min(1),
226
+ locator: LocatorSchema,
227
+ tab_id: import_zod2.z.number().finite().optional(),
228
+ click_count: import_zod2.z.number().finite().optional()
229
+ });
230
+ var DriveClickOutputSchema = OpResultSchema;
231
+ var DriveHoverInputSchema = import_zod2.z.object({
232
+ session_id: import_zod2.z.string().min(1),
233
+ locator: LocatorSchema,
234
+ delay_ms: import_zod2.z.number().min(0).max(1e4).optional(),
235
+ tab_id: import_zod2.z.number().finite().optional()
236
+ });
237
+ var DriveHoverOutputSchema = import_zod2.z.object({
238
+ format: import_zod2.z.literal("html"),
239
+ snapshot: import_zod2.z.string()
240
+ });
241
+ var DriveSelectInputSchema = import_zod2.z.object({
242
+ session_id: import_zod2.z.string().min(1),
243
+ locator: LocatorSchema,
244
+ value: import_zod2.z.string().min(1).optional(),
245
+ text: import_zod2.z.string().min(1).optional(),
246
+ index: import_zod2.z.number().int().min(0).optional(),
247
+ tab_id: import_zod2.z.number().finite().optional()
248
+ }).refine((value) => value.value || value.text || value.index !== void 0, {
249
+ message: "Either value, text, or index must be provided.",
250
+ path: ["select"]
251
+ });
252
+ var DriveSelectOutputSchema = OpResultSchema;
253
+ var DriveTypeInputSchema = import_zod2.z.object({
254
+ session_id: import_zod2.z.string().min(1),
255
+ locator: LocatorSchema.optional(),
256
+ text: import_zod2.z.string().min(1),
257
+ tab_id: import_zod2.z.number().finite().optional(),
258
+ clear: import_zod2.z.boolean().default(false),
259
+ submit: import_zod2.z.boolean().default(false)
260
+ });
261
+ var DriveTypeOutputSchema = OpResultSchema;
262
+ var DriveFillFormFieldSchema = import_zod2.z.object({
263
+ selector: import_zod2.z.string().min(1).optional(),
264
+ locator: LocatorSchema.optional(),
265
+ value: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.boolean()]),
266
+ type: import_zod2.z.enum(["auto", "text", "select", "checkbox", "radio", "contentEditable"]).default("auto"),
267
+ submit: import_zod2.z.boolean().default(false)
268
+ }).refine((value) => Boolean(value.selector || value.locator), {
269
+ message: "fill_form field requires selector or locator.",
270
+ path: ["selector"]
271
+ });
272
+ var DriveFillFormInputSchema = import_zod2.z.object({
273
+ session_id: import_zod2.z.string().min(1),
274
+ fields: import_zod2.z.array(DriveFillFormFieldSchema).min(1),
275
+ tab_id: import_zod2.z.number().finite().optional()
276
+ });
277
+ var DriveFillFormOutputSchema = import_zod2.z.object({
278
+ filled: import_zod2.z.number().finite(),
279
+ attempted: import_zod2.z.number().finite(),
280
+ errors: import_zod2.z.array(import_zod2.z.string()).optional()
281
+ });
282
+ var DriveDragInputSchema = import_zod2.z.object({
283
+ session_id: import_zod2.z.string().min(1),
284
+ from: LocatorSchema,
285
+ to: LocatorSchema,
286
+ steps: import_zod2.z.number().min(1).max(50).default(12),
287
+ tab_id: import_zod2.z.number().finite().optional()
288
+ });
289
+ var DriveDragOutputSchema = OpResultSchema;
290
+ var DriveHandleDialogInputSchema = import_zod2.z.object({
291
+ session_id: import_zod2.z.string().min(1),
292
+ action: import_zod2.z.enum(["accept", "dismiss"]),
293
+ promptText: import_zod2.z.string().optional(),
294
+ tab_id: import_zod2.z.number().finite().optional()
295
+ });
296
+ var DriveHandleDialogOutputSchema = OpResultSchema;
297
+ var DialogAcceptInputSchema = SessionIdSchema.extend({
298
+ promptText: import_zod2.z.string().optional(),
299
+ tab_id: import_zod2.z.number().finite().optional()
300
+ });
301
+ var DialogAcceptOutputSchema = OpResultSchema;
302
+ var DialogDismissInputSchema = SessionIdSchema.extend({
303
+ tab_id: import_zod2.z.number().finite().optional()
304
+ });
305
+ var DialogDismissOutputSchema = OpResultSchema;
306
+ var DriveKeyModifiersSchema = import_zod2.z.object({
307
+ ctrl: import_zod2.z.boolean().optional(),
308
+ alt: import_zod2.z.boolean().optional(),
309
+ shift: import_zod2.z.boolean().optional(),
310
+ meta: import_zod2.z.boolean().optional()
311
+ });
312
+ var DriveKeyPressInputSchema = import_zod2.z.object({
313
+ session_id: import_zod2.z.string().min(1),
314
+ key: import_zod2.z.string().min(1),
315
+ modifiers: DriveKeyModifiersSchema.optional(),
316
+ tab_id: import_zod2.z.number().finite().optional()
317
+ });
318
+ var DriveKeyPressOutputSchema = OpResultSchema;
319
+ var DriveKeyModifierSchema = import_zod2.z.enum(["ctrl", "alt", "shift", "meta"]);
320
+ var DriveKeyInputSchema = import_zod2.z.object({
321
+ session_id: import_zod2.z.string().min(1),
322
+ key: import_zod2.z.string().min(1),
323
+ modifiers: import_zod2.z.array(DriveKeyModifierSchema).optional(),
324
+ repeat: import_zod2.z.number().int().min(1).max(50).optional(),
325
+ tab_id: import_zod2.z.number().finite().optional()
326
+ });
327
+ var DriveKeyOutputSchema = OpResultSchema;
328
+ var DriveScrollInputSchema = import_zod2.z.object({
329
+ session_id: import_zod2.z.string().min(1),
330
+ delta_x: import_zod2.z.number().finite().optional(),
331
+ delta_y: import_zod2.z.number().finite().optional(),
332
+ top: import_zod2.z.number().finite().optional(),
333
+ left: import_zod2.z.number().finite().optional(),
334
+ behavior: import_zod2.z.enum(["auto", "smooth"]).optional(),
335
+ tab_id: import_zod2.z.number().finite().optional()
336
+ }).refine(
337
+ (value) => value.delta_x !== void 0 || value.delta_y !== void 0 || value.top !== void 0 || value.left !== void 0,
338
+ {
339
+ message: "scroll requires delta_x/delta_y or top/left.",
340
+ path: ["scroll"]
341
+ }
342
+ );
343
+ var DriveScrollOutputSchema = OpResultSchema;
344
+ var DriveWaitForInputSchema = import_zod2.z.object({
345
+ session_id: import_zod2.z.string().min(1),
346
+ condition: DriveWaitConditionSchema,
347
+ timeout_ms: import_zod2.z.number().finite().optional(),
348
+ tab_id: import_zod2.z.number().finite().optional()
349
+ });
350
+ var DriveWaitForOutputSchema = OpResultSchema;
351
+ var DriveTabInfoSchema = import_zod2.z.object({
352
+ tab_id: import_zod2.z.number().finite(),
353
+ window_id: import_zod2.z.number().finite(),
354
+ url: import_zod2.z.string().min(1),
355
+ title: import_zod2.z.string(),
356
+ active: import_zod2.z.boolean().optional(),
357
+ last_active_at: import_zod2.z.string().datetime().optional()
358
+ });
359
+ var DriveTabListInputSchema = SessionIdSchema;
360
+ var DriveTabListOutputSchema = import_zod2.z.object({
361
+ tabs: import_zod2.z.array(DriveTabInfoSchema)
362
+ });
363
+ var DriveTabActivateInputSchema = import_zod2.z.object({
364
+ session_id: import_zod2.z.string().min(1),
365
+ tab_id: import_zod2.z.number().finite()
366
+ });
367
+ var DriveTabActivateOutputSchema = OpResultSchema;
368
+ var DriveTabCloseInputSchema = import_zod2.z.object({
369
+ session_id: import_zod2.z.string().min(1),
370
+ tab_id: import_zod2.z.number().finite()
371
+ });
372
+ var DriveTabCloseOutputSchema = OpResultSchema;
373
+ var InspectDomFormatSchema = import_zod2.z.enum(["ax", "html"]);
374
+ var InspectConsistencySchema = import_zod2.z.enum(["best_effort", "quiesce"]);
375
+ var TargetHintSchema = import_zod2.z.object({
376
+ url: import_zod2.z.string().min(1).optional(),
377
+ title: import_zod2.z.string().min(1).optional(),
378
+ last_active_at: import_zod2.z.string().optional(),
379
+ lastActiveAt: import_zod2.z.string().optional()
380
+ });
381
+ var FormFieldInfoSchema = import_zod2.z.object({
382
+ name: import_zod2.z.string(),
383
+ type: import_zod2.z.string(),
384
+ value: import_zod2.z.string(),
385
+ options: import_zod2.z.array(import_zod2.z.string()).optional()
386
+ });
387
+ var FormInfoSchema = import_zod2.z.object({
388
+ selector: import_zod2.z.string(),
389
+ action: import_zod2.z.string().optional(),
390
+ method: import_zod2.z.string().optional(),
391
+ fields: import_zod2.z.array(FormFieldInfoSchema)
392
+ });
393
+ var StorageEntrySchema = import_zod2.z.object({
394
+ key: import_zod2.z.string(),
395
+ value: import_zod2.z.string()
396
+ });
397
+ var PageStateSchema = import_zod2.z.object({
398
+ forms: import_zod2.z.array(FormInfoSchema),
399
+ localStorage: import_zod2.z.array(StorageEntrySchema),
400
+ sessionStorage: import_zod2.z.array(StorageEntrySchema),
401
+ cookies: import_zod2.z.array(StorageEntrySchema),
402
+ warnings: import_zod2.z.array(import_zod2.z.string()).optional()
403
+ });
404
+ var DomSnapshotSchema = import_zod2.z.object({
405
+ format: InspectDomFormatSchema,
406
+ snapshot: import_zod2.z.unknown()
407
+ }).passthrough();
408
+ var InspectDomSnapshotInputSchema = import_zod2.z.object({
409
+ session_id: import_zod2.z.string().min(1),
410
+ format: InspectDomFormatSchema.default("ax"),
411
+ consistency: InspectConsistencySchema.default("best_effort"),
412
+ interactive: import_zod2.z.boolean().default(false),
413
+ compact: import_zod2.z.boolean().default(false),
414
+ selector: import_zod2.z.string().min(1).optional(),
415
+ target: TargetHintSchema.optional()
416
+ });
417
+ var InspectDomSnapshotOutputSchema = DomSnapshotSchema;
418
+ var DomDiffResultSchema = import_zod2.z.object({
419
+ added: import_zod2.z.array(import_zod2.z.string()),
420
+ removed: import_zod2.z.array(import_zod2.z.string()),
421
+ changed: import_zod2.z.array(import_zod2.z.string()),
422
+ summary: import_zod2.z.string()
423
+ });
424
+ var InspectDomDiffInputSchema = SessionIdSchema;
425
+ var InspectDomDiffOutputSchema = DomDiffResultSchema;
426
+ var InspectFindRoleInputSchema = SessionIdSchema.extend({
427
+ kind: import_zod2.z.literal("role"),
428
+ role: import_zod2.z.string().min(1),
429
+ name: import_zod2.z.string().min(1).optional(),
430
+ target: TargetHintSchema.optional()
431
+ });
432
+ var InspectFindTextInputSchema = SessionIdSchema.extend({
433
+ kind: import_zod2.z.literal("text"),
434
+ text: import_zod2.z.string().min(1),
435
+ target: TargetHintSchema.optional()
436
+ });
437
+ var InspectFindLabelInputSchema = SessionIdSchema.extend({
438
+ kind: import_zod2.z.literal("label"),
439
+ label: import_zod2.z.string().min(1),
440
+ target: TargetHintSchema.optional()
441
+ });
442
+ var InspectFindInputSchema = import_zod2.z.discriminatedUnion("kind", [
443
+ InspectFindRoleInputSchema,
444
+ InspectFindTextInputSchema,
445
+ InspectFindLabelInputSchema
446
+ ]);
447
+ var InspectFindMatchSchema = import_zod2.z.object({
448
+ ref: import_zod2.z.string(),
449
+ role: import_zod2.z.string().optional(),
450
+ name: import_zod2.z.string().optional()
451
+ });
452
+ var InspectFindOutputSchema = import_zod2.z.object({
453
+ matches: import_zod2.z.array(InspectFindMatchSchema),
454
+ warnings: import_zod2.z.array(import_zod2.z.string()).optional()
455
+ });
456
+ var InspectPageStateInputSchema = SessionIdSchema.extend({
457
+ target: TargetHintSchema.optional()
458
+ });
459
+ var InspectPageStateOutputSchema = PageStateSchema;
460
+ var InspectExtractContentFormatSchema = import_zod2.z.enum([
461
+ "markdown",
462
+ "text",
463
+ "article_json"
464
+ ]);
465
+ var InspectExtractContentInputSchema = SessionIdSchema.extend({
466
+ format: InspectExtractContentFormatSchema.default("markdown"),
467
+ include_metadata: import_zod2.z.boolean().default(true),
468
+ target: TargetHintSchema.optional()
469
+ });
470
+ var InspectExtractContentOutputSchema = import_zod2.z.object({
471
+ content: import_zod2.z.string(),
472
+ title: import_zod2.z.string().optional(),
473
+ byline: import_zod2.z.string().optional(),
474
+ excerpt: import_zod2.z.string().optional(),
475
+ siteName: import_zod2.z.string().optional(),
476
+ warnings: import_zod2.z.array(import_zod2.z.string()).optional()
477
+ });
478
+ var InspectConsoleListInputSchema = SessionIdSchema.extend({
479
+ target: TargetHintSchema.optional()
480
+ });
481
+ var ConsoleSourceLocationSchema = import_zod2.z.object({
482
+ url: import_zod2.z.string().optional(),
483
+ // 1-based line/column for human readability.
484
+ line: import_zod2.z.number().int().positive().optional(),
485
+ column: import_zod2.z.number().int().positive().optional()
486
+ }).passthrough();
487
+ var ConsoleStackFrameSchema = import_zod2.z.object({
488
+ functionName: import_zod2.z.string().optional(),
489
+ url: import_zod2.z.string().optional(),
490
+ // 1-based line/column for human readability.
491
+ line: import_zod2.z.number().int().positive().optional(),
492
+ column: import_zod2.z.number().int().positive().optional()
493
+ }).passthrough();
494
+ var ConsoleRemoteObjectSchema = import_zod2.z.object({
495
+ type: import_zod2.z.string().optional(),
496
+ subtype: import_zod2.z.string().optional(),
497
+ description: import_zod2.z.string().optional(),
498
+ value: import_zod2.z.unknown().optional(),
499
+ unserializableValue: import_zod2.z.string().optional()
500
+ }).passthrough();
501
+ var ConsoleEntrySchema = import_zod2.z.object({
502
+ level: import_zod2.z.string().optional(),
503
+ text: import_zod2.z.string().optional(),
504
+ timestamp: import_zod2.z.string().datetime().optional(),
505
+ source: ConsoleSourceLocationSchema.optional(),
506
+ stack: import_zod2.z.array(ConsoleStackFrameSchema).optional(),
507
+ exception: ConsoleRemoteObjectSchema.optional(),
508
+ args: import_zod2.z.array(ConsoleRemoteObjectSchema).optional()
509
+ }).passthrough();
510
+ var ConsoleListSchema = import_zod2.z.object({
511
+ entries: import_zod2.z.array(ConsoleEntrySchema)
512
+ }).passthrough();
513
+ var InspectConsoleListOutputSchema = ConsoleListSchema;
514
+ var ArtifactInfoSchema = import_zod2.z.object({
515
+ artifact_id: import_zod2.z.string(),
516
+ path: import_zod2.z.string(),
517
+ mime: import_zod2.z.string()
518
+ });
519
+ var InspectNetworkHarInputSchema = SessionIdSchema.extend({
520
+ target: TargetHintSchema.optional()
521
+ });
522
+ var InspectNetworkHarOutputSchema = ArtifactInfoSchema;
523
+ var InspectEvaluateInputSchema = import_zod2.z.object({
524
+ session_id: import_zod2.z.string().min(1),
525
+ expression: import_zod2.z.string().min(1).optional(),
526
+ target: TargetHintSchema.optional()
527
+ });
528
+ var EvaluateResultSchema = import_zod2.z.object({
529
+ value: import_zod2.z.unknown().optional(),
530
+ exception: import_zod2.z.unknown().optional()
531
+ }).passthrough();
532
+ var InspectEvaluateOutputSchema = EvaluateResultSchema;
533
+ var InspectPerformanceMetricsInputSchema = SessionIdSchema.extend({
534
+ target: TargetHintSchema.optional()
535
+ });
536
+ var PerformanceMetricSchema = import_zod2.z.object({
537
+ name: import_zod2.z.string(),
538
+ value: import_zod2.z.number().finite()
539
+ }).passthrough();
540
+ var PerformanceMetricsSchema = import_zod2.z.object({
541
+ metrics: import_zod2.z.array(PerformanceMetricSchema)
542
+ }).passthrough();
543
+ var InspectPerformanceMetricsOutputSchema = PerformanceMetricsSchema;
544
+ var ArtifactsScreenshotInputSchema = import_zod2.z.object({
545
+ session_id: import_zod2.z.string().min(1),
546
+ target: import_zod2.z.enum(["viewport", "full"]).default("viewport"),
547
+ fullPage: import_zod2.z.boolean().default(false),
548
+ format: import_zod2.z.enum(["png", "jpeg", "webp"]).default("png"),
549
+ quality: import_zod2.z.number().min(0).max(100).optional()
550
+ });
551
+ var ArtifactsScreenshotOutputSchema = ArtifactInfoSchema;
552
+ var DiagnosticsDoctorInputSchema = import_zod2.z.object({
553
+ session_id: import_zod2.z.string().min(1).optional()
554
+ });
555
+ var DiagnosticsDoctorOutputSchema = DiagnosticReportSchema;
556
+
557
+ // packages/cli/src/cli-output.ts
558
+ var import_zod3 = require("zod");
559
+ var CliError = class extends Error {
560
+ constructor(info) {
561
+ super(info.message);
562
+ this.info = info;
563
+ }
564
+ };
565
+ var parseInput = (schema, payload) => {
566
+ const result = schema.safeParse(payload);
567
+ if (result.success) {
568
+ return result.data;
569
+ }
570
+ const [issue] = result.error.issues;
571
+ throw new CliError({
572
+ code: "INVALID_ARGUMENT",
573
+ message: issue?.message ?? "Invalid input.",
574
+ retryable: false,
575
+ details: { issues: result.error.issues }
576
+ });
577
+ };
578
+ var outputEnvelope = (envelope2, options) => {
579
+ if (options.json) {
580
+ console.log(JSON.stringify(envelope2, null, 2));
581
+ return;
582
+ }
583
+ if (envelope2.ok) {
584
+ if (typeof envelope2.result === "string") {
585
+ console.log(envelope2.result);
586
+ return;
587
+ }
588
+ console.log(JSON.stringify(envelope2.result, null, 2));
589
+ return;
590
+ }
591
+ console.error(`${envelope2.error.code}: ${envelope2.error.message}`);
592
+ if (envelope2.error.details) {
593
+ console.error(JSON.stringify(envelope2.error.details, null, 2));
594
+ }
595
+ };
596
+ var toErrorInfo = (error) => {
597
+ if (error instanceof CliError) {
598
+ return error.info;
599
+ }
600
+ if (error instanceof import_zod3.ZodError) {
601
+ const [issue] = error.issues;
602
+ return {
603
+ code: "INVALID_ARGUMENT",
604
+ message: issue?.message ?? "Invalid input.",
605
+ retryable: false,
606
+ details: { issues: error.issues }
607
+ };
608
+ }
609
+ if (error instanceof Error) {
610
+ return {
611
+ code: "INTERNAL",
612
+ message: error.message,
613
+ retryable: false
614
+ };
615
+ }
616
+ return {
617
+ code: "INTERNAL",
618
+ message: "Unknown error.",
619
+ retryable: false
620
+ };
621
+ };
622
+ var outputError = (error, options) => {
623
+ const info = toErrorInfo(error);
624
+ const envelope2 = { ok: false, error: info };
625
+ if (options.json) {
626
+ console.log(JSON.stringify(envelope2, null, 2));
627
+ return;
628
+ }
629
+ console.error(`${info.code}: ${info.message}`);
630
+ if (info.details) {
631
+ console.error(JSON.stringify(info.details, null, 2));
632
+ }
633
+ };
634
+
635
+ // packages/cli/src/core-client.ts
636
+ var import_node_child_process = require("node:child_process");
637
+ var import_node_path = require("node:path");
638
+ var import_promises = require("node:timers/promises");
639
+ var DEFAULT_HOST = "127.0.0.1";
640
+ var DEFAULT_PORT = 3210;
641
+ var DEFAULT_TIMEOUT_MS = 4e3;
642
+ var HEALTH_RETRY_MS = 250;
643
+ var HEALTH_ATTEMPTS = 20;
644
+ var resolveHost = (host) => {
645
+ const candidate = host?.trim() || process.env.BROWSER_BRIDGE_CORE_HOST || process.env.BROWSER_VISION_CORE_HOST;
646
+ if (candidate && candidate.length > 0) {
647
+ return candidate;
648
+ }
649
+ return DEFAULT_HOST;
650
+ };
651
+ var resolvePort = (port) => {
652
+ const candidate = port ?? (process.env.BROWSER_BRIDGE_CORE_PORT ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_PORT, 10) : process.env.BROWSER_VISION_CORE_PORT ? Number.parseInt(process.env.BROWSER_VISION_CORE_PORT, 10) : void 0);
653
+ if (candidate === void 0 || candidate === null) {
654
+ return DEFAULT_PORT;
655
+ }
656
+ const parsed = typeof candidate === "number" ? candidate : Number.parseInt(candidate, 10);
657
+ if (!Number.isFinite(parsed) || parsed <= 0) {
658
+ throw new Error(`Invalid port: ${String(candidate)}`);
659
+ }
660
+ return parsed;
661
+ };
662
+ var resolveTimeoutMs = (timeoutMs) => {
663
+ const candidate = timeoutMs ?? (process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS, 10) : process.env.BROWSER_VISION_CORE_TIMEOUT_MS ? Number.parseInt(process.env.BROWSER_VISION_CORE_TIMEOUT_MS, 10) : void 0);
664
+ if (candidate === void 0 || candidate === null) {
665
+ return DEFAULT_TIMEOUT_MS;
666
+ }
667
+ const parsed = typeof candidate === "number" ? candidate : Number(candidate);
668
+ if (!Number.isFinite(parsed) || parsed <= 0) {
669
+ throw new Error(`Invalid timeoutMs: ${String(candidate)}`);
670
+ }
671
+ return Math.floor(parsed);
672
+ };
673
+ var normalizePath = (path2) => path2.startsWith("/") ? path2 : `/${path2}`;
674
+ var createCoreClient = (options = {}) => {
675
+ const host = resolveHost(options.host);
676
+ const port = resolvePort(options.port);
677
+ const baseUrl = `http://${host}:${port}`;
678
+ const timeoutMs = resolveTimeoutMs(options.timeoutMs);
679
+ const fetchImpl = options.fetchImpl ?? fetch;
680
+ const spawnImpl = options.spawnImpl ?? import_node_child_process.spawn;
681
+ const ensureDaemon = options.ensureDaemon ?? true;
682
+ const requestJson = async (method, path2, body) => {
683
+ const controller = new AbortController();
684
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
685
+ try {
686
+ const response = await fetchImpl(`${baseUrl}${normalizePath(path2)}`, {
687
+ method,
688
+ headers: {
689
+ "content-type": "application/json"
690
+ },
691
+ body: body === void 0 ? void 0 : JSON.stringify(body),
692
+ signal: controller.signal
693
+ });
694
+ const raw = await response.text();
695
+ if (!raw) {
696
+ throw new Error(`Empty response from Core (${response.status}).`);
697
+ }
698
+ try {
699
+ return JSON.parse(raw);
700
+ } catch (error) {
701
+ const message = error instanceof Error ? error.message : "Unknown JSON parse error";
702
+ throw new Error(`Failed to parse Core response: ${message}`);
703
+ }
704
+ } finally {
705
+ clearTimeout(timeout);
706
+ }
707
+ };
708
+ const checkHealth = async () => {
709
+ try {
710
+ const controller = new AbortController();
711
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
712
+ try {
713
+ const response = await fetchImpl(`${baseUrl}/health`, {
714
+ method: "GET",
715
+ signal: controller.signal
716
+ });
717
+ if (!response.ok) {
718
+ return false;
719
+ }
720
+ const data = await response.json().catch(() => null);
721
+ return Boolean(data?.ok);
722
+ } finally {
723
+ clearTimeout(timeout);
724
+ }
725
+ } catch {
726
+ return false;
727
+ }
728
+ };
729
+ const spawnDaemon = () => {
730
+ const coreEntry = (0, import_node_path.resolve)(__dirname, "api.js");
731
+ const script = `const { startCoreServer } = require(${JSON.stringify(
732
+ coreEntry
733
+ )});
734
+ startCoreServer({ host: ${JSON.stringify(
735
+ host
736
+ )}, port: ${port} })
737
+ .catch((err) => { console.error(err); process.exit(1); });`;
738
+ const child = spawnImpl(process.execPath, ["-e", script], {
739
+ detached: true,
740
+ stdio: "ignore",
741
+ env: {
742
+ ...process.env,
743
+ BROWSER_BRIDGE_CORE_HOST: host,
744
+ BROWSER_BRIDGE_CORE_PORT: String(port),
745
+ BROWSER_VISION_CORE_HOST: host,
746
+ BROWSER_VISION_CORE_PORT: String(port)
747
+ }
748
+ });
749
+ child.unref();
750
+ };
751
+ const ensureCoreRunning = async () => {
752
+ if (await checkHealth()) {
753
+ return;
754
+ }
755
+ spawnDaemon();
756
+ for (let attempt = 0; attempt < HEALTH_ATTEMPTS; attempt += 1) {
757
+ await (0, import_promises.setTimeout)(HEALTH_RETRY_MS);
758
+ if (await checkHealth()) {
759
+ return;
760
+ }
761
+ }
762
+ throw new Error(`Core daemon failed to start on ${host}:${port}.`);
763
+ };
764
+ let ensurePromise = null;
765
+ const ensureReady = async () => {
766
+ if (!ensureDaemon) {
767
+ return;
768
+ }
769
+ if (!ensurePromise) {
770
+ ensurePromise = ensureCoreRunning();
771
+ }
772
+ await ensurePromise;
773
+ };
774
+ const post = async (path2, body) => {
775
+ await ensureReady();
776
+ return requestJson("POST", path2, body);
777
+ };
778
+ return { baseUrl, ensureReady, post };
779
+ };
780
+
781
+ // packages/cli/src/cli-runtime.ts
782
+ var getRootCommand = (command) => {
783
+ let current = command;
784
+ while (current.parent) {
785
+ current = current.parent;
786
+ }
787
+ return current;
788
+ };
789
+ var getGlobalOptions = (command) => {
790
+ const root = getRootCommand(command);
791
+ return root.opts();
792
+ };
793
+ var createClientFromCommand = (command) => {
794
+ const options = getGlobalOptions(command);
795
+ return createCoreClient({
796
+ host: options.host,
797
+ port: options.port,
798
+ ensureDaemon: options.daemon !== false
799
+ });
800
+ };
801
+ var runCommand = async (command, work) => {
802
+ const options = getGlobalOptions(command);
803
+ const client = createClientFromCommand(command);
804
+ try {
805
+ const envelope2 = await work(client, options);
806
+ outputEnvelope(envelope2, { json: Boolean(options.json) });
807
+ if (!envelope2.ok) {
808
+ process.exitCode = 1;
809
+ }
810
+ } catch (error) {
811
+ outputError(error, { json: Boolean(options.json) });
812
+ process.exitCode = 1;
813
+ }
814
+ };
815
+ var runLocal = async (command, work) => {
816
+ const options = getGlobalOptions(command);
817
+ try {
818
+ const envelope2 = await work(options);
819
+ outputEnvelope(envelope2, { json: Boolean(options.json) });
820
+ if (!envelope2.ok) {
821
+ process.exitCode = 1;
822
+ }
823
+ } catch (error) {
824
+ outputError(error, { json: Boolean(options.json) });
825
+ process.exitCode = 1;
826
+ }
827
+ };
828
+
829
+ // packages/cli/src/commands/artifacts.ts
830
+ var parseNumber = (value) => {
831
+ if (value === void 0 || value === null || value === "") {
832
+ return void 0;
833
+ }
834
+ const parsed = Number(value);
835
+ return Number.isFinite(parsed) ? parsed : Number.NaN;
836
+ };
837
+ var registerArtifactsCommands = (program2) => {
838
+ const artifacts = program2.command("artifacts").description("Artifact commands");
839
+ artifacts.command("screenshot").description("Request a screenshot artifact").requiredOption("--session-id <id>", "Session identifier").option("--target <target>", "Screenshot target (viewport, full)").option("--full-page", "Capture full page (alias for --target full)").option("--format <format>", "Screenshot format (png, jpeg, webp)").option("--quality <quality>", "Screenshot quality (0-100) for jpeg/webp").action(async (options, command) => {
840
+ await runCommand(command, (client) => {
841
+ const payload = parseInput(ArtifactsScreenshotInputSchema, {
842
+ session_id: options.sessionId,
843
+ target: options.target,
844
+ fullPage: Boolean(options.fullPage),
845
+ format: options.format,
846
+ quality: parseNumber(options.quality)
847
+ });
848
+ return client.post("/artifacts/screenshot", payload);
849
+ });
850
+ });
851
+ };
852
+
853
+ // packages/cli/src/commands/dialog.ts
854
+ var parseNumber2 = (value) => {
855
+ if (value === void 0 || value === null || value === "") {
856
+ return void 0;
857
+ }
858
+ const parsed = Number(value);
859
+ return Number.isFinite(parsed) ? parsed : Number.NaN;
860
+ };
861
+ var registerDialogCommands = (program2) => {
862
+ const dialog = program2.command("dialog").description("Dialog commands");
863
+ dialog.command("accept").description("Accept a JavaScript dialog").requiredOption("--session-id <id>", "Session identifier").option("--prompt-text <text>", "Prompt text for prompt() dialogs").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
864
+ await runCommand(command, (client) => {
865
+ const payload = parseInput(DialogAcceptInputSchema, {
866
+ session_id: options.sessionId,
867
+ promptText: options.promptText,
868
+ tab_id: parseNumber2(options.tabId)
869
+ });
870
+ return client.post("/dialog/accept", payload);
871
+ });
872
+ });
873
+ dialog.command("dismiss").description("Dismiss a JavaScript dialog").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
874
+ await runCommand(command, (client) => {
875
+ const payload = parseInput(DialogDismissInputSchema, {
876
+ session_id: options.sessionId,
877
+ tab_id: parseNumber2(options.tabId)
878
+ });
879
+ return client.post("/dialog/dismiss", payload);
880
+ });
881
+ });
882
+ };
883
+
884
+ // packages/cli/src/commands/diagnostics.ts
885
+ var registerDiagnosticsCommands = (program2) => {
886
+ const diagnostics = program2.command("diagnostics").description("Diagnostics commands");
887
+ diagnostics.command("doctor").description("Run diagnostics").option("--session-id <id>", "Session identifier").action(async (options, command) => {
888
+ await runCommand(command, (client) => {
889
+ const payload = parseInput(DiagnosticsDoctorInputSchema, {
890
+ session_id: options.sessionId
891
+ });
892
+ return client.post("/diagnostics/doctor", payload);
893
+ });
894
+ });
895
+ };
896
+
897
+ // packages/cli/src/locator.ts
898
+ var buildLocator = (options) => {
899
+ const locator = {};
900
+ if (options.locatorRef) {
901
+ locator.ref = options.locatorRef;
902
+ }
903
+ if (options.locatorTestid) {
904
+ locator.testid = options.locatorTestid;
905
+ }
906
+ if (options.locatorCss) {
907
+ locator.css = options.locatorCss;
908
+ }
909
+ if (options.locatorText) {
910
+ locator.text = options.locatorText;
911
+ }
912
+ if (options.locatorRoleValue && !options.locatorRole) {
913
+ throw new CliError({
914
+ code: "INVALID_ARGUMENT",
915
+ message: "locator-role-value requires locator-role to be set.",
916
+ retryable: false,
917
+ details: { field: "locator.role.value" }
918
+ });
919
+ }
920
+ if (options.locatorRole) {
921
+ locator.role = {
922
+ name: options.locatorRole,
923
+ ...options.locatorRoleValue ? { value: options.locatorRoleValue } : {}
924
+ };
925
+ }
926
+ if (!locator.ref && !locator.testid && !locator.css && !locator.text && !locator.role) {
927
+ return void 0;
928
+ }
929
+ return locator;
930
+ };
931
+ var requireLocator = (options) => {
932
+ const locator = buildLocator(options);
933
+ if (!locator) {
934
+ throw new CliError({
935
+ code: "INVALID_ARGUMENT",
936
+ message: "Locator must include at least one selector.",
937
+ retryable: false,
938
+ details: { field: "locator" }
939
+ });
940
+ }
941
+ return locator;
942
+ };
943
+
944
+ // packages/cli/src/commands/drive.ts
945
+ var parseNumber3 = (value) => {
946
+ if (value === void 0 || value === null || value === "") {
947
+ return void 0;
948
+ }
949
+ const parsed = Number(value);
950
+ return Number.isFinite(parsed) ? parsed : Number.NaN;
951
+ };
952
+ var parseJson = (value, label) => {
953
+ try {
954
+ return JSON.parse(value);
955
+ } catch {
956
+ throw new Error(`${label} must be valid JSON.`);
957
+ }
958
+ };
959
+ var registerDriveCommands = (program2) => {
960
+ const drive = program2.command("drive").description("Drive commands");
961
+ drive.command("navigate").description("Navigate to a URL").requiredOption("--session-id <id>", "Session identifier").requiredOption("--url <url>", "URL to navigate to").option("--tab-id <id>", "Tab identifier (defaults to active tab)").option("--wait <mode>", "Wait mode (none, domcontentloaded)").action(async (options, command) => {
962
+ await runCommand(command, (client) => {
963
+ const payload = parseInput(DriveNavigateInputSchema, {
964
+ session_id: options.sessionId,
965
+ url: options.url,
966
+ tab_id: parseNumber3(options.tabId),
967
+ wait: options.wait
968
+ });
969
+ return client.post("/drive/navigate", payload);
970
+ });
971
+ });
972
+ drive.command("go-back").description("Go back in browser history").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
973
+ await runCommand(command, (client) => {
974
+ const payload = parseInput(DriveGoBackInputSchema, {
975
+ session_id: options.sessionId,
976
+ tab_id: parseNumber3(options.tabId)
977
+ });
978
+ return client.post("/drive/go_back", payload);
979
+ });
980
+ });
981
+ drive.command("back").description("Go back in browser history").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
982
+ await runCommand(command, (client) => {
983
+ const payload = parseInput(DriveBackInputSchema, {
984
+ session_id: options.sessionId,
985
+ tab_id: parseNumber3(options.tabId)
986
+ });
987
+ return client.post("/drive/back", payload);
988
+ });
989
+ });
990
+ drive.command("go-forward").description("Go forward in browser history").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
991
+ await runCommand(command, (client) => {
992
+ const payload = parseInput(DriveGoForwardInputSchema, {
993
+ session_id: options.sessionId,
994
+ tab_id: parseNumber3(options.tabId)
995
+ });
996
+ return client.post("/drive/go_forward", payload);
997
+ });
998
+ });
999
+ drive.command("forward").description("Go forward in browser history").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1000
+ await runCommand(command, (client) => {
1001
+ const payload = parseInput(DriveForwardInputSchema, {
1002
+ session_id: options.sessionId,
1003
+ tab_id: parseNumber3(options.tabId)
1004
+ });
1005
+ return client.post("/drive/forward", payload);
1006
+ });
1007
+ });
1008
+ drive.command("click").description("Click an element").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").option("--locator-ref <ref>", "Locator ref (e.g., @e1)").option("--locator-testid <id>", "Locator test id").option("--locator-css <selector>", "Locator CSS selector").option("--locator-text <text>", "Locator text").option("--locator-role <role>", "Locator role name").option("--locator-role-value <value>", "Locator role value").option("--click-count <count>", "Click count").action(async (options, command) => {
1009
+ await runCommand(command, (client) => {
1010
+ const locator = requireLocator({
1011
+ locatorRef: options.locatorRef,
1012
+ locatorTestid: options.locatorTestid,
1013
+ locatorCss: options.locatorCss,
1014
+ locatorText: options.locatorText,
1015
+ locatorRole: options.locatorRole,
1016
+ locatorRoleValue: options.locatorRoleValue
1017
+ });
1018
+ const payload = parseInput(DriveClickInputSchema, {
1019
+ session_id: options.sessionId,
1020
+ locator,
1021
+ tab_id: parseNumber3(options.tabId),
1022
+ click_count: parseNumber3(options.clickCount)
1023
+ });
1024
+ return client.post("/drive/click", payload);
1025
+ });
1026
+ });
1027
+ drive.command("hover").description("Hover over an element").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").option("--locator-ref <ref>", "Locator ref (e.g., @e1)").option("--locator-testid <id>", "Locator test id").option("--locator-css <selector>", "Locator CSS selector").option("--locator-text <text>", "Locator text").option("--locator-role <role>", "Locator role name").option("--locator-role-value <value>", "Locator role value").option("--delay-ms <ms>", "Delay after hover in milliseconds").action(async (options, command) => {
1028
+ await runCommand(command, (client) => {
1029
+ const locator = requireLocator({
1030
+ locatorRef: options.locatorRef,
1031
+ locatorTestid: options.locatorTestid,
1032
+ locatorCss: options.locatorCss,
1033
+ locatorText: options.locatorText,
1034
+ locatorRole: options.locatorRole,
1035
+ locatorRoleValue: options.locatorRoleValue
1036
+ });
1037
+ const payload = parseInput(DriveHoverInputSchema, {
1038
+ session_id: options.sessionId,
1039
+ locator,
1040
+ delay_ms: parseNumber3(options.delayMs),
1041
+ tab_id: parseNumber3(options.tabId)
1042
+ });
1043
+ return client.post("/drive/hover", payload);
1044
+ });
1045
+ });
1046
+ drive.command("select").description("Select an option in a dropdown").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").option("--locator-ref <ref>", "Locator ref (e.g., @e1)").option("--locator-testid <id>", "Locator test id").option("--locator-css <selector>", "Locator CSS selector").option("--locator-text <text>", "Locator text").option("--locator-role <role>", "Locator role name").option("--locator-role-value <value>", "Locator role value").option("--value <value>", "Option value attribute").option("--text <text>", "Option visible text").option("--index <index>", "Option index (0-based)").action(async (options, command) => {
1047
+ await runCommand(command, (client) => {
1048
+ const locator = requireLocator({
1049
+ locatorRef: options.locatorRef,
1050
+ locatorTestid: options.locatorTestid,
1051
+ locatorCss: options.locatorCss,
1052
+ locatorText: options.locatorText,
1053
+ locatorRole: options.locatorRole,
1054
+ locatorRoleValue: options.locatorRoleValue
1055
+ });
1056
+ const payload = parseInput(DriveSelectInputSchema, {
1057
+ session_id: options.sessionId,
1058
+ locator,
1059
+ value: options.value,
1060
+ text: options.text,
1061
+ index: parseNumber3(options.index),
1062
+ tab_id: parseNumber3(options.tabId)
1063
+ });
1064
+ return client.post("/drive/select", payload);
1065
+ });
1066
+ });
1067
+ drive.command("type").description("Type into a field").requiredOption("--session-id <id>", "Session identifier").requiredOption("--text <text>", "Text to enter").option("--tab-id <id>", "Tab identifier").option("--locator-ref <ref>", "Locator ref (e.g., @e1)").option("--locator-testid <id>", "Locator test id").option("--locator-css <selector>", "Locator CSS selector").option("--locator-text <text>", "Locator text").option("--locator-role <role>", "Locator role name").option("--locator-role-value <value>", "Locator role value").option("--clear", "Clear input before typing").option("--submit", "Submit after typing").action(async (options, command) => {
1068
+ await runCommand(command, (client) => {
1069
+ const locator = buildLocator({
1070
+ locatorRef: options.locatorRef,
1071
+ locatorTestid: options.locatorTestid,
1072
+ locatorCss: options.locatorCss,
1073
+ locatorText: options.locatorText,
1074
+ locatorRole: options.locatorRole,
1075
+ locatorRoleValue: options.locatorRoleValue
1076
+ });
1077
+ const payload = parseInput(DriveTypeInputSchema, {
1078
+ session_id: options.sessionId,
1079
+ locator,
1080
+ text: options.text,
1081
+ tab_id: parseNumber3(options.tabId),
1082
+ clear: Boolean(options.clear),
1083
+ submit: Boolean(options.submit)
1084
+ });
1085
+ return client.post("/drive/type", payload);
1086
+ });
1087
+ });
1088
+ drive.command("fill-form").description("Fill multiple form fields").requiredOption("--session-id <id>", "Session identifier").requiredOption("--fields <json>", "JSON array of fields to fill").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1089
+ await runCommand(command, (client) => {
1090
+ const fields = parseJson(options.fields, "fields");
1091
+ const payload = parseInput(DriveFillFormInputSchema, {
1092
+ session_id: options.sessionId,
1093
+ fields,
1094
+ tab_id: parseNumber3(options.tabId)
1095
+ });
1096
+ return client.post("/drive/fill_form", payload);
1097
+ });
1098
+ });
1099
+ drive.command("drag").description("Drag an element to a target").requiredOption("--session-id <id>", "Session identifier").option("--from-locator-ref <ref>", "Source locator ref (e.g., @e1)").option("--from-locator-testid <id>", "Source locator test id").option("--from-locator-css <selector>", "Source locator CSS selector").option("--from-locator-text <text>", "Source locator text").option("--from-locator-role <role>", "Source locator role name").option("--from-locator-role-value <value>", "Source locator role value").option("--to-locator-ref <ref>", "Target locator ref (e.g., @e1)").option("--to-locator-testid <id>", "Target locator test id").option("--to-locator-css <selector>", "Target locator CSS selector").option("--to-locator-text <text>", "Target locator text").option("--to-locator-role <role>", "Target locator role name").option("--to-locator-role-value <value>", "Target locator role value").option("--steps <steps>", "Number of drag steps").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1100
+ await runCommand(command, (client) => {
1101
+ const from = requireLocator({
1102
+ locatorRef: options.fromLocatorRef,
1103
+ locatorTestid: options.fromLocatorTestid,
1104
+ locatorCss: options.fromLocatorCss,
1105
+ locatorText: options.fromLocatorText,
1106
+ locatorRole: options.fromLocatorRole,
1107
+ locatorRoleValue: options.fromLocatorRoleValue
1108
+ });
1109
+ const to = requireLocator({
1110
+ locatorRef: options.toLocatorRef,
1111
+ locatorTestid: options.toLocatorTestid,
1112
+ locatorCss: options.toLocatorCss,
1113
+ locatorText: options.toLocatorText,
1114
+ locatorRole: options.toLocatorRole,
1115
+ locatorRoleValue: options.toLocatorRoleValue
1116
+ });
1117
+ const payload = parseInput(DriveDragInputSchema, {
1118
+ session_id: options.sessionId,
1119
+ from,
1120
+ to,
1121
+ steps: parseNumber3(options.steps),
1122
+ tab_id: parseNumber3(options.tabId)
1123
+ });
1124
+ return client.post("/drive/drag", payload);
1125
+ });
1126
+ });
1127
+ drive.command("handle-dialog").description("Handle a JavaScript dialog").requiredOption("--session-id <id>", "Session identifier").requiredOption("--action <action>", "Dialog action (accept, dismiss)").option("--prompt-text <text>", "Prompt text for prompt() dialogs").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1128
+ await runCommand(command, (client) => {
1129
+ const payload = parseInput(DriveHandleDialogInputSchema, {
1130
+ session_id: options.sessionId,
1131
+ action: options.action,
1132
+ promptText: options.promptText,
1133
+ tab_id: parseNumber3(options.tabId)
1134
+ });
1135
+ return client.post("/drive/handle_dialog", payload);
1136
+ });
1137
+ });
1138
+ drive.command("key-press").description("Press a keyboard key").requiredOption("--session-id <id>", "Session identifier").requiredOption("--key <key>", "Key to press (e.g. Enter, ArrowDown)").option("--ctrl", "Hold control modifier").option("--alt", "Hold alt modifier").option("--shift", "Hold shift modifier").option("--meta", "Hold meta modifier").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1139
+ await runCommand(command, (client) => {
1140
+ const payload = parseInput(DriveKeyPressInputSchema, {
1141
+ session_id: options.sessionId,
1142
+ key: options.key,
1143
+ modifiers: {
1144
+ ctrl: Boolean(options.ctrl),
1145
+ alt: Boolean(options.alt),
1146
+ shift: Boolean(options.shift),
1147
+ meta: Boolean(options.meta)
1148
+ },
1149
+ tab_id: parseNumber3(options.tabId)
1150
+ });
1151
+ return client.post("/drive/key_press", payload);
1152
+ });
1153
+ });
1154
+ drive.command("key").description("Press a keyboard key with modifiers").requiredOption("--session-id <id>", "Session identifier").requiredOption("--key <key>", "Key to press (e.g. Enter, ArrowDown)").option(
1155
+ "--modifier <modifier>",
1156
+ "Modifier key (ctrl, alt, shift, meta)",
1157
+ (value, previous) => [...previous ?? [], value],
1158
+ []
1159
+ ).option("--repeat <count>", "Number of times to press").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1160
+ await runCommand(command, (client) => {
1161
+ const payload = parseInput(DriveKeyInputSchema, {
1162
+ session_id: options.sessionId,
1163
+ key: options.key,
1164
+ modifiers: options.modifier,
1165
+ repeat: parseNumber3(options.repeat),
1166
+ tab_id: parseNumber3(options.tabId)
1167
+ });
1168
+ return client.post("/drive/key", payload);
1169
+ });
1170
+ });
1171
+ drive.command("scroll").description("Scroll the page").requiredOption("--session-id <id>", "Session identifier").option("--delta-x <px>", "Scroll delta X").option("--delta-y <px>", "Scroll delta Y").option("--top <px>", "Scroll top position").option("--left <px>", "Scroll left position").option("--behavior <mode>", "Scroll behavior (auto, smooth)").option("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1172
+ await runCommand(command, (client) => {
1173
+ const payload = parseInput(DriveScrollInputSchema, {
1174
+ session_id: options.sessionId,
1175
+ delta_x: parseNumber3(options.deltaX),
1176
+ delta_y: parseNumber3(options.deltaY),
1177
+ top: parseNumber3(options.top),
1178
+ left: parseNumber3(options.left),
1179
+ behavior: options.behavior,
1180
+ tab_id: parseNumber3(options.tabId)
1181
+ });
1182
+ return client.post("/drive/scroll", payload);
1183
+ });
1184
+ });
1185
+ drive.command("wait-for").description("Wait for a condition").requiredOption("--session-id <id>", "Session identifier").option("--tab-id <id>", "Tab identifier").requiredOption(
1186
+ "--kind <kind>",
1187
+ "Condition kind (locator_visible, text_present, url_matches)"
1188
+ ).requiredOption("--value <value>", "Condition value").option("--timeout-ms <ms>", "Timeout in milliseconds").action(async (options, command) => {
1189
+ await runCommand(command, (client) => {
1190
+ const payload = parseInput(DriveWaitForInputSchema, {
1191
+ session_id: options.sessionId,
1192
+ condition: {
1193
+ kind: options.kind,
1194
+ value: options.value
1195
+ },
1196
+ timeout_ms: parseNumber3(options.timeoutMs),
1197
+ tab_id: parseNumber3(options.tabId)
1198
+ });
1199
+ return client.post("/drive/wait_for", payload);
1200
+ });
1201
+ });
1202
+ drive.command("tab-list").description("List browser tabs").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
1203
+ await runCommand(command, (client) => {
1204
+ const payload = parseInput(DriveTabListInputSchema, {
1205
+ session_id: options.sessionId
1206
+ });
1207
+ return client.post("/drive/tab_list", payload);
1208
+ });
1209
+ });
1210
+ drive.command("tab-activate").description("Activate a tab").requiredOption("--session-id <id>", "Session identifier").requiredOption("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1211
+ await runCommand(command, (client) => {
1212
+ const payload = parseInput(DriveTabActivateInputSchema, {
1213
+ session_id: options.sessionId,
1214
+ tab_id: parseNumber3(options.tabId)
1215
+ });
1216
+ return client.post("/drive/tab_activate", payload);
1217
+ });
1218
+ });
1219
+ drive.command("tab-close").description("Close a tab").requiredOption("--session-id <id>", "Session identifier").requiredOption("--tab-id <id>", "Tab identifier").action(async (options, command) => {
1220
+ await runCommand(command, (client) => {
1221
+ const payload = parseInput(DriveTabCloseInputSchema, {
1222
+ session_id: options.sessionId,
1223
+ tab_id: parseNumber3(options.tabId)
1224
+ });
1225
+ return client.post("/drive/tab_close", payload);
1226
+ });
1227
+ });
1228
+ };
1229
+
1230
+ // packages/cli/src/commands/inspect.ts
1231
+ var registerInspectCommands = (program2) => {
1232
+ const inspect = program2.command("inspect").description("Inspect commands");
1233
+ inspect.command("dom-snapshot").description("Fetch a DOM snapshot").requiredOption("--session-id <id>", "Session identifier").option("--format <format>", "Snapshot format (ax, html)").option("--consistency <mode>", "Consistency mode (best_effort, quiesce)").option("-i, --interactive", "Only include interactive elements").option("-c, --compact", "Remove empty/decorative nodes").option("-s, --selector <selector>", "Limit snapshot to selector").action(async (options, command) => {
1234
+ await runCommand(command, (client) => {
1235
+ const payload = parseInput(InspectDomSnapshotInputSchema, {
1236
+ session_id: options.sessionId,
1237
+ format: options.format,
1238
+ consistency: options.consistency,
1239
+ interactive: options.interactive,
1240
+ compact: options.compact,
1241
+ selector: options.selector
1242
+ });
1243
+ return client.post("/inspect/dom_snapshot", payload);
1244
+ });
1245
+ });
1246
+ inspect.command("dom-diff").description("Compare recent DOM snapshots").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
1247
+ await runCommand(command, (client) => {
1248
+ const payload = parseInput(InspectDomDiffInputSchema, {
1249
+ session_id: options.sessionId
1250
+ });
1251
+ return client.post("/inspect/dom_diff", payload);
1252
+ });
1253
+ });
1254
+ inspect.command("find").description("Find elements and return refs").requiredOption("--session-id <id>", "Session identifier").argument("<kind>", "Find kind (role, text, label)").argument("<value>", "Role name or text to match").option("--name <name>", "Accessible name to match (role only)").action(async (kind, value, options, command) => {
1255
+ await runCommand(command, (client) => {
1256
+ const normalizedKind = String(kind ?? "").toLowerCase();
1257
+ let payload;
1258
+ if (normalizedKind === "role") {
1259
+ payload = {
1260
+ session_id: options.sessionId,
1261
+ kind: "role",
1262
+ role: value,
1263
+ name: options.name
1264
+ };
1265
+ } else if (normalizedKind === "text") {
1266
+ payload = {
1267
+ session_id: options.sessionId,
1268
+ kind: "text",
1269
+ text: value
1270
+ };
1271
+ } else if (normalizedKind === "label") {
1272
+ payload = {
1273
+ session_id: options.sessionId,
1274
+ kind: "label",
1275
+ label: value
1276
+ };
1277
+ } else {
1278
+ throw new CliError({
1279
+ code: "INVALID_ARGUMENT",
1280
+ message: "kind must be role, text, or label.",
1281
+ retryable: false,
1282
+ details: { field: "kind" }
1283
+ });
1284
+ }
1285
+ const parsed = parseInput(InspectFindInputSchema, payload);
1286
+ return client.post("/inspect/find", parsed);
1287
+ });
1288
+ });
1289
+ inspect.command("extract-content").description("Extract main content from the page").requiredOption("--session-id <id>", "Session identifier").option("--format <format>", "Output format (markdown, text, article_json)").option("--include-metadata", "Include article metadata").option("--no-include-metadata", "Exclude article metadata").action(async (options, command) => {
1290
+ await runCommand(command, (client) => {
1291
+ const payload = parseInput(InspectExtractContentInputSchema, {
1292
+ session_id: options.sessionId,
1293
+ format: options.format,
1294
+ include_metadata: options.includeMetadata
1295
+ });
1296
+ return client.post("/inspect/extract_content", payload);
1297
+ });
1298
+ });
1299
+ inspect.command("page-state").description("Capture form, storage, and cookie state").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
1300
+ await runCommand(command, (client) => {
1301
+ const payload = parseInput(InspectPageStateInputSchema, {
1302
+ session_id: options.sessionId
1303
+ });
1304
+ return client.post("/inspect/page_state", payload);
1305
+ });
1306
+ });
1307
+ inspect.command("console-list").description("Fetch console entries").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
1308
+ await runCommand(command, (client) => {
1309
+ const payload = parseInput(InspectConsoleListInputSchema, {
1310
+ session_id: options.sessionId
1311
+ });
1312
+ return client.post("/inspect/console_list", payload);
1313
+ });
1314
+ });
1315
+ inspect.command("network-har").description("Fetch network HAR").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
1316
+ await runCommand(command, (client) => {
1317
+ const payload = parseInput(InspectNetworkHarInputSchema, {
1318
+ session_id: options.sessionId
1319
+ });
1320
+ return client.post("/inspect/network_har", payload);
1321
+ });
1322
+ });
1323
+ inspect.command("evaluate").description("Evaluate a JavaScript expression").requiredOption("--session-id <id>", "Session identifier").option("--expression <expr>", "Expression to evaluate").action(async (options, command) => {
1324
+ await runCommand(command, (client) => {
1325
+ const payload = parseInput(InspectEvaluateInputSchema, {
1326
+ session_id: options.sessionId,
1327
+ expression: options.expression
1328
+ });
1329
+ return client.post("/inspect/evaluate", payload);
1330
+ });
1331
+ });
1332
+ inspect.command("performance-metrics").description("Fetch performance metrics").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
1333
+ await runCommand(command, (client) => {
1334
+ const payload = parseInput(InspectPerformanceMetricsInputSchema, {
1335
+ session_id: options.sessionId
1336
+ });
1337
+ return client.post("/inspect/performance_metrics", payload);
1338
+ });
1339
+ });
1340
+ };
1341
+
1342
+ // packages/mcp-adapter/src/core-client.ts
1343
+ var DEFAULT_HOST2 = "127.0.0.1";
1344
+ var DEFAULT_PORT2 = 3210;
1345
+ var DEFAULT_TIMEOUT_MS2 = 4e3;
1346
+ var resolveHost2 = (host) => {
1347
+ const candidate = host?.trim() || process.env.BROWSER_BRIDGE_CORE_HOST || process.env.BROWSER_VISION_CORE_HOST;
1348
+ if (candidate && candidate.length > 0) {
1349
+ return candidate;
1350
+ }
1351
+ return DEFAULT_HOST2;
1352
+ };
1353
+ var resolvePort2 = (port) => {
1354
+ const candidate = port ?? (process.env.BROWSER_BRIDGE_CORE_PORT ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_PORT, 10) : process.env.BROWSER_VISION_CORE_PORT ? Number.parseInt(process.env.BROWSER_VISION_CORE_PORT, 10) : void 0);
1355
+ if (candidate === void 0 || candidate === null) {
1356
+ return DEFAULT_PORT2;
1357
+ }
1358
+ const parsed = typeof candidate === "number" ? candidate : Number.parseInt(candidate, 10);
1359
+ if (!Number.isFinite(parsed) || parsed <= 0) {
1360
+ throw new Error(`Invalid port: ${String(candidate)}`);
1361
+ }
1362
+ return parsed;
1363
+ };
1364
+ var normalizePath2 = (path2) => path2.startsWith("/") ? path2 : `/${path2}`;
1365
+ var createCoreClient2 = (options = {}) => {
1366
+ const host = resolveHost2(options.host);
1367
+ const port = resolvePort2(options.port);
1368
+ const baseUrl = `http://${host}:${port}`;
1369
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
1370
+ const fetchImpl = options.fetchImpl ?? fetch;
1371
+ const requestJson = async (path2, body) => {
1372
+ const controller = new AbortController();
1373
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
1374
+ try {
1375
+ const response = await fetchImpl(`${baseUrl}${normalizePath2(path2)}`, {
1376
+ method: "POST",
1377
+ headers: {
1378
+ "content-type": "application/json"
1379
+ },
1380
+ body: body === void 0 ? void 0 : JSON.stringify(body),
1381
+ signal: controller.signal
1382
+ });
1383
+ const raw = await response.text();
1384
+ if (!raw) {
1385
+ throw new Error(`Empty response from Core (${response.status}).`);
1386
+ }
1387
+ try {
1388
+ return JSON.parse(raw);
1389
+ } catch (error) {
1390
+ const message = error instanceof Error ? error.message : "Unknown JSON parse error";
1391
+ throw new Error(`Failed to parse Core response: ${message}`);
1392
+ }
1393
+ } finally {
1394
+ clearTimeout(timeout);
1395
+ }
1396
+ };
1397
+ const post = async (path2, body) => {
1398
+ return requestJson(path2, body);
1399
+ };
1400
+ return { baseUrl, post };
1401
+ };
1402
+
1403
+ // packages/mcp-adapter/src/tools.ts
1404
+ var toToolResult = (payload) => {
1405
+ const content = [{ type: "text", text: JSON.stringify(payload) }];
1406
+ if (payload && typeof payload === "object") {
1407
+ return {
1408
+ content,
1409
+ structuredContent: payload
1410
+ };
1411
+ }
1412
+ return { content };
1413
+ };
1414
+ var toInternalErrorEnvelope = (error) => ({
1415
+ ok: false,
1416
+ error: {
1417
+ code: "INTERNAL",
1418
+ message: error instanceof Error ? error.message : "Unknown error.",
1419
+ retryable: false
1420
+ }
1421
+ });
1422
+ var envelope = (schema) => apiEnvelopeSchema(schema);
1423
+ var TOOL_DEFINITIONS = [
1424
+ {
1425
+ name: "session.create",
1426
+ config: {
1427
+ title: "Session Create",
1428
+ description: "Create a new browser session.",
1429
+ inputSchema: SessionCreateInputSchema,
1430
+ outputSchema: envelope(SessionCreateOutputSchema),
1431
+ corePath: "/session/create"
1432
+ }
1433
+ },
1434
+ {
1435
+ name: "session.status",
1436
+ config: {
1437
+ title: "Session Status",
1438
+ description: "Fetch session status.",
1439
+ inputSchema: SessionStatusInputSchema,
1440
+ outputSchema: envelope(SessionStatusOutputSchema),
1441
+ corePath: "/session/status"
1442
+ }
1443
+ },
1444
+ {
1445
+ name: "session.recover",
1446
+ config: {
1447
+ title: "Session Recover",
1448
+ description: "Recover a session after errors.",
1449
+ inputSchema: SessionRecoverInputSchema,
1450
+ outputSchema: envelope(SessionRecoverOutputSchema),
1451
+ corePath: "/session/recover"
1452
+ }
1453
+ },
1454
+ {
1455
+ name: "session.close",
1456
+ config: {
1457
+ title: "Session Close",
1458
+ description: "Close a session.",
1459
+ inputSchema: SessionCloseInputSchema,
1460
+ outputSchema: envelope(SessionCloseOutputSchema),
1461
+ corePath: "/session/close"
1462
+ }
1463
+ },
1464
+ {
1465
+ name: "drive.navigate",
1466
+ config: {
1467
+ title: "Drive Navigate",
1468
+ description: "Navigate to a URL.",
1469
+ inputSchema: DriveNavigateInputSchema,
1470
+ outputSchema: envelope(DriveNavigateOutputSchema),
1471
+ corePath: "/drive/navigate"
1472
+ }
1473
+ },
1474
+ {
1475
+ name: "drive.go_back",
1476
+ config: {
1477
+ title: "Drive Go Back",
1478
+ description: "Go back in browser history.",
1479
+ inputSchema: DriveGoBackInputSchema,
1480
+ outputSchema: envelope(DriveGoBackOutputSchema),
1481
+ corePath: "/drive/go_back"
1482
+ }
1483
+ },
1484
+ {
1485
+ name: "drive.go_forward",
1486
+ config: {
1487
+ title: "Drive Go Forward",
1488
+ description: "Go forward in browser history.",
1489
+ inputSchema: DriveGoForwardInputSchema,
1490
+ outputSchema: envelope(DriveGoForwardOutputSchema),
1491
+ corePath: "/drive/go_forward"
1492
+ }
1493
+ },
1494
+ {
1495
+ name: "drive.back",
1496
+ config: {
1497
+ title: "Drive Back",
1498
+ description: "Go back in browser history.",
1499
+ inputSchema: DriveBackInputSchema,
1500
+ outputSchema: envelope(DriveBackOutputSchema),
1501
+ corePath: "/drive/back"
1502
+ }
1503
+ },
1504
+ {
1505
+ name: "drive.forward",
1506
+ config: {
1507
+ title: "Drive Forward",
1508
+ description: "Go forward in browser history.",
1509
+ inputSchema: DriveForwardInputSchema,
1510
+ outputSchema: envelope(DriveForwardOutputSchema),
1511
+ corePath: "/drive/forward"
1512
+ }
1513
+ },
1514
+ {
1515
+ name: "drive.click",
1516
+ config: {
1517
+ title: "Drive Click",
1518
+ description: "Click an element.",
1519
+ inputSchema: DriveClickInputSchema,
1520
+ outputSchema: envelope(DriveClickOutputSchema),
1521
+ corePath: "/drive/click"
1522
+ }
1523
+ },
1524
+ {
1525
+ name: "drive.hover",
1526
+ config: {
1527
+ title: "Drive Hover",
1528
+ description: "Hover over an element.",
1529
+ inputSchema: DriveHoverInputSchema,
1530
+ outputSchema: envelope(DriveHoverOutputSchema),
1531
+ corePath: "/drive/hover"
1532
+ }
1533
+ },
1534
+ {
1535
+ name: "drive.select",
1536
+ config: {
1537
+ title: "Drive Select",
1538
+ description: "Select an option in a dropdown.",
1539
+ inputSchema: DriveSelectInputSchema,
1540
+ outputSchema: envelope(DriveSelectOutputSchema),
1541
+ corePath: "/drive/select"
1542
+ }
1543
+ },
1544
+ {
1545
+ name: "drive.type",
1546
+ config: {
1547
+ title: "Drive Type",
1548
+ description: "Type into an element.",
1549
+ inputSchema: DriveTypeInputSchema,
1550
+ outputSchema: envelope(DriveTypeOutputSchema),
1551
+ corePath: "/drive/type"
1552
+ }
1553
+ },
1554
+ {
1555
+ name: "drive.fill_form",
1556
+ config: {
1557
+ title: "Drive Fill Form",
1558
+ description: "Fill multiple form fields.",
1559
+ inputSchema: DriveFillFormInputSchema,
1560
+ outputSchema: envelope(DriveFillFormOutputSchema),
1561
+ corePath: "/drive/fill_form"
1562
+ }
1563
+ },
1564
+ {
1565
+ name: "drive.drag",
1566
+ config: {
1567
+ title: "Drive Drag",
1568
+ description: "Drag an element to a target.",
1569
+ inputSchema: DriveDragInputSchema,
1570
+ outputSchema: envelope(DriveDragOutputSchema),
1571
+ corePath: "/drive/drag"
1572
+ }
1573
+ },
1574
+ {
1575
+ name: "drive.handle_dialog",
1576
+ config: {
1577
+ title: "Drive Handle Dialog",
1578
+ description: "Handle a JavaScript dialog.",
1579
+ inputSchema: DriveHandleDialogInputSchema,
1580
+ outputSchema: envelope(DriveHandleDialogOutputSchema),
1581
+ corePath: "/drive/handle_dialog"
1582
+ }
1583
+ },
1584
+ {
1585
+ name: "dialog.accept",
1586
+ config: {
1587
+ title: "Dialog Accept",
1588
+ description: "Accept a JavaScript dialog.",
1589
+ inputSchema: DialogAcceptInputSchema,
1590
+ outputSchema: envelope(DialogAcceptOutputSchema),
1591
+ corePath: "/dialog/accept"
1592
+ }
1593
+ },
1594
+ {
1595
+ name: "dialog.dismiss",
1596
+ config: {
1597
+ title: "Dialog Dismiss",
1598
+ description: "Dismiss a JavaScript dialog.",
1599
+ inputSchema: DialogDismissInputSchema,
1600
+ outputSchema: envelope(DialogDismissOutputSchema),
1601
+ corePath: "/dialog/dismiss"
1602
+ }
1603
+ },
1604
+ {
1605
+ name: "drive.key",
1606
+ config: {
1607
+ title: "Drive Key",
1608
+ description: "Press a keyboard key.",
1609
+ inputSchema: DriveKeyInputSchema,
1610
+ outputSchema: envelope(DriveKeyOutputSchema),
1611
+ corePath: "/drive/key"
1612
+ }
1613
+ },
1614
+ {
1615
+ name: "drive.key_press",
1616
+ config: {
1617
+ title: "Drive Key Press",
1618
+ description: "Press a key on the active element.",
1619
+ inputSchema: DriveKeyPressInputSchema,
1620
+ outputSchema: envelope(DriveKeyPressOutputSchema),
1621
+ corePath: "/drive/key_press"
1622
+ }
1623
+ },
1624
+ {
1625
+ name: "drive.scroll",
1626
+ config: {
1627
+ title: "Drive Scroll",
1628
+ description: "Scroll the active tab.",
1629
+ inputSchema: DriveScrollInputSchema,
1630
+ outputSchema: envelope(DriveScrollOutputSchema),
1631
+ corePath: "/drive/scroll"
1632
+ }
1633
+ },
1634
+ {
1635
+ name: "drive.wait_for",
1636
+ config: {
1637
+ title: "Drive Wait For",
1638
+ description: "Wait for a drive condition.",
1639
+ inputSchema: DriveWaitForInputSchema,
1640
+ outputSchema: envelope(DriveWaitForOutputSchema),
1641
+ corePath: "/drive/wait_for"
1642
+ }
1643
+ },
1644
+ {
1645
+ name: "drive.tab_list",
1646
+ config: {
1647
+ title: "Drive Tab List",
1648
+ description: "List browser tabs.",
1649
+ inputSchema: DriveTabListInputSchema,
1650
+ outputSchema: envelope(DriveTabListOutputSchema),
1651
+ corePath: "/drive/tab_list"
1652
+ }
1653
+ },
1654
+ {
1655
+ name: "drive.tab_activate",
1656
+ config: {
1657
+ title: "Drive Tab Activate",
1658
+ description: "Activate a browser tab.",
1659
+ inputSchema: DriveTabActivateInputSchema,
1660
+ outputSchema: envelope(DriveTabActivateOutputSchema),
1661
+ corePath: "/drive/tab_activate"
1662
+ }
1663
+ },
1664
+ {
1665
+ name: "drive.tab_close",
1666
+ config: {
1667
+ title: "Drive Tab Close",
1668
+ description: "Close a browser tab.",
1669
+ inputSchema: DriveTabCloseInputSchema,
1670
+ outputSchema: envelope(DriveTabCloseOutputSchema),
1671
+ corePath: "/drive/tab_close"
1672
+ }
1673
+ },
1674
+ {
1675
+ name: "inspect.dom_snapshot",
1676
+ config: {
1677
+ title: "Inspect DOM Snapshot",
1678
+ description: "Capture a DOM snapshot.",
1679
+ inputSchema: InspectDomSnapshotInputSchema,
1680
+ outputSchema: envelope(InspectDomSnapshotOutputSchema),
1681
+ corePath: "/inspect/dom_snapshot"
1682
+ }
1683
+ },
1684
+ {
1685
+ name: "inspect.dom_diff",
1686
+ config: {
1687
+ title: "Inspect DOM Diff",
1688
+ description: "Compare recent DOM snapshots.",
1689
+ inputSchema: InspectDomDiffInputSchema,
1690
+ outputSchema: envelope(InspectDomDiffOutputSchema),
1691
+ corePath: "/inspect/dom_diff"
1692
+ }
1693
+ },
1694
+ {
1695
+ name: "inspect.find",
1696
+ config: {
1697
+ title: "Inspect Find",
1698
+ description: "Find elements in the accessibility tree and return refs.",
1699
+ inputSchema: InspectFindInputSchema,
1700
+ outputSchema: envelope(InspectFindOutputSchema),
1701
+ corePath: "/inspect/find"
1702
+ }
1703
+ },
1704
+ {
1705
+ name: "inspect.extract_content",
1706
+ config: {
1707
+ title: "Inspect Extract Content",
1708
+ description: "Extract main content as markdown or text.",
1709
+ inputSchema: InspectExtractContentInputSchema,
1710
+ outputSchema: envelope(InspectExtractContentOutputSchema),
1711
+ corePath: "/inspect/extract_content"
1712
+ }
1713
+ },
1714
+ {
1715
+ name: "inspect.page_state",
1716
+ config: {
1717
+ title: "Inspect Page State",
1718
+ description: "Capture form, storage, and cookie state.",
1719
+ inputSchema: InspectPageStateInputSchema,
1720
+ outputSchema: envelope(InspectPageStateOutputSchema),
1721
+ corePath: "/inspect/page_state"
1722
+ }
1723
+ },
1724
+ {
1725
+ name: "inspect.console_list",
1726
+ config: {
1727
+ title: "Inspect Console List",
1728
+ description: "List console entries.",
1729
+ inputSchema: InspectConsoleListInputSchema,
1730
+ outputSchema: envelope(InspectConsoleListOutputSchema),
1731
+ corePath: "/inspect/console_list"
1732
+ }
1733
+ },
1734
+ {
1735
+ name: "inspect.network_har",
1736
+ config: {
1737
+ title: "Inspect Network HAR",
1738
+ description: "Capture network HAR data.",
1739
+ inputSchema: InspectNetworkHarInputSchema,
1740
+ outputSchema: envelope(InspectNetworkHarOutputSchema),
1741
+ corePath: "/inspect/network_har"
1742
+ }
1743
+ },
1744
+ {
1745
+ name: "inspect.evaluate",
1746
+ config: {
1747
+ title: "Inspect Evaluate",
1748
+ description: "Evaluate an expression in the target.",
1749
+ inputSchema: InspectEvaluateInputSchema,
1750
+ outputSchema: envelope(InspectEvaluateOutputSchema),
1751
+ corePath: "/inspect/evaluate"
1752
+ }
1753
+ },
1754
+ {
1755
+ name: "inspect.performance_metrics",
1756
+ config: {
1757
+ title: "Inspect Performance Metrics",
1758
+ description: "Collect performance metrics.",
1759
+ inputSchema: InspectPerformanceMetricsInputSchema,
1760
+ outputSchema: envelope(InspectPerformanceMetricsOutputSchema),
1761
+ corePath: "/inspect/performance_metrics"
1762
+ }
1763
+ },
1764
+ {
1765
+ name: "artifacts.screenshot",
1766
+ config: {
1767
+ title: "Artifacts Screenshot",
1768
+ description: "Capture a screenshot artifact.",
1769
+ inputSchema: ArtifactsScreenshotInputSchema,
1770
+ outputSchema: envelope(ArtifactsScreenshotOutputSchema),
1771
+ corePath: "/artifacts/screenshot"
1772
+ }
1773
+ },
1774
+ {
1775
+ name: "diagnostics.doctor",
1776
+ config: {
1777
+ title: "Diagnostics Doctor",
1778
+ description: "Run diagnostics checks.",
1779
+ inputSchema: DiagnosticsDoctorInputSchema,
1780
+ outputSchema: envelope(DiagnosticsDoctorOutputSchema),
1781
+ corePath: "/diagnostics/doctor"
1782
+ }
1783
+ }
1784
+ ];
1785
+ var createToolHandler = (client, corePath) => {
1786
+ return (async (args, _extra) => {
1787
+ void _extra;
1788
+ try {
1789
+ const envelopeResult = await client.post(corePath, args);
1790
+ return toToolResult(envelopeResult);
1791
+ } catch (error) {
1792
+ const parsed = ErrorEnvelopeSchema.safeParse(error);
1793
+ if (parsed.success) {
1794
+ return toToolResult(parsed.data);
1795
+ }
1796
+ return toToolResult(toInternalErrorEnvelope(error));
1797
+ }
1798
+ });
1799
+ };
1800
+ var registerBrowserBridgeTools = (server, client) => {
1801
+ for (const tool of TOOL_DEFINITIONS) {
1802
+ server.registerTool(
1803
+ tool.name,
1804
+ {
1805
+ title: tool.config.title,
1806
+ description: tool.config.description,
1807
+ inputSchema: tool.config.inputSchema,
1808
+ outputSchema: tool.config.outputSchema
1809
+ },
1810
+ createToolHandler(client, tool.config.corePath)
1811
+ );
1812
+ }
1813
+ };
1814
+
1815
+ // packages/mcp-adapter/src/server.ts
1816
+ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
1817
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
1818
+ var DEFAULT_SERVER_NAME = "browser-bridge";
1819
+ var DEFAULT_SERVER_VERSION = "0.0.0";
1820
+ var createMcpServer = (options = {}) => {
1821
+ const server = new import_mcp.McpServer({
1822
+ name: options.name ?? DEFAULT_SERVER_NAME,
1823
+ version: options.version ?? DEFAULT_SERVER_VERSION
1824
+ });
1825
+ const client = options.coreClient ?? createCoreClient2(options);
1826
+ registerBrowserBridgeTools(server, client);
1827
+ return { server, client };
1828
+ };
1829
+ var startMcpServer = async (options = {}) => {
1830
+ const handle = createMcpServer(options);
1831
+ const transport = new import_stdio.StdioServerTransport();
1832
+ await handle.server.connect(transport);
1833
+ return { ...handle, transport };
1834
+ };
1835
+
1836
+ // packages/cli/src/commands/mcp.ts
1837
+ var registerMcpCommand = (program2) => {
1838
+ program2.command("mcp").description("Run the MCP server over stdio").option("--name <name>", "MCP server name").option("--version <version>", "MCP server version").action(async (options, command) => {
1839
+ const globals = getGlobalOptions(command);
1840
+ const coreClient = createCoreClient({
1841
+ host: globals.host,
1842
+ port: globals.port,
1843
+ ensureDaemon: globals.daemon !== false
1844
+ });
1845
+ try {
1846
+ await startMcpServer({
1847
+ name: options.name,
1848
+ version: options.version,
1849
+ coreClient
1850
+ });
1851
+ } catch (error) {
1852
+ console.error(error);
1853
+ process.exitCode = 1;
1854
+ }
1855
+ });
1856
+ };
1857
+
1858
+ // packages/core/src/server.ts
1859
+ var import_express2 = __toESM(require("express"));
1860
+
1861
+ // packages/core/src/routes/session.ts
1862
+ var import_express = require("express");
1863
+
1864
+ // packages/core/src/inspect.ts
1865
+ var import_readability = require("@mozilla/readability");
1866
+ var import_jsdom = require("jsdom");
1867
+ var import_turndown = __toESM(require("turndown"));
1868
+
1869
+ // packages/core/src/artifacts.ts
1870
+ var import_promises2 = require("node:fs/promises");
1871
+ var import_node_os = __toESM(require("node:os"));
1872
+ var import_node_path2 = __toESM(require("node:path"));
1873
+ var ARTIFACTS_DIR_NAME = "browser-agent";
1874
+ var resolveTempRoot = () => process.env.TMPDIR || process.env.TEMP || process.env.TMP || import_node_os.default.tmpdir();
1875
+ var getArtifactRootDir = (sessionId) => import_node_path2.default.join(resolveTempRoot(), ARTIFACTS_DIR_NAME, sessionId);
1876
+ var ensureArtifactRootDir = async (sessionId) => {
1877
+ const rootDir = getArtifactRootDir(sessionId);
1878
+ await (0, import_promises2.mkdir)(rootDir, { recursive: true });
1879
+ return rootDir;
1880
+ };
1881
+
1882
+ // packages/core/src/extension-bridge.ts
1883
+ var import_ws = require("ws");
1884
+
1885
+ // packages/core/src/drive.ts
1886
+ var DriveMutex = class {
1887
+ constructor() {
1888
+ this.tail = Promise.resolve();
1889
+ }
1890
+ async runExclusive(work) {
1891
+ const result = this.tail.then(work, work);
1892
+ this.tail = result.then(
1893
+ () => void 0,
1894
+ () => void 0
1895
+ );
1896
+ return await result;
1897
+ }
1898
+ };
1899
+ var driveMutex = new DriveMutex();
1900
+
1901
+ // packages/core/src/page-state-script.ts
1902
+ var PAGE_STATE_SCRIPT = [
1903
+ "(() => {",
1904
+ " const escape = (value) => {",
1905
+ " if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {",
1906
+ " return CSS.escape(value);",
1907
+ " }",
1908
+ ` return String(value).replace(/["'\\\\]/g, '\\\\$&');`,
1909
+ " };",
1910
+ " const truncate = (value, max) => {",
1911
+ " const text = String(value ?? '');",
1912
+ " return text.length > max ? text.slice(0, max) : text;",
1913
+ " };",
1914
+ " const selectorFor = (element) => {",
1915
+ " if (element.id) {",
1916
+ " return `#${escape(element.id)}`;",
1917
+ " }",
1918
+ " const name = element.getAttribute('name');",
1919
+ " if (name) {",
1920
+ ' return `${element.tagName.toLowerCase()}[name="${escape(name)}"]`;',
1921
+ " }",
1922
+ " const parts = [];",
1923
+ " let node = element;",
1924
+ " while (node && node.nodeType === 1 && parts.length < 4) {",
1925
+ " let part = node.tagName.toLowerCase();",
1926
+ " const parent = node.parentElement;",
1927
+ " if (parent) {",
1928
+ " const siblings = Array.from(parent.children).filter(",
1929
+ " (child) => child.tagName === node.tagName",
1930
+ " );",
1931
+ " if (siblings.length > 1) {",
1932
+ " part += `:nth-of-type(${siblings.indexOf(node) + 1})`;",
1933
+ " }",
1934
+ " }",
1935
+ " parts.unshift(part);",
1936
+ " node = parent;",
1937
+ " }",
1938
+ " return parts.join('>');",
1939
+ " };",
1940
+ " const readStorage = (storage, limit) => {",
1941
+ " try {",
1942
+ " return Object.keys(storage)",
1943
+ " .slice(0, limit)",
1944
+ " .map((key) => ({",
1945
+ " key,",
1946
+ " value: truncate(storage.getItem(key), 500),",
1947
+ " }));",
1948
+ " } catch {",
1949
+ " return [];",
1950
+ " }",
1951
+ " };",
1952
+ " const forms = Array.from(document.querySelectorAll('form')).map((form) => {",
1953
+ " const fields = Array.from(form.elements)",
1954
+ " .filter((element) => element && element.tagName)",
1955
+ " .map((element) => {",
1956
+ " const tag = element.tagName.toLowerCase();",
1957
+ " const type = 'type' in element && element.type ? element.type : tag;",
1958
+ " const name = element.name || element.getAttribute('name') || element.id || '';",
1959
+ " let value = '';",
1960
+ " let options;",
1961
+ " if (tag === 'select') {",
1962
+ " const select = element;",
1963
+ " value = select.value ?? '';",
1964
+ " options = Array.from(select.options).map((option) => option.text);",
1965
+ " } else if (tag === 'input' && element.type === 'password') {",
1966
+ " value = '[redacted]';",
1967
+ " } else if (tag === 'input' || tag === 'textarea') {",
1968
+ " value = element.value ?? '';",
1969
+ " } else if (element.isContentEditable) {",
1970
+ " value = element.textContent ?? '';",
1971
+ " } else if ('value' in element) {",
1972
+ " value = element.value ?? '';",
1973
+ " }",
1974
+ " return {",
1975
+ " name,",
1976
+ " type,",
1977
+ " value: truncate(value, 500),",
1978
+ " ...(options ? { options } : {}),",
1979
+ " };",
1980
+ " });",
1981
+ " return {",
1982
+ " selector: selectorFor(form),",
1983
+ " action: form.getAttribute('action') || undefined,",
1984
+ " method: form.getAttribute('method') || undefined,",
1985
+ " fields,",
1986
+ " };",
1987
+ " });",
1988
+ " const localStorage = readStorage(window.localStorage, 100);",
1989
+ " const sessionStorage = readStorage(window.sessionStorage, 100);",
1990
+ " const cookies = (document.cookie ? document.cookie.split(';') : [])",
1991
+ " .map((entry) => entry.trim())",
1992
+ " .filter((entry) => entry.length > 0)",
1993
+ " .slice(0, 50)",
1994
+ " .map((entry) => {",
1995
+ " const [key, ...rest] = entry.split('=');",
1996
+ " return { key, value: truncate(rest.join('='), 500) };",
1997
+ " });",
1998
+ " return { forms, localStorage, sessionStorage, cookies };",
1999
+ "})()"
2000
+ ].join("\n");
2001
+
2002
+ // packages/cli/src/open-path.ts
2003
+ var import_node_child_process2 = require("node:child_process");
2004
+ var openPath = async (target) => {
2005
+ const platform = process.platform;
2006
+ if (platform === "darwin") {
2007
+ const child2 = (0, import_node_child_process2.spawn)("open", [target], { detached: true, stdio: "ignore" });
2008
+ child2.unref();
2009
+ return;
2010
+ }
2011
+ if (platform === "win32") {
2012
+ const child2 = (0, import_node_child_process2.spawn)("cmd", ["/c", "start", "", target], {
2013
+ detached: true,
2014
+ stdio: "ignore"
2015
+ });
2016
+ child2.unref();
2017
+ return;
2018
+ }
2019
+ const child = (0, import_node_child_process2.spawn)("xdg-open", [target], {
2020
+ detached: true,
2021
+ stdio: "ignore"
2022
+ });
2023
+ child.unref();
2024
+ };
2025
+
2026
+ // packages/cli/src/commands/open-artifacts.ts
2027
+ var registerOpenArtifactsCommand = (program2) => {
2028
+ program2.command("open-artifacts").description("Open the artifact folder for a session").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
2029
+ await runLocal(command, async () => {
2030
+ const payload = parseInput(SessionIdSchema, {
2031
+ session_id: options.sessionId
2032
+ });
2033
+ const rootDir = await ensureArtifactRootDir(payload.session_id);
2034
+ await openPath(rootDir);
2035
+ return { ok: true, result: { path: rootDir, opened: true } };
2036
+ });
2037
+ });
2038
+ };
2039
+
2040
+ // packages/cli/src/commands/session.ts
2041
+ var registerSessionCommands = (program2) => {
2042
+ const session = program2.command("session").description("Manage Core sessions");
2043
+ session.command("create").description("Create a new session").action(async (options, command) => {
2044
+ await runCommand(command, (client) => {
2045
+ const payload = parseInput(SessionCreateInputSchema, {});
2046
+ return client.post("/session/create", payload);
2047
+ });
2048
+ });
2049
+ session.command("status").description("Get session status").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
2050
+ await runCommand(command, (client) => {
2051
+ const payload = parseInput(SessionStatusInputSchema, {
2052
+ session_id: options.sessionId
2053
+ });
2054
+ return client.post("/session/status", payload);
2055
+ });
2056
+ });
2057
+ session.command("recover").description("Attempt to recover a session").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
2058
+ await runCommand(command, (client) => {
2059
+ const payload = parseInput(SessionRecoverInputSchema, {
2060
+ session_id: options.sessionId
2061
+ });
2062
+ return client.post("/session/recover", payload);
2063
+ });
2064
+ });
2065
+ session.command("close").description("Close a session").requiredOption("--session-id <id>", "Session identifier").action(async (options, command) => {
2066
+ await runCommand(command, (client) => {
2067
+ const payload = parseInput(SessionCloseInputSchema, {
2068
+ session_id: options.sessionId
2069
+ });
2070
+ return client.post("/session/close", payload);
2071
+ });
2072
+ });
2073
+ };
2074
+
2075
+ // packages/cli/src/index.ts
2076
+ var program = new import_commander.Command();
2077
+ program.name("browser-bridge").description("Browser Bridge CLI").option("--host <host>", "Core host (default: 127.0.0.1)").option("--port <port>", "Core port (default: 3210)").option("--json", "Output JSON").option("--no-daemon", "Disable auto-starting Core");
2078
+ registerSessionCommands(program);
2079
+ registerDriveCommands(program);
2080
+ registerInspectCommands(program);
2081
+ registerArtifactsCommands(program);
2082
+ registerDiagnosticsCommands(program);
2083
+ registerDialogCommands(program);
2084
+ registerOpenArtifactsCommand(program);
2085
+ registerMcpCommand(program);
2086
+ void program.parseAsync(process.argv);
2087
+ //# sourceMappingURL=index.js.map