@olib-ai/owl-browser-sdk 1.2.1 → 1.2.3

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
@@ -267,6 +267,126 @@ await page.type('640x400', 'text here'); // Type at position
267
267
  await page.highlight('login button');
268
268
  ```
269
269
 
270
+ #### Advanced Interactions
271
+
272
+ ```typescript
273
+ // Hover over elements (for tooltips, dropdowns)
274
+ await page.hover('menu item');
275
+ await page.hover('.dropdown-trigger', 500); // hover for 500ms
276
+
277
+ // Double-click
278
+ await page.doubleClick('editable cell');
279
+
280
+ // Right-click (context menu)
281
+ await page.rightClick('file item');
282
+
283
+ // Clear input before typing
284
+ await page.clearInput('search box');
285
+ await page.type('search box', 'new search');
286
+
287
+ // Focus and blur (trigger validation)
288
+ await page.focus('email input');
289
+ await page.blur('email input');
290
+
291
+ // Select all text in input
292
+ await page.selectAll('text area');
293
+
294
+ // Keyboard combinations
295
+ await page.keyboardCombo('a', ['ctrl']); // Ctrl+A (select all)
296
+ await page.keyboardCombo('c', ['ctrl']); // Ctrl+C (copy)
297
+ await page.keyboardCombo('v', ['ctrl']); // Ctrl+V (paste)
298
+ await page.keyboardCombo('z', ['ctrl']); // Ctrl+Z (undo)
299
+ await page.keyboardCombo('s', ['ctrl', 'shift']); // Ctrl+Shift+S
300
+
301
+ // Human-like mouse movement (anti-bot detection)
302
+ await page.mouseMove(100, 100, 500, 300); // Move from (100,100) to (500,300)
303
+ await page.mouseMove(100, 100, 500, 300, 50); // With 50 intermediate steps
304
+ await page.mouseMove(100, 100, 500, 300, 0, [ // With stop points
305
+ [200, 150],
306
+ [350, 250]
307
+ ]);
308
+ ```
309
+
310
+ #### Element State Checks
311
+
312
+ ```typescript
313
+ // Check visibility
314
+ if (await page.isVisible('error message')) {
315
+ console.log('Error displayed');
316
+ }
317
+
318
+ // Check if enabled/disabled
319
+ if (await page.isEnabled('submit button')) {
320
+ await page.click('submit button');
321
+ }
322
+
323
+ // Check checkbox/radio state
324
+ const isChecked = await page.isChecked('remember me checkbox');
325
+
326
+ // Get element attribute
327
+ const href = await page.getAttribute('a.link', 'href');
328
+ const placeholder = await page.getAttribute('input', 'placeholder');
329
+
330
+ // Get element position and size
331
+ const box = await page.getBoundingBox('header');
332
+ console.log(`Position: ${box.x}, ${box.y}`);
333
+ console.log(`Size: ${box.width} x ${box.height}`);
334
+ ```
335
+
336
+ #### File Upload
337
+
338
+ ```typescript
339
+ // Upload single file
340
+ await page.uploadFile('input[type="file"]', ['/path/to/document.pdf']);
341
+
342
+ // Upload multiple files
343
+ await page.uploadFile('file input', [
344
+ '/path/to/image1.jpg',
345
+ '/path/to/image2.jpg'
346
+ ]);
347
+ ```
348
+
349
+ #### Frame/Iframe Handling
350
+
351
+ ```typescript
352
+ // List all frames on the page
353
+ const frames = await page.listFrames();
354
+ for (const frame of frames) {
355
+ console.log(`Frame: ${frame.name || frame.id} - ${frame.url}`);
356
+ }
357
+
358
+ // Switch to iframe by selector
359
+ await page.switchToFrame('#payment-iframe');
360
+
361
+ // Or by frame name/id
362
+ await page.switchToFrame('checkout-frame');
363
+
364
+ // Interact with elements inside iframe
365
+ await page.type('card number input', '4111111111111111');
366
+ await page.click('submit payment');
367
+
368
+ // Switch back to main frame
369
+ await page.switchToMainFrame();
370
+ ```
371
+
372
+ #### JavaScript Evaluation
373
+
374
+ ```typescript
375
+ // Execute JavaScript in page context
376
+ const title = await page.evaluate<string>('document.title');
377
+
378
+ // With arguments
379
+ const text = await page.evaluate<string>(
380
+ '(selector) => document.querySelector(selector)?.textContent',
381
+ ['h1']
382
+ );
383
+
384
+ // Return complex objects
385
+ const metrics = await page.evaluate<{width: number, height: number}>(
386
+ '() => ({ width: window.innerWidth, height: window.innerHeight })'
387
+ );
388
+ ```
389
+
270
390
  #### Content Extraction
271
391
 
272
392
  ```typescript
