Skip to content

Commit 02fdcb0

Browse files
author
Sentience Dev
committed
refactor agent for tracer support
1 parent 8b3ede6 commit 02fdcb0

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

sentience/agent.py

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import re
77
import time
8-
from typing import Any, Dict, List, Optional, Union
8+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
99

1010
from .actions import click, press, type_text
1111
from .base_agent import BaseAgent
@@ -23,6 +23,10 @@
2323
)
2424
from .snapshot import snapshot
2525

26+
if TYPE_CHECKING:
27+
from .agent_config import AgentConfig
28+
from .tracing import Tracer
29+
2630

2731
class SentienceAgent(BaseAgent):
2832
"""
@@ -54,6 +58,8 @@ def __init__(
5458
llm: LLMProvider,
5559
default_snapshot_limit: int = 50,
5660
verbose: bool = True,
61+
tracer: Optional["Tracer"] = None,
62+
config: Optional["AgentConfig"] = None,
5763
):
5864
"""
5965
Initialize Sentience Agent
@@ -63,11 +69,15 @@ def __init__(
6369
llm: LLM provider (OpenAIProvider, AnthropicProvider, etc.)
6470
default_snapshot_limit: Default maximum elements to include in context (default: 50)
6571
verbose: Print execution logs (default: True)
72+
tracer: Optional Tracer instance for execution tracking (default: None)
73+
config: Optional AgentConfig for advanced configuration (default: None)
6674
"""
6775
self.browser = browser
6876
self.llm = llm
6977
self.default_snapshot_limit = default_snapshot_limit
7078
self.verbose = verbose
79+
self.tracer = tracer
80+
self.config = config
7181

7282
# Execution history
7383
self.history: list[dict[str, Any]] = []
@@ -80,6 +90,9 @@ def __init__(
8090
"by_action": [],
8191
}
8292

93+
# Step counter for tracing
94+
self._step_count = 0
95+
8396
def act(
8497
self, goal: str, max_retries: int = 2, snapshot_options: SnapshotOptions | None = None
8598
) -> AgentActionResult:
@@ -107,6 +120,21 @@ def act(
107120
print(f"🤖 Agent Goal: {goal}")
108121
print(f"{'='*70}")
109122

123+
# Generate step ID for tracing
124+
self._step_count += 1
125+
step_id = f"step-{self._step_count}"
126+
127+
# Emit step_start trace event if tracer is enabled
128+
if self.tracer:
129+
pre_url = self.browser.page.url if self.browser.page else None
130+
self.tracer.emit_step_start(
131+
step_id=step_id,
132+
step_index=self._step_count,
133+
goal=goal,
134+
attempt=0,
135+
pre_url=pre_url,
136+
)
137+
110138
for attempt in range(max_retries + 1):
111139
try:
112140
# 1. OBSERVE: Get refined semantic snapshot
@@ -135,6 +163,18 @@ def act(
135163
if snap.status != "success":
136164
raise RuntimeError(f"Snapshot failed: {snap.error}")
137165

166+
# Emit snapshot trace event if tracer is enabled
167+
if self.tracer:
168+
self.tracer.emit(
169+
"snapshot",
170+
{
171+
"url": snap.url,
172+
"element_count": len(snap.elements),
173+
"timestamp": snap.timestamp,
174+
},
175+
step_id=step_id,
176+
)
177+
138178
# Apply element filtering based on goal
139179
filtered_elements = self.filter_elements(snap, goal)
140180

@@ -156,6 +196,19 @@ def act(
156196
# 3. THINK: Query LLM for next action
157197
llm_response = self._query_llm(context, goal)
158198

199+
# Emit LLM query trace event if tracer is enabled
200+
if self.tracer:
201+
self.tracer.emit(
202+
"llm_query",
203+
{
204+
"prompt_tokens": llm_response.prompt_tokens,
205+
"completion_tokens": llm_response.completion_tokens,
206+
"model": llm_response.model,
207+
"response": llm_response.content[:200], # Truncate for brevity
208+
},
209+
step_id=step_id,
210+
)
211+
159212
if self.verbose:
160213
print(f"🧠 LLM Decision: {llm_response.content}")
161214

@@ -186,6 +239,22 @@ def act(
186239
message=result_dict.get("message"),
187240
)
188241

242+
# Emit action execution trace event if tracer is enabled
243+
if self.tracer:
244+
post_url = self.browser.page.url if self.browser.page else None
245+
self.tracer.emit(
246+
"action",
247+
{
248+
"action": result.action,
249+
"element_id": result.element_id,
250+
"success": result.success,
251+
"outcome": result.outcome,
252+
"duration_ms": duration_ms,
253+
"post_url": post_url,
254+
},
255+
step_id=step_id,
256+
)
257+
189258
# 5. RECORD: Track history
190259
self.history.append(
191260
{
@@ -202,9 +271,25 @@ def act(
202271
status = "✅" if result.success else "❌"
203272
print(f"{status} Completed in {duration_ms}ms")
204273

274+
# Emit step completion trace event if tracer is enabled
275+
if self.tracer:
276+
self.tracer.emit(
277+
"step_end",
278+
{
279+
"success": result.success,
280+
"duration_ms": duration_ms,
281+
"action": result.action,
282+
},
283+
step_id=step_id,
284+
)
285+
205286
return result
206287

207288
except Exception as e:
289+
# Emit error trace event if tracer is enabled
290+
if self.tracer:
291+
self.tracer.emit_error(step_id=step_id, error=str(e), attempt=attempt)
292+
208293
if attempt < max_retries:
209294
if self.verbose:
210295
print(f"⚠️ Retry {attempt + 1}/{max_retries}: {e}")

0 commit comments

Comments
 (0)