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/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
- screenshot: bool | None = None,
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
- screenshot: Whether to capture screenshot (bool or dict with format/quality)
58
- limit: Limit number of elements returned
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
- # Build SnapshotOptions from individual parameters
70
- options = SnapshotOptions(
71
- screenshot=screenshot if screenshot is not None else False,
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, asdict
6
- from typing import Optional, List, Literal
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: Optional[str]
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: Optional[str] = None
41
- digest: Optional[str] = None
42
- url: Optional[str] = None
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: Optional[str] = None
53
- target_element_id: Optional[int] = None
54
- args_digest: Optional[str] = None
55
- success: Optional[bool] = None
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: Optional[str]
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: Optional[str]
87
- url_after: Optional[str]
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: List[StepIndex] = field(default_factory=list)
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: Dict[str, float], precision: int = 2) -> Dict[str, int]:
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: Dict[str, Any]) -> str:
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: Dict[str, Any]) -> str:
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: Dict[str, StepIndex] = {}
156
- step_order: List[str] = [] # Track order of first appearance
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.9
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.md
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
- The SDK is open under ELv2; the core semantic geometry and reliability logic runs in Sentience-hosted services.
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
- snap = snapshot(browser, screenshot=True, show_overlay=True)
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
- ## 📜 License
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
- - The Sentience backend services (including semantic geometry grounding, ranking, visual cues, and trace processing) are **not open source** and are governed by Sentience's Terms of Service.
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
- - Use of this SDK does **not** grant rights to operate, replicate, or reimplement Sentience's hosted services.
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
- For commercial usage, hosted offerings, or enterprise deployments, please contact Sentience to obtain a commercial license.
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
- See the full license text in [`LICENSE`](./LICENSE.md).
916
+ [Contact Us](mailto:support@sentienceapi.com) for Enterprise inquiries.
@@ -1,46 +1,50 @@
1
- sentience/__init__.py,sha256=5zlE1tx4AhGypFVLtRPpNTWu-GclCfjXpPhABz1WaBM,3409
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=rTAaQGiuZIohrJZXpCK-dZWuoAR3k_dQodjFLBkrCxY,24527
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=At0VYO3oagyaMrUcs6w2TxISztrQxSWpGpuSmVsAqwQ,17441
8
+ sentience/browser.py,sha256=Mnok-PZPbZVZUAEX9FVIANyaRrjIxaXA7fk6BBegFDo,24388
7
9
  sentience/cli.py,sha256=R95DgCSJmezuymAdfL6fzUdB1HpCF3iMWcLO73KJ8eY,3851
8
- sentience/cloud_tracing.py,sha256=Y_20sdvOiYoavIJWh_ogZYb6H3RMRP59uM9p4u3QrGo,10128
9
- sentience/conversational_agent.py,sha256=UUgltp-EkAbAzE6Pa_S72t7fWbdIwb3C2YppXzPx2jA,17207
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=BehSZgSsupT2E60EXAlAupgAhs_iVTNr-UGwFbVxOAs,13922
15
- sentience/models.py,sha256=uFMRu_B0J1K65z9GFFGCQ6dlW91Lbv6f-qL0qEiDeXc,12838
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=zFQa-jGh8MBPuyvZZ3kam_d8qN93UtmigCvj9m2V5Ts,9947
22
- sentience/text_search.py,sha256=Xu4dhU8_SYyv_MPWbChEZ8wTYvM-gzVsffxqtWBMx2s,4073
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=8E_5aRS3GJ4igDwWzMJvIV6ENPsqX19JGwXCPAMkX6s,2195
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=gblo3-etdwlWMB1JIIhyXwZeVhM3voNi7982xG58D8M,6437
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=LuLRaq3Wjc1dZn9eXxI426oE_nahep-XadtsLMDIHSw,499
39
- sentience/trace_indexing/index_schema.py,sha256=hgkb2vUUQ_aqfa6DN5MR2wMjDvGtbfGmyGXNA_07IZg,2213
40
- sentience/trace_indexing/indexer.py,sha256=mqayI_Hl160Yb_3OBF3G-zsfZ3Stc8dNDMjebDJvAcs,10885
41
- sentienceapi-0.90.9.dist-info/licenses/LICENSE.md,sha256=Pl8BWUOOkFtYpgVhNwCl3YKzRvUpYid2utlJELIgr_8,3783
42
- sentienceapi-0.90.9.dist-info/METADATA,sha256=dIKUAlvVW104gGxMLayOAYPqQv8pD7sFDbgN64hc304,26130
43
- sentienceapi-0.90.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
- sentienceapi-0.90.9.dist-info/entry_points.txt,sha256=HdW1BvgRJm3ZAbbqrwTvDWE2KbmVz-Ue0wllW-mLmvA,49
45
- sentienceapi-0.90.9.dist-info/top_level.txt,sha256=A9IKao--8PsFFz5vDfBIXWHgN6oh3HkMQSiQWgUTUBQ,10
46
- sentienceapi-0.90.9.dist-info/RECORD,,
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