@@ -573,6 +693,116 @@ const viewport: Viewport = await page.getViewport();
573
693
  | Built-in Ad Blocking | ✅ 72 domains | ❌ Manual setup |
574
694
  | Maintenance Overhead | ✅ Low (AI handles changes) | ⚠️ High (selectors break) |
575
695
 
696
+ ### Network Interception
697
+
698
+ Block, mock, or redirect network requests:
699
+
700
+ ```typescript
701
+ // Block ads
702
+ const ruleId = await page.addNetworkRule({
703
+ urlPattern: 'https://ads.example.com/*',
704
+ action: 'block'
705
+ });
706
+
707
+ // Mock API response
708
+ await page.addNetworkRule({
709
+ urlPattern: 'https://api.example.com/data',
710
+ action: 'mock',
711
+ mockBody: '{"status": "ok"}',
712
+ mockStatus: 200,
713
+ mockContentType: 'application/json'
714
+ });
715
+
716
+ // Redirect requests
717
+ await page.addNetworkRule({
718
+ urlPattern: 'https://old-api.example.com/*',
719
+ action: 'redirect',
720
+ redirectUrl: 'https://new-api.example.com/'
721
+ });
722
+
723
+ // Enable interception
724
+ await page.setNetworkInterception(true);
725
+
726
+ // Get network log
727
+ const log = await page.getNetworkLog();
728
+
729
+ // Remove rule
730
+ await page.removeNetworkRule(ruleId);
731
+ ```
732
+
733
+ ### File Downloads
734
+
735
+ Handle file downloads:
736
+
737
+ ```typescript
738
+ // Set download directory
739
+ await page.setDownloadPath('/tmp/downloads');
740
+
741
+ // Click a download link
742
+ await page.click('a[download]');
743
+
744
+ // Wait for download to complete
745
+ const download = await page.waitForDownload();
746
+ console.log(`Downloaded: ${download.filename} to ${download.path}`);
747
+
748
+ // Or get all downloads
749
+ const downloads = await page.getDownloads();
750
+
751
+ // Cancel a download
752
+ await page.cancelDownload(download.id);
753
+ ```
754
+
755
+ ### Dialog Handling
756
+
757
+ Handle JavaScript dialogs (alert, confirm, prompt):
758
+
759
+ ```typescript
760
+ // Auto-accept alerts
761
+ await page.setDialogAction('alert', 'accept');
762
+
763
+ // Auto-respond to prompts
764
+ await page.setDialogAction('prompt', 'accept_with_text', 'My answer');
765
+
766
+ // Dismiss confirms
767
+ await page.setDialogAction('confirm', 'dismiss');
768
+
769
+ // Or handle manually
770
+ const dialog = await page.waitForDialog();
771
+ console.log(`Dialog message: ${dialog.message}`);
772
+ await page.handleDialog(dialog.id, true, 'response text');
773
+ ```
774
+
775
+ ### Multi-Tab Management
776
+
777
+ Work with multiple tabs:
778
+
779
+ ```typescript
780
+ // Create new tab
781
+ const tab = await page.newTab('https://google.com');
782
+ console.log(`Tab ID: ${tab.tabId}`);
783
+
784
+ // List all tabs
785
+ const tabs = await page.getTabs();
786
+
787
+ // Switch to a tab
788
+ await page.switchTab(tabs[0].tabId);
789
+
790
+ // Get active tab
791
+ const active = await page.getActiveTab();
792
+
793
+ // Get tab count
794
+ const count = await page.getTabCount();
795
+
796
+ // Close a tab
797
+ await page.closeTab(tab.tabId);
798
+
799
+ // Configure popup handling
800
+ await page.setPopupPolicy('block'); // 'allow', 'block', 'new_tab', 'background'
801
+
802
+ // Get blocked popups
803
+ const blocked = await page.getBlockedPopups();
804
+ ```
805
+
576
806
  ## Advanced Features
577
807
 
578
808
  ### Semantic Element Matching
@@ -622,7 +852,12 @@ import {
622
852
  RateLimitError,
623
853
  IPBlockedError,
624
854
  LicenseError,
625
- BrowserInitializationError
855
+ BrowserInitializationError,
856
+ ActionError,
857
+ ActionStatus,
858
+ ElementNotFoundError,
859
+ NavigationError,
860
+ FirewallError
626
861
  } from '@olib-ai/owl-browser-sdk';
627
862
 
