Skip to content

Commit fc83a3e

Browse files
author
SentienceDEV
committed
add verification/assertion results to trace
1 parent 67729e4 commit fc83a3e

5 files changed

Lines changed: 50 additions & 0 deletions

File tree

sentience/agent.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,25 @@ def _compute_hash(self, text: str) -> str:
143143
"""Compute SHA256 hash of text."""
144144
return hashlib.sha256(text.encode("utf-8")).hexdigest()
145145

146+
def _best_effort_post_snapshot_digest(self, goal: str) -> str | None:
147+
"""
148+
Best-effort post-action snapshot digest for tracing.
149+
"""
150+
try:
151+
snap_opts = SnapshotOptions(
152+
limit=min(10, self.default_snapshot_limit),
153+
goal=f"{goal} (post)",
154+
)
155+
snap_opts.screenshot = False
156+
snap_opts.show_overlay = self.config.show_overlay if self.config else None
157+
post_snap = snapshot(self.browser, snap_opts)
158+
if post_snap.status != "success":
159+
return None
160+
digest_input = f"{post_snap.url}{post_snap.timestamp}"
161+
return f"sha256:{self._compute_hash(digest_input)}"
162+
except Exception:
163+
return None
164+
146165
def _get_element_bbox(self, element_id: int | None, snap: Snapshot) -> dict[str, float] | None:
147166
"""Get bounding box for an element from snapshot."""
148167
if element_id is None:
@@ -513,6 +532,10 @@ def act( # noqa: C901
513532
snapshot_event_data = TraceEventBuilder.build_snapshot_event(snap_with_diff)
514533
pre_elements = snapshot_event_data.get("elements", [])
515534

535+
post_snapshot_digest = (
536+
self._best_effort_post_snapshot_digest(goal) if self.tracer else None
537+
)
538+
516539
# Build complete step_end event
517540
step_end_data = TraceEventBuilder.build_step_end_event(
518541
step_id=step_id,
@@ -522,6 +545,7 @@ def act( # noqa: C901
522545
pre_url=pre_url,
523546
post_url=post_url,
524547
snapshot_digest=snapshot_digest,
548+
post_snapshot_digest=post_snapshot_digest,
525549
llm_data=llm_data,
526550
exec_data=exec_data,
527551
verify_data=verify_data,
@@ -601,6 +625,7 @@ def act( # noqa: C901
601625
pre_url=_step_pre_url,
602626
post_url=post_url,
603627
snapshot_digest=snapshot_digest,
628+
post_snapshot_digest=None,
604629
llm_data=llm_data,
605630
exec_data=exec_data,
606631
verify_data=None,
@@ -1155,6 +1180,10 @@ async def act( # noqa: C901
11551180
snapshot_event_data = TraceEventBuilder.build_snapshot_event(snap_with_diff)
11561181
pre_elements = snapshot_event_data.get("elements", [])
11571182

1183+
post_snapshot_digest = (
1184+
self._best_effort_post_snapshot_digest(goal) if self.tracer else None
1185+
)
1186+
11581187
# Build complete step_end event
11591188
step_end_data = TraceEventBuilder.build_step_end_event(
11601189
step_id=step_id,
@@ -1164,6 +1193,7 @@ async def act( # noqa: C901
11641193
pre_url=pre_url,
11651194
post_url=post_url,
11661195
snapshot_digest=snapshot_digest,
1196+
post_snapshot_digest=post_snapshot_digest,
11671197
llm_data=llm_data,
11681198
exec_data=exec_data,
11691199
verify_data=verify_data,
@@ -1243,6 +1273,7 @@ async def act( # noqa: C901
12431273
pre_url=_step_pre_url,
12441274
post_url=post_url,
12451275
snapshot_digest=snapshot_digest,
1276+
post_snapshot_digest=None,
12461277
llm_data=llm_data,
12471278
exec_data=exec_data,
12481279
verify_data=None,

sentience/integrations/langchain/core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ async def _trace(self, tool_name: str, exec_coro, exec_meta: dict[str, Any]):
113113
pre_url=pre_url or "",
114114
post_url=post_url or "",
115115
snapshot_digest=None,
116+
post_snapshot_digest=None,
116117
llm_data={},
117118
exec_data=exec_data,
118119
verify_data=verify_data,

sentience/integrations/pydanticai/toolset.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ async def _trace_tool_call(ctx: Any, tool_name: str, exec_coro, exec_meta: dict[
126126
pre_url=pre_url or "",
127127
post_url=post_url or "",
128128
snapshot_digest=None,
129+
post_snapshot_digest=None,
129130
llm_data={},
130131
exec_data=exec_data,
131132
verify_data=verify_data,

sentience/trace_event_builder.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def build_step_end_event(
9494
verify_data: dict[str, Any],
9595
pre_elements: list[dict[str, Any]] | None = None,
9696
assertions: list[dict[str, Any]] | None = None,
97+
post_snapshot_digest: str | None = None,
9798
) -> dict[str, Any]:
9899
"""
99100
Build step_end trace event data.
@@ -106,6 +107,7 @@ def build_step_end_event(
106107
pre_url: URL before action execution
107108
post_url: URL after action execution
108109
snapshot_digest: Digest of snapshot before action
110+
post_snapshot_digest: Digest of snapshot after action (optional)
109111
llm_data: LLM interaction data
110112
exec_data: Action execution data
111113
verify_data: Verification data
@@ -153,6 +155,11 @@ def build_step_end_event(
153155
"exec": exec_data,
154156
"post": {
155157
"url": post_url,
158+
**(
159+
{"snapshot_digest": post_snapshot_digest}
160+
if post_snapshot_digest
161+
else {}
162+
),
156163
},
157164
"verify": final_verify_data,
158165
}

sentience/visual_agent.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,10 @@ async def act(
11011101
},
11021102
}
11031103

1104+
post_snapshot_digest = (
1105+
self._best_effort_post_snapshot_digest(goal) if self.tracer else None
1106+
)
1107+
11041108
# Build complete step_end event
11051109
step_end_data = TraceEventBuilder.build_step_end_event(
11061110
step_id=step_id,
@@ -1110,6 +1114,7 @@ async def act(
11101114
pre_url=pre_url,
11111115
post_url=post_url or pre_url,
11121116
snapshot_digest=snapshot_digest,
1117+
post_snapshot_digest=post_snapshot_digest,
11131118
llm_data={
11141119
"response_text": llm_response_text,
11151120
"response_hash": f"sha256:{self._compute_hash(llm_response_text)}",
@@ -2011,6 +2016,10 @@ def act(
20112016
},
20122017
}
20132018

2019+
post_snapshot_digest = (
2020+
self._best_effort_post_snapshot_digest(goal) if self.tracer else None
2021+
)
2022+
20142023
# Build complete step_end event
20152024
step_end_data = TraceEventBuilder.build_step_end_event(
20162025
step_id=step_id,
@@ -2020,6 +2029,7 @@ def act(
20202029
pre_url=pre_url,
20212030
post_url=post_url or pre_url,
20222031
snapshot_digest=snapshot_digest,
2032+
post_snapshot_digest=post_snapshot_digest,
20232033
llm_data={
20242034
"response_text": llm_response_text,
20252035
"response_hash": f"sha256:{self._compute_hash(llm_response_text)}",

0 commit comments

Comments
 (0)