Skip to content

Commit ebc44d3

Browse files
committed
Phase 4: Modularize code
1 parent 1a2d85c commit ebc44d3

File tree

7 files changed

+418
-55
lines changed

7 files changed

+418
-55
lines changed

sentience/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from .expect import expect
1717

1818
# Formatting (v0.12.0+)
19-
from .formatting import format_snapshot_for_llm
19+
from .utils.formatting import format_snapshot_for_llm
2020
from .generator import ScriptGenerator, generate
2121
from .inspector import Inspector, inspect
2222
from .llm_provider import (
@@ -62,6 +62,7 @@
6262
from .tracing import JsonlTraceSink, TraceEvent, Tracer, TraceSink
6363

6464
# Utilities (v0.12.0+)
65+
# Import from utils package (re-exports from submodules for backward compatibility)
6566
from .utils import (
6667
canonical_snapshot_loose,
6768
canonical_snapshot_strict,

sentience/element_filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def filter_by_importance(
6464
@staticmethod
6565
def filter_by_goal(
6666
snapshot: Snapshot,
67-
goal: str | None,
67+
goal: Optional[str],
6868
max_elements: int = 50,
6969
) -> list[Element]:
7070
"""

sentience/formatting.py

Lines changed: 9 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,15 @@
11
"""
22
Snapshot formatting utilities for LLM prompts.
33
4-
Provides functions to convert Sentience snapshots into text format suitable
5-
for LLM consumption.
6-
"""
7-
8-
from typing import List
9-
10-
from .models import Snapshot
11-
12-
13-
def format_snapshot_for_llm(snap: Snapshot, limit: int = 50) -> str:
14-
"""
15-
Convert snapshot elements to text format for LLM consumption.
16-
17-
This is the canonical way Sentience formats DOM state for LLMs.
18-
The format includes element ID, role, text preview, visual cues,
19-
position, and importance score.
4+
DEPRECATED: This module is maintained for backward compatibility only.
5+
New code should import from sentience.utils.formatting or sentience directly:
206
21-
Args:
22-
snap: Snapshot object with elements
23-
limit: Maximum number of elements to include (default: 50)
24-
25-
Returns:
26-
Formatted string with one element per line
27-
28-
Example:
29-
>>> snap = snapshot(browser)
30-
>>> formatted = format_snapshot_for_llm(snap, limit=10)
31-
>>> print(formatted)
32-
[1] <button> "Sign In" {PRIMARY,CLICKABLE} @ (100,50) (Imp:10)
33-
[2] <input> "Email address" @ (100,100) (Imp:8)
34-
...
35-
"""
36-
lines: list[str] = []
37-
38-
for el in snap.elements[:limit]:
39-
# Build visual cues string
40-
cues = []
41-
if getattr(el.visual_cues, "is_primary", False):
42-
cues.append("PRIMARY")
43-
if getattr(el.visual_cues, "is_clickable", False):
44-
cues.append("CLICKABLE")
45-
46-
cues_str = f" {{{','.join(cues)}}}" if cues else ""
47-
48-
# Format text preview (truncate to 50 chars)
49-
text_preview = el.text or ""
50-
if len(text_preview) > 50:
51-
text_preview = text_preview[:50] + "..."
7+
from sentience.utils.formatting import format_snapshot_for_llm
8+
# or
9+
from sentience import format_snapshot_for_llm
10+
"""
5211

53-
# Build element line: [ID] <role> "text" {cues} @ (x,y) (Imp:score)
54-
lines.append(
55-
f'[{el.id}] <{el.role}> "{text_preview}"{cues_str} '
56-
f"@ ({int(el.bbox.x)},{int(el.bbox.y)}) (Imp:{el.importance})"
57-
)
12+
# Re-export from new location for backward compatibility
13+
from .utils.formatting import format_snapshot_for_llm
5814

59-
return "\n".join(lines)
15+
__all__ = ["format_snapshot_for_llm"]

sentience/utils/__init__.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""
2+
Utility functions for Sentience SDK.
3+
4+
This module re-exports all utility functions from submodules for backward compatibility.
5+
Users can continue using:
6+
from sentience.utils import compute_snapshot_digests, canonical_snapshot_strict
7+
from sentience import canonical_snapshot_strict, format_snapshot_for_llm
8+
"""
9+
10+
# Re-export all functions from submodules for backward compatibility
11+
from .browser import save_storage_state
12+
from .element import (
13+
BBox,
14+
ElementFingerprint,
15+
canonical_snapshot_loose,
16+
canonical_snapshot_strict,
17+
compute_snapshot_digests,
18+
extract_element_fingerprint,
19+
normalize_bbox,
20+
normalize_text_strict,
21+
sha256_digest,
22+
)
23+
from .formatting import format_snapshot_for_llm
24+
25+
__all__ = [
26+
# Browser utilities
27+
"save_storage_state",
28+
# Element/digest utilities
29+
"BBox",
30+
"ElementFingerprint",
31+
"canonical_snapshot_loose",
32+
"canonical_snapshot_strict",
33+
"compute_snapshot_digests",
34+
"extract_element_fingerprint",
35+
"normalize_bbox",
36+
"normalize_text_strict",
37+
"sha256_digest",
38+
# Formatting utilities
39+
"format_snapshot_for_llm",
40+
]
41+

sentience/utils/browser.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
Browser-related utilities for Sentience SDK.
3+
4+
Provides functions for managing browser storage state (cookies, localStorage).
5+
"""
6+
7+
import json
8+
from pathlib import Path
9+
10+
from playwright.sync_api import BrowserContext
11+
12+
13+
def save_storage_state(context: BrowserContext, file_path: str | Path) -> None:
14+
"""
15+
Save current browser storage state (cookies + localStorage) to a file.
16+
17+
This is useful for capturing a logged-in session to reuse later.
18+
19+
Args:
20+
context: Playwright BrowserContext
21+
file_path: Path to save the storage state JSON file
22+
23+
Example:
24+
```python
25+
from sentience import SentienceBrowser, save_storage_state
26+
27+
browser = SentienceBrowser()
28+
browser.start()
29+
30+
# User logs in manually or via agent
31+
browser.goto("https://example.com")
32+
# ... login happens ...
33+
34+
# Save session for later
35+
save_storage_state(browser.context, "auth.json")
36+
```
37+
38+
Raises:
39+
IOError: If file cannot be written
40+
"""
41+
storage_state = context.storage_state()
42+
file_path_obj = Path(file_path)
43+
file_path_obj.parent.mkdir(parents=True, exist_ok=True)
44+
with open(file_path_obj, "w") as f:
45+
json.dump(storage_state, f, indent=2)
46+
print(f"✅ [Sentience] Saved storage state to {file_path_obj}")
47+

0 commit comments

Comments
 (0)