sentienceapi 0.90.9__py3-none-any.whl → 0.90.16__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 +1 -1
- sentience/_extension_loader.py +40 -0
- sentience/agent.py +2 -17
- sentience/async_api.py +1160 -0
- sentience/browser.py +193 -26
- sentience/cloud_tracing.py +91 -1
- sentience/conversational_agent.py +3 -3
- sentience/extension/release.json +1 -1
- sentience/llm_provider.py +206 -0
- sentience/models.py +7 -1
- sentience/snapshot.py +18 -26
- sentience/text_search.py +41 -0
- sentience/trace_indexing/__init__.py +6 -6
- sentience/trace_indexing/index_schema.py +14 -14
- sentience/trace_indexing/indexer.py +13 -19
- sentience/wait.py +2 -2
- {sentienceapi-0.90.9.dist-info → sentienceapi-0.90.16.dist-info}/METADATA +60 -22
- {sentienceapi-0.90.9.dist-info → sentienceapi-0.90.16.dist-info}/RECORD +24 -20
- sentienceapi-0.90.16.dist-info/licenses/LICENSE +24 -0
- sentienceapi-0.90.16.dist-info/licenses/LICENSE-APACHE +201 -0
- sentienceapi-0.90.16.dist-info/licenses/LICENSE-MIT +21 -0
- sentienceapi-0.90.9.dist-info/licenses/LICENSE.md +0 -43
- {sentienceapi-0.90.9.dist-info → sentienceapi-0.90.16.dist-info}/WHEEL +0 -0
- {sentienceapi-0.90.9.dist-info → sentienceapi-0.90.16.dist-info}/entry_points.txt +0 -0
- {sentienceapi-0.90.9.dist-info → sentienceapi-0.90.16.dist-info}/top_level.txt +0 -0
sentience/snapshot.py
CHANGED
|
@@ -5,7 +5,7 @@ Snapshot functionality - calls window.sentience.snapshot() or server-side API
|
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
7
|
import time
|
|
8
|
-
from typing import Any
|
|
8
|
+
from typing import Any, Optional
|
|
9
9
|
|
|
10
10
|
import requests
|
|
11
11
|
|
|
@@ -41,41 +41,33 @@ def _save_trace_to_file(raw_elements: list[dict[str, Any]], trace_path: str | No
|
|
|
41
41
|
|
|
42
42
|
def snapshot(
|
|
43
43
|
browser: SentienceBrowser,
|
|
44
|
-
|
|
45
|
-
limit: int | None = None,
|
|
46
|
-
filter: dict[str, Any] | None = None,
|
|
47
|
-
use_api: bool | None = None,
|
|
48
|
-
save_trace: bool = False,
|
|
49
|
-
trace_path: str | None = None,
|
|
50
|
-
show_overlay: bool = False,
|
|
44
|
+
options: SnapshotOptions | None = None,
|
|
51
45
|
) -> Snapshot:
|
|
52
46
|
"""
|
|
53
47
|
Take a snapshot of the current page
|
|
54
48
|
|
|
55
49
|
Args:
|
|
56
50
|
browser: SentienceBrowser instance
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
filter: Filter options (min_area, allowed_roles, min_z_index)
|
|
60
|
-
use_api: Force use of server-side API if True, local extension if False.
|
|
61
|
-
If None, uses API if api_key is set, otherwise uses local extension.
|
|
62
|
-
save_trace: Whether to save raw_elements to JSON for benchmarking/training
|
|
63
|
-
trace_path: Path to save trace file. If None, uses "trace_{timestamp}.json"
|
|
64
|
-
show_overlay: Show visual overlay highlighting elements in browser
|
|
51
|
+
options: Snapshot options (screenshot, limit, filter, etc.)
|
|
52
|
+
If None, uses default options.
|
|
65
53
|
|
|
66
54
|
Returns:
|
|
67
55
|
Snapshot object
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
# Basic snapshot with defaults
|
|
59
|
+
snap = snapshot(browser)
|
|
60
|
+
|
|
61
|
+
# With options
|
|
62
|
+
snap = snapshot(browser, SnapshotOptions(
|
|
63
|
+
screenshot=True,
|
|
64
|
+
limit=100,
|
|
65
|
+
show_overlay=True
|
|
66
|
+
))
|
|
68
67
|
"""
|
|
69
|
-
#
|
|
70
|
-
options
|
|
71
|
-
|
|
72
|
-
limit=limit if limit is not None else 50,
|
|
73
|
-
filter=filter,
|
|
74
|
-
use_api=use_api,
|
|
75
|
-
save_trace=save_trace,
|
|
76
|
-
trace_path=trace_path,
|
|
77
|
-
show_overlay=show_overlay,
|
|
78
|
-
)
|
|
68
|
+
# Use default options if none provided
|
|
69
|
+
if options is None:
|
|
70
|
+
options = SnapshotOptions()
|
|
79
71
|
|
|
80
72
|
# Determine if we should use server-side API
|
|
81
73
|
should_use_api = (
|
sentience/text_search.py
CHANGED
|
@@ -88,6 +88,47 @@ def find_text_rect(
|
|
|
88
88
|
# Limit max_results to prevent performance issues
|
|
89
89
|
max_results = min(max_results, 100)
|
|
90
90
|
|
|
91
|
+
# CRITICAL: Wait for extension injection to complete (CSP-resistant architecture)
|
|
92
|
+
# The new architecture loads injected_api.js asynchronously, so window.sentience
|
|
93
|
+
# may not be immediately available after page load
|
|
94
|
+
try:
|
|
95
|
+
browser.page.wait_for_function(
|
|
96
|
+
"typeof window.sentience !== 'undefined'",
|
|
97
|
+
timeout=5000, # 5 second timeout
|
|
98
|
+
)
|
|
99
|
+
except Exception as e:
|
|
100
|
+
# Gather diagnostics if wait fails
|
|
101
|
+
try:
|
|
102
|
+
diag = browser.page.evaluate(
|
|
103
|
+
"""() => ({
|
|
104
|
+
sentience_defined: typeof window.sentience !== 'undefined',
|
|
105
|
+
extension_id: document.documentElement.dataset.sentienceExtensionId || 'not set',
|
|
106
|
+
url: window.location.href
|
|
107
|
+
})"""
|
|
108
|
+
)
|
|
109
|
+
except Exception:
|
|
110
|
+
diag = {"error": "Could not gather diagnostics"}
|
|
111
|
+
|
|
112
|
+
raise RuntimeError(
|
|
113
|
+
f"Sentience extension failed to inject window.sentience API. "
|
|
114
|
+
f"Is the extension loaded? Diagnostics: {diag}"
|
|
115
|
+
) from e
|
|
116
|
+
|
|
117
|
+
# Verify findTextRect method exists (for older extension versions that don't have it)
|
|
118
|
+
try:
|
|
119
|
+
has_find_text_rect = browser.page.evaluate(
|
|
120
|
+
"typeof window.sentience.findTextRect !== 'undefined'"
|
|
121
|
+
)
|
|
122
|
+
if not has_find_text_rect:
|
|
123
|
+
raise RuntimeError(
|
|
124
|
+
"window.sentience.findTextRect is not available. "
|
|
125
|
+
"Please update the Sentience extension to the latest version."
|
|
126
|
+
)
|
|
127
|
+
except RuntimeError:
|
|
128
|
+
raise
|
|
129
|
+
except Exception as e:
|
|
130
|
+
raise RuntimeError(f"Failed to verify findTextRect availability: {e}") from e
|
|
131
|
+
|
|
91
132
|
# Call the extension's findTextRect method
|
|
92
133
|
result_dict = browser.page.evaluate(
|
|
93
134
|
"""
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
Trace indexing module for Sentience SDK.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .indexer import build_trace_index, write_trace_index, read_step_events
|
|
6
5
|
from .index_schema import (
|
|
7
|
-
TraceIndex,
|
|
8
|
-
StepIndex,
|
|
9
|
-
TraceSummary,
|
|
10
|
-
TraceFileInfo,
|
|
11
|
-
SnapshotInfo,
|
|
12
6
|
ActionInfo,
|
|
7
|
+
SnapshotInfo,
|
|
13
8
|
StepCounters,
|
|
9
|
+
StepIndex,
|
|
10
|
+
TraceFileInfo,
|
|
11
|
+
TraceIndex,
|
|
12
|
+
TraceSummary,
|
|
14
13
|
)
|
|
14
|
+
from .indexer import build_trace_index, read_step_events, write_trace_index
|
|
15
15
|
|
|
16
16
|
__all__ = [
|
|
17
17
|
"build_trace_index",
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Type definitions for trace index schema using concrete classes.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from dataclasses import dataclass, field
|
|
6
|
-
from typing import
|
|
5
|
+
from dataclasses import asdict, dataclass, field
|
|
6
|
+
from typing import List, Literal, Optional
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@dataclass
|
|
@@ -27,7 +27,7 @@ class TraceSummary:
|
|
|
27
27
|
event_count: int
|
|
28
28
|
step_count: int
|
|
29
29
|
error_count: int
|
|
30
|
-
final_url:
|
|
30
|
+
final_url: str | None
|
|
31
31
|
|
|
32
32
|
def to_dict(self) -> dict:
|
|
33
33
|
return asdict(self)
|
|
@@ -37,9 +37,9 @@ class TraceSummary:
|
|
|
37
37
|
class SnapshotInfo:
|
|
38
38
|
"""Snapshot metadata for index."""
|
|
39
39
|
|
|
40
|
-
snapshot_id:
|
|
41
|
-
digest:
|
|
42
|
-
url:
|
|
40
|
+
snapshot_id: str | None = None
|
|
41
|
+
digest: str | None = None
|
|
42
|
+
url: str | None = None
|
|
43
43
|
|
|
44
44
|
def to_dict(self) -> dict:
|
|
45
45
|
return asdict(self)
|
|
@@ -49,10 +49,10 @@ class SnapshotInfo:
|
|
|
49
49
|
class ActionInfo:
|
|
50
50
|
"""Action metadata for index."""
|
|
51
51
|
|
|
52
|
-
type:
|
|
53
|
-
target_element_id:
|
|
54
|
-
args_digest:
|
|
55
|
-
success:
|
|
52
|
+
type: str | None = None
|
|
53
|
+
target_element_id: int | None = None
|
|
54
|
+
args_digest: str | None = None
|
|
55
|
+
success: bool | None = None
|
|
56
56
|
|
|
57
57
|
def to_dict(self) -> dict:
|
|
58
58
|
return asdict(self)
|
|
@@ -77,14 +77,14 @@ class StepIndex:
|
|
|
77
77
|
|
|
78
78
|
step_index: int
|
|
79
79
|
step_id: str
|
|
80
|
-
goal:
|
|
80
|
+
goal: str | None
|
|
81
81
|
status: Literal["ok", "error", "partial"]
|
|
82
82
|
ts_start: str
|
|
83
83
|
ts_end: str
|
|
84
84
|
offset_start: int
|
|
85
85
|
offset_end: int
|
|
86
|
-
url_before:
|
|
87
|
-
url_after:
|
|
86
|
+
url_before: str | None
|
|
87
|
+
url_after: str | None
|
|
88
88
|
snapshot_before: SnapshotInfo
|
|
89
89
|
snapshot_after: SnapshotInfo
|
|
90
90
|
action: ActionInfo
|
|
@@ -104,7 +104,7 @@ class TraceIndex:
|
|
|
104
104
|
created_at: str
|
|
105
105
|
trace_file: TraceFileInfo
|
|
106
106
|
summary: TraceSummary
|
|
107
|
-
steps:
|
|
107
|
+
steps: list[StepIndex] = field(default_factory=list)
|
|
108
108
|
|
|
109
109
|
def to_dict(self) -> dict:
|
|
110
110
|
"""Convert to dictionary for JSON serialization."""
|
|
@@ -10,13 +10,13 @@ from pathlib import Path
|
|
|
10
10
|
from typing import Any, Dict, List
|
|
11
11
|
|
|
12
12
|
from .index_schema import (
|
|
13
|
-
TraceIndex,
|
|
14
|
-
StepIndex,
|
|
15
|
-
TraceSummary,
|
|
16
|
-
TraceFileInfo,
|
|
17
|
-
SnapshotInfo,
|
|
18
13
|
ActionInfo,
|
|
14
|
+
SnapshotInfo,
|
|
19
15
|
StepCounters,
|
|
16
|
+
StepIndex,
|
|
17
|
+
TraceFileInfo,
|
|
18
|
+
TraceIndex,
|
|
19
|
+
TraceSummary,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ def _normalize_text(text: str | None, max_len: int = 80) -> str:
|
|
|
34
34
|
return normalized
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
def _round_bbox(bbox:
|
|
37
|
+
def _round_bbox(bbox: dict[str, float], precision: int = 2) -> dict[str, int]:
|
|
38
38
|
"""Round bbox coordinates to reduce noise (default: 2px precision)."""
|
|
39
39
|
return {
|
|
40
40
|
"x": round(bbox.get("x", 0) / precision) * precision,
|
|
@@ -44,7 +44,7 @@ def _round_bbox(bbox: Dict[str, float], precision: int = 2) -> Dict[str, int]:
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
def _compute_snapshot_digest(snapshot_data:
|
|
47
|
+
def _compute_snapshot_digest(snapshot_data: dict[str, Any]) -> str:
|
|
48
48
|
"""
|
|
49
49
|
Compute stable digest of snapshot for diffing.
|
|
50
50
|
|
|
@@ -62,9 +62,7 @@ def _compute_snapshot_digest(snapshot_data: Dict[str, Any]) -> str:
|
|
|
62
62
|
"id": elem.get("id"),
|
|
63
63
|
"role": elem.get("role", ""),
|
|
64
64
|
"text_norm": _normalize_text(elem.get("text")),
|
|
65
|
-
"bbox": _round_bbox(
|
|
66
|
-
elem.get("bbox", {"x": 0, "y": 0, "width": 0, "height": 0})
|
|
67
|
-
),
|
|
65
|
+
"bbox": _round_bbox(elem.get("bbox", {"x": 0, "y": 0, "width": 0, "height": 0})),
|
|
68
66
|
"is_primary": elem.get("is_primary", False),
|
|
69
67
|
"is_clickable": elem.get("is_clickable", False),
|
|
70
68
|
}
|
|
@@ -89,7 +87,7 @@ def _compute_snapshot_digest(snapshot_data: Dict[str, Any]) -> str:
|
|
|
89
87
|
return f"sha256:{digest}"
|
|
90
88
|
|
|
91
89
|
|
|
92
|
-
def _compute_action_digest(action_data:
|
|
90
|
+
def _compute_action_digest(action_data: dict[str, Any]) -> str:
|
|
93
91
|
"""
|
|
94
92
|
Compute digest of action args for privacy + determinism.
|
|
95
93
|
|
|
@@ -152,8 +150,8 @@ def build_trace_index(trace_path: str) -> TraceIndex:
|
|
|
152
150
|
error_count = 0
|
|
153
151
|
final_url = None
|
|
154
152
|
|
|
155
|
-
steps_by_id:
|
|
156
|
-
step_order:
|
|
153
|
+
steps_by_id: dict[str, StepIndex] = {}
|
|
154
|
+
step_order: list[str] = [] # Track order of first appearance
|
|
157
155
|
|
|
158
156
|
# Stream through file, tracking byte offsets
|
|
159
157
|
with open(trace_path, "rb") as f:
|
|
@@ -228,9 +226,7 @@ def build_trace_index(trace_path: str) -> TraceIndex:
|
|
|
228
226
|
)
|
|
229
227
|
step.url_before = step.url_before or url
|
|
230
228
|
|
|
231
|
-
step.snapshot_after = SnapshotInfo(
|
|
232
|
-
snapshot_id=snapshot_id, digest=digest, url=url
|
|
233
|
-
)
|
|
229
|
+
step.snapshot_after = SnapshotInfo(snapshot_id=snapshot_id, digest=digest, url=url)
|
|
234
230
|
step.url_after = url
|
|
235
231
|
step.counters.snapshots += 1
|
|
236
232
|
final_url = url
|
|
@@ -311,9 +307,7 @@ def write_trace_index(trace_path: str, index_path: str | None = None) -> str:
|
|
|
311
307
|
return index_path
|
|
312
308
|
|
|
313
309
|
|
|
314
|
-
def read_step_events(
|
|
315
|
-
trace_path: str, offset_start: int, offset_end: int
|
|
316
|
-
) -> List[Dict[str, Any]]:
|
|
310
|
+
def read_step_events(trace_path: str, offset_start: int, offset_end: int) -> list[dict[str, Any]]:
|
|
317
311
|
"""
|
|
318
312
|
Read events for a specific step using byte offsets from index.
|
|
319
313
|
|
sentience/wait.py
CHANGED
|
@@ -5,7 +5,7 @@ Wait functionality - wait_for element matching selector
|
|
|
5
5
|
import time
|
|
6
6
|
|
|
7
7
|
from .browser import SentienceBrowser
|
|
8
|
-
from .models import WaitResult
|
|
8
|
+
from .models import SnapshotOptions, WaitResult
|
|
9
9
|
from .query import find
|
|
10
10
|
from .snapshot import snapshot
|
|
11
11
|
|
|
@@ -46,7 +46,7 @@ def wait_for(
|
|
|
46
46
|
|
|
47
47
|
while time.time() - start_time < timeout:
|
|
48
48
|
# Take snapshot (may be local extension or remote API)
|
|
49
|
-
snap = snapshot(browser, use_api=use_api)
|
|
49
|
+
snap = snapshot(browser, SnapshotOptions(use_api=use_api))
|
|
50
50
|
|
|
51
51
|
# Try to find element
|
|
52
52
|
element = find(snap, selector)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sentienceapi
|
|
3
|
-
Version: 0.90.
|
|
3
|
+
Version: 0.90.16
|
|
4
4
|
Summary: Python SDK for Sentience AI Agent Browser Automation
|
|
5
5
|
Author: Sentience Team
|
|
6
|
-
License: MIT
|
|
6
|
+
License: MIT OR Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/SentienceAPI/sentience-python
|
|
8
8
|
Project-URL: Repository, https://github.com/SentienceAPI/sentience-python
|
|
9
9
|
Project-URL: Issues, https://github.com/SentienceAPI/sentience-python/issues
|
|
@@ -11,11 +11,14 @@ Keywords: browser-automation,playwright,ai-agent,web-automation,sentience
|
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
15
|
Classifier: Programming Language :: Python :: 3
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
17
|
Requires-Python: >=3.11
|
|
17
18
|
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
License-File: LICENSE-APACHE
|
|
21
|
+
License-File: LICENSE-MIT
|
|
19
22
|
Requires-Dist: playwright>=1.40.0
|
|
20
23
|
Requires-Dist: pydantic>=2.0.0
|
|
21
24
|
Requires-Dist: jsonschema>=4.0.0
|
|
@@ -29,7 +32,7 @@ Dynamic: license-file
|
|
|
29
32
|
|
|
30
33
|
# Sentience Python SDK
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
**Semantic geometry grounding for deterministic, debuggable AI web agents with time-travel traces.**
|
|
33
36
|
|
|
34
37
|
## 📦 Installation
|
|
35
38
|
|
|
@@ -201,18 +204,30 @@ with SentienceBrowser(headless=False) as browser:
|
|
|
201
204
|
<details>
|
|
202
205
|
<summary><h3>📸 Snapshot - Intelligent Page Analysis</h3></summary>
|
|
203
206
|
|
|
204
|
-
**`snapshot(browser, screenshot=True, show_overlay=False)`** - Capture page state with AI-ranked elements
|
|
207
|
+
**`snapshot(browser, options=SnapshotOptions(screenshot=True, show_overlay=False, limit=None, goal=None))`** - Capture page state with AI-ranked elements
|
|
205
208
|
|
|
206
209
|
Features:
|
|
207
210
|
- Returns semantic elements with roles, text, importance scores, and bounding boxes
|
|
208
|
-
- Optional screenshot capture (PNG/JPEG)
|
|
209
|
-
- Optional visual overlay to see what elements are detected
|
|
211
|
+
- Optional screenshot capture (PNG/JPEG) - set `screenshot=True`
|
|
212
|
+
- Optional visual overlay to see what elements are detected - set `show_overlay=True`
|
|
210
213
|
- Pydantic models for type safety
|
|
214
|
+
- Optional ML reranking when `goal` is provided
|
|
211
215
|
- **`snapshot.save(filepath)`** - Export to JSON
|
|
212
216
|
|
|
213
217
|
**Example:**
|
|
214
218
|
```python
|
|
215
|
-
|
|
219
|
+
from sentience import snapshot, SnapshotOptions
|
|
220
|
+
|
|
221
|
+
# Basic snapshot with defaults (no screenshot, no overlay)
|
|
222
|
+
snap = snapshot(browser)
|
|
223
|
+
|
|
224
|
+
# With screenshot and overlay
|
|
225
|
+
snap = snapshot(browser, SnapshotOptions(
|
|
226
|
+
screenshot=True,
|
|
227
|
+
show_overlay=True,
|
|
228
|
+
limit=100,
|
|
229
|
+
goal="Click the login button" # Optional: enables ML reranking
|
|
230
|
+
))
|
|
216
231
|
|
|
217
232
|
# Access structured data
|
|
218
233
|
print(f"URL: {snap.url}")
|
|
@@ -222,6 +237,10 @@ print(f"Elements: {len(snap.elements)}")
|
|
|
222
237
|
# Iterate over elements
|
|
223
238
|
for element in snap.elements:
|
|
224
239
|
print(f"{element.role}: {element.text} (importance: {element.importance})")
|
|
240
|
+
|
|
241
|
+
# Check ML reranking metadata (when goal is provided)
|
|
242
|
+
if element.rerank_index is not None:
|
|
243
|
+
print(f" ML rank: {element.rerank_index} (confidence: {element.ml_probability:.2%})")
|
|
225
244
|
```
|
|
226
245
|
|
|
227
246
|
</details>
|
|
@@ -500,6 +519,28 @@ for match in result.results:
|
|
|
500
519
|
|
|
501
520
|
---
|
|
502
521
|
|
|
522
|
+
## 🔄 Async API
|
|
523
|
+
|
|
524
|
+
For asyncio contexts (FastAPI, async frameworks):
|
|
525
|
+
|
|
526
|
+
```python
|
|
527
|
+
from sentience.async_api import AsyncSentienceBrowser, snapshot_async, click_async, find
|
|
528
|
+
|
|
529
|
+
async def main():
|
|
530
|
+
async with AsyncSentienceBrowser() as browser:
|
|
531
|
+
await browser.goto("https://example.com")
|
|
532
|
+
snap = await snapshot_async(browser)
|
|
533
|
+
button = find(snap, "role=button")
|
|
534
|
+
if button:
|
|
535
|
+
await click_async(browser, button.id)
|
|
536
|
+
|
|
537
|
+
asyncio.run(main())
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**See example:** `examples/async_api_demo.py`
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
503
544
|
## 📋 Reference
|
|
504
545
|
|
|
505
546
|
<details>
|
|
@@ -695,7 +736,7 @@ if result.url_changed:
|
|
|
695
736
|
snap = snapshot(browser)
|
|
696
737
|
|
|
697
738
|
# Slower - with screenshot (for debugging/verification)
|
|
698
|
-
snap = snapshot(browser, screenshot=True)
|
|
739
|
+
snap = snapshot(browser, SnapshotOptions(screenshot=True))
|
|
699
740
|
```
|
|
700
741
|
|
|
701
742
|
</details>
|
|
@@ -859,20 +900,17 @@ pytest -v tests/
|
|
|
859
900
|
|
|
860
901
|
---
|
|
861
902
|
|
|
862
|
-
##
|
|
863
|
-
|
|
864
|
-
This SDK is licensed under the **Elastic License 2.0 (ELv2)**.
|
|
865
|
-
|
|
866
|
-
The Elastic License 2.0 allows you to use, modify, and distribute this SDK for internal, research, and non-competitive purposes. It **does not permit offering this SDK or a derivative as a hosted or managed service**, nor using it to build a competing product or service.
|
|
867
|
-
|
|
868
|
-
### Important Notes
|
|
869
|
-
|
|
870
|
-
- This SDK is a **client-side library** that communicates with proprietary Sentience services and browser components.
|
|
903
|
+
## License & Commercial Use
|
|
871
904
|
|
|
872
|
-
|
|
905
|
+
### Open Source SDK
|
|
906
|
+
The Sentience SDK is dual-licensed under [MIT License](./LICENSE-MIT) and [Apache 2.0](./LICENSE-APACHE). You are free to use, modify, and distribute this SDK in your own projects (including commercial ones) without restriction.
|
|
873
907
|
|
|
874
|
-
|
|
908
|
+
### Commercial Platform
|
|
909
|
+
While the SDK is open source, the **Sentience Cloud Platform** (API, Hosting, Sentience Studio) is a commercial service.
|
|
875
910
|
|
|
876
|
-
|
|
911
|
+
**We offer Commercial Licenses for:**
|
|
912
|
+
* **High-Volume Production:** Usage beyond the free tier limits.
|
|
913
|
+
* **SLA & Support:** Guaranteed uptime and dedicated engineering support.
|
|
914
|
+
* **On-Premise / Self-Hosted Gateway:** If you need to run the Sentience Gateway (Rust+ONNX) in your own VPC for compliance (e.g., banking/healthcare), you need an Enterprise License.
|
|
877
915
|
|
|
878
|
-
|
|
916
|
+
[Contact Us](mailto:support@sentienceapi.com) for Enterprise inquiries.
|
|
@@ -1,46 +1,50 @@
|
|
|
1
|
-
sentience/__init__.py,sha256=
|
|
1
|
+
sentience/__init__.py,sha256=SFq6-EcrT4HxKerSK3eaZynY703myzFq-fOi5K3YJ3A,3410
|
|
2
|
+
sentience/_extension_loader.py,sha256=bnZgVE5eZnUk18i2Wm8gplsVekq-fB31DNWOZt5iWpw,1356
|
|
2
3
|
sentience/actions.py,sha256=RT8AoR_CNyp6bMCYhkToWH1WB8cyB8dcFJZMhfskTeo,13239
|
|
3
|
-
sentience/agent.py,sha256=
|
|
4
|
+
sentience/agent.py,sha256=IKSxDDCyMyGx8mMvIT4kq3HXtKNaK7BiHNGXnxHCkZc,23844
|
|
4
5
|
sentience/agent_config.py,sha256=blyCUh2pjMOI6YQGLWP8mSi6GTnpzWLWem4nwYg3ngA,1489
|
|
6
|
+
sentience/async_api.py,sha256=NSAM8XO9_ZjqVdOjMEwkeih2BKCXVgUHe7S2T5n8slg,38721
|
|
5
7
|
sentience/base_agent.py,sha256=861XkIJeig9nqdt7f2wfFKyxanGZtDhnrgsMDdXtkFM,2979
|
|
6
|
-
sentience/browser.py,sha256=
|
|
8
|
+
sentience/browser.py,sha256=Mnok-PZPbZVZUAEX9FVIANyaRrjIxaXA7fk6BBegFDo,24388
|
|
7
9
|
sentience/cli.py,sha256=R95DgCSJmezuymAdfL6fzUdB1HpCF3iMWcLO73KJ8eY,3851
|
|
8
|
-
sentience/cloud_tracing.py,sha256=
|
|
9
|
-
sentience/conversational_agent.py,sha256=
|
|
10
|
+
sentience/cloud_tracing.py,sha256=zQv42I7GOoBXMhH5f_RUx8DT_r5IXv2kQOCeAXcMCYQ,13495
|
|
11
|
+
sentience/conversational_agent.py,sha256=8o2bvdaxoqgK-hHM1AVOywwKWyZturp1oLFcl6JtqCw,17258
|
|
10
12
|
sentience/expect.py,sha256=BFSRocNJr6ZAusb6fy4OgfDNCukGfu5jto760bFN12E,2851
|
|
11
13
|
sentience/formatting.py,sha256=0_UklIUd94a4W32gTorjxoXNE03qdffR-omfTA5eHF0,1828
|
|
12
14
|
sentience/generator.py,sha256=Wj--yn6bVo02nABBzrAIKPMmU8TRQm3JHAOER9XXT4Y,8035
|
|
13
15
|
sentience/inspector.py,sha256=TvLi0DIjeFcWdBVqroCMMtN98SX11fLmjg5Tg5dlSdU,7244
|
|
14
|
-
sentience/llm_provider.py,sha256=
|
|
15
|
-
sentience/models.py,sha256=
|
|
16
|
+
sentience/llm_provider.py,sha256=ylDMUYYbk83Nh9kW6jNvmtg_vS44AersDrii39_Y6m4,20566
|
|
17
|
+
sentience/models.py,sha256=Y-EF7DN5f1PyYp6z9vlYqjEKusjiKzxCqitzPrIJ--w,13242
|
|
16
18
|
sentience/overlay.py,sha256=lPCqLhLGPnBk5X-W4oAaLGI54Pl_VLCS8P1b7PFUdlo,3857
|
|
17
19
|
sentience/query.py,sha256=P9Hs3otwESNncaArUwaw73mNNRFeOgpjy-fOTDQiCOI,10474
|
|
18
20
|
sentience/read.py,sha256=qoSbahcNumvb0mUe-WcWrKrkKCEqya6Ac7wqXFe3SRI,3490
|
|
19
21
|
sentience/recorder.py,sha256=RWzkJP6LWiFAJUfbXQS3aAnRgl7aDrWuKw3slp-gR1Y,12496
|
|
20
22
|
sentience/screenshot.py,sha256=1UJjRvPxPpiL3w1_MBvO_UPMAsmt-uyRujTYA50jim0,1607
|
|
21
|
-
sentience/snapshot.py,sha256=
|
|
22
|
-
sentience/text_search.py,sha256=
|
|
23
|
+
sentience/snapshot.py,sha256=_tR6LTH5Hvam80zEVW3zzvHV4xu5BwALNle4hq12IZU,9266
|
|
24
|
+
sentience/text_search.py,sha256=UF7-Dlo69Stx_vkfcu5ss3dKCVgyWODrafJoJXU9NCw,5753
|
|
23
25
|
sentience/tracer_factory.py,sha256=Fc_kb8ffJVGdy91cnxpxU2xjFZUyS2OiaI2pqtvl2lk,7643
|
|
24
26
|
sentience/tracing.py,sha256=ciYSW3QXcO0BYDtjeKQLfpAysObBIKQKCAlviwU74AQ,7240
|
|
25
27
|
sentience/utils.py,sha256=ryxiDVE_sUPHYmYnWYXADuyciD_ZawmsITDZNUeDVJg,8116
|
|
26
|
-
sentience/wait.py,sha256=
|
|
28
|
+
sentience/wait.py,sha256=BYPK96YU0iza6tjPD-hS01ud48j3ECHgM9TmnemRA5k,2229
|
|
27
29
|
sentience/extension/background.js,sha256=hnK32hVtHJrLtzBeXt2beRmMzr1l0U82r8zZEXyOibk,8954
|
|
28
30
|
sentience/extension/content.js,sha256=UIuFCDTVTkXdaiXB8LMf0OP8SB_WMrMoaav5ZBXmeIo,10442
|
|
29
31
|
sentience/extension/injected_api.js,sha256=Pr5j9MGJTInPOKfKKNuaMDjOJSK3ygM-HlmWAUUS-Yg,63790
|
|
30
32
|
sentience/extension/manifest.json,sha256=MfkfsS5zVxb-scqJllN8aubrRN9vsznQ3-Aw69pZ47c,897
|
|
31
|
-
sentience/extension/release.json,sha256=
|
|
33
|
+
sentience/extension/release.json,sha256=SnuTzbdXcwAsP4dhp9fMfzlf0wDsaj8Wyn_PpCsOThM,6437
|
|
32
34
|
sentience/extension/test-content.js,sha256=RX6A42W-5pjP-avqGwrRq_GVp5yX2NqBDlDLc-SWL5g,156
|
|
33
35
|
sentience/extension/pkg/sentience_core.d.ts,sha256=qrTEIR2WPkk1MmaSQzEpRyagbE9VirHowzZpbj41qeQ,1981
|
|
34
36
|
sentience/extension/pkg/sentience_core.js,sha256=zldlOubec0pbNYhquwDzoQKuBF4SUVcIeXW_qLx0dVA,17904
|
|
35
37
|
sentience/extension/pkg/sentience_core_bg.wasm,sha256=HtzBY8z4XgRgHHUqHQGm84EEQJirpf25wSVTXg-iJ1g,102522
|
|
36
38
|
sentience/extension/pkg/sentience_core_bg.wasm.d.ts,sha256=O3c3HaUqmB6Aob6Pt0n3GEtTxM4VGeaClaA_-z2m2J4,517
|
|
37
39
|
sentience/schemas/trace_v1.json,sha256=XpByPqRH1xzHmD7YeuaDE5ZaEb3L5fz762djcwXqPV8,7593
|
|
38
|
-
sentience/trace_indexing/__init__.py,sha256=
|
|
39
|
-
sentience/trace_indexing/index_schema.py,sha256=
|
|
40
|
-
sentience/trace_indexing/indexer.py,sha256=
|
|
41
|
-
sentienceapi-0.90.
|
|
42
|
-
sentienceapi-0.90.
|
|
43
|
-
sentienceapi-0.90.
|
|
44
|
-
sentienceapi-0.90.
|
|
45
|
-
sentienceapi-0.90.
|
|
46
|
-
sentienceapi-0.90.
|
|
40
|
+
sentience/trace_indexing/__init__.py,sha256=urjLuqqXCQE8pnwpYBqoMKnzZSqFJkM1SHmFve9RVE8,499
|
|
41
|
+
sentience/trace_indexing/index_schema.py,sha256=Hz9igHFrHATTZOqKNiLhESjnGbDPTyRTejMGT1AKC8g,2180
|
|
42
|
+
sentience/trace_indexing/indexer.py,sha256=m-p57Va0cFlCpuMWkXNSHqODpGzpESZzoOkt3OiejlM,10811
|
|
43
|
+
sentienceapi-0.90.16.dist-info/licenses/LICENSE,sha256=jePeclQKwKdmz3jc0Oec6-jQuzwxIcGWPhMfxVII34Q,924
|
|
44
|
+
sentienceapi-0.90.16.dist-info/licenses/LICENSE-APACHE,sha256=YIflUygmGOc0hS_1f6EacrQUrH73G3j8VBQbDoqmY6A,11352
|
|
45
|
+
sentienceapi-0.90.16.dist-info/licenses/LICENSE-MIT,sha256=KiWwku3f8ikn6c8a6t0IdelVEu5GBLLr4tUKdGNNgJ8,1082
|
|
46
|
+
sentienceapi-0.90.16.dist-info/METADATA,sha256=Nlotvwvkv5WMtT5avm1aqoyCRbT1qgqL0kKZL2d8pfQ,27286
|
|
47
|
+
sentienceapi-0.90.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
48
|
+
sentienceapi-0.90.16.dist-info/entry_points.txt,sha256=HdW1BvgRJm3ZAbbqrwTvDWE2KbmVz-Ue0wllW-mLmvA,49
|
|
49
|
+
sentienceapi-0.90.16.dist-info/top_level.txt,sha256=A9IKao--8PsFFz5vDfBIXWHgN6oh3HkMQSiQWgUTUBQ,10
|
|
50
|
+
sentienceapi-0.90.16.dist-info/RECORD,,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
This project is dual-licensed under your choice of either:
|
|
4
|
+
|
|
5
|
+
* **MIT License** ([LICENSE-MIT](./LICENSE-MIT))
|
|
6
|
+
* **Apache License 2.0** ([LICENSE-APACHE](./LICENSE-APACHE))
|
|
7
|
+
|
|
8
|
+
## Choosing a License
|
|
9
|
+
|
|
10
|
+
You may use this software under the terms of either license, at your option.
|
|
11
|
+
|
|
12
|
+
### MIT License
|
|
13
|
+
The MIT License is a permissive license that is short and to the point. It lets people do almost anything they want with your project, like making and distributing closed source versions.
|
|
14
|
+
|
|
15
|
+
### Apache License 2.0
|
|
16
|
+
The Apache License 2.0 is also a permissive license, similar to MIT, but it also provides an express grant of patent rights from contributors to users.
|
|
17
|
+
|
|
18
|
+
## Contribution
|
|
19
|
+
|
|
20
|
+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you shall be dual-licensed as above, without any additional terms or conditions.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
Copyright (c) 2025 Sentience Contributors
|