sentienceapi 0.90.12__py3-none-any.whl → 0.92.2__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 +14 -5
- sentience/_extension_loader.py +40 -0
- sentience/action_executor.py +215 -0
- sentience/actions.py +408 -25
- sentience/agent.py +804 -310
- sentience/agent_config.py +3 -0
- sentience/async_api.py +101 -0
- sentience/base_agent.py +95 -0
- sentience/browser.py +594 -25
- sentience/browser_evaluator.py +299 -0
- sentience/cloud_tracing.py +458 -36
- sentience/conversational_agent.py +79 -45
- sentience/element_filter.py +136 -0
- sentience/expect.py +98 -2
- sentience/extension/background.js +56 -185
- sentience/extension/content.js +117 -289
- sentience/extension/injected_api.js +799 -1374
- sentience/extension/manifest.json +1 -1
- sentience/extension/pkg/sentience_core.js +190 -396
- sentience/extension/pkg/sentience_core_bg.wasm +0 -0
- sentience/extension/release.json +47 -47
- sentience/formatting.py +9 -53
- sentience/inspector.py +183 -1
- sentience/llm_interaction_handler.py +191 -0
- sentience/llm_provider.py +256 -28
- sentience/llm_provider_utils.py +120 -0
- sentience/llm_response_builder.py +153 -0
- sentience/models.py +66 -1
- sentience/overlay.py +109 -2
- sentience/protocols.py +228 -0
- sentience/query.py +1 -1
- sentience/read.py +95 -3
- sentience/recorder.py +223 -3
- sentience/schemas/trace_v1.json +102 -9
- sentience/screenshot.py +48 -2
- sentience/sentience_methods.py +86 -0
- sentience/snapshot.py +309 -64
- sentience/snapshot_diff.py +141 -0
- sentience/text_search.py +119 -5
- sentience/trace_event_builder.py +129 -0
- sentience/trace_file_manager.py +197 -0
- sentience/trace_indexing/index_schema.py +95 -7
- sentience/trace_indexing/indexer.py +117 -14
- sentience/tracer_factory.py +119 -6
- sentience/tracing.py +172 -8
- 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 +1 -1
- sentience/visual_agent.py +2056 -0
- sentience/wait.py +70 -4
- {sentienceapi-0.90.12.dist-info → sentienceapi-0.92.2.dist-info}/METADATA +61 -22
- sentienceapi-0.92.2.dist-info/RECORD +65 -0
- sentienceapi-0.92.2.dist-info/licenses/LICENSE +24 -0
- sentienceapi-0.92.2.dist-info/licenses/LICENSE-APACHE +201 -0
- sentienceapi-0.92.2.dist-info/licenses/LICENSE-MIT +21 -0
- sentience/extension/test-content.js +0 -4
- sentienceapi-0.90.12.dist-info/RECORD +0 -46
- sentienceapi-0.90.12.dist-info/licenses/LICENSE.md +0 -43
- {sentienceapi-0.90.12.dist-info → sentienceapi-0.92.2.dist-info}/WHEEL +0 -0
- {sentienceapi-0.90.12.dist-info → sentienceapi-0.92.2.dist-info}/entry_points.txt +0 -0
- {sentienceapi-0.90.12.dist-info → sentienceapi-0.92.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Browser evaluation helper for common window.sentience API patterns.
|
|
3
|
+
|
|
4
|
+
Consolidates repeated patterns for:
|
|
5
|
+
- Waiting for extension injection
|
|
6
|
+
- Calling window.sentience methods
|
|
7
|
+
- Error handling with diagnostics
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any, Optional, Union
|
|
11
|
+
|
|
12
|
+
from playwright.async_api import Page as AsyncPage
|
|
13
|
+
from playwright.sync_api import Page
|
|
14
|
+
|
|
15
|
+
from .browser import AsyncSentienceBrowser, SentienceBrowser
|
|
16
|
+
from .sentience_methods import SentienceMethod
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BrowserEvaluator:
|
|
20
|
+
"""Helper class for common browser evaluation patterns"""
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def wait_for_extension(
|
|
24
|
+
page: Page | AsyncPage,
|
|
25
|
+
timeout_ms: int = 5000,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Wait for window.sentience API to be available.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
page: Playwright Page instance (sync or async)
|
|
32
|
+
timeout_ms: Timeout in milliseconds (default: 5000)
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
RuntimeError: If extension fails to inject within timeout
|
|
36
|
+
"""
|
|
37
|
+
if hasattr(page, "wait_for_function"):
|
|
38
|
+
# Sync page
|
|
39
|
+
try:
|
|
40
|
+
page.wait_for_function(
|
|
41
|
+
"typeof window.sentience !== 'undefined'",
|
|
42
|
+
timeout=timeout_ms,
|
|
43
|
+
)
|
|
44
|
+
except Exception as e:
|
|
45
|
+
diag = BrowserEvaluator._gather_diagnostics(page)
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
f"Sentience extension failed to inject window.sentience API. "
|
|
48
|
+
f"Is the extension loaded? Diagnostics: {diag}"
|
|
49
|
+
) from e
|
|
50
|
+
else:
|
|
51
|
+
# Async page - should use async version
|
|
52
|
+
raise TypeError("Use wait_for_extension_async for async pages")
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
async def wait_for_extension_async(
|
|
56
|
+
page: AsyncPage,
|
|
57
|
+
timeout_ms: int = 5000,
|
|
58
|
+
) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Wait for window.sentience API to be available (async).
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
page: Playwright AsyncPage instance
|
|
64
|
+
timeout_ms: Timeout in milliseconds (default: 5000)
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
RuntimeError: If extension fails to inject within timeout
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
await page.wait_for_function(
|
|
71
|
+
"typeof window.sentience !== 'undefined'",
|
|
72
|
+
timeout=timeout_ms,
|
|
73
|
+
)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
diag = await BrowserEvaluator._gather_diagnostics_async(page)
|
|
76
|
+
raise RuntimeError(
|
|
77
|
+
f"Sentience extension failed to inject window.sentience API. "
|
|
78
|
+
f"Is the extension loaded? Diagnostics: {diag}"
|
|
79
|
+
) from e
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def _gather_diagnostics(page: Page | AsyncPage) -> dict[str, Any]:
|
|
83
|
+
"""
|
|
84
|
+
Gather diagnostics about extension state.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
page: Playwright Page instance
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Dictionary with diagnostic information
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
if hasattr(page, "evaluate"):
|
|
94
|
+
# Sync page
|
|
95
|
+
return page.evaluate(
|
|
96
|
+
"""() => ({
|
|
97
|
+
sentience_defined: typeof window.sentience !== 'undefined',
|
|
98
|
+
extension_id: document.documentElement.dataset.sentienceExtensionId || 'not set',
|
|
99
|
+
url: window.location.href
|
|
100
|
+
})"""
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
return {"error": "Could not gather diagnostics - invalid page type"}
|
|
104
|
+
except Exception:
|
|
105
|
+
return {"error": "Could not gather diagnostics"}
|
|
106
|
+
|
|
107
|
+
@staticmethod
|
|
108
|
+
async def _gather_diagnostics_async(page: AsyncPage) -> dict[str, Any]:
|
|
109
|
+
"""
|
|
110
|
+
Gather diagnostics about extension state (async).
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
page: Playwright AsyncPage instance
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Dictionary with diagnostic information
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
return await page.evaluate(
|
|
120
|
+
"""() => ({
|
|
121
|
+
sentience_defined: typeof window.sentience !== 'undefined',
|
|
122
|
+
extension_id: document.documentElement.dataset.sentienceExtensionId || 'not set',
|
|
123
|
+
url: window.location.href
|
|
124
|
+
})"""
|
|
125
|
+
)
|
|
126
|
+
except Exception:
|
|
127
|
+
return {"error": "Could not gather diagnostics"}
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def invoke(
|
|
131
|
+
page: Page,
|
|
132
|
+
method: SentienceMethod | str,
|
|
133
|
+
*args: Any,
|
|
134
|
+
**kwargs: Any,
|
|
135
|
+
) -> Any:
|
|
136
|
+
"""
|
|
137
|
+
Invoke a window.sentience method with error handling (sync).
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
page: Playwright Page instance (sync)
|
|
141
|
+
method: SentienceMethod enum value or method name string (e.g., SentienceMethod.SNAPSHOT or "snapshot")
|
|
142
|
+
*args: Positional arguments to pass to the method
|
|
143
|
+
**kwargs: Keyword arguments to pass to the method
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Result from the method call
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
RuntimeError: If method is not available or call fails
|
|
150
|
+
|
|
151
|
+
Example:
|
|
152
|
+
```python
|
|
153
|
+
result = BrowserEvaluator.invoke(page, SentienceMethod.SNAPSHOT, limit=50)
|
|
154
|
+
success = BrowserEvaluator.invoke(page, SentienceMethod.CLICK, element_id)
|
|
155
|
+
```
|
|
156
|
+
"""
|
|
157
|
+
# Convert enum to string if needed
|
|
158
|
+
method_name = method.value if isinstance(method, SentienceMethod) else method
|
|
159
|
+
|
|
160
|
+
# Build JavaScript call
|
|
161
|
+
if args and kwargs:
|
|
162
|
+
# Both args and kwargs - use object spread
|
|
163
|
+
js_code = f"""
|
|
164
|
+
(args, kwargs) => {{
|
|
165
|
+
return window.sentience.{method_name}(...args, kwargs);
|
|
166
|
+
}}
|
|
167
|
+
"""
|
|
168
|
+
result = page.evaluate(js_code, list(args), kwargs)
|
|
169
|
+
elif args:
|
|
170
|
+
# Only args
|
|
171
|
+
js_code = f"""
|
|
172
|
+
(args) => {{
|
|
173
|
+
return window.sentience.{method_name}(...args);
|
|
174
|
+
}}
|
|
175
|
+
"""
|
|
176
|
+
result = page.evaluate(js_code, list(args))
|
|
177
|
+
elif kwargs:
|
|
178
|
+
# Only kwargs - pass as single object
|
|
179
|
+
js_code = f"""
|
|
180
|
+
(options) => {{
|
|
181
|
+
return window.sentience.{method_name}(options);
|
|
182
|
+
}}
|
|
183
|
+
"""
|
|
184
|
+
result = page.evaluate(js_code, kwargs)
|
|
185
|
+
else:
|
|
186
|
+
# No arguments
|
|
187
|
+
js_code = f"""
|
|
188
|
+
() => {{
|
|
189
|
+
return window.sentience.{method_name}();
|
|
190
|
+
}}
|
|
191
|
+
"""
|
|
192
|
+
result = page.evaluate(js_code)
|
|
193
|
+
|
|
194
|
+
return result
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
async def invoke_async(
|
|
198
|
+
page: AsyncPage,
|
|
199
|
+
method: SentienceMethod | str,
|
|
200
|
+
*args: Any,
|
|
201
|
+
**kwargs: Any,
|
|
202
|
+
) -> Any:
|
|
203
|
+
"""
|
|
204
|
+
Invoke a window.sentience method with error handling (async).
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
page: Playwright AsyncPage instance
|
|
208
|
+
method: SentienceMethod enum value or method name string (e.g., SentienceMethod.SNAPSHOT or "snapshot")
|
|
209
|
+
*args: Positional arguments to pass to the method
|
|
210
|
+
**kwargs: Keyword arguments to pass to the method
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Result from the method call
|
|
214
|
+
|
|
215
|
+
Raises:
|
|
216
|
+
RuntimeError: If method is not available or call fails
|
|
217
|
+
|
|
218
|
+
Example:
|
|
219
|
+
```python
|
|
220
|
+
result = await BrowserEvaluator.invoke_async(page, SentienceMethod.SNAPSHOT, limit=50)
|
|
221
|
+
success = await BrowserEvaluator.invoke_async(page, SentienceMethod.CLICK, element_id)
|
|
222
|
+
```
|
|
223
|
+
"""
|
|
224
|
+
# Convert enum to string if needed
|
|
225
|
+
method_name = method.value if isinstance(method, SentienceMethod) else method
|
|
226
|
+
|
|
227
|
+
# Build JavaScript call
|
|
228
|
+
if args and kwargs:
|
|
229
|
+
js_code = f"""
|
|
230
|
+
(args, kwargs) => {{
|
|
231
|
+
return window.sentience.{method_name}(...args, kwargs);
|
|
232
|
+
}}
|
|
233
|
+
"""
|
|
234
|
+
result = await page.evaluate(js_code, list(args), kwargs)
|
|
235
|
+
elif args:
|
|
236
|
+
js_code = f"""
|
|
237
|
+
(args) => {{
|
|
238
|
+
return window.sentience.{method_name}(...args);
|
|
239
|
+
}}
|
|
240
|
+
"""
|
|
241
|
+
result = await page.evaluate(js_code, list(args))
|
|
242
|
+
elif kwargs:
|
|
243
|
+
js_code = f"""
|
|
244
|
+
(options) => {{
|
|
245
|
+
return window.sentience.{method_name}(options);
|
|
246
|
+
}}
|
|
247
|
+
"""
|
|
248
|
+
result = await page.evaluate(js_code, kwargs)
|
|
249
|
+
else:
|
|
250
|
+
js_code = f"""
|
|
251
|
+
() => {{
|
|
252
|
+
return window.sentience.{method_name}();
|
|
253
|
+
}}
|
|
254
|
+
"""
|
|
255
|
+
result = await page.evaluate(js_code)
|
|
256
|
+
|
|
257
|
+
return result
|
|
258
|
+
|
|
259
|
+
@staticmethod
|
|
260
|
+
def verify_method_exists(
|
|
261
|
+
page: Page,
|
|
262
|
+
method: SentienceMethod | str,
|
|
263
|
+
) -> bool:
|
|
264
|
+
"""
|
|
265
|
+
Verify that a window.sentience method exists.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
page: Playwright Page instance (sync)
|
|
269
|
+
method: SentienceMethod enum value or method name string
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
True if method exists, False otherwise
|
|
273
|
+
"""
|
|
274
|
+
method_name = method.value if isinstance(method, SentienceMethod) else method
|
|
275
|
+
try:
|
|
276
|
+
return page.evaluate(f"typeof window.sentience.{method_name} !== 'undefined'")
|
|
277
|
+
except Exception:
|
|
278
|
+
return False
|
|
279
|
+
|
|
280
|
+
@staticmethod
|
|
281
|
+
async def verify_method_exists_async(
|
|
282
|
+
page: AsyncPage,
|
|
283
|
+
method: SentienceMethod | str,
|
|
284
|
+
) -> bool:
|
|
285
|
+
"""
|
|
286
|
+
Verify that a window.sentience method exists (async).
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
page: Playwright AsyncPage instance
|
|
290
|
+
method: SentienceMethod enum value or method name string
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
True if method exists, False otherwise
|
|
294
|
+
"""
|
|
295
|
+
method_name = method.value if isinstance(method, SentienceMethod) else method
|
|
296
|
+
try:
|
|
297
|
+
return await page.evaluate(f"typeof window.sentience.{method_name} !== 'undefined'")
|
|
298
|
+
except Exception:
|
|
299
|
+
return False
|