628
863
  async function withErrorHandling() {
@@ -641,9 +876,34 @@ async function withErrorHandling() {
641
876
  await page.goto('https://example.com');
642
877
 
643
878
  // Your automation code...
879
+ await page.click('non-existent button');
644
880
 
645
881
  } catch (error) {
646
- if (error instanceof AuthenticationError) {
882
+ if (error instanceof ElementNotFoundError) {
883
+ // Element was not found on the page
884
+ console.error('Element not found:', error.message);
885
+ } else if (error instanceof NavigationError) {
886
+ // Navigation failed (timeout, page load error, etc.)
887
+ console.error('Navigation failed:', error.message);
888
+ } else if (error instanceof ActionError) {
889
+ // Generic action error with detailed status
890
+ console.error('Action failed:', error.message);
891
+ console.error('Status:', error.status);
892
+ console.error('Selector:', error.selector);
893
+ // Check specific error types
894
+ if (error.isElementNotFound()) {
895
+ console.error('Could not find element');
896
+ } else if (error.isNavigationError()) {
897
+ console.error('Navigation issue');
898
+ } else if (error.isTimeout()) {
899
+ console.error('Operation timed out');
900
+ }
901
+ } else if (error instanceof FirewallError) {
902
+ // Web firewall/bot protection detected
903
+ console.error('Firewall detected:', error.provider);
904
+ console.error('Challenge type:', error.challengeType);
905
+ console.error('URL:', error.url);
906
+ } else if (error instanceof AuthenticationError) {
647
907
  // 401 - Invalid or expired token
648
908
  console.error('Auth failed:', error.message);
649
909
  console.error('Reason:', error.reason);
@@ -665,17 +925,92 @@ async function withErrorHandling() {
665
925
  }
666
926
  ```
667
927
 
928
+ ### Action Result Validation
929
+
930
+ The browser returns structured `ActionResult` responses for browser actions, providing detailed information about success or failure:
931
+
932
+ ```typescript
933
+ import {
934
+ ActionStatus,
935
+ ActionResult,
936
+ ActionError,
937
+ isActionResult,
938
+ throwIfActionFailed
939
+ } from '@olib-ai/owl-browser-sdk';
940
+
941
+ // ActionStatus enum values
942
+ ActionStatus.OK // Action succeeded
943
+ ActionStatus.ELEMENT_NOT_FOUND // Element not found on page
944
+ ActionStatus.ELEMENT_NOT_VISIBLE // Element exists but not visible
945
+ ActionStatus.ELEMENT_NOT_INTERACTABLE // Element not interactable
946
+ ActionStatus.NAVIGATION_FAILED // Navigation failed
947
+ ActionStatus.NAVIGATION_TIMEOUT // Navigation timed out
948
+ ActionStatus.PAGE_LOAD_ERROR // Page failed to load
949
+ ActionStatus.FIREWALL_DETECTED // Web firewall/bot protection detected
950
+ ActionStatus.CAPTCHA_DETECTED // CAPTCHA challenge detected
951
+ ActionStatus.CLICK_FAILED // Click action failed
952
+ ActionStatus.TYPE_FAILED // Type action failed
953
+ ActionStatus.CONTEXT_NOT_FOUND // Browser context not found
954
+ ActionStatus.INVALID_SELECTOR // Invalid selector provided
955
+ ActionStatus.TIMEOUT // Operation timed out
956
+
957
+ // ActionResult interface
958
+ interface ActionResult {
959
+ success: boolean;
960
+ status: ActionStatus | string;
961
+ message: string;
962
+ selector?: string; // The selector that failed (for element errors)
963
+ url?: string; // URL involved (for navigation errors)
964
+ http_status?: number; // HTTP status code (for navigation)
965
+ error_code?: string; // Browser error code
966
+ element_count?: number; // Elements found (for multiple_elements error)
967
+ }
968
+
969
+ // Helper functions
970
+ if (isActionResult(result)) {
971
+ if (!result.success) {
972
+ throwIfActionFailed(result); // Throws appropriate exception
973
+ }
974
+ }
975
+ ```
976
+
668
977
  ### Exception Types
669
978
 
670
979
  | Exception | HTTP Code | Description |
671
980
  |-----------|-----------|-------------|
981
+ | `ActionError` | - | Browser action failed with status code and details |
982
+ | `ElementNotFoundError` | - | Element not found on page |
983
+ | `NavigationError` | - | Navigation failed (timeout, load error) |
984
+ | `FirewallError` | - | Web firewall/bot protection detected (Cloudflare, Akamai, etc.) |
985
+ | `ContextError` | - | Browser context not found |
672
986
  | `AuthenticationError` | 401 | Invalid/expired token or JWT signature mismatch |
673
987
  | `RateLimitError` | 429 | Too many requests, includes `retryAfter` in seconds |
674
988
  | `IPBlockedError` | 403 | Client IP not in whitelist |
675
989
  | `LicenseError` | 503 | Browser license validation failed |
676
990
  | `BrowserInitializationError` | - | Failed to start/connect to browser |
677
991
  | `CommandTimeoutError` | - | Operation timed out |
678
- | `ElementNotFoundError` | - | Element not found on page |
992
+
993
+ ### FirewallError Properties
994
+
995
+ | Property | Type | Description |
996
+ |----------|------|-------------|
997
+ | `url` | `string` | The URL where the firewall was detected |
998
+ | `provider` | `string` | Firewall provider (Cloudflare, Akamai, Imperva, etc.) |
999
+ | `challengeType` | `string?` | Type of challenge (JS Challenge, CAPTCHA, etc.) |
1000
+
1001
+ The browser automatically detects web firewalls including Cloudflare, Akamai, Imperva, PerimeterX, DataDome, and AWS WAF.
1002
+
1003
+ ### ActionError Properties
1004
+
1005
+ | Property | Type | Description |
1006
+ |----------|------|-------------|
1007
+ | `status` | `ActionStatus` | Status code (e.g., `element_not_found`) |
1008
+ | `message` | `string` | Human-readable error message |
1009
+ | `selector` | `string?` | The selector that failed |
1010
+ | `url` | `string?` | URL involved in navigation errors |
1011
+ | `httpStatus` | `number?` | HTTP status code |
1012
+ | `errorCode` | `string?` | Browser error code |
1013
+ | `elementCount` | `number?` | Number of elements found |
679
1014
 
680
1015
  ## Performance Tips
681
1016
 
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
@@ -350,7 +350,31 @@ class LocalConnection {
350
350
  pending.reject(new Error(response.error));
351
351
  }
352
352
  else {
353
- pending.resolve(response.result);
353
+ // Check for ActionResult format (has success property)
354
+ // ActionResult: {"success": bool, "status": "code", "message": "...", ...}
355
+ const result = response.result;
356
+ if (result && typeof result === 'object' && 'success' in result) {
357
+ if (!result.success) {
358
+ // Create detailed error with status code and message
359
+ const errorMsg = result.message || `Action failed: ${result.status || 'unknown'}`;
360
+ const error = new Error(errorMsg);
361
+ error.status = result.status;
362
+ error.selector = result.selector;
363
+ error.url = result.url;
364
+ error.httpStatus = result.http_status;
365
+ error.errorCode = result.error_code;
366
+ error.elementCount = result.element_count;
367
+ pending.reject(error);
368
+ }
369
+ else {
370
+ // Success - resolve with the full result for detailed info
371
+ pending.resolve(result);
372
+ }
373
+ }
374
+ else {
375
+ // Legacy format - resolve as-is
376
+ pending.resolve(result);
377
+ }
354
378
  }
355
379
  }
356
380
  }
@@ -714,6 +738,11 @@ class HttpConnection {
714
738
  // Homepage is a local-only feature, return empty for HTTP mode
715
739
  return '';
716
740
  }
741
+ if (method === 'waitForNavigation') {
742
+ // waitForNavigation is not needed in HTTP mode - browser_navigate is synchronous
743
+ // Just return success
744
+ return;
745
+ }
717
746
  const tool = this.mapMethodToTool(method);
718
747
  const mappedParams = this.mapParams(method, params);
719
748
  if (this.verbose) {
@@ -725,17 +754,31 @@ class HttpConnection {
725
754
  if (!response.success) {
726
755
  throw new Error(response.error || 'Unknown error');
727
756
  }
757
+ // Unwrap nested IPC response format
758
+ // HTTP server wraps browser IPC responses: {success: true, result: {id: N, result: value}}
759
+ // We need to extract the inner 'result' value
760
+ let result = response.result;
761
+ if (result && typeof result === 'object' && 'id' in result && 'result' in result) {
762
+ result = result.result;
763
+ }
728
764
  // Handle special return value transformations
765
+ if (method === 'createContext') {
766
+ // createContext result is the context ID string (e.g., 'ctx_000001')
767
+ return result;
768
+ }
729
769
  if (method === 'getCurrentURL' || method === 'getPageTitle') {
730
770
  // These methods call getPageInfo but need specific fields
731
- if (method === 'getCurrentURL') {
732
- return response.result?.url || response.result;
733
- }
734
- if (method === 'getPageTitle') {
735
- return response.result?.title || response.result;
771
+ if (typeof result === 'object' && result !== null) {
772
+ if (method === 'getCurrentURL') {
773
+ return result.url || result;
774
+ }
775
+ if (method === 'getPageTitle') {
776
+ return result.title || result;
777
+ }
736
778
  }
779
+ return result;
737
780
  }
738
- return response.result;
781
+ return result;
739
782
  }, this.retryConfig, (error, attempt, delayMs) => {
740
783
  if (this.verbose) {
741
784
  console.error(`[HTTP] Retry ${attempt}/${this.retryConfig.maxRetries} for ${tool} after ${delayMs}ms: ${error.message}`);