-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdebugger.py
More file actions
74 lines (61 loc) · 2.43 KB
/
debugger.py
File metadata and controls
74 lines (61 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from __future__ import annotations
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING, Any
from .agent_runtime import AgentRuntime
from .models import SnapshotOptions
from .tools import ToolRegistry
if TYPE_CHECKING: # pragma: no cover - type hints only
from playwright.async_api import Page
from .tracing import Tracer
else: # pragma: no cover - avoid optional runtime imports
Page = Any # type: ignore
Tracer = Any # type: ignore
class SentienceDebugger:
"""
Verifier-only sidecar wrapper around AgentRuntime.
"""
def __init__(self, runtime: AgentRuntime, *, auto_step: bool = True) -> None:
self.runtime = runtime
self._step_open = False
self._auto_step = bool(auto_step)
@classmethod
def attach(
cls,
page: Page,
tracer: Tracer,
snapshot_options: SnapshotOptions | None = None,
sentience_api_key: str | None = None,
tool_registry: ToolRegistry | None = None,
) -> SentienceDebugger:
runtime = AgentRuntime.from_playwright_page(
page=page,
tracer=tracer,
snapshot_options=snapshot_options,
sentience_api_key=sentience_api_key,
tool_registry=tool_registry,
)
return cls(runtime=runtime)
def begin_step(self, goal: str, step_index: int | None = None) -> str:
self._step_open = True
return self.runtime.begin_step(goal, step_index=step_index)
async def end_step(self, **kwargs: Any) -> dict[str, Any]:
self._step_open = False
return await self.runtime.emit_step_end(**kwargs)
@asynccontextmanager
async def step(self, goal: str, step_index: int | None = None) -> AsyncIterator[None]:
self.begin_step(goal, step_index=step_index)
try:
yield
finally:
await self.end_step()
async def snapshot(self, **kwargs: Any):
return await self.runtime.snapshot(**kwargs)
def check(self, predicate, label: str, required: bool = False):
if not self._step_open:
if not self._auto_step:
raise RuntimeError(
f"No active step. Call dbg.begin_step(...) or use 'async with dbg.step(...)' before check(label={label!r})."
)
self.begin_step(f"verify:{label}")
return self.runtime.check(predicate, label, required=required)