|
27 | 27 | ) |
28 | 28 | from .protocols import AsyncBrowserProtocol, BrowserProtocol |
29 | 29 | from .snapshot import snapshot, snapshot_async |
| 30 | +from .snapshot_diff import SnapshotDiff |
30 | 31 | from .trace_event_builder import TraceEventBuilder |
31 | 32 |
|
32 | 33 | if TYPE_CHECKING: |
@@ -135,6 +136,9 @@ def __init__( |
135 | 136 | # Step counter for tracing |
136 | 137 | self._step_count = 0 |
137 | 138 |
|
| 139 | + # Previous snapshot for diff detection |
| 140 | + self._previous_snapshot: Snapshot | None = None |
| 141 | + |
138 | 142 | def _compute_hash(self, text: str) -> str: |
139 | 143 | """Compute SHA256 hash of text.""" |
140 | 144 | return hashlib.sha256(text.encode("utf-8")).hexdigest() |
@@ -235,13 +239,31 @@ def act( # noqa: C901 |
235 | 239 | if snap.status != "success": |
236 | 240 | raise RuntimeError(f"Snapshot failed: {snap.error}") |
237 | 241 |
|
| 242 | + # Compute diff_status by comparing with previous snapshot |
| 243 | + elements_with_diff = SnapshotDiff.compute_diff_status(snap, self._previous_snapshot) |
| 244 | + |
| 245 | + # Create snapshot with diff_status populated |
| 246 | + snap_with_diff = Snapshot( |
| 247 | + status=snap.status, |
| 248 | + timestamp=snap.timestamp, |
| 249 | + url=snap.url, |
| 250 | + viewport=snap.viewport, |
| 251 | + elements=elements_with_diff, |
| 252 | + screenshot=snap.screenshot, |
| 253 | + screenshot_format=snap.screenshot_format, |
| 254 | + error=snap.error, |
| 255 | + ) |
| 256 | + |
| 257 | + # Update previous snapshot for next comparison |
| 258 | + self._previous_snapshot = snap |
| 259 | + |
238 | 260 | # Apply element filtering based on goal |
239 | | - filtered_elements = self.filter_elements(snap, goal) |
| 261 | + filtered_elements = self.filter_elements(snap_with_diff, goal) |
240 | 262 |
|
241 | 263 | # Emit snapshot trace event if tracer is enabled |
242 | 264 | if self.tracer: |
243 | | - # Build snapshot event data |
244 | | - snapshot_data = TraceEventBuilder.build_snapshot_event(snap) |
| 265 | + # Build snapshot event data (use snap_with_diff to include diff_status) |
| 266 | + snapshot_data = TraceEventBuilder.build_snapshot_event(snap_with_diff) |
245 | 267 |
|
246 | 268 | # Always include screenshot in trace event for studio viewer compatibility |
247 | 269 | # CloudTraceSink will extract and upload screenshots separately, then remove |
@@ -271,16 +293,16 @@ def act( # noqa: C901 |
271 | 293 | step_id=step_id, |
272 | 294 | ) |
273 | 295 |
|
274 | | - # Create filtered snapshot |
| 296 | + # Create filtered snapshot (use snap_with_diff to preserve metadata) |
275 | 297 | filtered_snap = Snapshot( |
276 | | - status=snap.status, |
277 | | - timestamp=snap.timestamp, |
278 | | - url=snap.url, |
279 | | - viewport=snap.viewport, |
| 298 | + status=snap_with_diff.status, |
| 299 | + timestamp=snap_with_diff.timestamp, |
| 300 | + url=snap_with_diff.url, |
| 301 | + viewport=snap_with_diff.viewport, |
280 | 302 | elements=filtered_elements, |
281 | | - screenshot=snap.screenshot, |
282 | | - screenshot_format=snap.screenshot_format, |
283 | | - error=snap.error, |
| 303 | + screenshot=snap_with_diff.screenshot, |
| 304 | + screenshot_format=snap_with_diff.screenshot_format, |
| 305 | + error=snap_with_diff.error, |
284 | 306 | ) |
285 | 307 |
|
286 | 308 | # 2. GROUND: Format elements for LLM context |
@@ -673,6 +695,9 @@ def __init__( |
673 | 695 | # Step counter for tracing |
674 | 696 | self._step_count = 0 |
675 | 697 |
|
| 698 | + # Previous snapshot for diff detection |
| 699 | + self._previous_snapshot: Snapshot | None = None |
| 700 | + |
676 | 701 | def _compute_hash(self, text: str) -> str: |
677 | 702 | """Compute SHA256 hash of text.""" |
678 | 703 | return hashlib.sha256(text.encode("utf-8")).hexdigest() |
@@ -773,13 +798,31 @@ async def act( # noqa: C901 |
773 | 798 | if snap.status != "success": |
774 | 799 | raise RuntimeError(f"Snapshot failed: {snap.error}") |
775 | 800 |
|
| 801 | + # Compute diff_status by comparing with previous snapshot |
| 802 | + elements_with_diff = SnapshotDiff.compute_diff_status(snap, self._previous_snapshot) |
| 803 | + |
| 804 | + # Create snapshot with diff_status populated |
| 805 | + snap_with_diff = Snapshot( |
| 806 | + status=snap.status, |
| 807 | + timestamp=snap.timestamp, |
| 808 | + url=snap.url, |
| 809 | + viewport=snap.viewport, |
| 810 | + elements=elements_with_diff, |
| 811 | + screenshot=snap.screenshot, |
| 812 | + screenshot_format=snap.screenshot_format, |
| 813 | + error=snap.error, |
| 814 | + ) |
| 815 | + |
| 816 | + # Update previous snapshot for next comparison |
| 817 | + self._previous_snapshot = snap |
| 818 | + |
776 | 819 | # Apply element filtering based on goal |
777 | | - filtered_elements = self.filter_elements(snap, goal) |
| 820 | + filtered_elements = self.filter_elements(snap_with_diff, goal) |
778 | 821 |
|
779 | 822 | # Emit snapshot trace event if tracer is enabled |
780 | 823 | if self.tracer: |
781 | | - # Build snapshot event data |
782 | | - snapshot_data = TraceEventBuilder.build_snapshot_event(snap) |
| 824 | + # Build snapshot event data (use snap_with_diff to include diff_status) |
| 825 | + snapshot_data = TraceEventBuilder.build_snapshot_event(snap_with_diff) |
783 | 826 |
|
784 | 827 | # Always include screenshot in trace event for studio viewer compatibility |
785 | 828 | # CloudTraceSink will extract and upload screenshots separately, then remove |
@@ -809,16 +852,16 @@ async def act( # noqa: C901 |
809 | 852 | step_id=step_id, |
810 | 853 | ) |
811 | 854 |
|
812 | | - # Create filtered snapshot |
| 855 | + # Create filtered snapshot (use snap_with_diff to preserve metadata) |
813 | 856 | filtered_snap = Snapshot( |
814 | | - status=snap.status, |
815 | | - timestamp=snap.timestamp, |
816 | | - url=snap.url, |
817 | | - viewport=snap.viewport, |
| 857 | + status=snap_with_diff.status, |
| 858 | + timestamp=snap_with_diff.timestamp, |
| 859 | + url=snap_with_diff.url, |
| 860 | + viewport=snap_with_diff.viewport, |
818 | 861 | elements=filtered_elements, |
819 | | - screenshot=snap.screenshot, |
820 | | - screenshot_format=snap.screenshot_format, |
821 | | - error=snap.error, |
| 862 | + screenshot=snap_with_diff.screenshot, |
| 863 | + screenshot_format=snap_with_diff.screenshot_format, |
| 864 | + error=snap_with_diff.error, |
822 | 865 | ) |
823 | 866 |
|
824 | 867 | # 2. GROUND: Format elements for LLM context |
|
0 commit comments