@@ -250,6 +250,9 @@ def _snapshot_via_extension(
250250 if options .save_trace :
251251 _save_trace_to_file (result .get ("raw_elements" , []), options .trace_path )
252252
253+ # Validate and parse with Pydantic
254+ snapshot_obj = Snapshot (** result )
255+
253256 # Show visual overlay if requested
254257 if options .show_overlay :
255258 raw_elements = result .get ("raw_elements" , [])
@@ -265,8 +268,29 @@ def _snapshot_via_extension(
265268 raw_elements ,
266269 )
267270
268- # Validate and parse with Pydantic
269- snapshot_obj = Snapshot (** result )
271+ # Show grid overlay if requested
272+ if options .show_grid :
273+ # Get all grids (don't filter by grid_id here - we want to show all but highlight the target)
274+ grids = snapshot_obj .get_grid_bounds (grid_id = None )
275+ if grids :
276+ # Convert GridInfo to dict for JavaScript
277+ grid_dicts = [grid .model_dump () for grid in grids ]
278+ # Pass grid_id as targetGridId to highlight it in red
279+ target_grid_id = options .grid_id if options .grid_id is not None else None
280+ browser .page .evaluate (
281+ """
282+ (grids, targetGridId) => {
283+ if (window.sentience && window.sentience.showGrid) {
284+ window.sentience.showGrid(grids, targetGridId);
285+ } else {
286+ console.warn('[SDK] showGrid not available in extension');
287+ }
288+ }
289+ """ ,
290+ grid_dicts ,
291+ target_grid_id ,
292+ )
293+
270294 return snapshot_obj
271295
272296
@@ -308,6 +332,9 @@ def _snapshot_via_api(
308332 # Merge API result with local data (screenshot, etc.)
309333 snapshot_data = _merge_api_result_with_local (api_result , raw_result )
310334
335+ # Create snapshot object
336+ snapshot_obj = Snapshot (** snapshot_data )
337+
311338 # Show visual overlay if requested (use API-ranked elements)
312339 if options .show_overlay :
313340 elements = api_result .get ("elements" , [])
@@ -323,7 +350,29 @@ def _snapshot_via_api(
323350 elements ,
324351 )
325352
326- return Snapshot (** snapshot_data )
353+ # Show grid overlay if requested
354+ if options .show_grid :
355+ # Get all grids (don't filter by grid_id here - we want to show all but highlight the target)
356+ grids = snapshot_obj .get_grid_bounds (grid_id = None )
357+ if grids :
358+ grid_dicts = [grid .model_dump () for grid in grids ]
359+ # Pass grid_id as targetGridId to highlight it in red
360+ target_grid_id = options .grid_id if options .grid_id is not None else None
361+ browser .page .evaluate (
362+ """
363+ (grids, targetGridId) => {
364+ if (window.sentience && window.sentience.showGrid) {
365+ window.sentience.showGrid(grids, targetGridId);
366+ } else {
367+ console.warn('[SDK] showGrid not available in extension');
368+ }
369+ }
370+ """ ,
371+ grid_dicts ,
372+ target_grid_id ,
373+ )
374+
375+ return snapshot_obj
327376 except requests .exceptions .RequestException as e :
328377 raise RuntimeError (f"API request failed: { e } " ) from e
329378
@@ -440,6 +489,18 @@ async def _snapshot_via_extension_async(
440489 if options .save_trace :
441490 _save_trace_to_file (result .get ("raw_elements" , []), options .trace_path )
442491
492+ # Extract screenshot_format from data URL if not provided by extension
493+ if result .get ("screenshot" ) and not result .get ("screenshot_format" ):
494+ screenshot_data_url = result .get ("screenshot" , "" )
495+ if screenshot_data_url .startswith ("data:image/" ):
496+ # Extract format from "data:image/jpeg;base64,..." or "data:image/png;base64,..."
497+ format_match = screenshot_data_url .split (";" )[0 ].split ("/" )[- 1 ]
498+ if format_match in ["jpeg" , "jpg" , "png" ]:
499+ result ["screenshot_format" ] = "jpeg" if format_match in ["jpeg" , "jpg" ] else "png"
500+
501+ # Validate and parse with Pydantic
502+ snapshot_obj = Snapshot (** result )
503+
443504 # Show visual overlay if requested
444505 if options .show_overlay :
445506 raw_elements = result .get ("raw_elements" , [])
@@ -455,17 +516,28 @@ async def _snapshot_via_extension_async(
455516 raw_elements ,
456517 )
457518
458- # Extract screenshot_format from data URL if not provided by extension
459- if result .get ("screenshot" ) and not result .get ("screenshot_format" ):
460- screenshot_data_url = result .get ("screenshot" , "" )
461- if screenshot_data_url .startswith ("data:image/" ):
462- # Extract format from "data:image/jpeg;base64,..." or "data:image/png;base64,..."
463- format_match = screenshot_data_url .split (";" )[0 ].split ("/" )[- 1 ]
464- if format_match in ["jpeg" , "jpg" , "png" ]:
465- result ["screenshot_format" ] = "jpeg" if format_match in ["jpeg" , "jpg" ] else "png"
519+ # Show grid overlay if requested
520+ if options .show_grid :
521+ # Get all grids (don't filter by grid_id here - we want to show all but highlight the target)
522+ grids = snapshot_obj .get_grid_bounds (grid_id = None )
523+ if grids :
524+ grid_dicts = [grid .model_dump () for grid in grids ]
525+ # Pass grid_id as targetGridId to highlight it in red
526+ target_grid_id = options .grid_id if options .grid_id is not None else None
527+ await browser .page .evaluate (
528+ """
529+ (grids, targetGridId) => {
530+ if (window.sentience && window.sentience.showGrid) {
531+ window.sentience.showGrid(grids, targetGridId);
532+ } else {
533+ console.warn('[SDK] showGrid not available in extension');
534+ }
535+ }
536+ """ ,
537+ grid_dicts ,
538+ target_grid_id ,
539+ )
466540
467- # Validate and parse with Pydantic
468- snapshot_obj = Snapshot (** result )
469541 return snapshot_obj
470542
471543
@@ -584,6 +656,9 @@ async def _snapshot_via_api_async(
584656 "error" : api_result .get ("error" ),
585657 }
586658
659+ # Create snapshot object
660+ snapshot_obj = Snapshot (** snapshot_data )
661+
587662 # Show visual overlay if requested
588663 if options .show_overlay :
589664 elements = api_result .get ("elements" , [])
@@ -599,7 +674,29 @@ async def _snapshot_via_api_async(
599674 elements ,
600675 )
601676
602- return Snapshot (** snapshot_data )
677+ # Show grid overlay if requested
678+ if options .show_grid :
679+ # Get all grids (don't filter by grid_id here - we want to show all but highlight the target)
680+ grids = snapshot_obj .get_grid_bounds (grid_id = None )
681+ if grids :
682+ grid_dicts = [grid .model_dump () for grid in grids ]
683+ # Pass grid_id as targetGridId to highlight it in red
684+ target_grid_id = options .grid_id if options .grid_id is not None else None
685+ await browser .page .evaluate (
686+ """
687+ (grids, targetGridId) => {
688+ if (window.sentience && window.sentience.showGrid) {
689+ window.sentience.showGrid(grids, targetGridId);
690+ } else {
691+ console.warn('[SDK] showGrid not available in extension');
692+ }
693+ }
694+ """ ,
695+ grid_dicts ,
696+ target_grid_id ,
697+ )
698+
699+ return snapshot_obj
603700 except ImportError :
604701 # Fallback to requests if httpx not available (shouldn't happen in async context)
605702 raise RuntimeError (
0 commit comments