sentience-ts 0.10.3
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.
- package/README.md +193 -0
- package/dist/actions.d.ts +9 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +113 -0
- package/dist/actions.js.map +1 -0
- package/dist/browser.d.ts +24 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +236 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +158 -0
- package/dist/cli.js.map +1 -0
- package/dist/expect.d.ts +16 -0
- package/dist/expect.d.ts.map +1 -0
- package/dist/expect.js +66 -0
- package/dist/expect.js.map +1 -0
- package/dist/generator.d.ts +16 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +205 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector.d.ts +13 -0
- package/dist/inspector.d.ts.map +1 -0
- package/dist/inspector.js +147 -0
- package/dist/inspector.js.map +1 -0
- package/dist/query.d.ts +8 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +337 -0
- package/dist/query.js.map +1 -0
- package/dist/read.d.ts +40 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +86 -0
- package/dist/read.js.map +1 -0
- package/dist/recorder.d.ts +44 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +256 -0
- package/dist/recorder.js.map +1 -0
- package/dist/screenshot.d.ts +17 -0
- package/dist/screenshot.d.ts.map +1 -0
- package/dist/screenshot.js +37 -0
- package/dist/screenshot.js.map +1 -0
- package/dist/snapshot.d.ts +20 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +101 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/wait.d.ts +7 -0
- package/dist/wait.d.ts.map +1 -0
- package/dist/wait.js +37 -0
- package/dist/wait.js.map +1 -0
- package/package.json +58 -0
- package/spec/README.md +72 -0
- package/spec/SNAPSHOT_V1.md +208 -0
- package/spec/sdk-types.md +259 -0
- package/spec/snapshot.schema.json +148 -0
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sentience-ts",
|
|
3
|
+
"version": "0.10.3",
|
|
4
|
+
"description": "TypeScript SDK for Sentience AI Agent Browser Automation",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"prepare": "npm run build",
|
|
11
|
+
"prepublishOnly": "npm test && npm run build",
|
|
12
|
+
"example:hello": "ts-node examples/hello.ts",
|
|
13
|
+
"example:basic": "ts-node examples/basic-agent.ts",
|
|
14
|
+
"cli": "ts-node src/cli.ts"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"sentience": "./dist/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"playwright": "^1.40.0",
|
|
21
|
+
"turndown": "^7.2.2",
|
|
22
|
+
"zod": "^3.22.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/jest": "^29.5.14",
|
|
26
|
+
"@types/node": "^20.0.0",
|
|
27
|
+
"@types/turndown": "^5.0.3",
|
|
28
|
+
"jest": "^29.0.0",
|
|
29
|
+
"ts-jest": "^29.0.0",
|
|
30
|
+
"ts-node": "^10.9.0",
|
|
31
|
+
"typescript": "^5.0.0"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"spec",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"keywords": [
|
|
40
|
+
"browser-automation",
|
|
41
|
+
"playwright",
|
|
42
|
+
"ai-agent",
|
|
43
|
+
"web-automation",
|
|
44
|
+
"sentience"
|
|
45
|
+
],
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "https://github.com/SentienceAPI/sentience-ts.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/SentienceAPI/sentience-ts/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/SentienceAPI/sentience-ts#readme",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=20.0.0"
|
|
57
|
+
}
|
|
58
|
+
}
|
package/spec/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Sentience API Specification
|
|
2
|
+
|
|
3
|
+
This directory contains the **single source of truth** for the API contract between the Chrome extension and SDKs.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
- **`snapshot.schema.json`** - JSON Schema for snapshot response validation
|
|
8
|
+
- **`SNAPSHOT_V1.md`** - Human-readable snapshot API contract
|
|
9
|
+
- **`sdk-types.md`** - SDK-level type definitions (ActionResult, WaitResult, TraceStep)
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
These specifications ensure:
|
|
14
|
+
1. **Consistency**: Both Python and TypeScript SDKs implement the same contract
|
|
15
|
+
2. **Validation**: SDKs can validate extension responses
|
|
16
|
+
3. **Type Safety**: Strong typing in both languages
|
|
17
|
+
4. **Documentation**: Clear reference for developers
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### For SDK Developers
|
|
22
|
+
|
|
23
|
+
1. **Read** `SNAPSHOT_V1.md` for human-readable contract
|
|
24
|
+
2. **Use** `snapshot.schema.json` for JSON Schema validation
|
|
25
|
+
3. **Reference** `sdk-types.md` for SDK-level types
|
|
26
|
+
|
|
27
|
+
### For Extension Developers
|
|
28
|
+
|
|
29
|
+
1. **Ensure** extension output matches `snapshot.schema.json`
|
|
30
|
+
2. **Update** schema when adding new fields
|
|
31
|
+
3. **Version** schema for breaking changes
|
|
32
|
+
|
|
33
|
+
## Versioning
|
|
34
|
+
|
|
35
|
+
- **v1.0.0**: Initial stable version (Day 1)
|
|
36
|
+
- Future versions: Increment major version for breaking changes
|
|
37
|
+
- SDKs should validate version and handle compatibility
|
|
38
|
+
|
|
39
|
+
## Validation
|
|
40
|
+
|
|
41
|
+
Both SDKs should validate extension responses:
|
|
42
|
+
|
|
43
|
+
**Python**:
|
|
44
|
+
```python
|
|
45
|
+
import jsonschema
|
|
46
|
+
from spec.snapshot.schema import load_schema
|
|
47
|
+
|
|
48
|
+
schema = load_schema()
|
|
49
|
+
jsonschema.validate(snapshot_data, schema)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**TypeScript**:
|
|
53
|
+
```typescript
|
|
54
|
+
import Ajv from 'ajv';
|
|
55
|
+
import schema from './spec/snapshot.schema.json';
|
|
56
|
+
|
|
57
|
+
const ajv = new Ajv();
|
|
58
|
+
const validate = ajv.compile(schema);
|
|
59
|
+
validate(snapshot_data);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Testing
|
|
63
|
+
|
|
64
|
+
- Validate against real extension output
|
|
65
|
+
- Test with edge cases (empty pages, many elements, errors)
|
|
66
|
+
- Verify type coercion and defaults
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
**Last Updated**: Day 1 Implementation
|
|
71
|
+
**Status**: ✅ Stable
|
|
72
|
+
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Sentience Snapshot API Contract v1
|
|
2
|
+
|
|
3
|
+
**Version**: 1.0.0
|
|
4
|
+
**Last Updated**: [Current Date]
|
|
5
|
+
**Status**: Stable
|
|
6
|
+
|
|
7
|
+
This document defines the **single source of truth** for the snapshot data structure returned by `window.sentience.snapshot()`. Both Python and TypeScript SDKs must implement this contract exactly.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
The snapshot API returns a structured representation of the current page state, including:
|
|
12
|
+
- All interactive elements with semantic roles
|
|
13
|
+
- Element positions (bounding boxes)
|
|
14
|
+
- Importance scores (AI-optimized ranking)
|
|
15
|
+
- Visual cues (primary actions, colors, clickability)
|
|
16
|
+
- Optional screenshot
|
|
17
|
+
|
|
18
|
+
## Response Structure
|
|
19
|
+
|
|
20
|
+
### Top-Level Object
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
{
|
|
24
|
+
status: "success" | "error",
|
|
25
|
+
timestamp?: string, // ISO 8601
|
|
26
|
+
url: string,
|
|
27
|
+
viewport?: { width: number, height: number },
|
|
28
|
+
elements: Element[],
|
|
29
|
+
screenshot?: string, // Base64 data URL
|
|
30
|
+
screenshot_format?: "png" | "jpeg",
|
|
31
|
+
error?: string, // If status is "error"
|
|
32
|
+
requires_license?: boolean // If license required
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Element Object
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
{
|
|
40
|
+
id: number, // REQUIRED: Unique identifier (registry index)
|
|
41
|
+
role: string, // REQUIRED: Semantic role
|
|
42
|
+
text: string | null, // Text content, aria-label, or placeholder
|
|
43
|
+
importance: number, // REQUIRED: Importance score (-300 to ~1800)
|
|
44
|
+
bbox: BBox, // REQUIRED: Bounding box
|
|
45
|
+
visual_cues: VisualCues, // REQUIRED: Visual analysis
|
|
46
|
+
in_viewport: boolean, // Is element visible in viewport
|
|
47
|
+
is_occluded: boolean, // Is element covered by overlay
|
|
48
|
+
z_index: number // CSS z-index (0 if auto)
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### BBox (Bounding Box)
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
{
|
|
56
|
+
x: number, // Left edge in pixels
|
|
57
|
+
y: number, // Top edge in pixels
|
|
58
|
+
width: number, // Width in pixels
|
|
59
|
+
height: number // Height in pixels
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### VisualCues
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
{
|
|
67
|
+
is_primary: boolean, // Visually prominent primary action
|
|
68
|
+
background_color_name: string | null, // Named color from palette
|
|
69
|
+
is_clickable: boolean // Has pointer cursor or actionable role
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Field Details
|
|
74
|
+
|
|
75
|
+
### `id` (required)
|
|
76
|
+
- **Type**: `integer`
|
|
77
|
+
- **Description**: Unique element identifier, corresponds to index in `window.sentience_registry`
|
|
78
|
+
- **Usage**: Used for actions like `click(id)`
|
|
79
|
+
- **Stability**: May change between page loads (not persistent)
|
|
80
|
+
|
|
81
|
+
### `role` (required)
|
|
82
|
+
- **Type**: `string`
|
|
83
|
+
- **Values**: `"button"`, `"link"`, `"textbox"`, `"searchbox"`, `"checkbox"`, `"radio"`, `"combobox"`, `"image"`, `"generic"`
|
|
84
|
+
- **Description**: Semantic role inferred from HTML tag, ARIA attributes, and context
|
|
85
|
+
- **Usage**: Primary filter for query engine
|
|
86
|
+
|
|
87
|
+
### `text` (optional)
|
|
88
|
+
- **Type**: `string | null`
|
|
89
|
+
- **Description**: Text content extracted from element:
|
|
90
|
+
- `aria-label` if present
|
|
91
|
+
- `value` or `placeholder` for inputs
|
|
92
|
+
- `alt` for images
|
|
93
|
+
- `innerText` for other elements (truncated to 100 chars)
|
|
94
|
+
- **Usage**: Text matching in query engine
|
|
95
|
+
|
|
96
|
+
### `importance` (required)
|
|
97
|
+
- **Type**: `integer`
|
|
98
|
+
- **Range**: -300 to ~1800
|
|
99
|
+
- **Description**: AI-optimized importance score calculated from:
|
|
100
|
+
- Role priority (inputs: 1000, buttons: 500, links: 100)
|
|
101
|
+
- Area score (larger elements score higher, capped at 200)
|
|
102
|
+
- Visual prominence (+200 for primary actions)
|
|
103
|
+
- Viewport/occlusion penalties (-500 off-screen, -800 occluded)
|
|
104
|
+
- **Usage**: Ranking and filtering elements
|
|
105
|
+
|
|
106
|
+
### `bbox` (required)
|
|
107
|
+
- **Type**: `BBox` object
|
|
108
|
+
- **Description**: Element position and size in viewport coordinates
|
|
109
|
+
- **Coordinates**: Relative to viewport (0,0) at top-left
|
|
110
|
+
- **Usage**: Spatial queries, visual grounding, click coordinates
|
|
111
|
+
|
|
112
|
+
### `visual_cues` (required)
|
|
113
|
+
- **Type**: `VisualCues` object
|
|
114
|
+
- **Description**: Visual analysis results
|
|
115
|
+
- **Fields**:
|
|
116
|
+
- `is_primary`: True if element is visually prominent primary action
|
|
117
|
+
- `background_color_name`: Nearest named color (32-color palette) or null
|
|
118
|
+
- `is_clickable`: True if element has pointer cursor or actionable role
|
|
119
|
+
|
|
120
|
+
### `in_viewport` (optional)
|
|
121
|
+
- **Type**: `boolean`
|
|
122
|
+
- **Description**: True if element is visible in current viewport
|
|
123
|
+
- **Default**: `true` (if not present, assume visible)
|
|
124
|
+
|
|
125
|
+
### `is_occluded` (optional)
|
|
126
|
+
- **Type**: `boolean`
|
|
127
|
+
- **Description**: True if element is covered by another element
|
|
128
|
+
- **Default**: `false` (if not present, assume not occluded)
|
|
129
|
+
|
|
130
|
+
### `z_index` (optional)
|
|
131
|
+
- **Type**: `integer`
|
|
132
|
+
- **Description**: CSS z-index value (0 if "auto" or not set)
|
|
133
|
+
- **Default**: `0`
|
|
134
|
+
|
|
135
|
+
## Element Sorting
|
|
136
|
+
|
|
137
|
+
Elements in the `elements` array are sorted by:
|
|
138
|
+
1. **Primary sort**: `importance` (descending) - most important first
|
|
139
|
+
2. **Secondary sort**: `bbox.y` (ascending) - top-to-bottom reading order (if limit applied)
|
|
140
|
+
|
|
141
|
+
## Example Response
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"status": "success",
|
|
146
|
+
"timestamp": "2025-01-20T10:30:00Z",
|
|
147
|
+
"url": "https://example.com",
|
|
148
|
+
"viewport": {
|
|
149
|
+
"width": 1280,
|
|
150
|
+
"height": 800
|
|
151
|
+
},
|
|
152
|
+
"elements": [
|
|
153
|
+
{
|
|
154
|
+
"id": 42,
|
|
155
|
+
"role": "button",
|
|
156
|
+
"text": "Sign In",
|
|
157
|
+
"importance": 850,
|
|
158
|
+
"bbox": {
|
|
159
|
+
"x": 100,
|
|
160
|
+
"y": 200,
|
|
161
|
+
"width": 120,
|
|
162
|
+
"height": 40
|
|
163
|
+
},
|
|
164
|
+
"visual_cues": {
|
|
165
|
+
"is_primary": true,
|
|
166
|
+
"background_color_name": "blue",
|
|
167
|
+
"is_clickable": true
|
|
168
|
+
},
|
|
169
|
+
"in_viewport": true,
|
|
170
|
+
"is_occluded": false,
|
|
171
|
+
"z_index": 0
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Error Response
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"status": "error",
|
|
182
|
+
"error": "Headless mode requires a valid license key...",
|
|
183
|
+
"requires_license": true
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## SDK Implementation Requirements
|
|
188
|
+
|
|
189
|
+
Both Python and TypeScript SDKs must:
|
|
190
|
+
|
|
191
|
+
1. **Validate** snapshot response against this schema
|
|
192
|
+
2. **Parse** all required fields correctly
|
|
193
|
+
3. **Handle** optional fields gracefully (defaults)
|
|
194
|
+
4. **Type-check** all fields (Pydantic for Python, TypeScript types for TS)
|
|
195
|
+
5. **Preserve** field names exactly (no renaming)
|
|
196
|
+
|
|
197
|
+
## Versioning
|
|
198
|
+
|
|
199
|
+
- **v1.0.0**: Initial stable version
|
|
200
|
+
- Future versions will increment major version for breaking changes
|
|
201
|
+
- SDKs should validate version and handle compatibility
|
|
202
|
+
|
|
203
|
+
## Related Documents
|
|
204
|
+
|
|
205
|
+
- `snapshot.schema.json` - JSON Schema validation
|
|
206
|
+
- Extension implementation: `sentience-chrome/injected_api.js`
|
|
207
|
+
- WASM implementation: `sentience-chrome/src/lib.rs`
|
|
208
|
+
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# SDK-Level Type Definitions
|
|
2
|
+
|
|
3
|
+
**Purpose**: Define SDK-level types that extend the snapshot contract with action results, wait results, and trace steps.
|
|
4
|
+
|
|
5
|
+
## Core Types
|
|
6
|
+
|
|
7
|
+
### Snapshot
|
|
8
|
+
```typescript
|
|
9
|
+
interface Snapshot {
|
|
10
|
+
status: "success" | "error";
|
|
11
|
+
timestamp?: string;
|
|
12
|
+
url: string;
|
|
13
|
+
viewport?: { width: number; height: number };
|
|
14
|
+
elements: Element[];
|
|
15
|
+
screenshot?: string;
|
|
16
|
+
screenshot_format?: "png" | "jpeg";
|
|
17
|
+
error?: string;
|
|
18
|
+
requires_license?: boolean;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Element
|
|
23
|
+
```typescript
|
|
24
|
+
interface Element {
|
|
25
|
+
id: number;
|
|
26
|
+
role: string;
|
|
27
|
+
text: string | null;
|
|
28
|
+
importance: number;
|
|
29
|
+
bbox: BBox;
|
|
30
|
+
visual_cues: VisualCues;
|
|
31
|
+
in_viewport: boolean;
|
|
32
|
+
is_occluded: boolean;
|
|
33
|
+
z_index: number;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### BBox
|
|
38
|
+
```typescript
|
|
39
|
+
interface BBox {
|
|
40
|
+
x: number;
|
|
41
|
+
y: number;
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Viewport
|
|
48
|
+
```typescript
|
|
49
|
+
interface Viewport {
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### VisualCues
|
|
56
|
+
```typescript
|
|
57
|
+
interface VisualCues {
|
|
58
|
+
is_primary: boolean;
|
|
59
|
+
background_color_name: string | null;
|
|
60
|
+
is_clickable: boolean;
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Action Types
|
|
65
|
+
|
|
66
|
+
### ActionResult
|
|
67
|
+
```typescript
|
|
68
|
+
interface ActionResult {
|
|
69
|
+
success: boolean;
|
|
70
|
+
duration_ms: number;
|
|
71
|
+
outcome?: "navigated" | "dom_updated" | "no_change" | "error";
|
|
72
|
+
url_changed?: boolean;
|
|
73
|
+
snapshot_after?: Snapshot; // Optional in Week 1, required in Week 2
|
|
74
|
+
error?: {
|
|
75
|
+
code: string;
|
|
76
|
+
reason: string;
|
|
77
|
+
recovery_hint?: string;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Fields**:
|
|
83
|
+
- `success`: True if action completed successfully
|
|
84
|
+
- `duration_ms`: Time taken in milliseconds
|
|
85
|
+
- `outcome`: What happened after action (navigation, DOM update, no change, error)
|
|
86
|
+
- `url_changed`: True if URL changed (for navigation detection)
|
|
87
|
+
- `snapshot_after`: Post-action snapshot (optional in MVP, required for recorder)
|
|
88
|
+
- `error`: Error details if action failed
|
|
89
|
+
|
|
90
|
+
## Wait & Assert Types
|
|
91
|
+
|
|
92
|
+
### WaitResult
|
|
93
|
+
```typescript
|
|
94
|
+
interface WaitResult {
|
|
95
|
+
found: boolean;
|
|
96
|
+
element?: Element;
|
|
97
|
+
duration_ms: number;
|
|
98
|
+
timeout: boolean;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Fields**:
|
|
103
|
+
- `found`: True if element was found
|
|
104
|
+
- `element`: Found element (if found)
|
|
105
|
+
- `duration_ms`: Time taken to find (or timeout)
|
|
106
|
+
- `timeout`: True if wait timed out
|
|
107
|
+
|
|
108
|
+
### AssertionError
|
|
109
|
+
```typescript
|
|
110
|
+
class AssertionError extends Error {
|
|
111
|
+
predicate: string | object;
|
|
112
|
+
timeout: number;
|
|
113
|
+
element?: Element;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Trace Types (for Recorder)
|
|
118
|
+
|
|
119
|
+
### Trace
|
|
120
|
+
```typescript
|
|
121
|
+
interface Trace {
|
|
122
|
+
version: string; // "1.0.0"
|
|
123
|
+
created_at: string; // ISO 8601
|
|
124
|
+
start_url: string;
|
|
125
|
+
steps: TraceStep[];
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### TraceStep
|
|
130
|
+
```typescript
|
|
131
|
+
interface TraceStep {
|
|
132
|
+
ts: number; // Timestamp (milliseconds since start)
|
|
133
|
+
type: "navigation" | "click" | "type" | "press" | "wait" | "assert";
|
|
134
|
+
selector?: string; // Semantic selector (inferred)
|
|
135
|
+
element_id?: number; // Element ID
|
|
136
|
+
text?: string; // For type actions (may be masked)
|
|
137
|
+
key?: string; // For press actions
|
|
138
|
+
url?: string; // For navigation
|
|
139
|
+
snapshot?: Snapshot; // Optional: snapshot at this step
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Step Types**:
|
|
144
|
+
- `navigation`: `goto(url)`
|
|
145
|
+
- `click`: Click on element
|
|
146
|
+
- `type`: Type text into element
|
|
147
|
+
- `press`: Press keyboard key
|
|
148
|
+
- `wait`: Wait for element/predicate
|
|
149
|
+
- `assert`: Assertion check
|
|
150
|
+
|
|
151
|
+
## Query Types
|
|
152
|
+
|
|
153
|
+
### QuerySelector
|
|
154
|
+
```typescript
|
|
155
|
+
// String DSL
|
|
156
|
+
type QuerySelectorString = string; // e.g., "role=button text~'Sign in'"
|
|
157
|
+
|
|
158
|
+
// Structured object
|
|
159
|
+
interface QuerySelectorObject {
|
|
160
|
+
role?: string;
|
|
161
|
+
text?: string | RegExp;
|
|
162
|
+
name?: string | RegExp;
|
|
163
|
+
clickable?: boolean;
|
|
164
|
+
isPrimary?: boolean;
|
|
165
|
+
importance?: number | { min?: number; max?: number };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
type QuerySelector = QuerySelectorString | QuerySelectorObject;
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Python Equivalents (Pydantic)
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from pydantic import BaseModel
|
|
175
|
+
from typing import Optional, List, Union
|
|
176
|
+
from datetime import datetime
|
|
177
|
+
|
|
178
|
+
class BBox(BaseModel):
|
|
179
|
+
x: float
|
|
180
|
+
y: float
|
|
181
|
+
width: float
|
|
182
|
+
height: float
|
|
183
|
+
|
|
184
|
+
class Viewport(BaseModel):
|
|
185
|
+
width: float
|
|
186
|
+
height: float
|
|
187
|
+
|
|
188
|
+
class VisualCues(BaseModel):
|
|
189
|
+
is_primary: bool
|
|
190
|
+
background_color_name: Optional[str]
|
|
191
|
+
is_clickable: bool
|
|
192
|
+
|
|
193
|
+
class Element(BaseModel):
|
|
194
|
+
id: int
|
|
195
|
+
role: str
|
|
196
|
+
text: Optional[str]
|
|
197
|
+
importance: int
|
|
198
|
+
bbox: BBox
|
|
199
|
+
visual_cues: VisualCues
|
|
200
|
+
in_viewport: bool = True
|
|
201
|
+
is_occluded: bool = False
|
|
202
|
+
z_index: int = 0
|
|
203
|
+
|
|
204
|
+
class Snapshot(BaseModel):
|
|
205
|
+
status: str # "success" | "error"
|
|
206
|
+
timestamp: Optional[str] = None
|
|
207
|
+
url: str
|
|
208
|
+
viewport: Optional[Viewport] = None
|
|
209
|
+
elements: List[Element]
|
|
210
|
+
screenshot: Optional[str] = None
|
|
211
|
+
screenshot_format: Optional[str] = None
|
|
212
|
+
error: Optional[str] = None
|
|
213
|
+
requires_license: Optional[bool] = None
|
|
214
|
+
|
|
215
|
+
class ActionResult(BaseModel):
|
|
216
|
+
success: bool
|
|
217
|
+
duration_ms: int
|
|
218
|
+
outcome: Optional[str] = None
|
|
219
|
+
url_changed: Optional[bool] = None
|
|
220
|
+
snapshot_after: Optional[Snapshot] = None
|
|
221
|
+
error: Optional[dict] = None
|
|
222
|
+
|
|
223
|
+
class WaitResult(BaseModel):
|
|
224
|
+
found: bool
|
|
225
|
+
element: Optional[Element] = None
|
|
226
|
+
duration_ms: int
|
|
227
|
+
timeout: bool
|
|
228
|
+
|
|
229
|
+
class TraceStep(BaseModel):
|
|
230
|
+
ts: int
|
|
231
|
+
type: str
|
|
232
|
+
selector: Optional[str] = None
|
|
233
|
+
element_id: Optional[int] = None
|
|
234
|
+
text: Optional[str] = None
|
|
235
|
+
key: Optional[str] = None
|
|
236
|
+
url: Optional[str] = None
|
|
237
|
+
snapshot: Optional[Snapshot] = None
|
|
238
|
+
|
|
239
|
+
class Trace(BaseModel):
|
|
240
|
+
version: str
|
|
241
|
+
created_at: str
|
|
242
|
+
start_url: str
|
|
243
|
+
steps: List[TraceStep]
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Type Validation Rules
|
|
247
|
+
|
|
248
|
+
1. **Required Fields**: Must be present and non-null
|
|
249
|
+
2. **Optional Fields**: May be omitted or null
|
|
250
|
+
3. **Type Coercion**: Numbers should be validated (no NaN, Infinity)
|
|
251
|
+
4. **Enum Values**: String enums must match exactly
|
|
252
|
+
5. **Array Bounds**: Elements array should be validated (not empty for success status)
|
|
253
|
+
|
|
254
|
+
## Compatibility Notes
|
|
255
|
+
|
|
256
|
+
- SDKs should handle missing optional fields gracefully
|
|
257
|
+
- Default values should match extension behavior
|
|
258
|
+
- Type coercion should be minimal (prefer validation errors)
|
|
259
|
+
|