@@ -31,6 +31,10 @@ def __init__(self, license_key: Optional[str] = None, headless: bool = False):
3131 def start (self ) -> None :
3232 """Launch browser with extension loaded"""
3333 # Get extension path (sentience-chrome directory)
34+ # __file__ is sdk-python/sentience/browser.py, so:
35+ # parent = sdk-python/sentience/
36+ # parent.parent = sdk-python/
37+ # parent.parent.parent = Sentience/ (project root)
3438 repo_root = Path (__file__ ).parent .parent .parent
3539 extension_source = repo_root / "sentience-chrome"
3640
@@ -62,6 +66,11 @@ def start(self) -> None:
6266 if pkg_source .exists ():
6367 pkg_dest = os .path .join (temp_dir , "pkg" )
6468 shutil .copytree (pkg_source , pkg_dest , dirs_exist_ok = True )
69+ else :
70+ raise FileNotFoundError (
71+ f"WASM files not found at { pkg_source } . "
72+ "Build the extension first: cd sentience-chrome && ./build.sh"
73+ )
6574
6675 # Launch Playwright
6776 self .playwright = sync_playwright ().start ()
@@ -83,10 +92,28 @@ def start(self) -> None:
8392 else :
8493 self .page = self .context .new_page ()
8594
95+ # Navigate to a real page so extension can inject
96+ # Extension content scripts only run on actual pages (not about:blank)
97+ # Use a simple page that loads quickly
98+ self .page .goto ("https://example.com" , wait_until = "domcontentloaded" )
99+
100+ # Give extension time to initialize (WASM loading is async)
101+ self .page .wait_for_timeout (1000 )
102+
86103 # Wait for extension to load
87- self ._wait_for_extension ()
104+ if not self ._wait_for_extension ():
105+ # Extension might need more time, try waiting a bit longer
106+ self .page .wait_for_timeout (2000 )
107+ if not self ._wait_for_extension ():
108+ raise RuntimeError (
109+ "Extension failed to load after navigation. Make sure:\n "
110+ "1. Extension is built (cd sentience-chrome && ./build.sh)\n "
111+ "2. All files are present (manifest.json, content.js, injected_api.js, pkg/)\n "
112+ "3. Check browser console for errors\n "
113+ f"4. Extension path: { temp_dir } "
114+ )
88115
89- def _wait_for_extension (self , timeout : int = 10000 ) -> bool :
116+ def _wait_for_extension (self , timeout : int = 15000 ) -> bool :
90117 """Wait for window.sentience API to be available"""
91118 import time
92119 start = time .time ()
@@ -95,16 +122,29 @@ def _wait_for_extension(self, timeout: int = 10000) -> bool:
95122 try :
96123 result = self .page .evaluate ("""
97124 () => {
98- return typeof window.sentience !== 'undefined' &&
99- typeof window.sentience.snapshot === 'function';
125+ // Check if sentience API exists
126+ if (typeof window.sentience === 'undefined') {
127+ return { ready: false, reason: 'window.sentience not defined' };
128+ }
129+ // Check if snapshot function exists
130+ if (typeof window.sentience.snapshot !== 'function') {
131+ return { ready: false, reason: 'snapshot function not available' };
132+ }
133+ // Check if WASM module is loaded
134+ if (window.sentience_registry === undefined) {
135+ return { ready: false, reason: 'registry not initialized' };
136+ }
137+ return { ready: true };
100138 }
101139 """ )
102- if result :
140+
141+ if isinstance (result , dict ) and result .get ("ready" ):
103142 return True
104- except Exception :
143+ except Exception as e :
144+ # Continue waiting on errors
105145 pass
106146
107- time .sleep (0.1 )
147+ time .sleep (0.2 )
108148
109149 return False
110150
0 commit comments