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.

Files changed (50) hide show
  1. sentience/__init__.py +153 -0
  2. sentience/_extension_loader.py +40 -0
  3. sentience/actions.py +837 -0
  4. sentience/agent.py +1246 -0
  5. sentience/agent_config.py +43 -0
  6. sentience/async_api.py +101 -0
  7. sentience/base_agent.py +194 -0
  8. sentience/browser.py +1037 -0
  9. sentience/cli.py +130 -0
  10. sentience/cloud_tracing.py +382 -0
  11. sentience/conversational_agent.py +509 -0
  12. sentience/expect.py +188 -0
  13. sentience/extension/background.js +233 -0
  14. sentience/extension/content.js +298 -0
  15. sentience/extension/injected_api.js +1473 -0
  16. sentience/extension/manifest.json +36 -0
  17. sentience/extension/pkg/sentience_core.d.ts +51 -0
  18. sentience/extension/pkg/sentience_core.js +529 -0
  19. sentience/extension/pkg/sentience_core_bg.wasm +0 -0
  20. sentience/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
  21. sentience/extension/release.json +115 -0
  22. sentience/extension/test-content.js +4 -0
  23. sentience/formatting.py +59 -0
  24. sentience/generator.py +202 -0
  25. sentience/inspector.py +365 -0
  26. sentience/llm_provider.py +637 -0
  27. sentience/models.py +412 -0
  28. sentience/overlay.py +222 -0
  29. sentience/query.py +303 -0
  30. sentience/read.py +185 -0
  31. sentience/recorder.py +589 -0
  32. sentience/schemas/trace_v1.json +216 -0
  33. sentience/screenshot.py +100 -0
  34. sentience/snapshot.py +516 -0
  35. sentience/text_search.py +290 -0
  36. sentience/trace_indexing/__init__.py +27 -0
  37. sentience/trace_indexing/index_schema.py +111 -0
  38. sentience/trace_indexing/indexer.py +357 -0
  39. sentience/tracer_factory.py +211 -0
  40. sentience/tracing.py +285 -0
  41. sentience/utils.py +296 -0
  42. sentience/wait.py +137 -0
  43. sentienceapi-0.90.17.dist-info/METADATA +917 -0
  44. sentienceapi-0.90.17.dist-info/RECORD +50 -0
  45. sentienceapi-0.90.17.dist-info/WHEEL +5 -0
  46. sentienceapi-0.90.17.dist-info/entry_points.txt +2 -0
  47. sentienceapi-0.90.17.dist-info/licenses/LICENSE +24 -0
  48. sentienceapi-0.90.17.dist-info/licenses/LICENSE-APACHE +201 -0
  49. sentienceapi-0.90.17.dist-info/licenses/LICENSE-MIT +21 -0
  50. 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)