sentienceapi 0.90.17__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.

Files changed (50) hide show
  1. sentience/__init__.py +153 -0
  2. sentience/_extension_loader.py +40 -0
  3. sentience/actions.py +837 -0
  4. sentience/agent.py +1246 -0
  5. sentience/agent_config.py +43 -0
  6. sentience/async_api.py +101 -0
  7. sentience/base_agent.py +194 -0
  8. sentience/browser.py +1037 -0
  9. sentience/cli.py +130 -0
  10. sentience/cloud_tracing.py +382 -0
  11. sentience/conversational_agent.py +509 -0
  12. sentience/expect.py +188 -0
  13. sentience/extension/background.js +233 -0
  14. sentience/extension/content.js +298 -0
  15. sentience/extension/injected_api.js +1473 -0
  16. sentience/extension/manifest.json +36 -0
  17. sentience/extension/pkg/sentience_core.d.ts +51 -0
  18. sentience/extension/pkg/sentience_core.js +529 -0
  19. sentience/extension/pkg/sentience_core_bg.wasm +0 -0
  20. sentience/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
  21. sentience/extension/release.json +115 -0
  22. sentience/extension/test-content.js +4 -0
  23. sentience/formatting.py +59 -0
  24. sentience/generator.py +202 -0
  25. sentience/inspector.py +365 -0
  26. sentience/llm_provider.py +637 -0
  27. sentience/models.py +412 -0
  28. sentience/overlay.py +222 -0
  29. sentience/query.py +303 -0
  30. sentience/read.py +185 -0
  31. sentience/recorder.py +589 -0
  32. sentience/schemas/trace_v1.json +216 -0
  33. sentience/screenshot.py +100 -0
  34. sentience/snapshot.py +516 -0
  35. sentience/text_search.py +290 -0
  36. sentience/trace_indexing/__init__.py +27 -0
  37. sentience/trace_indexing/index_schema.py +111 -0
  38. sentience/trace_indexing/indexer.py +357 -0
  39. sentience/tracer_factory.py +211 -0
  40. sentience/tracing.py +285 -0
  41. sentience/utils.py +296 -0
  42. sentience/wait.py +137 -0
  43. sentienceapi-0.90.17.dist-info/METADATA +917 -0
  44. sentienceapi-0.90.17.dist-info/RECORD +50 -0
  45. sentienceapi-0.90.17.dist-info/WHEEL +5 -0
  46. sentienceapi-0.90.17.dist-info/entry_points.txt +2 -0
  47. sentienceapi-0.90.17.dist-info/licenses/LICENSE +24 -0
  48. sentienceapi-0.90.17.dist-info/licenses/LICENSE-APACHE +201 -0
  49. sentienceapi-0.90.17.dist-info/licenses/LICENSE-MIT +21 -0
  50. sentienceapi-0.90.17.dist-info/top_level.txt +1 -0
