sentienceapi 0.90.9__py3-none-any.whl → 0.90.12__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 CHANGED
@@ -70,7 +70,7 @@ from .utils import (
70
70
  )
71
71
  from .wait import wait_for
72
72
 
73
- __version__ = "0.90.9"
73
+ __version__ = "0.90.12"
74
74
 
75
75
  __all__ = [
76
76
  # Core SDK
sentience/browser.py CHANGED
@@ -33,6 +33,8 @@ class SentienceBrowser:
33
33
  proxy: str | None = None,
34
34
  user_data_dir: str | None = None,
35
35
  storage_state: str | Path | StorageState | dict | None = None,
36
+ record_video_dir: str | Path | None = None,
37
+ record_video_size: dict[str, int] | None = None,
36
38
  ):
37
39
  """
38
40
  Initialize Sentience browser
@@ -57,6 +59,14 @@ class SentienceBrowser:
57
59
  - StorageState object
58
60
  - Dictionary with 'cookies' and/or 'origins' keys
59
61
  If provided, browser starts with pre-injected authentication.
62
+ record_video_dir: Optional directory path to save video recordings.
63
+ If provided, browser will record video of all pages.
64
+ Videos are saved as .webm files in the specified directory.
65
+ If None, no video recording is performed.
66
+ record_video_size: Optional video resolution as dict with 'width' and 'height' keys.
67
+ Examples: {"width": 1280, "height": 800} (default)
68
+ {"width": 1920, "height": 1080} (1080p)
69
+ If None, defaults to 1280x800.
60
70
  """
61
71
  self.api_key = api_key
62
72
  # Only set api_url if api_key is provided, otherwise None (free tier)
@@ -80,6 +90,10 @@ class SentienceBrowser:
80
90
  self.user_data_dir = user_data_dir
81
91
  self.storage_state = storage_state
82
92
 
93
+ # Video recording support
94
+ self.record_video_dir = record_video_dir
95
+ self.record_video_size = record_video_size or {"width": 1280, "height": 800}
96
+
83
97
  self.playwright: Playwright | None = None
84
98
  self.context: BrowserContext | None = None
85
99
  self.page: Page | None = None
@@ -209,6 +223,17 @@ class SentienceBrowser:
209
223
  launch_params["ignore_https_errors"] = True
210
224
  print(f"🌐 [Sentience] Using proxy: {proxy_config.server}")
211
225
 
226
+ # Add video recording if configured
227
+ if self.record_video_dir:
228
+ video_dir = Path(self.record_video_dir)
229
+ video_dir.mkdir(parents=True, exist_ok=True)
230
+ launch_params["record_video_dir"] = str(video_dir)
231
+ launch_params["record_video_size"] = self.record_video_size
232
+ print(f"🎥 [Sentience] Recording video to: {video_dir}")
233
+ print(
234
+ f" Resolution: {self.record_video_size['width']}x{self.record_video_size['height']}"
235
+ )
236
+
212
237
  # Launch persistent context (required for extensions)
213
238
  # Note: We pass headless=False to launch_persistent_context because we handle
214
239
  # headless mode via the --headless=new arg above. This is a Playwright workaround.
@@ -390,15 +415,71 @@ class SentienceBrowser:
390
415
 
391
416
  return False
392
417
 
393
- def close(self) -> None:
394
- """Close browser and cleanup"""
418
+ def close(self, output_path: str | Path | None = None) -> str | None:
419
+ """
420
+ Close browser and cleanup
421
+
422
+ Args:
423
+ output_path: Optional path to rename the video file to.
424
+ If provided, the recorded video will be moved to this location.
425
+ Useful for giving videos meaningful names instead of random hashes.
426
+
427
+ Returns:
428
+ Path to video file if recording was enabled, None otherwise
429
+ Note: Video files are saved automatically by Playwright when context closes.
430
+ If multiple pages exist, returns the path to the first page's video.
431
+ """
432
+ temp_video_path = None
433
+
434
+ # Get video path before closing (if recording was enabled)
435
+ # Note: Playwright saves videos when pages/context close, but we can get the
436
+ # expected path before closing. The actual file will be available after close.
437
+ if self.record_video_dir:
438
+ try:
439
+ # Try to get video path from the first page
440
+ if self.page and self.page.video:
441
+ temp_video_path = self.page.video.path()
442
+ # If that fails, check all pages in the context
443
+ elif self.context:
444
+ for page in self.context.pages:
445
+ if page.video:
446
+ temp_video_path = page.video.path()
447
+ break
448
+ except Exception:
449
+ # Video path might not be available until after close
450
+ # In that case, we'll return None and user can check the directory
451
+ pass
452
+
453
+ # Close context (this triggers video file finalization)
395
454
  if self.context:
