sentienceapi 0.92.2__py3-none-any.whl → 0.98.0__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 +107 -2
- sentience/_extension_loader.py +156 -1
- sentience/action_executor.py +2 -0
- sentience/actions.py +354 -9
- sentience/agent.py +4 -0
- sentience/agent_runtime.py +840 -0
- sentience/asserts/__init__.py +70 -0
- sentience/asserts/expect.py +621 -0
- sentience/asserts/query.py +383 -0
- sentience/async_api.py +8 -1
- sentience/backends/__init__.py +137 -0
- sentience/backends/actions.py +372 -0
- sentience/backends/browser_use_adapter.py +241 -0
- sentience/backends/cdp_backend.py +393 -0
- sentience/backends/exceptions.py +211 -0
- sentience/backends/playwright_backend.py +194 -0
- sentience/backends/protocol.py +216 -0
- sentience/backends/sentience_context.py +469 -0
- sentience/backends/snapshot.py +483 -0
- sentience/browser.py +230 -74
- sentience/canonicalization.py +207 -0
- sentience/cloud_tracing.py +65 -24
- sentience/constants.py +6 -0
- sentience/cursor_policy.py +142 -0
- sentience/extension/content.js +35 -0
- sentience/extension/injected_api.js +310 -15
- sentience/extension/manifest.json +1 -1
- sentience/extension/pkg/sentience_core.d.ts +22 -22
- sentience/extension/pkg/sentience_core.js +192 -144
- sentience/extension/pkg/sentience_core_bg.wasm +0 -0
- sentience/extension/release.json +29 -29
- sentience/failure_artifacts.py +241 -0
- sentience/integrations/__init__.py +6 -0
- sentience/integrations/langchain/__init__.py +12 -0
- sentience/integrations/langchain/context.py +18 -0
- sentience/integrations/langchain/core.py +326 -0
- sentience/integrations/langchain/tools.py +180 -0
- sentience/integrations/models.py +46 -0
- sentience/integrations/pydanticai/__init__.py +15 -0
- sentience/integrations/pydanticai/deps.py +20 -0
- sentience/integrations/pydanticai/toolset.py +468 -0
- sentience/llm_provider.py +695 -18
- sentience/models.py +536 -3
- sentience/ordinal.py +280 -0
- sentience/query.py +66 -4
- sentience/schemas/trace_v1.json +27 -1
- sentience/snapshot.py +384 -93
- sentience/snapshot_diff.py +39 -54
- sentience/text_search.py +1 -0
- sentience/trace_event_builder.py +20 -1
- sentience/trace_indexing/indexer.py +3 -49
- sentience/tracer_factory.py +1 -3
- sentience/verification.py +618 -0
- sentience/visual_agent.py +3 -1
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/METADATA +198 -40
- sentienceapi-0.98.0.dist-info/RECORD +92 -0
- sentience/utils.py +0 -296
- sentienceapi-0.92.2.dist-info/RECORD +0 -65
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/WHEEL +0 -0
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/entry_points.txt +0 -0
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/licenses/LICENSE +0 -0
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/licenses/LICENSE-APACHE +0 -0
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/licenses/LICENSE-MIT +0 -0
- {sentienceapi-0.92.2.dist-info → sentienceapi-0.98.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from .context import SentienceLangChainContext
|
|
8
|
+
from .core import SentienceLangChainCore
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_sentience_langchain_tools(ctx: SentienceLangChainContext) -> list[Any]:
|
|
12
|
+
"""
|
|
13
|
+
Build LangChain tools backed by Sentience.
|
|
14
|
+
|
|
15
|
+
LangChain is an optional dependency; imports are done lazily here so that
|
|
16
|
+
`import sentience` works without LangChain installed.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from langchain_core.tools import StructuredTool
|
|
21
|
+
except Exception: # pragma: no cover
|
|
22
|
+
from langchain.tools import StructuredTool # type: ignore
|
|
23
|
+
|
|
24
|
+
core = SentienceLangChainCore(ctx)
|
|
25
|
+
|
|
26
|
+
# ---- Schemas ----
|
|
27
|
+
class SnapshotStateArgs(BaseModel):
|
|
28
|
+
limit: int = Field(50, ge=1, le=500, description="Max elements to return (default 50)")
|
|
29
|
+
include_screenshot: bool = Field(
|
|
30
|
+
False, description="Include screenshot in snapshot (default false)"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
class ReadPageArgs(BaseModel):
|
|
34
|
+
format: Literal["raw", "text", "markdown"] = Field("text", description="Output format")
|
|
35
|
+
enhance_markdown: bool = Field(
|
|
36
|
+
True, description="Enhance markdown conversion (default true)"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
class ClickArgs(BaseModel):
|
|
40
|
+
element_id: int = Field(..., description="Sentience element id from snapshot_state()")
|
|
41
|
+
|
|
42
|
+
class TypeTextArgs(BaseModel):
|
|
43
|
+
element_id: int = Field(..., description="Sentience element id from snapshot_state()")
|
|
44
|
+
text: str = Field(..., description="Text to type")
|
|
45
|
+
|
|
46
|
+
class PressKeyArgs(BaseModel):
|
|
47
|
+
key: str = Field(..., description="Key to press (e.g., Enter, Escape, Tab)")
|
|
48
|
+
|
|
49
|
+
class ScrollToArgs(BaseModel):
|
|
50
|
+
element_id: int = Field(..., description="Sentience element id from snapshot_state()")
|
|
51
|
+
behavior: Literal["smooth", "instant", "auto"] = Field(
|
|
52
|
+
"smooth", description="Scroll behavior"
|
|
53
|
+
)
|
|
54
|
+
block: Literal["start", "center", "end", "nearest"] = Field(
|
|
55
|
+
"center", description="Vertical alignment"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
class NavigateArgs(BaseModel):
|
|
59
|
+
url: str = Field(..., description="URL to navigate to")
|
|
60
|
+
|
|
61
|
+
class ClickRectArgs(BaseModel):
|
|
62
|
+
x: float = Field(..., description="Rect x (px)")
|
|
63
|
+
y: float = Field(..., description="Rect y (px)")
|
|
64
|
+
width: float = Field(..., description="Rect width (px)")
|
|
65
|
+
height: float = Field(..., description="Rect height (px)")
|
|
66
|
+
button: Literal["left", "right", "middle"] = Field("left", description="Mouse button")
|
|
67
|
+
click_count: int = Field(1, ge=1, le=3, description="Click count")
|
|
68
|
+
|
|
69
|
+
class FindTextRectArgs(BaseModel):
|
|
70
|
+
text: str = Field(..., description="Text to search for")
|
|
71
|
+
case_sensitive: bool = Field(False, description="Case sensitive search")
|
|
72
|
+
whole_word: bool = Field(False, description="Whole-word match only")
|
|
73
|
+
max_results: int = Field(10, ge=1, le=100, description="Max matches (capped at 100)")
|
|
74
|
+
|
|
75
|
+
class VerifyUrlMatchesArgs(BaseModel):
|
|
76
|
+
pattern: str = Field(..., description="Regex pattern to match against current URL")
|
|
77
|
+
|
|
78
|
+
class VerifyTextPresentArgs(BaseModel):
|
|
79
|
+
text: str = Field(..., description="Text to check for in read_page output")
|
|
80
|
+
format: Literal["text", "markdown", "raw"] = Field("text", description="Read format")
|
|
81
|
+
case_sensitive: bool = Field(False, description="Case sensitive check")
|
|
82
|
+
|
|
83
|
+
class AssertEventuallyUrlMatchesArgs(BaseModel):
|
|
84
|
+
pattern: str = Field(..., description="Regex pattern to match against current URL")
|
|
85
|
+
timeout_s: float = Field(10.0, ge=0.1, description="Timeout seconds")
|
|
86
|
+
poll_s: float = Field(0.25, ge=0.05, description="Polling interval seconds")
|
|
87
|
+
|
|
88
|
+
# ---- Sync wrappers (explicitly unsupported) ----
|
|
89
|
+
def _sync_unsupported(*args, **kwargs):
|
|
90
|
+
raise RuntimeError(
|
|
91
|
+
"Sentience LangChain tools are async-only. Use an async LangChain agent/runner."
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# ---- Tools ----
|
|
95
|
+
return [
|
|
96
|
+
StructuredTool(
|
|
97
|
+
name="sentience_snapshot_state",
|
|
98
|
+
description="Observe: take a bounded Sentience snapshot and return a typed BrowserState (url + elements).",
|
|
99
|
+
args_schema=SnapshotStateArgs,
|
|
100
|
+
func=_sync_unsupported,
|
|
101
|
+
coroutine=lambda **kw: core.snapshot_state(**kw),
|
|
102
|
+
),
|
|
103
|
+
StructuredTool(
|
|
104
|
+
name="sentience_read_page",
|
|
105
|
+
description="Observe: read page content as text/markdown/raw HTML.",
|
|
106
|
+
args_schema=ReadPageArgs,
|
|
107
|
+
func=_sync_unsupported,
|
|
108
|
+
coroutine=lambda **kw: core.read_page(**kw),
|
|
109
|
+
),
|
|
110
|
+
StructuredTool(
|
|
111
|
+
name="sentience_click",
|
|
112
|
+
description="Act: click an element by element_id from snapshot_state.",
|
|
113
|
+
args_schema=ClickArgs,
|
|
114
|
+
func=_sync_unsupported,
|
|
115
|
+
coroutine=lambda **kw: core.click(**kw),
|
|
116
|
+
),
|
|
117
|
+
StructuredTool(
|
|
118
|
+
name="sentience_type_text",
|
|
119
|
+
description="Act: type text into an element by element_id from snapshot_state.",
|
|
120
|
+
args_schema=TypeTextArgs,
|
|
121
|
+
func=_sync_unsupported,
|
|
122
|
+
coroutine=lambda **kw: core.type_text(**kw),
|
|
123
|
+
),
|
|
124
|
+
StructuredTool(
|
|
125
|
+
name="sentience_press_key",
|
|
126
|
+
description="Act: press a keyboard key (Enter/Escape/Tab/etc.).",
|
|
127
|
+
args_schema=PressKeyArgs,
|
|
128
|
+
func=_sync_unsupported,
|
|
129
|
+
coroutine=lambda **kw: core.press_key(**kw),
|
|
130
|
+
),
|
|
131
|
+
StructuredTool(
|
|
132
|
+
name="sentience_scroll_to",
|
|
133
|
+
description="Act: scroll an element into view by element_id from snapshot_state.",
|
|
134
|
+
args_schema=ScrollToArgs,
|
|
135
|
+
func=_sync_unsupported,
|
|
136
|
+
coroutine=lambda **kw: core.scroll_to(**kw),
|
|
137
|
+
),
|
|
138
|
+
StructuredTool(
|
|
139
|
+
name="sentience_navigate",
|
|
140
|
+
description="Act: navigate to a URL using the underlying Playwright page.goto.",
|
|
141
|
+
args_schema=NavigateArgs,
|
|
142
|
+
func=_sync_unsupported,
|
|
143
|
+
coroutine=lambda **kw: core.navigate(**kw),
|
|
144
|
+
),
|
|
145
|
+
StructuredTool(
|
|
146
|
+
name="sentience_click_rect",
|
|
147
|
+
description="Act: click a rectangle by pixel coordinates (useful with find_text_rect).",
|
|
148
|
+
args_schema=ClickRectArgs,
|
|
149
|
+
func=_sync_unsupported,
|
|
150
|
+
coroutine=lambda **kw: core.click_rect(**kw),
|
|
151
|
+
),
|
|
152
|
+
StructuredTool(
|
|
153
|
+
name="sentience_find_text_rect",
|
|
154
|
+
description="Locate: find text occurrences on the page and return pixel coordinates.",
|
|
155
|
+
args_schema=FindTextRectArgs,
|
|
156
|
+
func=_sync_unsupported,
|
|
157
|
+
coroutine=lambda **kw: core.find_text_rect(**kw),
|
|
158
|
+
),
|
|
159
|
+
StructuredTool(
|
|
160
|
+
name="sentience_verify_url_matches",
|
|
161
|
+
description="Verify: check current URL matches a regex pattern (post-action guard).",
|
|
162
|
+
args_schema=VerifyUrlMatchesArgs,
|
|
163
|
+
func=_sync_unsupported,
|
|
164
|
+
coroutine=lambda **kw: core.verify_url_matches(**kw),
|
|
165
|
+
),
|
|
166
|
+
StructuredTool(
|
|
167
|
+
name="sentience_verify_text_present",
|
|
168
|
+
description="Verify: check that a text substring is present in read_page output.",
|
|
169
|
+
args_schema=VerifyTextPresentArgs,
|
|
170
|
+
func=_sync_unsupported,
|
|
171
|
+
coroutine=lambda **kw: core.verify_text_present(**kw),
|
|
172
|
+
),
|
|
173
|
+
StructuredTool(
|
|
174
|
+
name="sentience_assert_eventually_url_matches",
|
|
175
|
+
description="Verify: retry URL regex match until timeout (use for delayed navigation/redirects).",
|
|
176
|
+
args_schema=AssertEventuallyUrlMatchesArgs,
|
|
177
|
+
func=_sync_unsupported,
|
|
178
|
+
coroutine=lambda **kw: core.assert_eventually_url_matches(**kw),
|
|
179
|
+
),
|
|
180
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared typed models for integrations (internal).
|
|
3
|
+
|
|
4
|
+
These are intentionally small, framework-friendly return types for tool wrappers.
|
|
5
|
+
They wrap/derive from existing Sentience SDK types while keeping payloads bounded
|
|
6
|
+
and predictable for LLM tool calls.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel
|
|
14
|
+
|
|
15
|
+
from sentience.models import BBox
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ElementSummary(BaseModel):
|
|
19
|
+
"""A small, stable subset of `sentience.models.Element` suitable for tool returns."""
|
|
20
|
+
|
|
21
|
+
id: int
|
|
22
|
+
role: str
|
|
23
|
+
text: str | None = None
|
|
24
|
+
importance: int | None = None
|
|
25
|
+
bbox: BBox | None = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class BrowserState(BaseModel):
|
|
29
|
+
"""
|
|
30
|
+
Minimal browser state for integrations.
|
|
31
|
+
|
|
32
|
+
Notes:
|
|
33
|
+
- Keep this payload bounded: prefer `snapshot(limit=50)` and summarize elements.
|
|
34
|
+
- Integrations can extend this in their own packages without changing core SDK.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
url: str
|
|
38
|
+
elements: list[ElementSummary]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AssertionResult(BaseModel):
|
|
42
|
+
"""Framework-friendly assertion/guard result."""
|
|
43
|
+
|
|
44
|
+
passed: bool
|
|
45
|
+
reason: str = ""
|
|
46
|
+
details: dict[str, Any] = {}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PydanticAI integration helpers (optional).
|
|
3
|
+
|
|
4
|
+
This module does NOT import `pydantic_ai` at import time so the base SDK can be
|
|
5
|
+
installed without the optional dependency. Users should install:
|
|
6
|
+
|
|
7
|
+
pip install sentienceapi[pydanticai]
|
|
8
|
+
|
|
9
|
+
and then use `register_sentience_tools(...)` with a PydanticAI `Agent`.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .deps import SentiencePydanticDeps
|
|
13
|
+
from .toolset import register_sentience_tools
|
|
14
|
+
|
|
15
|
+
__all__ = ["SentiencePydanticDeps", "register_sentience_tools"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from sentience.browser import AsyncSentienceBrowser
|
|
7
|
+
from sentience.tracing import Tracer
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class SentiencePydanticDeps:
|
|
12
|
+
"""
|
|
13
|
+
Dependencies passed into PydanticAI tools via ctx.deps.
|
|
14
|
+
|
|
15
|
+
At minimum we carry the live `AsyncSentienceBrowser`.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
browser: AsyncSentienceBrowser
|
|
19
|
+
runtime: Any | None = None
|
|
20
|
+
tracer: Tracer | None = None
|