sentienceapi 0.95.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sentienceapi might be problematic. Click here for more details.
- sentience/__init__.py +253 -0
- sentience/_extension_loader.py +195 -0
- sentience/action_executor.py +215 -0
- sentience/actions.py +1020 -0
- sentience/agent.py +1181 -0
- sentience/agent_config.py +46 -0
- sentience/agent_runtime.py +424 -0
- sentience/asserts/__init__.py +70 -0
- sentience/asserts/expect.py +621 -0
- sentience/asserts/query.py +383 -0
- sentience/async_api.py +108 -0
- sentience/backends/__init__.py +137 -0
- sentience/backends/actions.py +343 -0
- sentience/backends/browser_use_adapter.py +241 -0
- sentience/backends/cdp_backend.py +393 -0
- sentience/backends/exceptions.py +211 -0
- sentience/backends/playwright_backend.py +194 -0
- sentience/backends/protocol.py +216 -0
- sentience/backends/sentience_context.py +469 -0
- sentience/backends/snapshot.py +427 -0
- sentience/base_agent.py +196 -0
- sentience/browser.py +1215 -0
- sentience/browser_evaluator.py +299 -0
- sentience/canonicalization.py +207 -0
- sentience/cli.py +130 -0
- sentience/cloud_tracing.py +807 -0
- sentience/constants.py +6 -0
- sentience/conversational_agent.py +543 -0
- sentience/element_filter.py +136 -0
- sentience/expect.py +188 -0
- sentience/extension/background.js +104 -0
- sentience/extension/content.js +161 -0
- sentience/extension/injected_api.js +914 -0
- sentience/extension/manifest.json +36 -0
- sentience/extension/pkg/sentience_core.d.ts +51 -0
- sentience/extension/pkg/sentience_core.js +323 -0
- sentience/extension/pkg/sentience_core_bg.wasm +0 -0
- sentience/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
- sentience/extension/release.json +115 -0
- sentience/formatting.py +15 -0
- sentience/generator.py +202 -0
- sentience/inspector.py +367 -0
- sentience/llm_interaction_handler.py +191 -0
- sentience/llm_provider.py +875 -0
- sentience/llm_provider_utils.py +120 -0
- sentience/llm_response_builder.py +153 -0
- sentience/models.py +846 -0
- sentience/ordinal.py +280 -0
- sentience/overlay.py +222 -0
- sentience/protocols.py +228 -0
- sentience/query.py +303 -0
- sentience/read.py +188 -0
- sentience/recorder.py +589 -0
- sentience/schemas/trace_v1.json +335 -0
- sentience/screenshot.py +100 -0
- sentience/sentience_methods.py +86 -0
- sentience/snapshot.py +706 -0
- sentience/snapshot_diff.py +126 -0
- sentience/text_search.py +262 -0
- sentience/trace_event_builder.py +148 -0
- sentience/trace_file_manager.py +197 -0
- sentience/trace_indexing/__init__.py +27 -0
- sentience/trace_indexing/index_schema.py +199 -0
- sentience/trace_indexing/indexer.py +414 -0
- sentience/tracer_factory.py +322 -0
- sentience/tracing.py +449 -0
- sentience/utils/__init__.py +40 -0
- sentience/utils/browser.py +46 -0
- sentience/utils/element.py +257 -0
- sentience/utils/formatting.py +59 -0
- sentience/utils.py +296 -0
- sentience/verification.py +380 -0
- sentience/visual_agent.py +2058 -0
- sentience/wait.py +139 -0
- sentienceapi-0.95.0.dist-info/METADATA +984 -0
- sentienceapi-0.95.0.dist-info/RECORD +82 -0
- sentienceapi-0.95.0.dist-info/WHEEL +5 -0
- sentienceapi-0.95.0.dist-info/entry_points.txt +2 -0
- sentienceapi-0.95.0.dist-info/licenses/LICENSE +24 -0
- sentienceapi-0.95.0.dist-info/licenses/LICENSE-APACHE +201 -0
- sentienceapi-0.95.0.dist-info/licenses/LICENSE-MIT +21 -0
- sentienceapi-0.95.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://sentience.ai/schemas/trace/v1",
|
|
4
|
+
"title": "Sentience Agent Trace Event",
|
|
5
|
+
"description": "Schema for Sentience agent trace events in JSONL format",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["v", "type", "ts", "run_id", "seq", "data"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"v": {
|
|
10
|
+
"type": "integer",
|
|
11
|
+
"const": 1,
|
|
12
|
+
"description": "Schema version"
|
|
13
|
+
},
|
|
14
|
+
"type": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": ["run_start", "step_start", "snapshot", "snapshot_taken", "llm_called", "llm_response", "action", "action_executed", "verification", "recovery", "step_end", "run_end", "error"],
|
|
17
|
+
"description": "Event type"
|
|
18
|
+
},
|
|
19
|
+
"ts": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"format": "date-time",
|
|
22
|
+
"description": "ISO 8601 timestamp"
|
|
23
|
+
},
|
|
24
|
+
"ts_ms": {
|
|
25
|
+
"type": "integer",
|
|
26
|
+
"description": "Unix timestamp in milliseconds"
|
|
27
|
+
},
|
|
28
|
+
"run_id": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
|
31
|
+
"description": "UUID for the agent run"
|
|
32
|
+
},
|
|
33
|
+
"seq": {
|
|
34
|
+
"type": "integer",
|
|
35
|
+
"minimum": 1,
|
|
36
|
+
"description": "Monotonically increasing sequence number"
|
|
37
|
+
},
|
|
38
|
+
"step_id": {
|
|
39
|
+
"type": ["string", "null"],
|
|
40
|
+
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
|
41
|
+
"description": "UUID for the step (present for step-scoped events)"
|
|
42
|
+
},
|
|
43
|
+
"data": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"description": "Event-specific payload",
|
|
46
|
+
"oneOf": [
|
|
47
|
+
{
|
|
48
|
+
"description": "run_start data",
|
|
49
|
+
"properties": {
|
|
50
|
+
"agent": {"type": "string"},
|
|
51
|
+
"llm_model": {"type": ["string", "null"]},
|
|
52
|
+
"config": {"type": "object"}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"description": "step_start data",
|
|
57
|
+
"required": ["step_id", "step_index", "goal", "attempt"],
|
|
58
|
+
"properties": {
|
|
59
|
+
"step_id": {"type": "string"},
|
|
60
|
+
"step_index": {"type": "integer"},
|
|
61
|
+
"goal": {"type": "string"},
|
|
62
|
+
"attempt": {"type": "integer"},
|
|
63
|
+
"pre_url": {"type": ["string", "null"]}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"description": "snapshot or snapshot_taken data",
|
|
68
|
+
"properties": {
|
|
69
|
+
"step_id": {"type": ["string", "null"]},
|
|
70
|
+
"snapshot_id": {"type": ["string", "null"]},
|
|
71
|
+
"snapshot_digest": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
|
|
72
|
+
"snapshot_digest_loose": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
|
|
73
|
+
"url": {"type": ["string", "null"]},
|
|
74
|
+
"element_count": {"type": "integer"},
|
|
75
|
+
"timestamp": {"type": ["string", "null"]},
|
|
76
|
+
"elements": {
|
|
77
|
+
"type": "array",
|
|
78
|
+
"items": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"properties": {
|
|
81
|
+
"id": {"type": "integer"},
|
|
82
|
+
"role": {"type": "string"},
|
|
83
|
+
"text": {"type": ["string", "null"]},
|
|
84
|
+
"importance": {"type": "number"},
|
|
85
|
+
"importance_score": {"type": "number"},
|
|
86
|
+
"bbox": {
|
|
87
|
+
"type": "object",
|
|
88
|
+
"properties": {
|
|
89
|
+
"x": {"type": "number"},
|
|
90
|
+
"y": {"type": "number"},
|
|
91
|
+
"width": {"type": "number"},
|
|
92
|
+
"height": {"type": "number"}
|
|
93
|
+
},
|
|
94
|
+
"required": ["x", "y", "width", "height"]
|
|
95
|
+
},
|
|
96
|
+
"visual_cues": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {
|
|
99
|
+
"is_primary": {"type": "boolean"},
|
|
100
|
+
"is_clickable": {"type": "boolean"},
|
|
101
|
+
"background_color_name": {"type": ["string", "null"]}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"in_viewport": {"type": "boolean"},
|
|
105
|
+
"is_occluded": {"type": "boolean"},
|
|
106
|
+
"z_index": {"type": "integer"},
|
|
107
|
+
"rerank_index": {"type": ["integer", "null"]},
|
|
108
|
+
"heuristic_index": {"type": ["integer", "null"]},
|
|
109
|
+
"ml_probability": {"type": ["number", "null"]},
|
|
110
|
+
"ml_score": {"type": ["number", "null"]},
|
|
111
|
+
"diff_status": {
|
|
112
|
+
"type": ["string", "null"],
|
|
113
|
+
"enum": ["ADDED", "REMOVED", "MODIFIED", "MOVED", null],
|
|
114
|
+
"description": "Diff status for Diff Overlay feature. ADDED: new element, REMOVED: element was removed, MODIFIED: element changed, MOVED: element position changed, null: no change"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"required": ["id", "role", "importance", "bbox", "visual_cues"]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"screenshot_base64": {"type": ["string", "null"]},
|
|
121
|
+
"screenshot_format": {"type": ["string", "null"], "enum": ["png", "jpeg", null]}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"description": "llm_called data",
|
|
126
|
+
"required": ["step_id", "response_text", "response_hash"],
|
|
127
|
+
"properties": {
|
|
128
|
+
"step_id": {"type": "string"},
|
|
129
|
+
"model": {"type": ["string", "null"]},
|
|
130
|
+
"temperature": {"type": "number"},
|
|
131
|
+
"system_prompt_hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
|
|
132
|
+
"user_prompt_hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
|
|
133
|
+
"response_text": {"type": "string"},
|
|
134
|
+
"response_hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
|
|
135
|
+
"usage": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"properties": {
|
|
138
|
+
"prompt_tokens": {"type": "integer"},
|
|
139
|
+
"completion_tokens": {"type": "integer"},
|
|
140
|
+
"total_tokens": {"type": "integer"}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"description": "step_end data (StepResult)",
|
|
147
|
+
"required": ["step_id", "step_index", "goal", "attempt", "pre", "llm", "exec", "post", "verify"],
|
|
148
|
+
"properties": {
|
|
149
|
+
"v": {"type": "integer", "const": 1},
|
|
150
|
+
"step_id": {"type": "string"},
|
|
151
|
+
"step_index": {"type": "integer"},
|
|
152
|
+
"goal": {"type": "string"},
|
|
153
|
+
"attempt": {"type": "integer"},
|
|
154
|
+
"pre": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"required": ["snapshot_digest"],
|
|
157
|
+
"properties": {
|
|
158
|
+
"url": {"type": ["string", "null"]},
|
|
159
|
+
"snapshot_digest": {"type": "string"},
|
|
160
|
+
"snapshot_digest_loose": {"type": "string"}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"llm": {
|
|
164
|
+
"type": "object",
|
|
165
|
+
"required": ["response_text", "response_hash"],
|
|
166
|
+
"properties": {
|
|
167
|
+
"response_text": {"type": "string"},
|
|
168
|
+
"response_hash": {"type": "string"},
|
|
169
|
+
"usage": {
|
|
170
|
+
"type": "object",
|
|
171
|
+
"properties": {
|
|
172
|
+
"prompt_tokens": {"type": "integer"},
|
|
173
|
+
"completion_tokens": {"type": "integer"},
|
|
174
|
+
"total_tokens": {"type": "integer"}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"action": {
|
|
180
|
+
"type": "object",
|
|
181
|
+
"required": ["kind"],
|
|
182
|
+
"properties": {
|
|
183
|
+
"kind": {"type": "string", "enum": ["click", "type", "press", "finish", "navigate"]},
|
|
184
|
+
"element_id": {"type": "integer"},
|
|
185
|
+
"text": {"type": "string"},
|
|
186
|
+
"key": {"type": "string"},
|
|
187
|
+
"url": {"type": "string"},
|
|
188
|
+
"raw": {"type": "string"}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"exec": {
|
|
192
|
+
"type": "object",
|
|
193
|
+
"required": ["success", "outcome", "duration_ms"],
|
|
194
|
+
"properties": {
|
|
195
|
+
"success": {"type": "boolean"},
|
|
196
|
+
"outcome": {"type": "string"},
|
|
197
|
+
"action": {"type": "string"},
|
|
198
|
+
"element_id": {"type": "integer"},
|
|
199
|
+
"text": {"type": "string"},
|
|
200
|
+
"key": {"type": "string"},
|
|
201
|
+
"url_changed": {"type": ["boolean", "null"]},
|
|
202
|
+
"duration_ms": {"type": "integer"},
|
|
203
|
+
"error": {"type": ["string", "null"]},
|
|
204
|
+
"bounding_box": {
|
|
205
|
+
"type": "object",
|
|
206
|
+
"properties": {
|
|
207
|
+
"x": {"type": "number"},
|
|
208
|
+
"y": {"type": "number"},
|
|
209
|
+
"width": {"type": "number"},
|
|
210
|
+
"height": {"type": "number"}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
"post": {
|
|
216
|
+
"type": "object",
|
|
217
|
+
"properties": {
|
|
218
|
+
"url": {"type": ["string", "null"]},
|
|
219
|
+
"snapshot_digest": {"type": "string"},
|
|
220
|
+
"snapshot_digest_loose": {"type": "string"}
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"verify": {
|
|
224
|
+
"type": "object",
|
|
225
|
+
"required": ["passed"],
|
|
226
|
+
"properties": {
|
|
227
|
+
"policy": {"type": "string"},
|
|
228
|
+
"passed": {"type": "boolean"},
|
|
229
|
+
"signals": {
|
|
230
|
+
"type": "object",
|
|
231
|
+
"properties": {
|
|
232
|
+
"url_changed": {"type": "boolean"},
|
|
233
|
+
"error": {"type": ["string", "null"]},
|
|
234
|
+
"elements_found": {
|
|
235
|
+
"type": "array",
|
|
236
|
+
"items": {
|
|
237
|
+
"type": "object",
|
|
238
|
+
"properties": {
|
|
239
|
+
"label": {"type": "string"},
|
|
240
|
+
"bounding_box": {
|
|
241
|
+
"type": "object",
|
|
242
|
+
"properties": {
|
|
243
|
+
"x": {"type": "number"},
|
|
244
|
+
"y": {"type": "number"},
|
|
245
|
+
"width": {"type": "number"},
|
|
246
|
+
"height": {"type": "number"}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"assertions": {
|
|
253
|
+
"type": "array",
|
|
254
|
+
"description": "Assertion results from agent verification loop",
|
|
255
|
+
"items": {
|
|
256
|
+
"type": "object",
|
|
257
|
+
"required": ["label", "passed"],
|
|
258
|
+
"properties": {
|
|
259
|
+
"label": {"type": "string", "description": "Human-readable assertion label"},
|
|
260
|
+
"passed": {"type": "boolean", "description": "Whether the assertion passed"},
|
|
261
|
+
"required": {"type": "boolean", "description": "If true, assertion gates step success"},
|
|
262
|
+
"reason": {"type": "string", "description": "Explanation (especially when failed)"},
|
|
263
|
+
"details": {"type": "object", "description": "Additional structured data for debugging"}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
"task_done": {"type": "boolean", "description": "True if task completion assertion passed"},
|
|
268
|
+
"task_done_label": {"type": "string", "description": "Label of the task completion assertion"}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"recovery": {
|
|
274
|
+
"type": ["object", "null"],
|
|
275
|
+
"properties": {
|
|
276
|
+
"attempted": {"type": "boolean"},
|
|
277
|
+
"success": {"type": "boolean"},
|
|
278
|
+
"strategy": {"type": "string"},
|
|
279
|
+
"attempts": {"type": "array"}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"description": "verification data",
|
|
286
|
+
"required": ["step_id", "passed"],
|
|
287
|
+
"properties": {
|
|
288
|
+
"step_id": {"type": "string"},
|
|
289
|
+
"passed": {"type": "boolean"},
|
|
290
|
+
"kind": {
|
|
291
|
+
"type": "string",
|
|
292
|
+
"enum": ["assert", "task_done"],
|
|
293
|
+
"description": "Type of verification event"
|
|
294
|
+
},
|
|
295
|
+
"label": {"type": "string", "description": "Human-readable label for the assertion"},
|
|
296
|
+
"required": {"type": "boolean", "description": "If true, assertion gates step success"},
|
|
297
|
+
"reason": {"type": "string", "description": "Explanation (especially when failed)"},
|
|
298
|
+
"details": {"type": "object", "description": "Additional structured data for debugging"},
|
|
299
|
+
"signals": {"type": "object"}
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"description": "recovery data",
|
|
304
|
+
"required": ["step_id", "strategy"],
|
|
305
|
+
"properties": {
|
|
306
|
+
"step_id": {"type": "string"},
|
|
307
|
+
"strategy": {"type": "string"},
|
|
308
|
+
"attempt": {"type": "integer"}
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"description": "run_end data",
|
|
313
|
+
"required": ["steps"],
|
|
314
|
+
"properties": {
|
|
315
|
+
"steps": {"type": "integer"},
|
|
316
|
+
"status": {
|
|
317
|
+
"type": "string",
|
|
318
|
+
"enum": ["success", "failure", "partial", "unknown"],
|
|
319
|
+
"description": "Final execution status"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"description": "error data",
|
|
325
|
+
"required": ["step_id", "error"],
|
|
326
|
+
"properties": {
|
|
327
|
+
"step_id": {"type": "string"},
|
|
328
|
+
"attempt": {"type": "integer"},
|
|
329
|
+
"error": {"type": "string"}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
sentience/screenshot.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Screenshot functionality - standalone screenshot capture
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import base64
|
|
6
|
+
from typing import Any, Literal, Optional
|
|
7
|
+
|
|
8
|
+
from .browser import AsyncSentienceBrowser, SentienceBrowser
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def screenshot(
|
|
12
|
+
browser: SentienceBrowser,
|
|
13
|
+
format: Literal["png", "jpeg"] = "png",
|
|
14
|
+
quality: int | None = None,
|
|
15
|
+
) -> str:
|
|
16
|
+
"""
|
|
17
|
+
Capture screenshot of current page
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
browser: SentienceBrowser instance
|
|
21
|
+
format: Image format - "png" or "jpeg"
|
|
22
|
+
quality: JPEG quality (1-100), only used for JPEG format
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Base64-encoded screenshot data URL (e.g., "data:image/png;base64,...")
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
RuntimeError: If browser not started
|
|
29
|
+
ValueError: If quality is invalid for JPEG
|
|
30
|
+
"""
|
|
31
|
+
if not browser.page:
|
|
32
|
+
raise RuntimeError("Browser not started. Call browser.start() first.")
|
|
33
|
+
|
|
34
|
+
if format == "jpeg" and quality is not None:
|
|
35
|
+
if not (1 <= quality <= 100):
|
|
36
|
+
raise ValueError("Quality must be between 1 and 100 for JPEG format")
|
|
37
|
+
|
|
38
|
+
# Use Playwright's screenshot with base64 encoding
|
|
39
|
+
screenshot_options: dict[str, Any] = {
|
|
40
|
+
"type": format,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if format == "jpeg" and quality is not None:
|
|
44
|
+
screenshot_options["quality"] = quality
|
|
45
|
+
|
|
46
|
+
# Capture screenshot as base64
|
|
47
|
+
# Playwright returns bytes when encoding is not specified, so we encode manually
|
|
48
|
+
import base64
|
|
49
|
+
|
|
50
|
+
image_bytes = browser.page.screenshot(**screenshot_options)
|
|
51
|
+
base64_data = base64.b64encode(image_bytes).decode("utf-8")
|
|
52
|
+
|
|
53
|
+
# Return as data URL
|
|
54
|
+
mime_type = "image/png" if format == "png" else "image/jpeg"
|
|
55
|
+
return f"data:{mime_type};base64,{base64_data}"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
async def screenshot_async(
|
|
59
|
+
browser: AsyncSentienceBrowser,
|
|
60
|
+
format: Literal["png", "jpeg"] = "png",
|
|
61
|
+
quality: int | None = None,
|
|
62
|
+
) -> str:
|
|
63
|
+
"""
|
|
64
|
+
Capture screenshot of current page (async)
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
browser: AsyncSentienceBrowser instance
|
|
68
|
+
format: Image format - "png" or "jpeg"
|
|
69
|
+
quality: JPEG quality (1-100), only used for JPEG format
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Base64-encoded screenshot data URL (e.g., "data:image/png;base64,...")
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
RuntimeError: If browser not started
|
|
76
|
+
ValueError: If quality is invalid for JPEG
|
|
77
|
+
"""
|
|
78
|
+
if not browser.page:
|
|
79
|
+
raise RuntimeError("Browser not started. Call await browser.start() first.")
|
|
80
|
+
|
|
81
|
+
if format == "jpeg" and quality is not None:
|
|
82
|
+
if not (1 <= quality <= 100):
|
|
83
|
+
raise ValueError("Quality must be between 1 and 100 for JPEG format")
|
|
84
|
+
|
|
85
|
+
# Use Playwright's screenshot with base64 encoding
|
|
86
|
+
screenshot_options: dict[str, Any] = {
|
|
87
|
+
"type": format,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if format == "jpeg" and quality is not None:
|
|
91
|
+
screenshot_options["quality"] = quality
|
|
92
|
+
|
|
93
|
+
# Capture screenshot as base64
|
|
94
|
+
# Playwright returns bytes when encoding is not specified, so we encode manually
|
|
95
|
+
image_bytes = await browser.page.screenshot(**screenshot_options)
|
|
96
|
+
base64_data = base64.b64encode(image_bytes).decode("utf-8")
|
|
97
|
+
|
|
98
|
+
# Return as data URL
|
|
99
|
+
mime_type = "image/png" if format == "png" else "image/jpeg"
|
|
100
|
+
return f"data:{mime_type};base64,{base64_data}"
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Enums for Sentience API methods and agent actions.
|
|
3
|
+
|
|
4
|
+
This module provides type-safe enums for:
|
|
5
|
+
1. window.sentience API methods (extension-level)
|
|
6
|
+
2. Agent action types (high-level automation commands)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from enum import Enum
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SentienceMethod(str, Enum):
|
|
13
|
+
"""
|
|
14
|
+
Enum for window.sentience API methods.
|
|
15
|
+
|
|
16
|
+
These are the actual methods available on the window.sentience object
|
|
17
|
+
injected by the Chrome extension.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# Core snapshot and element discovery
|
|
21
|
+
SNAPSHOT = "snapshot"
|
|
22
|
+
"""Take a snapshot of the current page with element geometry and metadata."""
|
|
23
|
+
|
|
24
|
+
# Element interaction
|
|
25
|
+
CLICK = "click"
|
|
26
|
+
"""Click an element by its ID from the snapshot registry."""
|
|
27
|
+
|
|
28
|
+
# Content extraction
|
|
29
|
+
READ = "read"
|
|
30
|
+
"""Read page content as raw HTML, text, or markdown."""
|
|
31
|
+
|
|
32
|
+
FIND_TEXT_RECT = "findTextRect"
|
|
33
|
+
"""Find exact pixel coordinates of text occurrences on the page."""
|
|
34
|
+
|
|
35
|
+
# Visual overlay
|
|
36
|
+
SHOW_OVERLAY = "showOverlay"
|
|
37
|
+
"""Show visual overlay highlighting elements with importance scores."""
|
|
38
|
+
|
|
39
|
+
CLEAR_OVERLAY = "clearOverlay"
|
|
40
|
+
"""Clear the visual overlay."""
|
|
41
|
+
|
|
42
|
+
# Developer tools
|
|
43
|
+
START_RECORDING = "startRecording"
|
|
44
|
+
"""Start recording mode for golden set collection (developer tool)."""
|
|
45
|
+
|
|
46
|
+
def __str__(self) -> str:
|
|
47
|
+
"""Return the method name as a string."""
|
|
48
|
+
return self.value
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AgentAction(str, Enum):
|
|
52
|
+
"""
|
|
53
|
+
Enum for high-level agent action types.
|
|
54
|
+
|
|
55
|
+
These are the action commands that agents can execute. They may use
|
|
56
|
+
one or more window.sentience methods or Playwright APIs directly.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
# Element interaction
|
|
60
|
+
CLICK = "click"
|
|
61
|
+
"""Click an element by ID. Uses window.sentience.click() or Playwright mouse.click()."""
|
|
62
|
+
|
|
63
|
+
TYPE = "type"
|
|
64
|
+
"""Type text into an input element. Uses Playwright keyboard.type() directly."""
|
|
65
|
+
|
|
66
|
+
PRESS = "press"
|
|
67
|
+
"""Press a keyboard key (Enter, Escape, Tab, etc.). Uses Playwright keyboard.press()."""
|
|
68
|
+
|
|
69
|
+
# Navigation
|
|
70
|
+
NAVIGATE = "navigate"
|
|
71
|
+
"""Navigate to a URL. Uses Playwright page.goto() directly."""
|
|
72
|
+
|
|
73
|
+
SCROLL = "scroll"
|
|
74
|
+
"""Scroll the page or an element. Uses Playwright page.mouse.wheel() or element.scrollIntoView()."""
|
|
75
|
+
|
|
76
|
+
# Completion
|
|
77
|
+
FINISH = "finish"
|
|
78
|
+
"""Signal that the agent task is complete. No browser action, just status update."""
|
|
79
|
+
|
|
80
|
+
# Wait/verification
|
|
81
|
+
WAIT = "wait"
|
|
82
|
+
"""Wait for a condition or duration. Uses Playwright wait_for_* methods."""
|
|
83
|
+
|
|
84
|
+
def __str__(self) -> str:
|
|
85
|
+
"""Return the action name as a string."""
|
|
86
|
+
return self.value
|