396
455
  self.context.close()
456
+
457
+ # Close playwright
397
458
  if self.playwright:
398
459
  self.playwright.stop()
460
+
461
+ # Clean up extension directory
399
462
  if self._extension_path and os.path.exists(self._extension_path):
400
463
  shutil.rmtree(self._extension_path)
401
464
 
465
+ # Rename/move video if output_path is specified
466
+ final_path = temp_video_path
467
+ if temp_video_path and output_path and os.path.exists(temp_video_path):
468
+ try:
469
+ output_path = str(output_path)
470
+ # Ensure parent directory exists
471
+ Path(output_path).parent.mkdir(parents=True, exist_ok=True)
472
+ shutil.move(temp_video_path, output_path)
473
+ final_path = output_path
474
+ except Exception as e:
475
+ import warnings
476
+
477
+ warnings.warn(f"Failed to rename video file: {e}")
478
+ # Return original path if rename fails
479
+ final_path = temp_video_path
480
+
481
+ return final_path
482
+
402
483
  def __enter__(self):
403
484
  """Context manager entry"""
404
485
  self.start()
@@ -213,7 +213,10 @@ class CloudTraceSink(TraceSink):
213
213
  if on_progress:
214
214
  on_progress(compressed_size, compressed_size)
215
215
 
216
- # Call /v1/traces/complete to report file sizes (NEW)
216
+ # Upload trace index file
217
+ self._upload_index()
218
+
219
+ # Call /v1/traces/complete to report file sizes
217
220
  self._complete_trace()
218
221
 
219
222
  # Delete file only on successful upload
@@ -244,6 +247,95 @@ class CloudTraceSink(TraceSink):
244
247
  # Non-fatal: log but don't crash
245
248
  print(f"⚠️ Failed to generate trace index: {e}")
246
249
 
250
+ def _upload_index(self) -> None:
251
+ """
252
+ Upload trace index file to cloud storage.
253
+
254
+ Called after successful trace upload to provide fast timeline rendering.
255
+ The index file enables O(1) step lookups without parsing the entire trace.
256
+ """
257
+ # Construct index file path (same as trace file with .index.json extension)
258
+ index_path = Path(str(self._path).replace(".jsonl", ".index.json"))
259
+
260
+ if not index_path.exists():
261
+ if self.logger:
262
+ self.logger.warning("Index file not found, skipping index upload")
263
+ return
264
+
265
+ try:
266
+ # Request index upload URL from API
267
+ if not self.api_key:
268
+ # No API key - skip index upload
269
+ if self.logger:
270
+ self.logger.info("No API key provided, skipping index upload")
271
+ return
272
+
273
+ response = requests.post(
274
+ f"{self.api_url}/v1/traces/index_upload",
275
+ headers={"Authorization": f"Bearer {self.api_key}"},
276
+ json={"run_id": self.run_id},
277
+ timeout=10,
278
+ )
279
+
280
+ if response.status_code != 200:
281
+ if self.logger:
282
+ self.logger.warning(
283
+ f"Failed to get index upload URL: HTTP {response.status_code}"
284
+ )
285
+ return
286
+
287
+ upload_data = response.json()
288
+ index_upload_url = upload_data.get("upload_url")
289
+
290
+ if not index_upload_url:
291
+ if self.logger:
292
+ self.logger.warning("No upload URL in index upload response")
293
+ return
294
+
295
+ # Read and compress index file
296
+ with open(index_path, "rb") as f:
297
+ index_data = f.read()
298
+
299
+ compressed_index = gzip.compress(index_data)
300
+ index_size = len(compressed_index)
301
+
302
+ if self.logger:
303
+ self.logger.info(f"Index file size: {index_size / 1024:.2f} KB")
304
+
305
+ print(f"📤 [Sentience] Uploading trace index ({index_size} bytes)...")
306
+
307
+ # Upload index to cloud storage
308
+ index_response = requests.put(
309
+ index_upload_url,
310
+ data=compressed_index,
311
+ headers={
312
+ "Content-Type": "application/json",
313
+ "Content-Encoding": "gzip",
314
+ },
315
+ timeout=30,
316
+ )
317
+
318
+ if index_response.status_code == 200:
319
+ print("✅ [Sentience] Trace index uploaded successfully")
320
+
321
+ # Delete local index file after successful upload
322
+ try:
323
+ os.remove(index_path)
324
+ except Exception:
325
+ pass # Ignore cleanup errors
326
+ else:
327
+ if self.logger:
328
+ self.logger.warning(
329
+ f"Index upload failed: HTTP {index_response.status_code}"
330
+ )
331
+ print(f"⚠️ [Sentience] Index upload failed: HTTP {index_response.status_code}")
332
+
333
+ except Exception as e:
334
+ # Non-fatal: log but don't crash
335
+ if self.logger:
336
+ self.logger.warning(f"Error uploading trace index: {e}")
337
+ print(f"⚠️ [Sentience] Error uploading trace index: {e}")
338
+
247
339
  def _complete_trace(self) -> None:
