zan-browser 1.0.0
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/dist/ai.d.ts +10 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +136 -0
- package/dist/ai.js.map +1 -0
- package/dist/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +38 -0
- package/dist/browser.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor.d.ts +24 -0
- package/dist/interceptor.d.ts.map +1 -0
- package/dist/interceptor.js +225 -0
- package/dist/interceptor.js.map +1 -0
- package/dist/observer.d.ts +14 -0
- package/dist/observer.d.ts.map +1 -0
- package/dist/observer.js +254 -0
- package/dist/observer.js.map +1 -0
- package/dist/session.d.ts +28 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +174 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +104 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
package/dist/ai.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ObserveResult, AgentAction } from "./types";
|
|
2
|
+
export declare class AIClient {
|
|
3
|
+
private client;
|
|
4
|
+
private model;
|
|
5
|
+
constructor(apiKey: string, model?: string);
|
|
6
|
+
decideFromObservation(goal: string, observation: ObserveResult, history: string[]): Promise<AgentAction>;
|
|
7
|
+
decideFromScreenshot(goal: string, screenshotBase64: string, history: string[]): Promise<AgentAction>;
|
|
8
|
+
private parseAction;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=ai.d.ts.map
|
package/dist/ai.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM1D,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,MAAM,EAAE,KAAK,SAAgB;IAM3C,qBAAqB,CACzB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,aAAa,EAC1B,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,WAAW,CAAC;IA+CjB,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,WAAW,CAAC;IAsDvB,OAAO,CAAC,WAAW;CA2BpB"}
|
package/dist/ai.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AIClient = void 0;
|
|
7
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
8
|
+
const DEFAULT_MODEL = "claude-haiku-4-5-20251001";
|
|
9
|
+
// AI is only used when observe() is not enough to make a decision.
|
|
10
|
+
// In practice: 0–2 calls per session.
|
|
11
|
+
class AIClient {
|
|
12
|
+
client;
|
|
13
|
+
model;
|
|
14
|
+
constructor(apiKey, model = DEFAULT_MODEL) {
|
|
15
|
+
this.client = new sdk_1.default({ apiKey });
|
|
16
|
+
this.model = model;
|
|
17
|
+
}
|
|
18
|
+
// Decide the next action given the observed DOM state (text first, no screenshot)
|
|
19
|
+
async decideFromObservation(goal, observation, history) {
|
|
20
|
+
const historyText = history.length > 0
|
|
21
|
+
? `\nPREVIOUS STEPS:\n${history.slice(-5).join("\n")}`
|
|
22
|
+
: "";
|
|
23
|
+
const prompt = `You are controlling a browser to achieve a goal.
|
|
24
|
+
Decide the SINGLE next action to take based on the current page state.
|
|
25
|
+
|
|
26
|
+
GOAL: ${goal}
|
|
27
|
+
${historyText}
|
|
28
|
+
|
|
29
|
+
CURRENT PAGE STATE:
|
|
30
|
+
${observation.text}
|
|
31
|
+
|
|
32
|
+
IMPORTANT RULES:
|
|
33
|
+
- Always dismiss cookie banners first if hasCookieBanner=true
|
|
34
|
+
- If a modal is open, interact with it first
|
|
35
|
+
- If the page is loading, return a wait action
|
|
36
|
+
- Take the minimum actions needed — stop as soon as the goal is achievable
|
|
37
|
+
- If you cannot achieve the goal, return "impossible"
|
|
38
|
+
- If the goal is achieved, return "done"
|
|
39
|
+
|
|
40
|
+
Respond with a JSON object (no markdown):
|
|
41
|
+
{
|
|
42
|
+
"type": "click" | "fill" | "scroll" | "wait" | "screenshot" | "done" | "impossible",
|
|
43
|
+
"elementId": "@B3" (required for click/fill),
|
|
44
|
+
"value": "text to type" (required for fill),
|
|
45
|
+
"direction": "up" | "down" (required for scroll),
|
|
46
|
+
"amount": 300 (optional for scroll, pixels),
|
|
47
|
+
"ms": 1000 (required for wait),
|
|
48
|
+
"reason": "why this action"
|
|
49
|
+
}`;
|
|
50
|
+
const response = await this.client.messages.create({
|
|
51
|
+
model: this.model,
|
|
52
|
+
max_tokens: 256,
|
|
53
|
+
messages: [{ role: "user", content: prompt }],
|
|
54
|
+
});
|
|
55
|
+
const text = response.content[0].type === "text" ? response.content[0].text : "";
|
|
56
|
+
return this.parseAction(text);
|
|
57
|
+
}
|
|
58
|
+
// Vision fallback — only called when observe() returns ambiguous state
|
|
59
|
+
// e.g. canvas-rendered UI, complex dynamic content
|
|
60
|
+
async decideFromScreenshot(goal, screenshotBase64, history) {
|
|
61
|
+
const historyText = history.length > 0
|
|
62
|
+
? `\nPREVIOUS STEPS:\n${history.slice(-3).join("\n")}`
|
|
63
|
+
: "";
|
|
64
|
+
const prompt = `You are controlling a browser to achieve a goal.
|
|
65
|
+
The DOM observer couldn't identify enough elements — you're seeing a screenshot instead.
|
|
66
|
+
Decide the SINGLE next action.
|
|
67
|
+
|
|
68
|
+
GOAL: ${goal}
|
|
69
|
+
${historyText}
|
|
70
|
+
|
|
71
|
+
RULES: Take minimum actions needed. Return "done" when goal is achievable.
|
|
72
|
+
Return "impossible" if it cannot be done.
|
|
73
|
+
|
|
74
|
+
Respond with JSON (no markdown):
|
|
75
|
+
{
|
|
76
|
+
"type": "click" | "fill" | "scroll" | "wait" | "screenshot" | "done" | "impossible",
|
|
77
|
+
"elementId": "describe the element visually if no ID available",
|
|
78
|
+
"value": "text to type" (for fill),
|
|
79
|
+
"direction": "up" | "down" (for scroll),
|
|
80
|
+
"ms": 1000 (for wait),
|
|
81
|
+
"reason": "why"
|
|
82
|
+
}`;
|
|
83
|
+
const response = await this.client.messages.create({
|
|
84
|
+
model: this.model,
|
|
85
|
+
max_tokens: 256,
|
|
86
|
+
messages: [
|
|
87
|
+
{
|
|
88
|
+
role: "user",
|
|
89
|
+
content: [
|
|
90
|
+
{
|
|
91
|
+
type: "image",
|
|
92
|
+
source: {
|
|
93
|
+
type: "base64",
|
|
94
|
+
media_type: "image/jpeg",
|
|
95
|
+
data: screenshotBase64,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{ type: "text", text: prompt },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
});
|
|
103
|
+
const text = response.content[0].type === "text" ? response.content[0].text : "";
|
|
104
|
+
return this.parseAction(text);
|
|
105
|
+
}
|
|
106
|
+
// ─── Private ─────────────────────────────────────────────────────────────────
|
|
107
|
+
parseAction(raw) {
|
|
108
|
+
try {
|
|
109
|
+
const cleaned = raw.replace(/```json\n?/g, "").replace(/```\n?/g, "").trim();
|
|
110
|
+
const parsed = JSON.parse(cleaned);
|
|
111
|
+
switch (parsed.type) {
|
|
112
|
+
case "click":
|
|
113
|
+
return { type: "click", elementId: parsed.elementId ?? "", reason: parsed.reason ?? "" };
|
|
114
|
+
case "fill":
|
|
115
|
+
return { type: "fill", elementId: parsed.elementId ?? "", value: parsed.value ?? "", reason: parsed.reason ?? "" };
|
|
116
|
+
case "scroll":
|
|
117
|
+
return { type: "scroll", direction: parsed.direction ?? "down", amount: parsed.amount, reason: parsed.reason ?? "" };
|
|
118
|
+
case "wait":
|
|
119
|
+
return { type: "wait", ms: parsed.ms ?? 1000, reason: parsed.reason ?? "" };
|
|
120
|
+
case "screenshot":
|
|
121
|
+
return { type: "screenshot", reason: parsed.reason ?? "need visual confirmation" };
|
|
122
|
+
case "done":
|
|
123
|
+
return { type: "done", reason: parsed.reason ?? "" };
|
|
124
|
+
case "impossible":
|
|
125
|
+
return { type: "impossible", reason: parsed.reason ?? "could not achieve goal" };
|
|
126
|
+
default:
|
|
127
|
+
return { type: "impossible", reason: `unknown action type: ${parsed.type}` };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return { type: "impossible", reason: `failed to parse AI response: ${raw.slice(0, 100)}` };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.AIClient = AIClient;
|
|
136
|
+
//# sourceMappingURL=ai.js.map
|
package/dist/ai.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BrowserConfig } from "./types";
|
|
2
|
+
import { Session } from "./session";
|
|
3
|
+
export declare class RensanBrowser {
|
|
4
|
+
private config;
|
|
5
|
+
private ai;
|
|
6
|
+
constructor(config: BrowserConfig);
|
|
7
|
+
newSession(): Promise<Session>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,EAAE,CAAW;gBAET,MAAM,EAAE,aAAa;IAM3B,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;CA2BrC"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RensanBrowser = void 0;
|
|
4
|
+
const playwright_1 = require("playwright");
|
|
5
|
+
const session_1 = require("./session");
|
|
6
|
+
const ai_1 = require("./ai");
|
|
7
|
+
class RensanBrowser {
|
|
8
|
+
config;
|
|
9
|
+
ai;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.ai = new ai_1.AIClient(config.ai.apiKey, config.ai.model);
|
|
13
|
+
}
|
|
14
|
+
// Create a new browser session connected to the cloud browser
|
|
15
|
+
async newSession() {
|
|
16
|
+
const { wsEndpoint, proxy, viewport, timeout } = this.config.session;
|
|
17
|
+
// Connect to the remote cloud browser via WebSocket
|
|
18
|
+
const browser = await playwright_1.chromium.connectOverCDP(wsEndpoint);
|
|
19
|
+
const contextOptions = {
|
|
20
|
+
viewport: viewport ?? { width: 1280, height: 800 },
|
|
21
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
22
|
+
locale: "en-US",
|
|
23
|
+
timezoneId: "America/New_York",
|
|
24
|
+
};
|
|
25
|
+
if (proxy) {
|
|
26
|
+
contextOptions.proxy = {
|
|
27
|
+
server: proxy.server,
|
|
28
|
+
username: proxy.username,
|
|
29
|
+
password: proxy.password,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const context = await browser.newContext(contextOptions);
|
|
33
|
+
const page = await context.newPage();
|
|
34
|
+
return new session_1.Session(page, browser, this.ai, timeout);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.RensanBrowser = RensanBrowser;
|
|
38
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":";;;AAAA,2CAAsC;AAEtC,uCAAoC;AACpC,6BAAgC;AAEhC,MAAa,aAAa;IAChB,MAAM,CAAgB;IACtB,EAAE,CAAW;IAErB,YAAY,MAAqB;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,IAAI,aAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,UAAU;QACd,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAErE,oDAAoD;QACpD,MAAM,OAAO,GAAG,MAAM,qBAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAE1D,MAAM,cAAc,GAA6C;YAC/D,QAAQ,EAAE,QAAQ,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;YAClD,SAAS,EACP,iHAAiH;YACnH,MAAM,EAAE,OAAO;YACf,UAAU,EAAE,kBAAkB;SAC/B,CAAC;QAEF,IAAI,KAAK,EAAE,CAAC;YACV,cAAc,CAAC,KAAK,GAAG;gBACrB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAErC,OAAO,IAAI,iBAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;CACF;AArCD,sCAqCC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { RensanBrowser } from "./browser";
|
|
2
|
+
export { Session } from "./session";
|
|
3
|
+
export type { ObservedElement, ObserveResult, CapturedRequest, AgentAction, ActResult, FindDataResult, SessionConfig, AIConfig, BrowserConfig, Screenshot, ElementType, } from "./types";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EACV,eAAe,EACf,aAAa,EACb,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,QAAQ,EACR,aAAa,EACb,UAAU,EACV,WAAW,GACZ,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Session = exports.RensanBrowser = void 0;
|
|
4
|
+
var browser_1 = require("./browser");
|
|
5
|
+
Object.defineProperty(exports, "RensanBrowser", { enumerable: true, get: function () { return browser_1.RensanBrowser; } });
|
|
6
|
+
var session_1 = require("./session");
|
|
7
|
+
Object.defineProperty(exports, "Session", { enumerable: true, get: function () { return session_1.Session; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qCAA0C;AAAjC,wGAAA,aAAa,OAAA;AACtB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import type { Page } from "playwright";
|
|
3
|
+
import type { CapturedRequest } from "./types";
|
|
4
|
+
export declare class Interceptor extends EventEmitter {
|
|
5
|
+
private captured;
|
|
6
|
+
private requestMap;
|
|
7
|
+
private active;
|
|
8
|
+
private page;
|
|
9
|
+
constructor(page: Page);
|
|
10
|
+
start(): void;
|
|
11
|
+
stop(): void;
|
|
12
|
+
getAll(): CapturedRequest[];
|
|
13
|
+
getUseful(minScore?: number): CapturedRequest[];
|
|
14
|
+
clear(): void;
|
|
15
|
+
private onRequest;
|
|
16
|
+
private onResponse;
|
|
17
|
+
private onRequestFailed;
|
|
18
|
+
private scoreRequest;
|
|
19
|
+
private shouldIgnore;
|
|
20
|
+
private isAsset;
|
|
21
|
+
private isXHR;
|
|
22
|
+
private isUsefulContentType;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAgD/C,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAO;gBAEP,IAAI,EAAE,IAAI;IAMtB,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI;IASZ,MAAM,IAAI,eAAe,EAAE;IAK3B,SAAS,CAAC,QAAQ,SAAI,GAAG,eAAe,EAAE;IAM1C,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,SAAS,CAoBf;IAEF,OAAO,CAAC,UAAU,CAkChB;IAEF,OAAO,CAAC,eAAe,CASrB;IAIF,OAAO,CAAC,YAAY;IA2DpB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,mBAAmB;CAG5B"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Interceptor = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
// Patterns that strongly indicate a real data API
|
|
7
|
+
const API_PATH_PATTERNS = [
|
|
8
|
+
/\/api\//i,
|
|
9
|
+
/\/v\d+\//i,
|
|
10
|
+
/\/graphql/i,
|
|
11
|
+
/\/rest\//i,
|
|
12
|
+
/\/data\//i,
|
|
13
|
+
/\/feed/i,
|
|
14
|
+
/\/search/i,
|
|
15
|
+
/\/query/i,
|
|
16
|
+
];
|
|
17
|
+
const CONTENT_PATH_PATTERNS = [
|
|
18
|
+
/\/products/i,
|
|
19
|
+
/\/articles/i,
|
|
20
|
+
/\/flights/i,
|
|
21
|
+
/\/prices/i,
|
|
22
|
+
/\/rates/i,
|
|
23
|
+
/\/results/i,
|
|
24
|
+
/\/items/i,
|
|
25
|
+
];
|
|
26
|
+
// Tracking params that lower score
|
|
27
|
+
const TRACKING_PARAMS = [
|
|
28
|
+
"utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term",
|
|
29
|
+
"_ga", "fbclid", "gclid", "msclkid", "ref", "source",
|
|
30
|
+
];
|
|
31
|
+
// File extensions that are never useful
|
|
32
|
+
const ASSET_EXTENSIONS = [
|
|
33
|
+
".js", ".css", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".woff",
|
|
34
|
+
".woff2", ".ttf", ".eot", ".ico", ".webp", ".avif", ".mp4", ".mp3",
|
|
35
|
+
".pdf", ".zip",
|
|
36
|
+
];
|
|
37
|
+
// Content types we care about
|
|
38
|
+
const USEFUL_CONTENT_TYPES = [
|
|
39
|
+
"application/json",
|
|
40
|
+
"application/xml",
|
|
41
|
+
"text/xml",
|
|
42
|
+
"application/rss+xml",
|
|
43
|
+
"text/plain",
|
|
44
|
+
"application/x-www-form-urlencoded",
|
|
45
|
+
];
|
|
46
|
+
class Interceptor extends events_1.EventEmitter {
|
|
47
|
+
captured = new Map();
|
|
48
|
+
requestMap = new Map(); // playwright req id → our id
|
|
49
|
+
active = false;
|
|
50
|
+
page;
|
|
51
|
+
constructor(page) {
|
|
52
|
+
super();
|
|
53
|
+
this.page = page;
|
|
54
|
+
}
|
|
55
|
+
// Start capturing immediately — called as soon as session opens (t=0)
|
|
56
|
+
start() {
|
|
57
|
+
if (this.active)
|
|
58
|
+
return;
|
|
59
|
+
this.active = true;
|
|
60
|
+
this.page.on("request", this.onRequest);
|
|
61
|
+
this.page.on("response", this.onResponse);
|
|
62
|
+
this.page.on("requestfailed", this.onRequestFailed);
|
|
63
|
+
}
|
|
64
|
+
stop() {
|
|
65
|
+
if (!this.active)
|
|
66
|
+
return;
|
|
67
|
+
this.active = false;
|
|
68
|
+
this.page.off("request", this.onRequest);
|
|
69
|
+
this.page.off("response", this.onResponse);
|
|
70
|
+
this.page.off("requestfailed", this.onRequestFailed);
|
|
71
|
+
}
|
|
72
|
+
getAll() {
|
|
73
|
+
return Array.from(this.captured.values()).sort((a, b) => b.score - a.score);
|
|
74
|
+
}
|
|
75
|
+
// Get only XHR/fetch requests with score > threshold, sorted by relevance
|
|
76
|
+
getUseful(minScore = 1) {
|
|
77
|
+
return this.getAll().filter((r) => !r.isAsset && r.isXHR && r.score >= minScore);
|
|
78
|
+
}
|
|
79
|
+
clear() {
|
|
80
|
+
this.captured.clear();
|
|
81
|
+
this.requestMap.clear();
|
|
82
|
+
}
|
|
83
|
+
// ─── Private handlers ───────────────────────────────────────────────────────
|
|
84
|
+
onRequest = (request) => {
|
|
85
|
+
const url = request.url();
|
|
86
|
+
if (this.shouldIgnore(url))
|
|
87
|
+
return;
|
|
88
|
+
const id = (0, crypto_1.randomUUID)();
|
|
89
|
+
this.requestMap.set(request.url() + request.method(), id);
|
|
90
|
+
const entry = {
|
|
91
|
+
id,
|
|
92
|
+
timestamp: Date.now(),
|
|
93
|
+
method: request.method(),
|
|
94
|
+
url,
|
|
95
|
+
requestHeaders: request.headers(),
|
|
96
|
+
requestBody: request.postData() ?? undefined,
|
|
97
|
+
isXHR: this.isXHR(request),
|
|
98
|
+
isAsset: this.isAsset(url),
|
|
99
|
+
score: 0, // scored when response arrives
|
|
100
|
+
};
|
|
101
|
+
this.captured.set(id, entry);
|
|
102
|
+
};
|
|
103
|
+
onResponse = async (response) => {
|
|
104
|
+
const url = response.url();
|
|
105
|
+
if (this.shouldIgnore(url))
|
|
106
|
+
return;
|
|
107
|
+
const key = url + response.request().method();
|
|
108
|
+
const id = this.requestMap.get(key);
|
|
109
|
+
if (!id)
|
|
110
|
+
return;
|
|
111
|
+
const entry = this.captured.get(id);
|
|
112
|
+
if (!entry)
|
|
113
|
+
return;
|
|
114
|
+
const contentType = response.headers()["content-type"] ?? "";
|
|
115
|
+
// Only read body for useful content types to avoid wasting memory
|
|
116
|
+
let body;
|
|
117
|
+
if (this.isUsefulContentType(contentType)) {
|
|
118
|
+
try {
|
|
119
|
+
body = await response.text();
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
body = undefined;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const updated = {
|
|
126
|
+
...entry,
|
|
127
|
+
status: response.status(),
|
|
128
|
+
responseHeaders: response.headers(),
|
|
129
|
+
responseBody: body,
|
|
130
|
+
contentType,
|
|
131
|
+
score: this.scoreRequest(entry, response.status(), contentType, body),
|
|
132
|
+
};
|
|
133
|
+
this.captured.set(id, updated);
|
|
134
|
+
this.emit("request", updated); // real-time stream
|
|
135
|
+
};
|
|
136
|
+
onRequestFailed = (request) => {
|
|
137
|
+
const key = request.url() + request.method();
|
|
138
|
+
const id = this.requestMap.get(key);
|
|
139
|
+
if (!id)
|
|
140
|
+
return;
|
|
141
|
+
const entry = this.captured.get(id);
|
|
142
|
+
if (!entry)
|
|
143
|
+
return;
|
|
144
|
+
this.captured.set(id, { ...entry, status: 0 });
|
|
145
|
+
};
|
|
146
|
+
// ─── Scoring ────────────────────────────────────────────────────────────────
|
|
147
|
+
scoreRequest(req, status, contentType, body) {
|
|
148
|
+
let score = 0;
|
|
149
|
+
if (req.isAsset)
|
|
150
|
+
return -10;
|
|
151
|
+
if (!req.isXHR)
|
|
152
|
+
return -5;
|
|
153
|
+
// Status must be successful
|
|
154
|
+
if (status >= 400 || status === 0)
|
|
155
|
+
return -1;
|
|
156
|
+
// First-party domain check (same domain as page)
|
|
157
|
+
try {
|
|
158
|
+
const pageHost = new URL(this.page.url()).hostname;
|
|
159
|
+
const reqHost = new URL(req.url).hostname;
|
|
160
|
+
if (reqHost === pageHost || reqHost.endsWith(`.${pageHost}`))
|
|
161
|
+
score += 10;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// ignore
|
|
165
|
+
}
|
|
166
|
+
// API path patterns
|
|
167
|
+
if (API_PATH_PATTERNS.some((p) => p.test(req.url)))
|
|
168
|
+
score += 5;
|
|
169
|
+
// Content path patterns
|
|
170
|
+
if (CONTENT_PATH_PATTERNS.some((p) => p.test(req.url)))
|
|
171
|
+
score += 3;
|
|
172
|
+
// Content type
|
|
173
|
+
if (contentType.includes("application/json"))
|
|
174
|
+
score += 5;
|
|
175
|
+
if (contentType.includes("xml") || contentType.includes("rss"))
|
|
176
|
+
score += 3;
|
|
177
|
+
// Has body with actual data
|
|
178
|
+
if (body && body.length > 100)
|
|
179
|
+
score += 3;
|
|
180
|
+
if (body && body.length > 1000)
|
|
181
|
+
score += 2;
|
|
182
|
+
// Tracking params lower score
|
|
183
|
+
try {
|
|
184
|
+
const params = new URL(req.url).searchParams;
|
|
185
|
+
for (const t of TRACKING_PARAMS) {
|
|
186
|
+
if (params.has(t))
|
|
187
|
+
score -= 2;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// ignore
|
|
192
|
+
}
|
|
193
|
+
// Very long URLs are usually tracking
|
|
194
|
+
if (req.url.length > 300)
|
|
195
|
+
score -= 3;
|
|
196
|
+
if (req.url.length > 500)
|
|
197
|
+
score -= 2;
|
|
198
|
+
// access-control-allow-origin: * means it's designed to be called directly
|
|
199
|
+
if (req.responseHeaders?.["access-control-allow-origin"] === "*")
|
|
200
|
+
score += 3;
|
|
201
|
+
return score;
|
|
202
|
+
}
|
|
203
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
204
|
+
shouldIgnore(url) {
|
|
205
|
+
return url.startsWith("data:") || url.startsWith("blob:");
|
|
206
|
+
}
|
|
207
|
+
isAsset(url) {
|
|
208
|
+
try {
|
|
209
|
+
const path = new URL(url).pathname.toLowerCase();
|
|
210
|
+
return ASSET_EXTENSIONS.some((ext) => path.endsWith(ext));
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
isXHR(request) {
|
|
217
|
+
const type = request.resourceType();
|
|
218
|
+
return type === "xhr" || type === "fetch";
|
|
219
|
+
}
|
|
220
|
+
isUsefulContentType(contentType) {
|
|
221
|
+
return USEFUL_CONTENT_TYPES.some((t) => contentType.includes(t));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.Interceptor = Interceptor;
|
|
225
|
+
//# sourceMappingURL=interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.js","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Page } from "playwright";
|
|
2
|
+
import type { ObserveResult } from "./types";
|
|
3
|
+
export declare class Observer {
|
|
4
|
+
private page;
|
|
5
|
+
constructor(page: Page);
|
|
6
|
+
observe(): Promise<ObserveResult>;
|
|
7
|
+
resolveElementId(id: string): Promise<{
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
} | null>;
|
|
11
|
+
private resolveType;
|
|
12
|
+
private buildTextRepresentation;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAmB,aAAa,EAAe,MAAM,SAAS,CAAC;AAc3E,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAO;gBAEP,IAAI,EAAE,IAAI;IAMhB,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IAwLjC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA2B5E,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,uBAAuB;CAkChC"}
|
package/dist/observer.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Observer = void 0;
|
|
4
|
+
// Prefix map for element IDs
|
|
5
|
+
const PREFIX = {
|
|
6
|
+
button: "B",
|
|
7
|
+
input: "I",
|
|
8
|
+
link: "L",
|
|
9
|
+
select: "S",
|
|
10
|
+
textarea: "T",
|
|
11
|
+
checkbox: "C",
|
|
12
|
+
radio: "R",
|
|
13
|
+
other: "O",
|
|
14
|
+
};
|
|
15
|
+
class Observer {
|
|
16
|
+
page;
|
|
17
|
+
constructor(page) {
|
|
18
|
+
this.page = page;
|
|
19
|
+
}
|
|
20
|
+
// Returns the full DOM state as structured data + human-readable text
|
|
21
|
+
// This is always called FIRST before any screenshot
|
|
22
|
+
async observe() {
|
|
23
|
+
const result = await this.page.evaluate(() => {
|
|
24
|
+
const elements = [];
|
|
25
|
+
const isVisible = (el) => {
|
|
26
|
+
const rect = el.getBoundingClientRect();
|
|
27
|
+
const style = window.getComputedStyle(el);
|
|
28
|
+
return (rect.width > 0 &&
|
|
29
|
+
rect.height > 0 &&
|
|
30
|
+
style.display !== "none" &&
|
|
31
|
+
style.visibility !== "hidden" &&
|
|
32
|
+
style.opacity !== "0");
|
|
33
|
+
};
|
|
34
|
+
const getText = (el) => {
|
|
35
|
+
const aria = el.getAttribute("aria-label");
|
|
36
|
+
if (aria)
|
|
37
|
+
return aria.trim();
|
|
38
|
+
const title = el.getAttribute("title");
|
|
39
|
+
if (title)
|
|
40
|
+
return title.trim();
|
|
41
|
+
return (el.textContent ?? "").replace(/\s+/g, " ").trim().slice(0, 100);
|
|
42
|
+
};
|
|
43
|
+
// Buttons
|
|
44
|
+
document.querySelectorAll("button, [role='button'], input[type='submit'], input[type='button']").forEach((el) => {
|
|
45
|
+
elements.push({
|
|
46
|
+
tag: "button",
|
|
47
|
+
text: getText(el),
|
|
48
|
+
disabled: el.disabled ?? false,
|
|
49
|
+
visible: isVisible(el),
|
|
50
|
+
ariaLabel: el.getAttribute("aria-label") ?? undefined,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
// Inputs
|
|
54
|
+
document.querySelectorAll("input:not([type='submit']):not([type='button']):not([type='hidden']):not([type='checkbox']):not([type='radio'])").forEach((el) => {
|
|
55
|
+
const input = el;
|
|
56
|
+
elements.push({
|
|
57
|
+
tag: "input",
|
|
58
|
+
type: input.type,
|
|
59
|
+
text: getText(el),
|
|
60
|
+
placeholder: input.placeholder || undefined,
|
|
61
|
+
value: input.value || undefined,
|
|
62
|
+
disabled: input.disabled,
|
|
63
|
+
visible: isVisible(el),
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
// Links
|
|
67
|
+
document.querySelectorAll("a[href]").forEach((el) => {
|
|
68
|
+
const anchor = el;
|
|
69
|
+
const text = getText(el);
|
|
70
|
+
if (!text)
|
|
71
|
+
return; // skip empty links
|
|
72
|
+
elements.push({
|
|
73
|
+
tag: "link",
|
|
74
|
+
text,
|
|
75
|
+
href: anchor.href,
|
|
76
|
+
disabled: false,
|
|
77
|
+
visible: isVisible(el),
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
// Selects
|
|
81
|
+
document.querySelectorAll("select").forEach((el) => {
|
|
82
|
+
const select = el;
|
|
83
|
+
elements.push({
|
|
84
|
+
tag: "select",
|
|
85
|
+
text: getText(el),
|
|
86
|
+
value: select.value || undefined,
|
|
87
|
+
disabled: select.disabled,
|
|
88
|
+
visible: isVisible(el),
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
// Textareas
|
|
92
|
+
document.querySelectorAll("textarea").forEach((el) => {
|
|
93
|
+
const textarea = el;
|
|
94
|
+
elements.push({
|
|
95
|
+
tag: "textarea",
|
|
96
|
+
text: getText(el),
|
|
97
|
+
placeholder: textarea.placeholder || undefined,
|
|
98
|
+
value: textarea.value || undefined,
|
|
99
|
+
disabled: textarea.disabled,
|
|
100
|
+
visible: isVisible(el),
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
// Checkboxes & radios
|
|
104
|
+
document.querySelectorAll("input[type='checkbox'], input[type='radio']").forEach((el) => {
|
|
105
|
+
const input = el;
|
|
106
|
+
elements.push({
|
|
107
|
+
tag: input.type,
|
|
108
|
+
text: getText(el),
|
|
109
|
+
value: input.checked ? "checked" : "unchecked",
|
|
110
|
+
disabled: input.disabled,
|
|
111
|
+
visible: isVisible(el),
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
// Modal detection
|
|
115
|
+
const modalSelectors = [
|
|
116
|
+
"[role='dialog']",
|
|
117
|
+
"[role='alertdialog']",
|
|
118
|
+
".modal",
|
|
119
|
+
".overlay",
|
|
120
|
+
"[aria-modal='true']",
|
|
121
|
+
];
|
|
122
|
+
const hasModal = modalSelectors.some((s) => document.querySelector(s) !== null);
|
|
123
|
+
// Cookie banner detection
|
|
124
|
+
const cookieKeywords = ["cookie", "gdpr", "consent", "accept all"];
|
|
125
|
+
const bodyText = document.body.innerText.toLowerCase();
|
|
126
|
+
const hasCookieBanner = cookieKeywords.some((k) => bodyText.includes(k));
|
|
127
|
+
// Loading detection
|
|
128
|
+
const loadingSelectors = [
|
|
129
|
+
"[aria-busy='true']",
|
|
130
|
+
".loading",
|
|
131
|
+
".spinner",
|
|
132
|
+
"[role='progressbar']",
|
|
133
|
+
];
|
|
134
|
+
const isLoading = loadingSelectors.some((s) => document.querySelector(s) !== null);
|
|
135
|
+
return {
|
|
136
|
+
url: window.location.href,
|
|
137
|
+
title: document.title,
|
|
138
|
+
elements,
|
|
139
|
+
hasModal,
|
|
140
|
+
hasCookieBanner,
|
|
141
|
+
isLoading,
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
// Assign IDs and build structured list
|
|
145
|
+
const counters = {};
|
|
146
|
+
const typedElements = [];
|
|
147
|
+
for (const raw of result.elements) {
|
|
148
|
+
const type = this.resolveType(raw.tag, raw.type);
|
|
149
|
+
counters[type] = (counters[type] ?? 0) + 1;
|
|
150
|
+
const id = `@${PREFIX[type]}${counters[type]}`;
|
|
151
|
+
typedElements.push({
|
|
152
|
+
id,
|
|
153
|
+
type,
|
|
154
|
+
text: raw.text || undefined,
|
|
155
|
+
placeholder: raw.placeholder,
|
|
156
|
+
href: raw.href,
|
|
157
|
+
value: raw.value,
|
|
158
|
+
disabled: raw.disabled,
|
|
159
|
+
visible: raw.visible,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const text = this.buildTextRepresentation(typedElements, result);
|
|
163
|
+
return {
|
|
164
|
+
url: result.url,
|
|
165
|
+
title: result.title,
|
|
166
|
+
elements: typedElements,
|
|
167
|
+
hasModal: result.hasModal,
|
|
168
|
+
hasCookieBanner: result.hasCookieBanner,
|
|
169
|
+
isLoading: result.isLoading,
|
|
170
|
+
text,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Find an element by ID (@B3, @I1, etc.) and return its locator
|
|
174
|
+
async resolveElementId(id) {
|
|
175
|
+
const elements = await this.observe();
|
|
176
|
+
const el = elements.elements.find((e) => e.id === id);
|
|
177
|
+
if (!el)
|
|
178
|
+
return null;
|
|
179
|
+
// Get coordinates by re-querying the DOM
|
|
180
|
+
return await this.page.evaluate((targetText) => {
|
|
181
|
+
const all = document.querySelectorAll("button, input, a, select, textarea, [role='button']");
|
|
182
|
+
for (const el of Array.from(all)) {
|
|
183
|
+
const text = (el.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
184
|
+
const aria = el.getAttribute("aria-label") ?? "";
|
|
185
|
+
if (text.includes(targetText) || aria.includes(targetText)) {
|
|
186
|
+
const rect = el.getBoundingClientRect();
|
|
187
|
+
return {
|
|
188
|
+
x: rect.left + rect.width / 2,
|
|
189
|
+
y: rect.top + rect.height / 2,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}, el.text ?? el.placeholder ?? "");
|
|
195
|
+
}
|
|
196
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
197
|
+
resolveType(tag, inputType) {
|
|
198
|
+
if (tag === "button")
|
|
199
|
+
return "button";
|
|
200
|
+
if (tag === "input") {
|
|
201
|
+
if (inputType === "checkbox")
|
|
202
|
+
return "checkbox";
|
|
203
|
+
if (inputType === "radio")
|
|
204
|
+
return "radio";
|
|
205
|
+
return "input";
|
|
206
|
+
}
|
|
207
|
+
if (tag === "link")
|
|
208
|
+
return "link";
|
|
209
|
+
if (tag === "select")
|
|
210
|
+
return "select";
|
|
211
|
+
if (tag === "textarea")
|
|
212
|
+
return "textarea";
|
|
213
|
+
if (tag === "checkbox")
|
|
214
|
+
return "checkbox";
|
|
215
|
+
if (tag === "radio")
|
|
216
|
+
return "radio";
|
|
217
|
+
return "other";
|
|
218
|
+
}
|
|
219
|
+
buildTextRepresentation(elements, meta) {
|
|
220
|
+
const lines = [
|
|
221
|
+
`PAGE: ${meta.title}`,
|
|
222
|
+
`URL: ${meta.url}`,
|
|
223
|
+
];
|
|
224
|
+
if (meta.isLoading)
|
|
225
|
+
lines.push("[⏳ PAGE IS LOADING]");
|
|
226
|
+
if (meta.hasModal)
|
|
227
|
+
lines.push("[⚠️ MODAL IS OPEN — may block interactions]");
|
|
228
|
+
if (meta.hasCookieBanner)
|
|
229
|
+
lines.push("[🍪 COOKIE BANNER DETECTED — dismiss first]");
|
|
230
|
+
lines.push("", "INTERACTIVE ELEMENTS:");
|
|
231
|
+
const visible = elements.filter((e) => e.visible !== false);
|
|
232
|
+
const hidden = elements.filter((e) => e.visible === false);
|
|
233
|
+
for (const el of visible) {
|
|
234
|
+
let desc = ` ${el.id} [${el.type}]`;
|
|
235
|
+
if (el.text)
|
|
236
|
+
desc += ` "${el.text}"`;
|
|
237
|
+
if (el.placeholder)
|
|
238
|
+
desc += ` placeholder="${el.placeholder}"`;
|
|
239
|
+
if (el.value)
|
|
240
|
+
desc += ` value="${el.value}"`;
|
|
241
|
+
if (el.href)
|
|
242
|
+
desc += ` → ${el.href.slice(0, 80)}`;
|
|
243
|
+
if (el.disabled)
|
|
244
|
+
desc += " (disabled)";
|
|
245
|
+
lines.push(desc);
|
|
246
|
+
}
|
|
247
|
+
if (hidden.length > 0) {
|
|
248
|
+
lines.push(` ... and ${hidden.length} hidden elements`);
|
|
249
|
+
}
|
|
250
|
+
return lines.join("\n");
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.Observer = Observer;
|
|
254
|
+
//# sourceMappingURL=observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer.js","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Page, Browser } from "playwright";
|
|
2
|
+
import type { ObserveResult, CapturedRequest, ActResult, FindDataResult, Screenshot } from "./types";
|
|
3
|
+
import { AIClient } from "./ai";
|
|
4
|
+
export declare class Session {
|
|
5
|
+
private page;
|
|
6
|
+
private browser;
|
|
7
|
+
private interceptor;
|
|
8
|
+
private observer;
|
|
9
|
+
private ai;
|
|
10
|
+
private defaultTimeout;
|
|
11
|
+
constructor(page: Page, browser: Browser, ai: AIClient, timeout?: number);
|
|
12
|
+
goto(url: string): Promise<void>;
|
|
13
|
+
wait(ms: number): Promise<void>;
|
|
14
|
+
get url(): string;
|
|
15
|
+
observe(): Promise<ObserveResult>;
|
|
16
|
+
screenshot(): Promise<Screenshot>;
|
|
17
|
+
clickById(elementId: string): Promise<void>;
|
|
18
|
+
fillById(elementId: string, value: string): Promise<void>;
|
|
19
|
+
getCapturedRequests(): CapturedRequest[];
|
|
20
|
+
getUsefulRequests(minScore?: number): CapturedRequest[];
|
|
21
|
+
onRequest(handler: (req: CapturedRequest) => void): void;
|
|
22
|
+
act(goal: string, maxSteps?: number): Promise<ActResult>;
|
|
23
|
+
findData(goal: string, maxSteps?: number): Promise<FindDataResult>;
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
closeAll(): Promise<void>;
|
|
26
|
+
private executeAction;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,SAAS,EACT,cAAc,EAEd,UAAU,EACX,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC,qBAAa,OAAO;IAClB,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,cAAc,CAAS;gBAG7B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,QAAQ,EACZ,OAAO,SAAS;IAiBZ,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,IAAI,GAAG,IAAI,MAAM,CAEhB;IAIK,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IAMjC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IAYjC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/D,mBAAmB,IAAI,eAAe,EAAE;IAKxC,iBAAiB,CAAC,QAAQ,SAAI,GAAG,eAAe,EAAE;IAKlD,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAMlD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,OAAO,CAAC,SAAS,CAAC;IAgDpD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,OAAO,CAAC,cAAc,CAAC;IAmB9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAOjB,aAAa;CAoC5B"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Session = void 0;
|
|
4
|
+
const interceptor_1 = require("./interceptor");
|
|
5
|
+
const observer_1 = require("./observer");
|
|
6
|
+
class Session {
|
|
7
|
+
page;
|
|
8
|
+
browser;
|
|
9
|
+
interceptor;
|
|
10
|
+
observer;
|
|
11
|
+
ai;
|
|
12
|
+
defaultTimeout;
|
|
13
|
+
constructor(page, browser, ai, timeout = 30_000) {
|
|
14
|
+
this.page = page;
|
|
15
|
+
this.browser = browser;
|
|
16
|
+
this.ai = ai;
|
|
17
|
+
this.defaultTimeout = timeout;
|
|
18
|
+
this.interceptor = new interceptor_1.Interceptor(page);
|
|
19
|
+
this.observer = new observer_1.Observer(page);
|
|
20
|
+
// Start capturing traffic immediately — t=0
|
|
21
|
+
// This catches requests the site fires on load before we do anything
|
|
22
|
+
this.interceptor.start();
|
|
23
|
+
}
|
|
24
|
+
// ─── Navigation ───────────────────────────────────────────────────────────────
|
|
25
|
+
async goto(url) {
|
|
26
|
+
await this.page.goto(url, {
|
|
27
|
+
waitUntil: "domcontentloaded",
|
|
28
|
+
timeout: this.defaultTimeout,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async wait(ms) {
|
|
32
|
+
await this.page.waitForTimeout(ms);
|
|
33
|
+
}
|
|
34
|
+
get url() {
|
|
35
|
+
return this.page.url();
|
|
36
|
+
}
|
|
37
|
+
// ─── Observe — always first, before any action ────────────────────────────────
|
|
38
|
+
async observe() {
|
|
39
|
+
return this.observer.observe();
|
|
40
|
+
}
|
|
41
|
+
// ─── Screenshot — only when observe() is not enough ──────────────────────────
|
|
42
|
+
async screenshot() {
|
|
43
|
+
const buffer = await this.page.screenshot({ type: "jpeg", quality: 80 });
|
|
44
|
+
return {
|
|
45
|
+
base64: buffer.toString("base64"),
|
|
46
|
+
mimeType: "image/jpeg",
|
|
47
|
+
timestamp: Date.now(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// ─── Interaction ──────────────────────────────────────────────────────────────
|
|
51
|
+
// Click by element ID from observe() (e.g. @B3)
|
|
52
|
+
async clickById(elementId) {
|
|
53
|
+
const coords = await this.observer.resolveElementId(elementId);
|
|
54
|
+
if (!coords)
|
|
55
|
+
throw new Error(`Element ${elementId} not found in DOM`);
|
|
56
|
+
await this.page.mouse.click(coords.x, coords.y);
|
|
57
|
+
}
|
|
58
|
+
// Fill input by element ID from observe()
|
|
59
|
+
async fillById(elementId, value) {
|
|
60
|
+
const coords = await this.observer.resolveElementId(elementId);
|
|
61
|
+
if (!coords)
|
|
62
|
+
throw new Error(`Element ${elementId} not found in DOM`);
|
|
63
|
+
await this.page.mouse.click(coords.x, coords.y);
|
|
64
|
+
await this.page.keyboard.press("Control+a");
|
|
65
|
+
await this.page.keyboard.type(value);
|
|
66
|
+
}
|
|
67
|
+
// ─── Captured requests ────────────────────────────────────────────────────────
|
|
68
|
+
// All captured requests sorted by relevance score
|
|
69
|
+
getCapturedRequests() {
|
|
70
|
+
return this.interceptor.getAll();
|
|
71
|
+
}
|
|
72
|
+
// Only useful XHR/fetch requests above score threshold
|
|
73
|
+
getUsefulRequests(minScore = 1) {
|
|
74
|
+
return this.interceptor.getUseful(minScore);
|
|
75
|
+
}
|
|
76
|
+
// Listen to requests in real-time as they come in
|
|
77
|
+
onRequest(handler) {
|
|
78
|
+
this.interceptor.on("request", handler);
|
|
79
|
+
}
|
|
80
|
+
// ─── act() — achieve a goal through multi-step navigation ────────────────────
|
|
81
|
+
async act(goal, maxSteps = 10) {
|
|
82
|
+
const steps = [];
|
|
83
|
+
const history = [];
|
|
84
|
+
for (let i = 0; i < maxSteps; i++) {
|
|
85
|
+
// ALWAYS observe first — no screenshot by default
|
|
86
|
+
const observation = await this.observe();
|
|
87
|
+
let action;
|
|
88
|
+
let usedScreenshot = false;
|
|
89
|
+
// If observe() gives us enough elements, use text-based decision
|
|
90
|
+
if (observation.elements.filter((e) => e.visible).length > 0) {
|
|
91
|
+
action = await this.ai.decideFromObservation(goal, observation, history);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Fallback: page has no readable elements (canvas, iframe, etc.) → screenshot
|
|
95
|
+
const shot = await this.screenshot();
|
|
96
|
+
action = await this.ai.decideFromScreenshot(goal, shot.base64, history);
|
|
97
|
+
usedScreenshot = true;
|
|
98
|
+
}
|
|
99
|
+
steps.push({ action, observeBefore: observation, usedScreenshot });
|
|
100
|
+
history.push(`Step ${i + 1}: ${action.type} — ${action.reason}`);
|
|
101
|
+
// Terminal states
|
|
102
|
+
if (action.type === "done") {
|
|
103
|
+
return { success: true, steps, finalUrl: this.url, reason: action.reason };
|
|
104
|
+
}
|
|
105
|
+
if (action.type === "impossible") {
|
|
106
|
+
return { success: false, steps, finalUrl: this.url, reason: action.reason };
|
|
107
|
+
}
|
|
108
|
+
// Execute action
|
|
109
|
+
await this.executeAction(action);
|
|
110
|
+
// Short wait after interactions for page to settle
|
|
111
|
+
await this.page.waitForTimeout(500);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
success: false,
|
|
115
|
+
steps,
|
|
116
|
+
finalUrl: this.url,
|
|
117
|
+
reason: `Reached max steps (${maxSteps}) without completing goal`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// ─── findData() — navigate + capture requests until goal achieved ─────────────
|
|
121
|
+
async findData(goal, maxSteps = 15) {
|
|
122
|
+
// Clear previous captures for a clean run
|
|
123
|
+
this.interceptor.clear();
|
|
124
|
+
// Restart capture (was already running, but clear resets the map)
|
|
125
|
+
// Give the page a moment to emit any initial requests
|
|
126
|
+
await this.page.waitForTimeout(300);
|
|
127
|
+
const actResult = await this.act(goal, maxSteps);
|
|
128
|
+
const capturedRequests = this.interceptor.getUseful();
|
|
129
|
+
return {
|
|
130
|
+
...actResult,
|
|
131
|
+
capturedRequests,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// ─── Cleanup ──────────────────────────────────────────────────────────────────
|
|
135
|
+
async close() {
|
|
136
|
+
this.interceptor.stop();
|
|
137
|
+
await this.page.close();
|
|
138
|
+
}
|
|
139
|
+
async closeAll() {
|
|
140
|
+
this.interceptor.stop();
|
|
141
|
+
await this.browser.close();
|
|
142
|
+
}
|
|
143
|
+
// ─── Execute action ───────────────────────────────────────────────────────────
|
|
144
|
+
async executeAction(action) {
|
|
145
|
+
switch (action.type) {
|
|
146
|
+
case "click":
|
|
147
|
+
await this.clickById(action.elementId).catch(async () => {
|
|
148
|
+
// If ID resolution fails, try clicking by text content
|
|
149
|
+
await this.page.getByText(action.elementId).first().click();
|
|
150
|
+
});
|
|
151
|
+
break;
|
|
152
|
+
case "fill":
|
|
153
|
+
await this.fillById(action.elementId, action.value).catch(async () => {
|
|
154
|
+
await this.page.getByRole("textbox").first().fill(action.value);
|
|
155
|
+
});
|
|
156
|
+
break;
|
|
157
|
+
case "scroll":
|
|
158
|
+
await this.page.evaluate(({ direction, amount }) => {
|
|
159
|
+
window.scrollBy(0, direction === "down" ? amount : -amount);
|
|
160
|
+
}, { direction: action.direction, amount: action.amount ?? 300 });
|
|
161
|
+
break;
|
|
162
|
+
case "wait":
|
|
163
|
+
await this.page.waitForTimeout(action.ms);
|
|
164
|
+
break;
|
|
165
|
+
case "screenshot":
|
|
166
|
+
// Already handled in act() loop — screenshot triggers AI vision fallback
|
|
167
|
+
break;
|
|
168
|
+
default:
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
exports.Session = Session;
|
|
174
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export type ElementType = "button" | "input" | "link" | "select" | "textarea" | "checkbox" | "radio" | "other";
|
|
2
|
+
export interface ObservedElement {
|
|
3
|
+
id: string;
|
|
4
|
+
type: ElementType;
|
|
5
|
+
text?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
href?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
visible?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ObserveResult {
|
|
13
|
+
url: string;
|
|
14
|
+
title: string;
|
|
15
|
+
elements: ObservedElement[];
|
|
16
|
+
hasModal: boolean;
|
|
17
|
+
hasCookieBanner: boolean;
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
text: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CapturedRequest {
|
|
22
|
+
id: string;
|
|
23
|
+
timestamp: number;
|
|
24
|
+
method: string;
|
|
25
|
+
url: string;
|
|
26
|
+
requestHeaders: Record<string, string>;
|
|
27
|
+
requestBody?: string;
|
|
28
|
+
status?: number;
|
|
29
|
+
responseHeaders?: Record<string, string>;
|
|
30
|
+
responseBody?: string;
|
|
31
|
+
contentType?: string;
|
|
32
|
+
isXHR: boolean;
|
|
33
|
+
isAsset: boolean;
|
|
34
|
+
score: number;
|
|
35
|
+
}
|
|
36
|
+
export type AgentAction = {
|
|
37
|
+
type: "click";
|
|
38
|
+
elementId: string;
|
|
39
|
+
reason: string;
|
|
40
|
+
} | {
|
|
41
|
+
type: "fill";
|
|
42
|
+
elementId: string;
|
|
43
|
+
value: string;
|
|
44
|
+
reason: string;
|
|
45
|
+
} | {
|
|
46
|
+
type: "scroll";
|
|
47
|
+
direction: "up" | "down";
|
|
48
|
+
amount?: number;
|
|
49
|
+
reason: string;
|
|
50
|
+
} | {
|
|
51
|
+
type: "wait";
|
|
52
|
+
ms: number;
|
|
53
|
+
reason: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: "screenshot";
|
|
56
|
+
reason: string;
|
|
57
|
+
} | {
|
|
58
|
+
type: "done";
|
|
59
|
+
reason: string;
|
|
60
|
+
} | {
|
|
61
|
+
type: "impossible";
|
|
62
|
+
reason: string;
|
|
63
|
+
};
|
|
64
|
+
export interface ActResult {
|
|
65
|
+
success: boolean;
|
|
66
|
+
steps: Array<{
|
|
67
|
+
action: AgentAction;
|
|
68
|
+
observeBefore: ObserveResult;
|
|
69
|
+
usedScreenshot: boolean;
|
|
70
|
+
}>;
|
|
71
|
+
finalUrl: string;
|
|
72
|
+
reason: string;
|
|
73
|
+
}
|
|
74
|
+
export interface FindDataResult extends ActResult {
|
|
75
|
+
capturedRequests: CapturedRequest[];
|
|
76
|
+
}
|
|
77
|
+
export interface SessionConfig {
|
|
78
|
+
wsEndpoint: string;
|
|
79
|
+
proxy?: {
|
|
80
|
+
server: string;
|
|
81
|
+
username?: string;
|
|
82
|
+
password?: string;
|
|
83
|
+
};
|
|
84
|
+
profileId?: string;
|
|
85
|
+
timeout?: number;
|
|
86
|
+
viewport?: {
|
|
87
|
+
width: number;
|
|
88
|
+
height: number;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export interface AIConfig {
|
|
92
|
+
apiKey: string;
|
|
93
|
+
model?: string;
|
|
94
|
+
}
|
|
95
|
+
export interface BrowserConfig {
|
|
96
|
+
session: SessionConfig;
|
|
97
|
+
ai: AIConfig;
|
|
98
|
+
}
|
|
99
|
+
export interface Screenshot {
|
|
100
|
+
base64: string;
|
|
101
|
+
mimeType: "image/jpeg" | "image/png";
|
|
102
|
+
timestamp: number;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,gFAAgF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zan-browser",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI-powered cloud browser library with observe-first, screenshot-as-fallback pattern",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"browser",
|
|
17
|
+
"automation",
|
|
18
|
+
"playwright",
|
|
19
|
+
"ai",
|
|
20
|
+
"claude",
|
|
21
|
+
"scraping",
|
|
22
|
+
"observe",
|
|
23
|
+
"cloud-browser"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
28
|
+
"playwright": "^1.49.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"typescript": "^5.7.2",
|
|
32
|
+
"@types/node": "^22.10.0"
|
|
33
|
+
}
|
|
34
|
+
}
|