sentienceapi 0.90.1
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/LICENSE.md +43 -0
- package/README.md +946 -0
- package/dist/actions.d.ts +54 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +349 -0
- package/dist/actions.js.map +1 -0
- package/dist/agent.d.ts +157 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +437 -0
- package/dist/agent.js.map +1 -0
- package/dist/browser.d.ts +46 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +622 -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 +174 -0
- package/dist/cli.js.map +1 -0
- package/dist/conversational-agent.d.ts +123 -0
- package/dist/conversational-agent.d.ts.map +1 -0
- package/dist/conversational-agent.js +327 -0
- package/dist/conversational-agent.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 +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -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/llm-provider.d.ts +60 -0
- package/dist/llm-provider.d.ts.map +1 -0
- package/dist/llm-provider.js +106 -0
- package/dist/llm-provider.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 +23 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +187 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/tracing/cloud-sink.d.ts +74 -0
- package/dist/tracing/cloud-sink.d.ts.map +1 -0
- package/dist/tracing/cloud-sink.js +262 -0
- package/dist/tracing/cloud-sink.js.map +1 -0
- package/dist/tracing/index.d.ts +12 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +28 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/tracing/jsonl-sink.d.ts +41 -0
- package/dist/tracing/jsonl-sink.d.ts.map +1 -0
- package/dist/tracing/jsonl-sink.js +168 -0
- package/dist/tracing/jsonl-sink.js.map +1 -0
- package/dist/tracing/sink.d.ts +24 -0
- package/dist/tracing/sink.d.ts.map +1 -0
- package/dist/tracing/sink.js +15 -0
- package/dist/tracing/sink.js.map +1 -0
- package/dist/tracing/tracer-factory.d.ts +57 -0
- package/dist/tracing/tracer-factory.d.ts.map +1 -0
- package/dist/tracing/tracer-factory.js +274 -0
- package/dist/tracing/tracer-factory.js.map +1 -0
- package/dist/tracing/tracer.d.ts +74 -0
- package/dist/tracing/tracer.d.ts.map +1 -0
- package/dist/tracing/tracer.js +131 -0
- package/dist/tracing/tracer.js.map +1 -0
- package/dist/tracing/types.d.ts +63 -0
- package/dist/tracing/types.d.ts.map +1 -0
- package/dist/tracing/types.js +8 -0
- package/dist/tracing/types.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +29 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +74 -0
- package/dist/utils.js.map +1 -0
- package/dist/wait.d.ts +20 -0
- package/dist/wait.d.ts.map +1 -0
- package/dist/wait.js +63 -0
- package/dist/wait.js.map +1 -0
- package/package.json +72 -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/dist/read.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../src/read.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;AAyCH,oBAkEC;AAxGD,wDAAuC;AAgBvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACI,KAAK,UAAU,IAAI,CACxB,OAAyB,EACzB,UAAuB,EAAE;IAEzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,8CAA8C;IACtF,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,KAAK,KAAK,CAAC,CAAC,kBAAkB;IAE7E,IAAI,MAAM,KAAK,UAAU,IAAI,eAAe,EAAE,CAAC;QAC7C,wCAAwC;QACxC,MAAM,aAAa,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CACxC,CAAC,IAAI,EAAE,EAAE;YACP,OAAQ,MAAc,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,EACD,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAe,CAAC;QAEjB,IAAI,aAAa,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,IAAI,kBAAe,CAAC;oBAC1C,YAAY,EAAE,KAAK;oBACnB,EAAE,EAAE,KAAK;oBACT,gBAAgB,EAAE,GAAG;oBACrB,cAAc,EAAE,QAAQ;oBACxB,WAAW,EAAE,GAAG;iBACjB,CAAC,CAAC;gBAEH,uCAAuC;gBACvC,eAAe,CAAC,OAAO,CAAC,eAAe,EAAE;oBACvC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;oBAC9E,WAAW,EAAE,UAAU,OAAO;wBAC5B,OAAO,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;oBAC/B,CAAC;iBACF,CAAC,CAAC;gBAEH,yCAAyC;gBACzC,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAQ,CAAC,CAAC;gBAEzE,MAAM,eAAe,GAAG,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAC9D,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,GAAG,EAAE,aAAa,CAAC,GAAG;oBACtB,MAAM,EAAE,UAAU;oBAClB,OAAO,EAAE,eAAe;oBACxB,MAAM,EAAE,eAAe,CAAC,MAAM;iBAC/B,CAAC;YACJ,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,OAAO,yCAAyC,CAAC,CAAC;gBAChG,qDAAqD;YACvD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,0CAA0C,aAAa,CAAC,KAAK,yCAAyC,CAAC,CAAC;YACrH,6DAA6D;QAC/D,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CACjC,CAAC,IAAI,EAAE,EAAE;QACP,OAAQ,MAAc,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,EACD,EAAE,MAAM,EAAE,CACX,CAAe,CAAC;IAEjB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recorder - captures user actions into a trace
|
|
3
|
+
*/
|
|
4
|
+
import { SentienceBrowser } from './browser';
|
|
5
|
+
import { Snapshot } from './types';
|
|
6
|
+
export interface TraceStep {
|
|
7
|
+
ts: number;
|
|
8
|
+
type: 'navigation' | 'click' | 'type' | 'press' | 'wait' | 'assert';
|
|
9
|
+
selector?: string;
|
|
10
|
+
element_id?: number;
|
|
11
|
+
text?: string;
|
|
12
|
+
key?: string;
|
|
13
|
+
url?: string;
|
|
14
|
+
snapshot?: Snapshot;
|
|
15
|
+
}
|
|
16
|
+
export interface Trace {
|
|
17
|
+
version: string;
|
|
18
|
+
created_at: string;
|
|
19
|
+
start_url: string;
|
|
20
|
+
steps: TraceStep[];
|
|
21
|
+
}
|
|
22
|
+
export declare class Recorder {
|
|
23
|
+
private browser;
|
|
24
|
+
private captureSnapshots;
|
|
25
|
+
private trace;
|
|
26
|
+
private active;
|
|
27
|
+
private startTime;
|
|
28
|
+
private maskPatterns;
|
|
29
|
+
constructor(browser: SentienceBrowser, captureSnapshots?: boolean);
|
|
30
|
+
start(): void;
|
|
31
|
+
stop(): void;
|
|
32
|
+
addMaskPattern(pattern: string): void;
|
|
33
|
+
private shouldMask;
|
|
34
|
+
recordNavigation(url: string): void;
|
|
35
|
+
recordClick(elementId: number, selector?: string): Promise<void>;
|
|
36
|
+
recordType(elementId: number, text: string, selector?: string): Promise<void>;
|
|
37
|
+
recordPress(key: string): void;
|
|
38
|
+
getTrace(): Trace;
|
|
39
|
+
save(filepath: string): Promise<void>;
|
|
40
|
+
static load(filepath: string): Promise<Trace>;
|
|
41
|
+
private inferSelector;
|
|
42
|
+
}
|
|
43
|
+
export declare function record(browser: SentienceBrowser, captureSnapshots?: boolean): Recorder;
|
|
44
|
+
//# sourceMappingURL=recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAW,MAAM,SAAS,CAAC;AAI5C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,qBAAa,QAAQ;IAOjB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,gBAAgB;IAP1B,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,YAAY,CAAgB;gBAG1B,OAAO,EAAE,gBAAgB,EACzB,gBAAgB,GAAE,OAAe;IAG3C,KAAK,IAAI,IAAI;IAcb,IAAI,IAAI,IAAI;IAIZ,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIrC,OAAO,CAAC,UAAU;IAKlB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW7B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwChE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnF,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAW9B,QAAQ,IAAI,KAAK;IAOX,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAS9B,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;YAMrC,aAAa;CAwF5B;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,GAAE,OAAe,GAAG,QAAQ,CAE7F"}
|
package/dist/recorder.js
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Recorder - captures user actions into a trace
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Recorder = void 0;
|
|
40
|
+
exports.record = record;
|
|
41
|
+
const snapshot_1 = require("./snapshot");
|
|
42
|
+
const query_1 = require("./query");
|
|
43
|
+
class Recorder {
|
|
44
|
+
constructor(browser, captureSnapshots = false) {
|
|
45
|
+
this.browser = browser;
|
|
46
|
+
this.captureSnapshots = captureSnapshots;
|
|
47
|
+
this.trace = null;
|
|
48
|
+
this.active = false;
|
|
49
|
+
this.startTime = new Date();
|
|
50
|
+
this.maskPatterns = [];
|
|
51
|
+
}
|
|
52
|
+
start() {
|
|
53
|
+
const page = this.browser.getPage();
|
|
54
|
+
this.active = true;
|
|
55
|
+
const startUrl = page.url();
|
|
56
|
+
this.startTime = new Date();
|
|
57
|
+
this.trace = {
|
|
58
|
+
version: '1.0.0',
|
|
59
|
+
created_at: new Date().toISOString(),
|
|
60
|
+
start_url: startUrl,
|
|
61
|
+
steps: [],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
stop() {
|
|
65
|
+
this.active = false;
|
|
66
|
+
}
|
|
67
|
+
addMaskPattern(pattern) {
|
|
68
|
+
this.maskPatterns.push(pattern.toLowerCase());
|
|
69
|
+
}
|
|
70
|
+
shouldMask(text) {
|
|
71
|
+
const textLower = text.toLowerCase();
|
|
72
|
+
return this.maskPatterns.some((pattern) => textLower.includes(pattern));
|
|
73
|
+
}
|
|
74
|
+
recordNavigation(url) {
|
|
75
|
+
if (!this.active || !this.trace)
|
|
76
|
+
return;
|
|
77
|
+
const ts = Date.now() - this.startTime.getTime();
|
|
78
|
+
this.trace.steps.push({
|
|
79
|
+
ts,
|
|
80
|
+
type: 'navigation',
|
|
81
|
+
url,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async recordClick(elementId, selector) {
|
|
85
|
+
if (!this.active || !this.trace)
|
|
86
|
+
return;
|
|
87
|
+
// If no selector provided, try to infer one
|
|
88
|
+
if (!selector) {
|
|
89
|
+
selector = await this.inferSelector(elementId);
|
|
90
|
+
}
|
|
91
|
+
const ts = Date.now() - this.startTime.getTime();
|
|
92
|
+
// Optionally capture snapshot
|
|
93
|
+
if (this.captureSnapshots) {
|
|
94
|
+
try {
|
|
95
|
+
const snap = await (0, snapshot_1.snapshot)(this.browser);
|
|
96
|
+
this.trace.steps.push({
|
|
97
|
+
ts,
|
|
98
|
+
type: 'click',
|
|
99
|
+
element_id: elementId,
|
|
100
|
+
selector,
|
|
101
|
+
snapshot: snap,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
// If snapshot fails, just record without it
|
|
106
|
+
this.trace.steps.push({
|
|
107
|
+
ts,
|
|
108
|
+
type: 'click',
|
|
109
|
+
element_id: elementId,
|
|
110
|
+
selector,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.trace.steps.push({
|
|
116
|
+
ts,
|
|
117
|
+
type: 'click',
|
|
118
|
+
element_id: elementId,
|
|
119
|
+
selector,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async recordType(elementId, text, selector) {
|
|
124
|
+
if (!this.active || !this.trace)
|
|
125
|
+
return;
|
|
126
|
+
// If no selector provided, try to infer one
|
|
127
|
+
if (!selector) {
|
|
128
|
+
selector = await this.inferSelector(elementId);
|
|
129
|
+
}
|
|
130
|
+
const ts = Date.now() - this.startTime.getTime();
|
|
131
|
+
const mask = this.shouldMask(text);
|
|
132
|
+
const maskedText = mask ? '***' : text;
|
|
133
|
+
this.trace.steps.push({
|
|
134
|
+
ts,
|
|
135
|
+
type: 'type',
|
|
136
|
+
element_id: elementId,
|
|
137
|
+
text: maskedText,
|
|
138
|
+
selector,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
recordPress(key) {
|
|
142
|
+
if (!this.active || !this.trace)
|
|
143
|
+
return;
|
|
144
|
+
const ts = Date.now() - this.startTime.getTime();
|
|
145
|
+
this.trace.steps.push({
|
|
146
|
+
ts,
|
|
147
|
+
type: 'press',
|
|
148
|
+
key,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
getTrace() {
|
|
152
|
+
if (!this.trace) {
|
|
153
|
+
throw new Error('No trace available. Start recording first.');
|
|
154
|
+
}
|
|
155
|
+
return this.trace;
|
|
156
|
+
}
|
|
157
|
+
async save(filepath) {
|
|
158
|
+
if (!this.trace) {
|
|
159
|
+
throw new Error('No trace to save. Start recording first.');
|
|
160
|
+
}
|
|
161
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
162
|
+
fs.writeFileSync(filepath, JSON.stringify(this.trace, null, 2), 'utf-8');
|
|
163
|
+
}
|
|
164
|
+
static async load(filepath) {
|
|
165
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
166
|
+
const data = fs.readFileSync(filepath, 'utf-8');
|
|
167
|
+
return JSON.parse(data);
|
|
168
|
+
}
|
|
169
|
+
async inferSelector(elementId) {
|
|
170
|
+
try {
|
|
171
|
+
// Take a snapshot to get element info
|
|
172
|
+
const snap = await (0, snapshot_1.snapshot)(this.browser);
|
|
173
|
+
// Find the element in the snapshot
|
|
174
|
+
let element;
|
|
175
|
+
for (const el of snap.elements) {
|
|
176
|
+
if (el.id === elementId) {
|
|
177
|
+
element = el;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!element) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
// Build candidate selector
|
|
185
|
+
const parts = [];
|
|
186
|
+
// Add role
|
|
187
|
+
if (element.role && element.role !== 'generic') {
|
|
188
|
+
parts.push(`role=${element.role}`);
|
|
189
|
+
}
|
|
190
|
+
// Add text if available
|
|
191
|
+
if (element.text) {
|
|
192
|
+
const textPart = element.text.replace(/"/g, '\\"').substring(0, 50);
|
|
193
|
+
parts.push(`text~"${textPart}"`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// Try to get name/aria-label/placeholder from DOM
|
|
197
|
+
try {
|
|
198
|
+
const el = await this.browser.getPage().evaluate((id) => {
|
|
199
|
+
const registry = window.sentience_registry;
|
|
200
|
+
if (!registry || !registry[id])
|
|
201
|
+
return null;
|
|
202
|
+
const elem = registry[id];
|
|
203
|
+
return {
|
|
204
|
+
name: elem.name || null,
|
|
205
|
+
ariaLabel: elem.getAttribute('aria-label') || null,
|
|
206
|
+
placeholder: elem.placeholder || null,
|
|
207
|
+
};
|
|
208
|
+
}, elementId);
|
|
209
|
+
if (el) {
|
|
210
|
+
if (el.name) {
|
|
211
|
+
parts.push(`name="${el.name}"`);
|
|
212
|
+
}
|
|
213
|
+
else if (el.ariaLabel) {
|
|
214
|
+
parts.push(`text~"${el.ariaLabel}"`);
|
|
215
|
+
}
|
|
216
|
+
else if (el.placeholder) {
|
|
217
|
+
parts.push(`text~"${el.placeholder}"`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
// Ignore errors
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Add clickable if relevant
|
|
226
|
+
if (element.visual_cues.is_clickable) {
|
|
227
|
+
parts.push('clickable=true');
|
|
228
|
+
}
|
|
229
|
+
if (parts.length === 0) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
const selector = parts.join(' ');
|
|
233
|
+
// Validate selector - should match exactly 1 element
|
|
234
|
+
const matches = (0, query_1.query)(snap, selector);
|
|
235
|
+
if (matches.length === 1) {
|
|
236
|
+
return selector;
|
|
237
|
+
}
|
|
238
|
+
else if (matches.length > 1) {
|
|
239
|
+
// Multiple matches - return selector anyway (could add more constraints later)
|
|
240
|
+
return selector;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
// Selector doesn't match - return undefined (will use element_id)
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch (e) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
exports.Recorder = Recorder;
|
|
253
|
+
function record(browser, captureSnapshots = false) {
|
|
254
|
+
return new Recorder(browser, captureSnapshots);
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screenshot functionality - standalone screenshot capture
|
|
3
|
+
*/
|
|
4
|
+
import { SentienceBrowser } from './browser';
|
|
5
|
+
export interface ScreenshotOptions {
|
|
6
|
+
format?: 'png' | 'jpeg';
|
|
7
|
+
quality?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Capture screenshot of current page
|
|
11
|
+
*
|
|
12
|
+
* @param browser - SentienceBrowser instance
|
|
13
|
+
* @param options - Screenshot options
|
|
14
|
+
* @returns Base64-encoded screenshot data URL (e.g., "data:image/png;base64,...")
|
|
15
|
+
*/
|
|
16
|
+
export declare function screenshot(browser: SentienceBrowser, options?: ScreenshotOptions): Promise<string>;
|
|
17
|
+
//# sourceMappingURL=screenshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Screenshot functionality - standalone screenshot capture
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.screenshot = screenshot;
|
|
7
|
+
/**
|
|
8
|
+
* Capture screenshot of current page
|
|
9
|
+
*
|
|
10
|
+
* @param browser - SentienceBrowser instance
|
|
11
|
+
* @param options - Screenshot options
|
|
12
|
+
* @returns Base64-encoded screenshot data URL (e.g., "data:image/png;base64,...")
|
|
13
|
+
*/
|
|
14
|
+
async function screenshot(browser, options = {}) {
|
|
15
|
+
const page = browser.getPage();
|
|
16
|
+
const format = options.format || 'png';
|
|
17
|
+
const quality = options.quality;
|
|
18
|
+
if (format === 'jpeg' && quality !== undefined) {
|
|
19
|
+
if (quality < 1 || quality > 100) {
|
|
20
|
+
throw new Error('Quality must be between 1 and 100 for JPEG format');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Use Playwright's screenshot with base64 encoding
|
|
24
|
+
const screenshotOptions = {
|
|
25
|
+
type: format,
|
|
26
|
+
encoding: 'base64',
|
|
27
|
+
};
|
|
28
|
+
if (format === 'jpeg' && quality !== undefined) {
|
|
29
|
+
screenshotOptions.quality = quality;
|
|
30
|
+
}
|
|
31
|
+
// Capture screenshot
|
|
32
|
+
const base64Data = await page.screenshot(screenshotOptions);
|
|
33
|
+
// Return as data URL
|
|
34
|
+
const mimeType = format === 'png' ? 'image/png' : 'image/jpeg';
|
|
35
|
+
return `data:${mimeType};base64,${base64Data}`;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../src/screenshot.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAgBH,gCA8BC;AArCD;;;;;;GAMG;AACI,KAAK,UAAU,UAAU,CAC9B,OAAyB,EACzB,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,IAAI,MAAM,KAAK,MAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/C,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,iBAAiB,GAAQ;QAC7B,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,QAAQ;KACnB,CAAC;IAEF,IAAI,MAAM,KAAK,MAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/C,iBAAiB,CAAC,OAAO,GAAG,OAAO,CAAC;IACtC,CAAC;IAED,qBAAqB;IACrB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAE5D,qBAAqB;IACrB,MAAM,QAAQ,GAAG,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC;IAC/D,OAAO,QAAQ,QAAQ,WAAW,UAAU,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot functionality - calls window.sentience.snapshot() or server-side API
|
|
3
|
+
*/
|
|
4
|
+
import { SentienceBrowser } from './browser';
|
|
5
|
+
import { Snapshot } from './types';
|
|
6
|
+
export interface SnapshotOptions {
|
|
7
|
+
screenshot?: boolean | {
|
|
8
|
+
format: 'png' | 'jpeg';
|
|
9
|
+
quality?: number;
|
|
10
|
+
};
|
|
11
|
+
limit?: number;
|
|
12
|
+
filter?: {
|
|
13
|
+
min_area?: number;
|
|
14
|
+
allowed_roles?: string[];
|
|
15
|
+
min_z_index?: number;
|
|
16
|
+
};
|
|
17
|
+
use_api?: boolean;
|
|
18
|
+
save_trace?: boolean;
|
|
19
|
+
trace_path?: string;
|
|
20
|
+
goal?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function snapshot(browser: SentienceBrowser, options?: SnapshotOptions): Promise<Snapshot>;
|
|
23
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAInC,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAwBD,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAiBnB"}
|
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot functionality - calls window.sentience.snapshot() or server-side API
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.snapshot = snapshot;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
/**
|
|
43
|
+
* Save raw_elements to a JSON file for benchmarking/training
|
|
44
|
+
*
|
|
45
|
+
* @param rawElements Raw elements data from snapshot
|
|
46
|
+
* @param tracePath Path to save trace file. If undefined, uses "trace_{timestamp}.json"
|
|
47
|
+
*/
|
|
48
|
+
function _saveTraceToFile(rawElements, tracePath) {
|
|
49
|
+
// Default filename if none provided
|
|
50
|
+
const filename = tracePath || `trace_${Date.now()}.json`;
|
|
51
|
+
// Ensure directory exists
|
|
52
|
+
const dir = path.dirname(filename);
|
|
53
|
+
if (dir !== '.') {
|
|
54
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
// Save the raw elements to JSON
|
|
57
|
+
fs.writeFileSync(filename, JSON.stringify(rawElements, null, 2));
|
|
58
|
+
console.log(`[SDK] Trace saved to: ${filename}`);
|
|
59
|
+
}
|
|
60
|
+
async function snapshot(browser, options = {}) {
|
|
61
|
+
// Get API configuration
|
|
62
|
+
const apiKey = browser.getApiKey();
|
|
63
|
+
const apiUrl = browser.getApiUrl();
|
|
64
|
+
// Determine if we should use server-side API
|
|
65
|
+
const shouldUseApi = options.use_api !== undefined
|
|
66
|
+
? options.use_api
|
|
67
|
+
: (apiKey !== undefined);
|
|
68
|
+
if (shouldUseApi && apiKey) {
|
|
69
|
+
// Use server-side API (Pro/Enterprise tier)
|
|
70
|
+
return snapshotViaApi(browser, options, apiKey, apiUrl);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Use local extension (Free tier)
|
|
74
|
+
return snapshotViaExtension(browser, options);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function snapshotViaExtension(browser, options) {
|
|
78
|
+
const page = browser.getPage();
|
|
79
|
+
// CRITICAL: Wait for extension injection to complete (CSP-resistant architecture)
|
|
80
|
+
// The new architecture loads injected_api.js asynchronously, so window.sentience
|
|
81
|
+
// may not be immediately available after page load
|
|
82
|
+
try {
|
|
83
|
+
await page.waitForFunction(() => typeof window.sentience !== 'undefined', { timeout: 5000 });
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
// Gather diagnostics if wait fails
|
|
87
|
+
const diag = await page.evaluate(() => ({
|
|
88
|
+
sentience_defined: typeof window.sentience !== 'undefined',
|
|
89
|
+
extension_id: document.documentElement.dataset.sentienceExtensionId || 'not set',
|
|
90
|
+
url: window.location.href
|
|
91
|
+
})).catch(() => ({ error: 'Could not gather diagnostics' }));
|
|
92
|
+
throw new Error(`Sentience extension failed to inject window.sentience API. ` +
|
|
93
|
+
`Is the extension loaded? Diagnostics: ${JSON.stringify(diag)}`);
|
|
94
|
+
}
|
|
95
|
+
// Build options object
|
|
96
|
+
const opts = {};
|
|
97
|
+
if (options.screenshot !== undefined) {
|
|
98
|
+
opts.screenshot = options.screenshot;
|
|
99
|
+
}
|
|
100
|
+
if (options.limit !== undefined) {
|
|
101
|
+
opts.limit = options.limit;
|
|
102
|
+
}
|
|
103
|
+
if (options.filter !== undefined) {
|
|
104
|
+
opts.filter = options.filter;
|
|
105
|
+
}
|
|
106
|
+
// Call extension API
|
|
107
|
+
const result = await page.evaluate((opts) => {
|
|
108
|
+
return window.sentience.snapshot(opts);
|
|
109
|
+
}, opts);
|
|
110
|
+
// Save trace if requested
|
|
111
|
+
if (options.save_trace && result.raw_elements) {
|
|
112
|
+
_saveTraceToFile(result.raw_elements, options.trace_path);
|
|
113
|
+
}
|
|
114
|
+
// Basic validation
|
|
115
|
+
if (result.status !== 'success' && result.status !== 'error') {
|
|
116
|
+
throw new Error(`Invalid snapshot status: ${result.status}`);
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
async function snapshotViaApi(browser, options, apiKey, apiUrl) {
|
|
121
|
+
const page = browser.getPage();
|
|
122
|
+
// CRITICAL: Wait for extension injection to complete (CSP-resistant architecture)
|
|
123
|
+
// Even for API mode, we need the extension to collect raw data locally
|
|
124
|
+
try {
|
|
125
|
+
await page.waitForFunction(() => typeof window.sentience !== 'undefined', { timeout: 5000 });
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
throw new Error('Sentience extension failed to inject. Cannot collect raw data for API processing.');
|
|
129
|
+
}
|
|
130
|
+
// Step 1: Get raw data from local extension (always happens locally)
|
|
131
|
+
const rawOpts = {};
|
|
132
|
+
if (options.screenshot !== undefined) {
|
|
133
|
+
rawOpts.screenshot = options.screenshot;
|
|
134
|
+
}
|
|
135
|
+
const rawResult = await page.evaluate((opts) => {
|
|
136
|
+
return window.sentience.snapshot(opts);
|
|
137
|
+
}, rawOpts);
|
|
138
|
+
// Save trace if requested (save raw data before API processing)
|
|
139
|
+
if (options.save_trace && rawResult.raw_elements) {
|
|
140
|
+
_saveTraceToFile(rawResult.raw_elements, options.trace_path);
|
|
141
|
+
}
|
|
142
|
+
// Step 2: Send to server for smart ranking/filtering
|
|
143
|
+
// Use raw_elements (raw data) instead of elements (processed data)
|
|
144
|
+
// Server validates API key and applies proprietary ranking logic
|
|
145
|
+
const payload = {
|
|
146
|
+
raw_elements: rawResult.raw_elements || [], // Raw data needed for server processing
|
|
147
|
+
url: rawResult.url || '',
|
|
148
|
+
viewport: rawResult.viewport,
|
|
149
|
+
goal: options.goal, // Optional goal/task description
|
|
150
|
+
options: {
|
|
151
|
+
limit: options.limit,
|
|
152
|
+
filter: options.filter,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const headers = {
|
|
156
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
157
|
+
'Content-Type': 'application/json',
|
|
158
|
+
};
|
|
159
|
+
try {
|
|
160
|
+
const response = await fetch(`${apiUrl}/v1/snapshot`, {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers,
|
|
163
|
+
body: JSON.stringify(payload),
|
|
164
|
+
});
|
|
165
|
+
if (!response.ok) {
|
|
166
|
+
const errorText = await response.text();
|
|
167
|
+
throw new Error(`API request failed: ${response.status} ${errorText}`);
|
|
168
|
+
}
|
|
169
|
+
const apiResult = await response.json();
|
|
170
|
+
// Merge API result with local data (screenshot, etc.)
|
|
171
|
+
const snapshotData = {
|
|
172
|
+
status: apiResult.status || 'success',
|
|
173
|
+
timestamp: apiResult.timestamp,
|
|
174
|
+
url: apiResult.url || rawResult.url || '',
|
|
175
|
+
viewport: apiResult.viewport || rawResult.viewport,
|
|
176
|
+
elements: apiResult.elements || [],
|
|
177
|
+
screenshot: rawResult.screenshot, // Keep local screenshot
|
|
178
|
+
screenshot_format: rawResult.screenshot_format,
|
|
179
|
+
error: apiResult.error,
|
|
180
|
+
};
|
|
181
|
+
return snapshotData;
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
throw new Error(`API request failed: ${e.message}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"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"}
|