browser-pilot 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -403,6 +403,45 @@ Output:
403
403
 
404
404
  Run `bp actions` for complete action reference.
405
405
 
406
+ ### Recording Browser Actions
407
+
408
+ Record human interactions to create automation recipes:
409
+
410
+ ```bash
411
+ # Auto-connect to local Chrome and record (creates new session)
412
+ bp record
413
+
414
+ # Use most recent session
415
+ bp record -s
416
+
417
+ # Use specific session with custom output file
418
+ bp record -s my-session -f login-flow.json
419
+
420
+ # Review and edit the recording
421
+ cat recording.json
422
+
423
+ # Replay the recording
424
+ bp exec -s my-session --file recording.json
425
+ ```
426
+
427
+ The output format is compatible with `page.batch()`:
428
+ ```json
429
+ {
430
+ "recordedAt": "2026-01-06T10:00:00.000Z",
431
+ "startUrl": "https://example.com",
432
+ "duration": 15000,
433
+ "steps": [
434
+ { "action": "fill", "selector": ["[data-testid=\"email\"]", "#email"], "value": "user@example.com" },
435
+ { "action": "click", "selector": ["[data-testid=\"submit\"]", "#login-btn"] }
436
+ ]
437
+ }
438
+ ```
439
+
440
+ **Notes:**
441
+ - Password fields are automatically redacted as `[REDACTED]`
442
+ - Selectors are multi-selector arrays ordered by reliability (data attributes > IDs > CSS paths)
443
+ - Edit the JSON to adjust selectors or add `optional: true` flags
444
+
406
445
  ## Examples
407
446
 
408
447
  ### Login Flow with Error Handling
package/dist/actions.cjs CHANGED
@@ -110,7 +110,8 @@ var BatchExecutor = class {
110
110
  await this.page.fill(step.selector, step.value, {
111
111
  timeout,
112
112
  optional,
113
- clear: step.clear ?? true
113
+ clear: step.clear ?? true,
114
+ blur: step.blur
114
115
  });
115
116
  return { selectorUsed: this.getUsedSelector(step.selector) };
116
117
  }
@@ -1,5 +1,5 @@
1
- import { P as Page, S as Step, B as BatchOptions, b as BatchResult } from './types-C6m0bT04.cjs';
2
- export { A as ActionType, c as StepResult } from './types-C6m0bT04.cjs';
1
+ import { P as Page, S as Step, B as BatchOptions, b as BatchResult } from './types-TVlTA7nH.cjs';
2
+ export { A as ActionType, c as StepResult } from './types-TVlTA7nH.cjs';
3
3
  import './client-7Nqka5MV.cjs';
4
4
 
5
5
  /**
package/dist/actions.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as Page, S as Step, B as BatchOptions, b as BatchResult } from './types-BJv2dzu0.js';
2
- export { A as ActionType, c as StepResult } from './types-BJv2dzu0.js';
1
+ import { P as Page, S as Step, B as BatchOptions, b as BatchResult } from './types-CbdmaocU.js';
2
+ export { A as ActionType, c as StepResult } from './types-CbdmaocU.js';
3
3
  import './client-7Nqka5MV.js';
4
4
 
5
5
  /**
package/dist/actions.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BatchExecutor,
3
3
  addBatchToPage
4
- } from "./chunk-YEHK2XY3.mjs";
4
+ } from "./chunk-6RB3GKQP.mjs";
5
5
  export {
6
6
  BatchExecutor,
7
7
  addBatchToPage
package/dist/browser.cjs CHANGED
@@ -542,7 +542,8 @@ var BatchExecutor = class {
542
542
  await this.page.fill(step.selector, step.value, {
543
543
  timeout,
544
544
  optional,
545
- clear: step.clear ?? true
545
+ clear: step.clear ?? true,
546
+ blur: step.blur
546
547
  });
547
548
  return { selectorUsed: this.getUsedSelector(step.selector) };
548
549
  }
@@ -1133,6 +1134,13 @@ var Page = class {
1133
1134
  this.cdp = cdp;
1134
1135
  this.batchExecutor = new BatchExecutor(this);
1135
1136
  }
1137
+ /**
1138
+ * Get the underlying CDP client for advanced operations.
1139
+ * Use with caution - prefer high-level Page methods when possible.
1140
+ */
1141
+ get cdpClient() {
1142
+ return this.cdp;
1143
+ }
1136
1144
  /**
1137
1145
  * Initialize the page (enable required CDP domains)
1138
1146
  */
