diff --git a/pyproject.toml b/pyproject.toml index 8884e59..2f540ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "sentienceapi" -version = "0.90.0" +version = "0.90.1" description = "Python SDK for Sentience AI Agent Browser Automation" readme = "README.md" requires-python = ">=3.11" diff --git a/sentience/__init__.py b/sentience/__init__.py index c3927e4..a03de3d 100644 --- a/sentience/__init__.py +++ b/sentience/__init__.py @@ -63,7 +63,7 @@ ) from .wait import wait_for -__version__ = "0.90.0" +__version__ = "0.90.1" __all__ = [ # Core SDK diff --git a/sentience/agent.py b/sentience/agent.py index 17686b8..8639e01 100644 --- a/sentience/agent.py +++ b/sentience/agent.py @@ -145,6 +145,9 @@ def act( # noqa: C901 # Use provided options or create default snap_opts = snapshot_options or SnapshotOptions(limit=self.default_snapshot_limit) + # Only set goal if not already provided + if snap_opts.goal is None: + snap_opts.goal = goal # Convert screenshot config to dict if needed screenshot_param = snap_opts.screenshot @@ -161,6 +164,7 @@ def act( # noqa: C901 limit=snap_opts.limit, filter=snap_opts.filter.model_dump() if snap_opts.filter else None, use_api=snap_opts.use_api, + goal=snap_opts.goal, # Pass goal to snapshot ) if snap.status != "success": diff --git a/sentience/models.py b/sentience/models.py index b0ec47b..9be5221 100644 --- a/sentience/models.py +++ b/sentience/models.py @@ -116,6 +116,7 @@ class SnapshotOptions(BaseModel): use_api: bool | None = None # Force API vs extension save_trace: bool = False # Save raw_elements to JSON for benchmarking/training trace_path: str | None = None # Path to save trace (default: "trace_{timestamp}.json") + goal: str | None = None # Optional goal/task description for the snapshot class Config: arbitrary_types_allowed = True diff --git a/sentience/snapshot.py b/sentience/snapshot.py index c13d252..9a0f6f7 100644 --- a/sentience/snapshot.py +++ b/sentience/snapshot.py @@ -196,6 +196,7 @@ def _snapshot_via_api( "raw_elements": raw_result.get("raw_elements", []), # Raw data needed for server processing "url": raw_result.get("url", ""), "viewport": raw_result.get("viewport"), + "goal": options.goal, # Optional goal/task description "options": { "limit": options.limit, "filter": options.filter.model_dump() if options.filter else None, diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 50033c8..a4001d1 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -101,3 +101,36 @@ def test_snapshot_save(): assert "elements" in data finally: os.unlink(temp_path) + + +@pytest.mark.requires_extension +def test_snapshot_with_goal(): + """Test snapshot with goal parameter""" + with SentienceBrowser() as browser: + browser.page.goto("https://example.com") + browser.page.wait_for_load_state("networkidle") + + # Test snapshot with goal + snap = snapshot(browser, goal="Find the main heading") + + assert snap.status == "success" + assert snap.url == "https://example.com/" + assert len(snap.elements) > 0 + + # Verify snapshot works normally with goal parameter + assert all(el.id >= 0 for el in snap.elements) + assert all( + el.role + in [ + "button", + "link", + "textbox", + "searchbox", + "checkbox", + "radio", + "combobox", + "image", + "generic", + ] + for el in snap.elements + )