sentienceapi 0.90.11__py3-none-any.whl → 0.90.13__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.
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.11"
73
+ __version__ = "0.90.13"
74
74
 
75
75
  __all__ = [
76
76
  # Core SDK
sentience/agent.py CHANGED
@@ -149,23 +149,8 @@ class SentienceAgent(BaseAgent):
149
149
  if snap_opts.goal is None:
150
150
  snap_opts.goal = goal
151
151
 
152
- # Convert screenshot config to dict if needed
153
- screenshot_param = snap_opts.screenshot
154
- if isinstance(snap_opts.screenshot, ScreenshotConfig):
155
- screenshot_param = {
156
- "format": snap_opts.screenshot.format,
157
- "quality": snap_opts.screenshot.quality,
158
- }
159
-
160
- # Call snapshot with converted parameters
161
- snap = snapshot(
162
- self.browser,
163
- screenshot=screenshot_param,
164
- limit=snap_opts.limit,
165
- filter=snap_opts.filter.model_dump() if snap_opts.filter else None,
166
- use_api=snap_opts.use_api,
167
- goal=snap_opts.goal, # Pass goal to snapshot
168
- )
152
+ # Call snapshot with options object (matches TypeScript API)
153
+ snap = snapshot(self.browser, snap_opts)
169
154
 
170
155
  if snap.status != "success":
171
156
  raise RuntimeError(f"Snapshot failed: {snap.error}")
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.
@@ -10,7 +10,7 @@ from typing import Any
10
10
  from .agent import SentienceAgent
11
11
  from .browser import SentienceBrowser
12
12
  from .llm_provider import LLMProvider
13
- from .models import Snapshot
13
+ from .models import Snapshot, SnapshotOptions
14
14
  from .snapshot import snapshot
15
15
 
16
16
 
@@ -274,7 +274,7 @@ Create a step-by-step execution plan."""
274
274
  elif action == "EXTRACT_INFO":
275
275
  info_type = params["info_type"]
276
276
  # Get current page snapshot and extract info
277
- snap = snapshot(self.browser, limit=50)
277
+ snap = snapshot(self.browser, SnapshotOptions(limit=50))
278
278
 
279
279
  # Use LLM to extract specific information
280
280
  extracted = self._extract_information(snap, info_type)
@@ -361,7 +361,7 @@ Return JSON with extracted information:
361
361
  True if condition is met, False otherwise
362
362
  """
363
363
  try:
364
- snap = snapshot(self.browser, limit=30)
364
+ snap = snapshot(self.browser, SnapshotOptions(limit=30))
365
365
 
366
366
  # Build context
367
367
  elements_text = "\n".join([f"{el.role}: {el.text}" for el in snap.elements[:20]])
@@ -67,7 +67,7 @@
67
67
  "state": "uploaded",
68
68
  "size": 78091,
69
69
  "digest": "sha256:e281f8b755b61da4b8015d6172064aa9a337c14133ceceff4ab29199ee53307e",
70
- "download_count": 2,
70
+ "download_count": 4,
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/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: Optional[SnapshotOptions] = 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
@@ -127,9 +127,7 @@ def find_text_rect(
127
127
  except RuntimeError:
128
128
  raise
129
129
  except Exception as e:
130
- raise RuntimeError(
131
- f"Failed to verify findTextRect availability: {e}"
132
- ) from e
130
+ raise RuntimeError(f"Failed to verify findTextRect availability: {e}") from e
133
131
 
134
132
  # Call the extension's findTextRect method
135
133
  result_dict = browser.page.evaluate(
@@ -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 WaitResult, SnapshotOptions
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentienceapi
3
- Version: 0.90.11
3
+ Version: 0.90.13
4
4
  Summary: Python SDK for Sentience AI Agent Browser Automation
5
5
  Author: Sentience Team
6
6
  License: MIT
@@ -1,12 +1,12 @@
1
- sentience/__init__.py,sha256=qYtKo0JklnM7rI5GKH_mU717mWYBxxneR9copIPEkxI,3410
1
+ sentience/__init__.py,sha256=AssM2lIDnK5UV7x1n_4S5yJbZ2xEgkGr86DKiQKHkTg,3410
2
2
  sentience/actions.py,sha256=RT8AoR_CNyp6bMCYhkToWH1WB8cyB8dcFJZMhfskTeo,13239
3
- sentience/agent.py,sha256=rTAaQGiuZIohrJZXpCK-dZWuoAR3k_dQodjFLBkrCxY,24527
3
+ sentience/agent.py,sha256=IKSxDDCyMyGx8mMvIT4kq3HXtKNaK7BiHNGXnxHCkZc,23844
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
9
- sentience/conversational_agent.py,sha256=UUgltp-EkAbAzE6Pa_S72t7fWbdIwb3C2YppXzPx2jA,17207
8
+ sentience/cloud_tracing.py,sha256=KxVIT-HQW9EaX5GWC9DEVM2cdObomD3hkPNEnTceSpc,13541
9
+ sentience/conversational_agent.py,sha256=8o2bvdaxoqgK-hHM1AVOywwKWyZturp1oLFcl6JtqCw,17258
10
10
  sentience/expect.py,sha256=BFSRocNJr6ZAusb6fy4OgfDNCukGfu5jto760bFN12E,2851
11
11
  sentience/formatting.py,sha256=0_UklIUd94a4W32gTorjxoXNE03qdffR-omfTA5eHF0,1828
12
12
  sentience/generator.py,sha256=Wj--yn6bVo02nABBzrAIKPMmU8TRQm3JHAOER9XXT4Y,8035
@@ -18,29 +18,29 @@ sentience/query.py,sha256=P9Hs3otwESNncaArUwaw73mNNRFeOgpjy-fOTDQiCOI,10474
18
18
  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
- sentience/snapshot.py,sha256=zFQa-jGh8MBPuyvZZ3kam_d8qN93UtmigCvj9m2V5Ts,9947
22
- sentience/text_search.py,sha256=MK36zgtB7zqAW_Yxy6e9MqU3avTrIzKCgHc63nYjIJc,5775
21
+ sentience/snapshot.py,sha256=OTxrp8tJQbkhHKZQHglJSn5dF4roeO4_JhzHx6t3HsA,9269
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
26
- sentience/wait.py,sha256=8E_5aRS3GJ4igDwWzMJvIV6ENPsqX19JGwXCPAMkX6s,2195
26
+ sentience/wait.py,sha256=KJT7ITX-cO7hKOqwn4rvjIZrv8Id-Ug_o7fb-IHUwgM,2229
27
27
  sentience/extension/background.js,sha256=USlH3L6khes4YdhSkO2AkiSkqfGxdAbzt5KPsLMv9B0,8967
28
28
  sentience/extension/content.js,sha256=3lMCz9A9azFH-SdToUPqRd9b6Ssbn4R_WKzigHw8d_k,10458
29
29
  sentience/extension/injected_api.js,sha256=5SY-U0V2Kv-T85ss3zZcOvdRTLB2E3wvvK8GOX5vR3A,65355
30
30
  sentience/extension/manifest.json,sha256=MfkfsS5zVxb-scqJllN8aubrRN9vsznQ3-Aw69pZ47c,897
31
- sentience/extension/release.json,sha256=ikdgGGy_Jf6r_P6dKOUUaVZOQYMIRHz3ok5dVclxoT8,6437
31
+ sentience/extension/release.json,sha256=KRRWbaBPVhWCES26NbU4alvSN2624b9skkv4_Wb5HXU,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.11.dist-info/licenses/LICENSE.md,sha256=Pl8BWUOOkFtYpgVhNwCl3YKzRvUpYid2utlJELIgr_8,3783
42
- sentienceapi-0.90.11.dist-info/METADATA,sha256=lMhnwilyuN5dilccgmd-MMv7PQcPRpghyerZRjDzbqg,26131
43
- sentienceapi-0.90.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
- sentienceapi-0.90.11.dist-info/entry_points.txt,sha256=HdW1BvgRJm3ZAbbqrwTvDWE2KbmVz-Ue0wllW-mLmvA,49
45
- sentienceapi-0.90.11.dist-info/top_level.txt,sha256=A9IKao--8PsFFz5vDfBIXWHgN6oh3HkMQSiQWgUTUBQ,10
46
- sentienceapi-0.90.11.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.13.dist-info/licenses/LICENSE.md,sha256=Pl8BWUOOkFtYpgVhNwCl3YKzRvUpYid2utlJELIgr_8,3783
42
+ sentienceapi-0.90.13.dist-info/METADATA,sha256=xC9snXYmpohGd5NyyL7J4lahIW-r_hjQRPr1iiMOYSA,26131
43
+ sentienceapi-0.90.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ sentienceapi-0.90.13.dist-info/entry_points.txt,sha256=HdW1BvgRJm3ZAbbqrwTvDWE2KbmVz-Ue0wllW-mLmvA,49
45
+ sentienceapi-0.90.13.dist-info/top_level.txt,sha256=A9IKao--8PsFFz5vDfBIXWHgN6oh3HkMQSiQWgUTUBQ,10
46
+ sentienceapi-0.90.13.dist-info/RECORD,,