248
340
  """
249
341
  Call /v1/traces/complete to report file sizes to gateway.
@@ -67,7 +67,7 @@
67
67
  "state": "uploaded",
68
68
  "size": 78091,
69
69
  "digest": "sha256:e281f8b755b61da4b8015d6172064aa9a337c14133ceceff4ab29199ee53307e",
70
- "download_count": 0,
70
+ "download_count": 2,
71
71
  "created_at": "2025-12-29T03:57:09Z",
72
72
  "updated_at": "2025-12-29T03:57:09Z",
73
73
  "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.7/extension-files.tar.gz"
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentienceapi
3
- Version: 0.90.9
3
+ Version: 0.90.12
4
4
  Summary: Python SDK for Sentience AI Agent Browser Automation
5
5
  Author: Sentience Team
6
6
  License: MIT
@@ -1,11 +1,11 @@
1
- sentience/__init__.py,sha256=5zlE1tx4AhGypFVLtRPpNTWu-GclCfjXpPhABz1WaBM,3409
1
+ sentience/__init__.py,sha256=DETDLYDNA_A5llT6mjgcvB4FPuCELiD8ppsz3hvTEbs,3410
2
2
  sentience/actions.py,sha256=RT8AoR_CNyp6bMCYhkToWH1WB8cyB8dcFJZMhfskTeo,13239
3
3
  sentience/agent.py,sha256=rTAaQGiuZIohrJZXpCK-dZWuoAR3k_dQodjFLBkrCxY,24527
4
4
  sentience/agent_config.py,sha256=blyCUh2pjMOI6YQGLWP8mSi6GTnpzWLWem4nwYg3ngA,1489
5
5
  sentience/base_agent.py,sha256=861XkIJeig9nqdt7f2wfFKyxanGZtDhnrgsMDdXtkFM,2979
6
- sentience/browser.py,sha256=At0VYO3oagyaMrUcs6w2TxISztrQxSWpGpuSmVsAqwQ,17441
6
+ sentience/browser.py,sha256=jB59HfZHHUOKTORA7gsaQlIKEZyxwivvW4VU9swyy_k,21311
7
7
  sentience/cli.py,sha256=R95DgCSJmezuymAdfL6fzUdB1HpCF3iMWcLO73KJ8eY,3851
8
- sentience/cloud_tracing.py,sha256=Y_20sdvOiYoavIJWh_ogZYb6H3RMRP59uM9p4u3QrGo,10128
8
+ sentience/cloud_tracing.py,sha256=KxVIT-HQW9EaX5GWC9DEVM2cdObomD3hkPNEnTceSpc,13541
9
9
  sentience/conversational_agent.py,sha256=UUgltp-EkAbAzE6Pa_S72t7fWbdIwb3C2YppXzPx2jA,17207
10
10
  sentience/expect.py,sha256=BFSRocNJr6ZAusb6fy4OgfDNCukGfu5jto760bFN12E,2851
11
11
  sentience/formatting.py,sha256=0_UklIUd94a4W32gTorjxoXNE03qdffR-omfTA5eHF0,1828
@@ -19,7 +19,7 @@ sentience/read.py,sha256=qoSbahcNumvb0mUe-WcWrKrkKCEqya6Ac7wqXFe3SRI,3490
19
19
  sentience/recorder.py,sha256=RWzkJP6LWiFAJUfbXQS3aAnRgl7aDrWuKw3slp-gR1Y,12496
20
20
  sentience/screenshot.py,sha256=1UJjRvPxPpiL3w1_MBvO_UPMAsmt-uyRujTYA50jim0,1607
21
21
  sentience/snapshot.py,sha256=zFQa-jGh8MBPuyvZZ3kam_d8qN93UtmigCvj9m2V5Ts,9947
22
- sentience/text_search.py,sha256=Xu4dhU8_SYyv_MPWbChEZ8wTYvM-gzVsffxqtWBMx2s,4073
22
+ sentience/text_search.py,sha256=UF7-Dlo69Stx_vkfcu5ss3dKCVgyWODrafJoJXU9NCw,5753
23
23
  sentience/tracer_factory.py,sha256=Fc_kb8ffJVGdy91cnxpxU2xjFZUyS2OiaI2pqtvl2lk,7643
24
24
  sentience/tracing.py,sha256=ciYSW3QXcO0BYDtjeKQLfpAysObBIKQKCAlviwU74AQ,7240
25
25
  sentience/utils.py,sha256=ryxiDVE_sUPHYmYnWYXADuyciD_ZawmsITDZNUeDVJg,8116
@@ -28,19 +28,19 @@ sentience/extension/background.js,sha256=hnK32hVtHJrLtzBeXt2beRmMzr1l0U82r8zZEXy
28
28
  sentience/extension/content.js,sha256=UIuFCDTVTkXdaiXB8LMf0OP8SB_WMrMoaav5ZBXmeIo,10442
29
29
  sentience/extension/injected_api.js,sha256=Pr5j9MGJTInPOKfKKNuaMDjOJSK3ygM-HlmWAUUS-Yg,63790
30
30
  sentience/extension/manifest.json,sha256=MfkfsS5zVxb-scqJllN8aubrRN9vsznQ3-Aw69pZ47c,897
31
- sentience/extension/release.json,sha256=gblo3-etdwlWMB1JIIhyXwZeVhM3voNi7982xG58D8M,6437
31
+ sentience/extension/release.json,sha256=ikdgGGy_Jf6r_P6dKOUUaVZOQYMIRHz3ok5dVclxoT8,6437
32
32
  sentience/extension/test-content.js,sha256=RX6A42W-5pjP-avqGwrRq_GVp5yX2NqBDlDLc-SWL5g,156
33
33
  sentience/extension/pkg/sentience_core.d.ts,sha256=qrTEIR2WPkk1MmaSQzEpRyagbE9VirHowzZpbj41qeQ,1981
34
34
  sentience/extension/pkg/sentience_core.js,sha256=zldlOubec0pbNYhquwDzoQKuBF4SUVcIeXW_qLx0dVA,17904
35
35
  sentience/extension/pkg/sentience_core_bg.wasm,sha256=HtzBY8z4XgRgHHUqHQGm84EEQJirpf25wSVTXg-iJ1g,102522
36
36
  sentience/extension/pkg/sentience_core_bg.wasm.d.ts,sha256=O3c3HaUqmB6Aob6Pt0n3GEtTxM4VGeaClaA_-z2m2J4,517
37
37
  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,,
38
+ sentience/trace_indexing/__init__.py,sha256=urjLuqqXCQE8pnwpYBqoMKnzZSqFJkM1SHmFve9RVE8,499
39
+ sentience/trace_indexing/index_schema.py,sha256=Hz9igHFrHATTZOqKNiLhESjnGbDPTyRTejMGT1AKC8g,2180
40
+ sentience/trace_indexing/indexer.py,sha256=m-p57Va0cFlCpuMWkXNSHqODpGzpESZzoOkt3OiejlM,10811
41
+ sentienceapi-0.90.12.dist-info/licenses/LICENSE.md,sha256=Pl8BWUOOkFtYpgVhNwCl3YKzRvUpYid2utlJELIgr_8,3783
42
+ sentienceapi-0.90.12.dist-info/METADATA,sha256=DblGVp6eXuV5WD44nR-auKp93Ig7iiXVoG-LajlznVc,26131
43
+ sentienceapi-0.90.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ sentienceapi-0.90.12.dist-info/entry_points.txt,sha256=HdW1BvgRJm3ZAbbqrwTvDWE2KbmVz-Ue0wllW-mLmvA,49
45
+ sentienceapi-0.90.12.dist-info/top_level.txt,sha256=A9IKao--8PsFFz5vDfBIXWHgN6oh3HkMQSiQWgUTUBQ,10
46
+ sentienceapi-0.90.12.dist-info/RECORD,,