@@ -0,0 +1,216 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://sentience.ai/schemas/trace/v1",
4
+ "title": "Sentience Agent Trace Event",
5
+ "description": "Schema for Sentience agent trace events in JSONL format",
6
+ "type": "object",
7
+ "required": ["v", "type", "ts", "run_id", "seq", "data"],
8
+ "properties": {
9
+ "v": {
10
+ "type": "integer",
11
+ "const": 1,
12
+ "description": "Schema version"
13
+ },
14
+ "type": {
15
+ "type": "string",
16
+ "enum": ["run_start", "step_start", "snapshot_taken", "llm_called", "action_executed", "verification", "recovery", "step_end", "run_end", "error"],
17
+ "description": "Event type"
18
+ },
19
+ "ts": {
20
+ "type": "string",
21
+ "format": "date-time",
22
+ "description": "ISO 8601 timestamp"
23
+ },
24
+ "ts_ms": {
25
+ "type": "integer",
26
+ "description": "Unix timestamp in milliseconds"
27
+ },
28
+ "run_id": {
29
+ "type": "string",
30
+ "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
31
+ "description": "UUID for the agent run"
32
+ },
33
+ "seq": {
34
+ "type": "integer",
35
+ "minimum": 1,
36
+ "description": "Monotonically increasing sequence number"
37
+ },
38
+ "step_id": {
39
+ "type": ["string", "null"],
40
+ "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
41
+ "description": "UUID for the step (present for step-scoped events)"
42
+ },
43
+ "data": {
44
+ "type": "object",
45
+ "description": "Event-specific payload",
46
+ "oneOf": [
47
+ {
48
+ "description": "run_start data",
49
+ "properties": {
50
+ "agent": {"type": "string"},
51
+ "llm_model": {"type": ["string", "null"]},
52
+ "config": {"type": "object"}
53
+ }
54
+ },
55
+ {
56
+ "description": "step_start data",
57
+ "required": ["step_id", "step_index", "goal", "attempt"],
58
+ "properties": {
59
+ "step_id": {"type": "string"},
60
+ "step_index": {"type": "integer"},
61
+ "goal": {"type": "string"},
62
+ "attempt": {"type": "integer"},
63
+ "pre_url": {"type": ["string", "null"]}
64
+ }
65
+ },
66
+ {
67
+ "description": "snapshot_taken data",
68
+ "required": ["step_id", "snapshot_digest"],
69
+ "properties": {
70
+ "step_id": {"type": "string"},
71
+ "snapshot_id": {"type": ["string", "null"]},
72
+ "snapshot_digest": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
73
+ "snapshot_digest_loose": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
74
+ "url": {"type": ["string", "null"]},
75
+ "element_count": {"type": "integer"}
76
+ }
77
+ },
78
+ {
79
+ "description": "llm_called data",
80
+ "required": ["step_id", "response_text", "response_hash"],
81
+ "properties": {
82
+ "step_id": {"type": "string"},
83
+ "model": {"type": ["string", "null"]},
84
+ "temperature": {"type": "number"},
85
+ "system_prompt_hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
86
+ "user_prompt_hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
87
+ "response_text": {"type": "string"},
88
+ "response_hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
89
+ "usage": {
90
+ "type": "object",
91
+ "properties": {
92
+ "prompt_tokens": {"type": "integer"},
93
+ "completion_tokens": {"type": "integer"},
94
+ "total_tokens": {"type": "integer"}
95
+ }
96
+ }
97
+ }
98
+ },
99
+ {
100
+ "description": "step_end data (StepResult)",
101
+ "required": ["step_id", "step_index", "goal", "attempt", "pre", "llm", "exec", "post", "verify"],
102
+ "properties": {
103
+ "v": {"type": "integer", "const": 1},
104
+ "step_id": {"type": "string"},
105
+ "step_index": {"type": "integer"},
106
+ "goal": {"type": "string"},
107
+ "attempt": {"type": "integer"},
108
+ "pre": {
109
+ "type": "object",
110
+ "required": ["snapshot_digest"],
111
+ "properties": {
112
+ "url": {"type": ["string", "null"]},
113
+ "snapshot_digest": {"type": "string"},
114
+ "snapshot_digest_loose": {"type": "string"}
115
+ }
116
+ },
117
+ "llm": {
118
+ "type": "object",
119
+ "required": ["response_text", "response_hash"],
120
+ "properties": {
121
+ "response_text": {"type": "string"},
122
+ "response_hash": {"type": "string"}
123
+ }
124
+ },
125
+ "action": {
126
+ "type": "object",
127
+ "required": ["kind"],
128
+ "properties": {
129
+ "kind": {"type": "string", "enum": ["click", "type", "press", "finish", "navigate"]},
130
+ "element_id": {"type": "integer"},
131
+ "text": {"type": "string"},
132
+ "key": {"type": "string"},
133
+ "url": {"type": "string"},
134
+ "raw": {"type": "string"}
135
+ }
136
+ },
137
+ "exec": {
138
+ "type": "object",
139
+ "required": ["success", "outcome", "duration_ms"],
140
+ "properties": {
141
+ "success": {"type": "boolean"},
142
+ "outcome": {"type": "string"},
143
+ "action": {"type": "string"},
144
+ "element_id": {"type": "integer"},
145
+ "text": {"type": "string"},
146
+ "key": {"type": "string"},
147
+ "url_changed": {"type": ["boolean", "null"]},
148
+ "duration_ms": {"type": "integer"}
149
+ }
150
+ },
151
+ "post": {
152
+ "type": "object",
153
+ "properties": {
154
+ "url": {"type": ["string", "null"]},
155
+ "snapshot_digest": {"type": "string"},
156
+ "snapshot_digest_loose": {"type": "string"}
157
+ }
158
+ },
159
+ "verify": {
160
+ "type": "object",
161
+ "required": ["passed"],
162
+ "properties": {
163
+ "policy": {"type": "string"},
164
+ "passed": {"type": "boolean"},
165
+ "signals": {"type": "object"}
166
+ }
167
+ },
168
+ "recovery": {
169
+ "type": ["object", "null"],
170
+ "properties": {
171
+ "attempted": {"type": "boolean"},
172
+ "success": {"type": "boolean"},
173
+ "strategy": {"type": "string"},
174
+ "attempts": {"type": "array"}
175
+ }
176
+ }
177
+ }
178
+ },
179
+ {
180
+ "description": "verification data",
181
+ "required": ["step_id", "passed"],
182
+ "properties": {
183
+ "step_id": {"type": "string"},
184
+ "passed": {"type": "boolean"},
185
+ "signals": {"type": "object"}
186
+ }
187
+ },
188
+ {
189
+ "description": "recovery data",
190
+ "required": ["step_id", "strategy"],
191
+ "properties": {
192
+ "step_id": {"type": "string"},
193
+ "strategy": {"type": "string"},
194
+ "attempt": {"type": "integer"}
195
+ }
196
+ },
197
+ {
198
+ "description": "run_end data",
199
+ "required": ["steps"],
200
+ "properties": {
201
+ "steps": {"type": "integer"}
202
+ }
203
+ },
204
+ {
205
+ "description": "error data",
206
+ "required": ["step_id", "error"],
207
+ "properties": {
208
+ "step_id": {"type": "string"},
209
+ "attempt": {"type": "integer"},
210
+ "error": {"type": "string"}
211
+ }
212
+ }
213
+ ]
214
+ }
215
+ }
216
+ }
@@ -0,0 +1,100 @@
1
+ """
2
+ Screenshot functionality - standalone screenshot capture
3
+ """
4
+
5
+ import base64
6
+ from typing import Any, Literal
7
+
8
+ from .browser import AsyncSentienceBrowser, SentienceBrowser
9
+
10
+
11
+ def screenshot(
12
+ browser: SentienceBrowser,
13
+ format: Literal["png", "jpeg"] = "png",
14
+ quality: int | None = None,
15
+ ) -> str:
16
+ """
17
+ Capture screenshot of current page
18
+
19
+ Args:
20
+ browser: SentienceBrowser instance
21
+ format: Image format - "png" or "jpeg"
22
+ quality: JPEG quality (1-100), only used for JPEG format
23
+
24
+ Returns:
25
+ Base64-encoded screenshot data URL (e.g., "data:image/png;base64,...")
26
+
27
+ Raises:
28
+ RuntimeError: If browser not started
29
+ ValueError: If quality is invalid for JPEG
30
+ """
31
+ if not browser.page:
32
+ raise RuntimeError("Browser not started. Call browser.start() first.")
33
+
34
+ if format == "jpeg" and quality is not None:
35
+ if not (1 <= quality <= 100):
36
+ raise ValueError("Quality must be between 1 and 100 for JPEG format")
37
+
38
+ # Use Playwright's screenshot with base64 encoding
39
+ screenshot_options: dict[str, Any] = {
40
+ "type": format,
41
+ }
42
+
43
+ if format == "jpeg" and quality is not None:
44
+ screenshot_options["quality"] = quality
45
+
46
+ # Capture screenshot as base64
47
+ # Playwright returns bytes when encoding is not specified, so we encode manually
48
+ import base64
49
+
50
+ image_bytes = browser.page.screenshot(**screenshot_options)
51
+ base64_data = base64.b64encode(image_bytes).decode("utf-8")
52
+
53
+ # Return as data URL
54
+ mime_type = "image/png" if format == "png" else "image/jpeg"
55
+ return f"data:{mime_type};base64,{base64_data}"
56
+
57
+
58
+ async def screenshot_async(
59
+ browser: AsyncSentienceBrowser,
60
+ format: Literal["png", "jpeg"] = "png",
61
+ quality: int | None = None,
62
+ ) -> str:
63
+ """
64
+ Capture screenshot of current page (async)
65
+
66
+ Args:
67
+ browser: AsyncSentienceBrowser instance
68
+ format: Image format - "png" or "jpeg"
69
+ quality: JPEG quality (1-100), only used for JPEG format
70
+
71
+ Returns:
72
+ Base64-encoded screenshot data URL (e.g., "data:image/png;base64,...")
73
+
74
+ Raises:
75
+ RuntimeError: If browser not started
76
+ ValueError: If quality is invalid for JPEG
77
+ """
78
+ if not browser.page:
79
+ raise RuntimeError("Browser not started. Call await browser.start() first.")
80
+
81
+ if format == "jpeg" and quality is not None:
82
+ if not (1 <= quality <= 100):
83
+ raise ValueError("Quality must be between 1 and 100 for JPEG format")
84
+
85
+ # Use Playwright's screenshot with base64 encoding
86
+ screenshot_options: dict[str, Any] = {
87
+ "type": format,
88
+ }
89
+
90
+ if format == "jpeg" and quality is not None:
91
+ screenshot_options["quality"] = quality
92
+
93
+ # Capture screenshot as base64
94
+ # Playwright returns bytes when encoding is not specified, so we encode manually
95
+ image_bytes = await browser.page.screenshot(**screenshot_options)
96
+ base64_data = base64.b64encode(image_bytes).decode("utf-8")
97
+
98
+ # Return as data URL
99
+ mime_type = "image/png" if format == "png" else "image/jpeg"
100
+ return f"data:{mime_type};base64,{base64_data}"