@@ -1283,7 +1291,7 @@ var Page = class {
1283
1291
  * Fill an input field (clears first by default)
1284
1292
  */
1285
1293
  async fill(selector, value, options = {}) {
1286
- const { clear = true } = options;
1294
+ const { clear = true, blur = false } = options;
1287
1295
  return this.withStaleNodeRetry(async () => {
1288
1296
  const element = await this.findElement(selector, options);
1289
1297
  if (!element) {
@@ -1297,7 +1305,11 @@ var Page = class {
1297
1305
  const el = document.querySelector(${JSON.stringify(element.selector)});
1298
1306
  if (el) {
1299
1307
  el.value = '';
1300
- el.dispatchEvent(new Event('input', { bubbles: true }));
1308
+ el.dispatchEvent(new InputEvent('input', {
1309
+ bubbles: true,
1310
+ cancelable: true,
1311
+ inputType: 'deleteContent'
1312
+ }));
1301
1313
  }
1302
1314
  })()`
1303
1315
  );
@@ -1307,11 +1319,21 @@ var Page = class {
1307
1319
  `(() => {
1308
1320
  const el = document.querySelector(${JSON.stringify(element.selector)});
1309
1321
  if (el) {
1310
- el.dispatchEvent(new Event('input', { bubbles: true }));
1322
+ el.dispatchEvent(new InputEvent('input', {
1323
+ bubbles: true,
1324
+ cancelable: true,
1325
+ inputType: 'insertText',
1326
+ data: ${JSON.stringify(value)}
1327
+ }));
1311
1328
  el.dispatchEvent(new Event('change', { bubbles: true }));
1312
1329
  }
1313
1330
  })()`
1314
1331
  );
1332
+ if (blur) {
1333
+ await this.evaluateInFrame(
1334
+ `document.querySelector(${JSON.stringify(element.selector)})?.blur()`
1335
+ );
1336
+ }
1315
1337
  return true;
1316
1338
  });
1317
1339
  }
@@ -1,7 +1,7 @@
1
1
  import { C as CDPClient } from './client-7Nqka5MV.cjs';
2
2
  import { C as ConnectOptions } from './types-D_uDqh0Z.cjs';
3
- import { P as Page } from './types-C6m0bT04.cjs';
4
- export { d as ActionOptions, e as ActionResult, C as ConsoleHandler, f as ConsoleMessage, g as ConsoleMessageType, h as CustomSelectConfig, D as Dialog, i as DialogHandler, j as DialogType, k as Download, E as ElementInfo, l as ElementNotFoundError, m as EmulationState, n as ErrorHandler, F as FileInput, o as FillOptions, G as GeolocationOptions, I as InteractiveElement, N as NavigationError, p as NetworkIdleOptions, q as PageError, r as PageSnapshot, s as SnapshotNode, t as SubmitOptions, T as TimeoutError, u as TypeOptions, U as UserAgentMetadata, v as UserAgentOptions, V as ViewportOptions, W as WaitForOptions } from './types-C6m0bT04.cjs';
3
+ import { P as Page } from './types-TVlTA7nH.cjs';
4
+ export { d as ActionOptions, e as ActionResult, C as ConsoleHandler, f as ConsoleMessage, g as ConsoleMessageType, h as CustomSelectConfig, D as Dialog, i as DialogHandler, j as DialogType, k as Download, E as ElementInfo, l as ElementNotFoundError, m as EmulationState, n as ErrorHandler, F as FileInput, o as FillOptions, G as GeolocationOptions, I as InteractiveElement, N as NavigationError, p as NetworkIdleOptions, q as PageError, r as PageSnapshot, s as SnapshotNode, t as SubmitOptions, T as TimeoutError, u as TypeOptions, U as UserAgentMetadata, v as UserAgentOptions, V as ViewportOptions, W as WaitForOptions } from './types-TVlTA7nH.cjs';
5
5
 
6
6
  /**
7
7
  * Browser class - manages CDP connection and pages
package/dist/browser.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { C as CDPClient } from './client-7Nqka5MV.js';
2
2
  import { C as ConnectOptions } from './types-D_uDqh0Z.js';
3
- import { P as Page } from './types-BJv2dzu0.js';
4
- export { d as ActionOptions, e as ActionResult, C as ConsoleHandler, f as ConsoleMessage, g as ConsoleMessageType, h as CustomSelectConfig, D as Dialog, i as DialogHandler, j as DialogType, k as Download, E as ElementInfo, l as ElementNotFoundError, m as EmulationState, n as ErrorHandler, F as FileInput, o as FillOptions, G as GeolocationOptions, I as InteractiveElement, N as NavigationError, p as NetworkIdleOptions, q as PageError, r as PageSnapshot, s as SnapshotNode, t as SubmitOptions, T as TimeoutError, u as TypeOptions, U as UserAgentMetadata, v as UserAgentOptions, V as ViewportOptions, W as WaitForOptions } from './types-BJv2dzu0.js';
3
+ import { P as Page } from './types-CbdmaocU.js';
4
+ export { d as ActionOptions, e as ActionResult, C as ConsoleHandler, f as ConsoleMessage, g as ConsoleMessageType, h as CustomSelectConfig, D as Dialog, i as DialogHandler, j as DialogType, k as Download, E as ElementInfo, l as ElementNotFoundError, m as EmulationState, n as ErrorHandler, F as FileInput, o as FillOptions, G as GeolocationOptions, I as InteractiveElement, N as NavigationError, p as NetworkIdleOptions, q as PageError, r as PageSnapshot, s as SnapshotNode, t as SubmitOptions, T as TimeoutError, u as TypeOptions, U as UserAgentMetadata, v as UserAgentOptions, V as ViewportOptions, W as WaitForOptions } from './types-CbdmaocU.js';
5
5
 
6
6
  /**
7
7
  * Browser class - manages CDP connection and pages
package/dist/browser.mjs CHANGED
@@ -5,10 +5,10 @@ import {
5
5
  Page,
6
6
  TimeoutError,
7
7
  connect
8
- } from "./chunk-CWSTSVWO.mjs";
8
+ } from "./chunk-PCNEJAJ7.mjs";
9
9
  import "./chunk-BCOZUKWS.mjs";
10
10
  import "./chunk-R3PS4PCM.mjs";
11
- import "./chunk-YEHK2XY3.mjs";
11
+ import "./chunk-6RB3GKQP.mjs";
12
12
  export {
13
13
  Browser,
14
14
  ElementNotFoundError,
@@ -83,7 +83,8 @@ var BatchExecutor = class {
83
83
  await this.page.fill(step.selector, step.value, {
84
84
  timeout,
85
85
  optional,
86
- clear: step.clear ?? true
86
+ clear: step.clear ?? true,
87
+ blur: step.blur
87
88
  });
88
89
  return { selectorUsed: this.getUsedSelector(step.selector) };
89
90
  }
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-R3PS4PCM.mjs";
7
7
  import {
8
8
  BatchExecutor
9
- } from "./chunk-YEHK2XY3.mjs";
9
+ } from "./chunk-6RB3GKQP.mjs";
10
10
 
11
11
  // src/network/interceptor.ts
12
12
  var RequestInterceptor = class {
@@ -471,6 +471,13 @@ var Page = class {
471
471
  this.cdp = cdp;
472
472
  this.batchExecutor = new BatchExecutor(this);
473
473
  }
474
+ /**
475
+ * Get the underlying CDP client for advanced operations.
476
+ * Use with caution - prefer high-level Page methods when possible.
477
+ */
478
+ get cdpClient() {
479
+ return this.cdp;
480
+ }
474
481
  /**
475
482
  * Initialize the page (enable required CDP domains)
476
483
  */
@@ -621,7 +628,7 @@ var Page = class {
621
628
  * Fill an input field (clears first by default)
622
629
  */
623
630
  async fill(selector, value, options = {}) {
624
- const { clear = true } = options;
631
+ const { clear = true, blur = false } = options;
625
632
  return this.withStaleNodeRetry(async () => {
626
633
  const element = await this.findElement(selector, options);
627
634
  if (!element) {
@@ -635,7 +642,11 @@ var Page = class {
635
642
  const el = document.querySelector(${JSON.stringify(element.selector)});
636
643
  if (el) {
637
644
  el.value = '';
638
- el.dispatchEvent(new Event('input', { bubbles: true }));
645
+ el.dispatchEvent(new InputEvent('input', {
646
+ bubbles: true,
647
+ cancelable: true,
648
+ inputType: 'deleteContent'
649
+ }));
639
650
  }
640
651
  })()`
641
652
  );
@@ -645,11 +656,21 @@ var Page = class {
645
656
  `(() => {
646
657
  const el = document.querySelector(${JSON.stringify(element.selector)});
647
658
  if (el) {
648
- el.dispatchEvent(new Event('input', { bubbles: true }));
659
+ el.dispatchEvent(new InputEvent('input', {
660
+ bubbles: true,
661
+ cancelable: true,
662
+ inputType: 'insertText',
663
+ data: ${JSON.stringify(value)}
664
+ }));
649
665
  el.dispatchEvent(new Event('change', { bubbles: true }));
650
666
  }
651
667
  })()`
652
668
  );
669
+ if (blur) {
670
+ await this.evaluateInFrame(
671
+ `document.querySelector(${JSON.stringify(element.selector)})?.blur()`
672
+ );
673
+ }
653
674
  return true;
654
675
  });
655
676
  }