sentienceapi 0.90.17__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 +153 -0
- sentience/_extension_loader.py +40 -0
- sentience/actions.py +837 -0
- sentience/agent.py +1246 -0
- sentience/agent_config.py +43 -0
- sentience/async_api.py +101 -0
- sentience/base_agent.py +194 -0
- sentience/browser.py +1037 -0
- sentience/cli.py +130 -0
- sentience/cloud_tracing.py +382 -0
- sentience/conversational_agent.py +509 -0
- sentience/expect.py +188 -0
- sentience/extension/background.js +233 -0
- sentience/extension/content.js +298 -0
- sentience/extension/injected_api.js +1473 -0
- sentience/extension/manifest.json +36 -0
- sentience/extension/pkg/sentience_core.d.ts +51 -0
- sentience/extension/pkg/sentience_core.js +529 -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/extension/test-content.js +4 -0
- sentience/formatting.py +59 -0
- sentience/generator.py +202 -0
- sentience/inspector.py +365 -0
- sentience/llm_provider.py +637 -0
- sentience/models.py +412 -0
- sentience/overlay.py +222 -0
- sentience/query.py +303 -0
- sentience/read.py +185 -0
- sentience/recorder.py +589 -0
- sentience/schemas/trace_v1.json +216 -0
- sentience/screenshot.py +100 -0
- sentience/snapshot.py +516 -0
- sentience/text_search.py +290 -0
- sentience/trace_indexing/__init__.py +27 -0
- sentience/trace_indexing/index_schema.py +111 -0
- sentience/trace_indexing/indexer.py +357 -0
- sentience/tracer_factory.py +211 -0
- sentience/tracing.py +285 -0
- sentience/utils.py +296 -0
- sentience/wait.py +137 -0
- sentienceapi-0.90.17.dist-info/METADATA +917 -0
- sentienceapi-0.90.17.dist-info/RECORD +50 -0
- sentienceapi-0.90.17.dist-info/WHEEL +5 -0
- sentienceapi-0.90.17.dist-info/entry_points.txt +2 -0
- sentienceapi-0.90.17.dist-info/licenses/LICENSE +24 -0
- sentienceapi-0.90.17.dist-info/licenses/LICENSE-APACHE +201 -0
- sentienceapi-0.90.17.dist-info/licenses/LICENSE-MIT +21 -0
- sentienceapi-0.90.17.dist-info/top_level.txt +1 -0
sentience/inspector.py
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Inspector tool - helps developers see what the agent "sees"
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .browser import AsyncSentienceBrowser, SentienceBrowser
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Inspector:
|
|
9
|
+
"""Inspector for debugging - shows element info on hover/click"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, browser: SentienceBrowser):
|
|
12
|
+
self.browser = browser
|
|
13
|
+
self._active = False
|
|
14
|
+
self._last_element_id: int | None = None
|
|
15
|
+
|
|
16
|
+
def start(self) -> None:
|
|
17
|
+
"""Start inspection mode - prints element info on mouse move/click"""
|
|
18
|
+
if not self.browser.page:
|
|
19
|
+
raise RuntimeError("Browser not started. Call browser.start() first.")
|
|
20
|
+
|
|
21
|
+
self._active = True
|
|
22
|
+
|
|
23
|
+
# Inject inspector script into page
|
|
24
|
+
self.browser.page.evaluate(
|
|
25
|
+
"""
|
|
26
|
+
(() => {
|
|
27
|
+
// Remove existing inspector if any
|
|
28
|
+
if (window.__sentience_inspector_active) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
window.__sentience_inspector_active = true;
|
|
33
|
+
window.__sentience_last_element_id = null;
|
|
34
|
+
|
|
35
|
+
// Get element at point
|
|
36
|
+
function getElementAtPoint(x, y) {
|
|
37
|
+
const el = document.elementFromPoint(x, y);
|
|
38
|
+
if (!el) return null;
|
|
39
|
+
|
|
40
|
+
// Find element in registry
|
|
41
|
+
if (window.sentience_registry) {
|
|
42
|
+
for (let i = 0; i < window.sentience_registry.length; i++) {
|
|
43
|
+
if (window.sentience_registry[i] === el) {
|
|
44
|
+
return i;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Mouse move handler
|
|
52
|
+
function handleMouseMove(e) {
|
|
53
|
+
if (!window.__sentience_inspector_active) return;
|
|
54
|
+
|
|
55
|
+
const elementId = getElementAtPoint(e.clientX, e.clientY);
|
|
56
|
+
if (elementId === null || elementId === window.__sentience_last_element_id) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
window.__sentience_last_element_id = elementId;
|
|
61
|
+
|
|
62
|
+
// Get element info from snapshot if available
|
|
63
|
+
if (window.sentience && window.sentience_registry) {
|
|
64
|
+
const el = window.sentience_registry[elementId];
|
|
65
|
+
if (el) {
|
|
66
|
+
const rect = el.getBoundingClientRect();
|
|
67
|
+
const text = el.getAttribute('aria-label') ||
|
|
68
|
+
el.value ||
|
|
69
|
+
el.placeholder ||
|
|
70
|
+
el.alt ||
|
|
71
|
+
(el.innerText || '').substring(0, 50);
|
|
72
|
+
|
|
73
|
+
const role = el.getAttribute('role') || el.tagName.toLowerCase();
|
|
74
|
+
|
|
75
|
+
console.log(`[Sentience Inspector] Element #${elementId}: role=${role}, text="${text}", bbox=(${Math.round(rect.x)}, ${Math.round(rect.y)}, ${Math.round(rect.width)}, ${Math.round(rect.height)})`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Click handler
|
|
81
|
+
function handleClick(e) {
|
|
82
|
+
if (!window.__sentience_inspector_active) return;
|
|
83
|
+
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
e.stopPropagation();
|
|
86
|
+
|
|
87
|
+
const elementId = getElementAtPoint(e.clientX, e.clientY);
|
|
88
|
+
if (elementId === null) return;
|
|
89
|
+
|
|
90
|
+
// Get full element info
|
|
91
|
+
if (window.sentience && window.sentience_registry) {
|
|
92
|
+
const el = window.sentience_registry[elementId];
|
|
93
|
+
if (el) {
|
|
94
|
+
const rect = el.getBoundingClientRect();
|
|
95
|
+
const info = {
|
|
96
|
+
id: elementId,
|
|
97
|
+
tag: el.tagName.toLowerCase(),
|
|
98
|
+
role: el.getAttribute('role') || 'generic',
|
|
99
|
+
text: el.getAttribute('aria-label') ||
|
|
100
|
+
el.value ||
|
|
101
|
+
el.placeholder ||
|
|
102
|
+
el.alt ||
|
|
103
|
+
(el.innerText || '').substring(0, 100),
|
|
104
|
+
bbox: {
|
|
105
|
+
x: Math.round(rect.x),
|
|
106
|
+
y: Math.round(rect.y),
|
|
107
|
+
width: Math.round(rect.width),
|
|
108
|
+
height: Math.round(rect.height)
|
|
109
|
+
},
|
|
110
|
+
attributes: {
|
|
111
|
+
id: el.id || null,
|
|
112
|
+
class: el.className || null,
|
|
113
|
+
name: el.name || null,
|
|
114
|
+
type: el.type || null
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
console.log('[Sentience Inspector] Clicked element:', JSON.stringify(info, null, 2));
|
|
119
|
+
|
|
120
|
+
// Also try to get from snapshot if available
|
|
121
|
+
window.sentience.snapshot({ limit: 100 }).then(snap => {
|
|
122
|
+
const element = snap.elements.find(el => el.id === elementId);
|
|
123
|
+
if (element) {
|
|
124
|
+
console.log('[Sentience Inspector] Snapshot element:', JSON.stringify(element, null, 2));
|
|
125
|
+
}
|
|
126
|
+
}).catch(() => {});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Add event listeners
|
|
132
|
+
document.addEventListener('mousemove', handleMouseMove, true);
|
|
133
|
+
document.addEventListener('click', handleClick, true);
|
|
134
|
+
|
|
135
|
+
// Store cleanup function
|
|
136
|
+
window.__sentience_inspector_cleanup = () => {
|
|
137
|
+
document.removeEventListener('mousemove', handleMouseMove, true);
|
|
138
|
+
document.removeEventListener('click', handleClick, true);
|
|
139
|
+
window.__sentience_inspector_active = false;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
console.log('[Sentience Inspector] ✅ Inspection mode active. Hover elements to see info, click to see full details.');
|
|
143
|
+
})();
|
|
144
|
+
"""
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def stop(self) -> None:
|
|
148
|
+
"""Stop inspection mode"""
|
|
149
|
+
if not self.browser.page:
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
self._active = False
|
|
153
|
+
|
|
154
|
+
# Cleanup inspector
|
|
155
|
+
self.browser.page.evaluate(
|
|
156
|
+
"""
|
|
157
|
+
() => {
|
|
158
|
+
if (window.__sentience_inspector_cleanup) {
|
|
159
|
+
window.__sentience_inspector_cleanup();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
"""
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def __enter__(self):
|
|
166
|
+
"""Context manager entry"""
|
|
167
|
+
self.start()
|
|
168
|
+
return self
|
|
169
|
+
|
|
170
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
171
|
+
"""Context manager exit"""
|
|
172
|
+
self.stop()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def inspect(browser: SentienceBrowser) -> Inspector:
|
|
176
|
+
"""
|
|
177
|
+
Create an inspector instance
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
browser: SentienceBrowser instance
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Inspector instance
|
|
184
|
+
"""
|
|
185
|
+
return Inspector(browser)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class InspectorAsync:
|
|
189
|
+
"""Inspector for debugging - shows element info on hover/click (async)"""
|
|
190
|
+
|
|
191
|
+
def __init__(self, browser: AsyncSentienceBrowser):
|
|
192
|
+
self.browser = browser
|
|
193
|
+
self._active = False
|
|
194
|
+
self._last_element_id: int | None = None
|
|
195
|
+
|
|
196
|
+
async def start(self) -> None:
|
|
197
|
+
"""Start inspection mode - prints element info on mouse move/click (async)"""
|
|
198
|
+
if not self.browser.page:
|
|
199
|
+
raise RuntimeError("Browser not started. Call await browser.start() first.")
|
|
200
|
+
|
|
201
|
+
self._active = True
|
|
202
|
+
|
|
203
|
+
# Inject inspector script into page
|
|
204
|
+
await self.browser.page.evaluate(
|
|
205
|
+
"""
|
|
206
|
+
(() => {
|
|
207
|
+
// Remove existing inspector if any
|
|
208
|
+
if (window.__sentience_inspector_active) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
window.__sentience_inspector_active = true;
|
|
213
|
+
window.__sentience_last_element_id = null;
|
|
214
|
+
|
|
215
|
+
// Get element at point
|
|
216
|
+
function getElementAtPoint(x, y) {
|
|
217
|
+
const el = document.elementFromPoint(x, y);
|
|
218
|
+
if (!el) return null;
|
|
219
|
+
|
|
220
|
+
// Find element in registry
|
|
221
|
+
if (window.sentience_registry) {
|
|
222
|
+
for (let i = 0; i < window.sentience_registry.length; i++) {
|
|
223
|
+
if (window.sentience_registry[i] === el) {
|
|
224
|
+
return i;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Mouse move handler
|
|
232
|
+
function handleMouseMove(e) {
|
|
233
|
+
if (!window.__sentience_inspector_active) return;
|
|
234
|
+
|
|
235
|
+
const elementId = getElementAtPoint(e.clientX, e.clientY);
|
|
236
|
+
if (elementId === null || elementId === window.__sentience_last_element_id) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
window.__sentience_last_element_id = elementId;
|
|
241
|
+
|
|
242
|
+
// Get element info from snapshot if available
|
|
243
|
+
if (window.sentience && window.sentience_registry) {
|
|
244
|
+
const el = window.sentience_registry[elementId];
|
|
245
|
+
if (el) {
|
|
246
|
+
const rect = el.getBoundingClientRect();
|
|
247
|
+
const text = el.getAttribute('aria-label') ||
|
|
248
|
+
el.value ||
|
|
249
|
+
el.placeholder ||
|
|
250
|
+
el.alt ||
|
|
251
|
+
(el.innerText || '').substring(0, 50);
|
|
252
|
+
|
|
253
|
+
const role = el.getAttribute('role') || el.tagName.toLowerCase();
|
|
254
|
+
|
|
255
|
+
console.log(`[Sentience Inspector] Element #${elementId}: role=${role}, text="${text}", bbox=(${Math.round(rect.x)}, ${Math.round(rect.y)}, ${Math.round(rect.width)}, ${Math.round(rect.height)})`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Click handler
|
|
261
|
+
function handleClick(e) {
|
|
262
|
+
if (!window.__sentience_inspector_active) return;
|
|
263
|
+
|
|
264
|
+
e.preventDefault();
|
|
265
|
+
e.stopPropagation();
|
|
266
|
+
|
|
267
|
+
const elementId = getElementAtPoint(e.clientX, e.clientY);
|
|
268
|
+
if (elementId === null) return;
|
|
269
|
+
|
|
270
|
+
// Get full element info
|
|
271
|
+
if (window.sentience && window.sentience_registry) {
|
|
272
|
+
const el = window.sentience_registry[elementId];
|
|
273
|
+
if (el) {
|
|
274
|
+
const rect = el.getBoundingClientRect();
|
|
275
|
+
const info = {
|
|
276
|
+
id: elementId,
|
|
277
|
+
tag: el.tagName.toLowerCase(),
|
|
278
|
+
role: el.getAttribute('role') || 'generic',
|
|
279
|
+
text: el.getAttribute('aria-label') ||
|
|
280
|
+
el.value ||
|
|
281
|
+
el.placeholder ||
|
|
282
|
+
el.alt ||
|
|
283
|
+
(el.innerText || '').substring(0, 100),
|
|
284
|
+
bbox: {
|
|
285
|
+
x: Math.round(rect.x),
|
|
286
|
+
y: Math.round(rect.y),
|
|
287
|
+
width: Math.round(rect.width),
|
|
288
|
+
height: Math.round(rect.height)
|
|
289
|
+
},
|
|
290
|
+
attributes: {
|
|
291
|
+
id: el.id || null,
|
|
292
|
+
class: el.className || null,
|
|
293
|
+
name: el.name || null,
|
|
294
|
+
type: el.type || null
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
console.log('[Sentience Inspector] Clicked element:', JSON.stringify(info, null, 2));
|
|
299
|
+
|
|
300
|
+
// Also try to get from snapshot if available
|
|
301
|
+
window.sentience.snapshot({ limit: 100 }).then(snap => {
|
|
302
|
+
const element = snap.elements.find(el => el.id === elementId);
|
|
303
|
+
if (element) {
|
|
304
|
+
console.log('[Sentience Inspector] Snapshot element:', JSON.stringify(element, null, 2));
|
|
305
|
+
}
|
|
306
|
+
}).catch(() => {});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Add event listeners
|
|
312
|
+
document.addEventListener('mousemove', handleMouseMove, true);
|
|
313
|
+
document.addEventListener('click', handleClick, true);
|
|
314
|
+
|
|
315
|
+
// Store cleanup function
|
|
316
|
+
window.__sentience_inspector_cleanup = () => {
|
|
317
|
+
document.removeEventListener('mousemove', handleMouseMove, true);
|
|
318
|
+
document.removeEventListener('click', handleClick, true);
|
|
319
|
+
window.__sentience_inspector_active = false;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
console.log('[Sentience Inspector] ✅ Inspection mode active. Hover elements to see info, click to see full details.');
|
|
323
|
+
})();
|
|
324
|
+
"""
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
async def stop(self) -> None:
|
|
328
|
+
"""Stop inspection mode (async)"""
|
|
329
|
+
if not self.browser.page:
|
|
330
|
+
return
|
|
331
|
+
|
|
332
|
+
self._active = False
|
|
333
|
+
|
|
334
|
+
# Cleanup inspector
|
|
335
|
+
await self.browser.page.evaluate(
|
|
336
|
+
"""
|
|
337
|
+
() => {
|
|
338
|
+
if (window.__sentience_inspector_cleanup) {
|
|
339
|
+
window.__sentience_inspector_cleanup();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
"""
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
async def __aenter__(self):
|
|
346
|
+
"""Context manager entry"""
|
|
347
|
+
await self.start()
|
|
348
|
+
return self
|
|
349
|
+
|
|
350
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
351
|
+
"""Context manager exit"""
|
|
352
|
+
await self.stop()
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def inspect_async(browser: AsyncSentienceBrowser) -> InspectorAsync:
|
|
356
|
+
"""
|
|
357
|
+
Create an inspector instance (async)
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
browser: AsyncSentienceBrowser instance
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
InspectorAsync instance
|
|
364
|
+
"""
|
|
365
|
+
return InspectorAsync(browser)
|