|
2 | 2 | Snapshot functionality - calls window.sentience.snapshot() or server-side API |
3 | 3 | """ |
4 | 4 |
|
5 | | -import json |
6 | | -from typing import Any, Dict, Optional |
| 5 | +from typing import Any |
7 | 6 |
|
8 | 7 | import requests |
9 | 8 |
|
@@ -53,6 +52,31 @@ def _snapshot_via_extension( |
53 | 52 | if not browser.page: |
54 | 53 | raise RuntimeError("Browser not started. Call browser.start() first.") |
55 | 54 |
|
| 55 | + # CRITICAL: Wait for extension injection to complete (CSP-resistant architecture) |
| 56 | + # The new architecture loads injected_api.js asynchronously, so window.sentience |
| 57 | + # may not be immediately available after page load |
| 58 | + try: |
| 59 | + browser.page.wait_for_function( |
| 60 | + "typeof window.sentience !== 'undefined'", timeout=5000 # 5 second timeout |
| 61 | + ) |
| 62 | + except Exception as e: |
| 63 | + # Gather diagnostics if wait fails |
| 64 | + try: |
| 65 | + diag = browser.page.evaluate( |
| 66 | + """() => ({ |
| 67 | + sentience_defined: typeof window.sentience !== 'undefined', |
| 68 | + extension_id: document.documentElement.dataset.sentienceExtensionId || 'not set', |
| 69 | + url: window.location.href |
| 70 | + })""" |
| 71 | + ) |
| 72 | + except Exception: |
| 73 | + diag = {"error": "Could not gather diagnostics"} |
| 74 | + |
| 75 | + raise RuntimeError( |
| 76 | + f"Sentience extension failed to inject window.sentience API. " |
| 77 | + f"Is the extension loaded? Diagnostics: {diag}" |
| 78 | + ) from e |
| 79 | + |
56 | 80 | # Build options |
57 | 81 | options: dict[str, Any] = {} |
58 | 82 | if screenshot is not None: |
@@ -93,6 +117,15 @@ def _snapshot_via_api( |
93 | 117 | if not browser.api_url: |
94 | 118 | raise ValueError("API URL required for server-side processing") |
95 | 119 |
|
| 120 | + # CRITICAL: Wait for extension injection to complete (CSP-resistant architecture) |
| 121 | + # Even for API mode, we need the extension to collect raw data locally |
| 122 | + try: |
| 123 | + browser.page.wait_for_function("typeof window.sentience !== 'undefined'", timeout=5000) |
| 124 | + except Exception as e: |
| 125 | + raise RuntimeError( |
| 126 | + "Sentience extension failed to inject. Cannot collect raw data for API processing." |
| 127 | + ) from e |
| 128 | + |
96 | 129 | # Step 1: Get raw data from local extension (always happens locally) |
97 | 130 | raw_options: dict[str, Any] = {} |
98 | 131 | if screenshot is not None: |
|
0 commit comments