@hera-al/browser-server 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/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.js +74 -0
- package/dist/core/cdp.d.ts +124 -0
- package/dist/core/cdp.helpers.d.ts +14 -0
- package/dist/core/cdp.helpers.js +148 -0
- package/dist/core/cdp.js +309 -0
- package/dist/core/chrome.d.ts +21 -0
- package/dist/core/chrome.executables.d.ts +10 -0
- package/dist/core/chrome.executables.js +559 -0
- package/dist/core/chrome.js +257 -0
- package/dist/core/chrome.profile-decoration.d.ts +11 -0
- package/dist/core/chrome.profile-decoration.js +148 -0
- package/dist/core/constants.d.ts +9 -0
- package/dist/core/constants.js +9 -0
- package/dist/core/profiles.d.ts +31 -0
- package/dist/core/profiles.js +99 -0
- package/dist/core/target-id.d.ts +12 -0
- package/dist/core/target-id.js +21 -0
- package/dist/data-dir.d.ts +2 -0
- package/dist/data-dir.js +6 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.js +125 -0
- package/dist/playwright/pw-role-snapshot.d.ts +32 -0
- package/dist/playwright/pw-role-snapshot.js +337 -0
- package/dist/playwright/pw-session.d.ts +119 -0
- package/dist/playwright/pw-session.js +530 -0
- package/dist/playwright/pw-tools-core.activity.d.ts +22 -0
- package/dist/playwright/pw-tools-core.activity.js +47 -0
- package/dist/playwright/pw-tools-core.d.ts +9 -0
- package/dist/playwright/pw-tools-core.downloads.d.ts +35 -0
- package/dist/playwright/pw-tools-core.downloads.js +186 -0
- package/dist/playwright/pw-tools-core.interactions.d.ts +104 -0
- package/dist/playwright/pw-tools-core.interactions.js +404 -0
- package/dist/playwright/pw-tools-core.js +9 -0
- package/dist/playwright/pw-tools-core.responses.d.ts +14 -0
- package/dist/playwright/pw-tools-core.responses.js +91 -0
- package/dist/playwright/pw-tools-core.shared.d.ts +7 -0
- package/dist/playwright/pw-tools-core.shared.js +50 -0
- package/dist/playwright/pw-tools-core.snapshot.d.ts +65 -0
- package/dist/playwright/pw-tools-core.snapshot.js +144 -0
- package/dist/playwright/pw-tools-core.state.d.ts +47 -0
- package/dist/playwright/pw-tools-core.state.js +154 -0
- package/dist/playwright/pw-tools-core.storage.d.ts +48 -0
- package/dist/playwright/pw-tools-core.storage.js +76 -0
- package/dist/playwright/pw-tools-core.trace.d.ts +13 -0
- package/dist/playwright/pw-tools-core.trace.js +26 -0
- package/dist/server/browser-context.d.ts +29 -0
- package/dist/server/browser-context.js +137 -0
- package/dist/server/browser-server.d.ts +7 -0
- package/dist/server/browser-server.js +49 -0
- package/dist/server/routes/act.d.ts +4 -0
- package/dist/server/routes/act.js +176 -0
- package/dist/server/routes/basic.d.ts +4 -0
- package/dist/server/routes/basic.js +36 -0
- package/dist/server/routes/index.d.ts +4 -0
- package/dist/server/routes/index.js +16 -0
- package/dist/server/routes/snapshot.d.ts +4 -0
- package/dist/server/routes/snapshot.js +143 -0
- package/dist/server/routes/storage.d.ts +4 -0
- package/dist/server/routes/storage.js +117 -0
- package/dist/server/routes/tabs.d.ts +4 -0
- package/dist/server/routes/tabs.js +51 -0
- package/dist/server/standalone.d.ts +9 -0
- package/dist/server/standalone.js +42 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +58 -0
- package/package.json +66 -0
package/dist/logger.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { appendFileSync, statSync, renameSync, unlinkSync, mkdirSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const LEVEL_PRIORITY = {
|
|
4
|
+
debug: 0,
|
|
5
|
+
info: 1,
|
|
6
|
+
warn: 2,
|
|
7
|
+
error: 3,
|
|
8
|
+
};
|
|
9
|
+
let globalLevel = "info";
|
|
10
|
+
export function setLogLevel(level) {
|
|
11
|
+
globalLevel = level;
|
|
12
|
+
}
|
|
13
|
+
export function getLogLevel() {
|
|
14
|
+
return globalLevel;
|
|
15
|
+
}
|
|
16
|
+
function fmt(level, tag, msg) {
|
|
17
|
+
const ts = new Date().toISOString();
|
|
18
|
+
return `${ts} [${level.toUpperCase().padEnd(5)}] [${tag}] ${msg}`;
|
|
19
|
+
}
|
|
20
|
+
// --- Log file writer with rotation ---
|
|
21
|
+
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
22
|
+
const MAX_FILES = 9; // gmab.1.log through gmab.9.log
|
|
23
|
+
const SIZE_CHECK_INTERVAL = 100; // check size every N writes
|
|
24
|
+
class LogFileWriter {
|
|
25
|
+
dir;
|
|
26
|
+
filePath;
|
|
27
|
+
writeCount = 0;
|
|
28
|
+
constructor(dir) {
|
|
29
|
+
this.dir = dir;
|
|
30
|
+
this.filePath = join(dir, "gmab.log");
|
|
31
|
+
mkdirSync(dir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
append(line) {
|
|
34
|
+
try {
|
|
35
|
+
appendFileSync(this.filePath, line + "\n");
|
|
36
|
+
this.writeCount++;
|
|
37
|
+
if (this.writeCount >= SIZE_CHECK_INTERVAL) {
|
|
38
|
+
this.writeCount = 0;
|
|
39
|
+
this.checkRotation();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Silently ignore file write errors to avoid infinite loops
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
checkRotation() {
|
|
47
|
+
try {
|
|
48
|
+
const stats = statSync(this.filePath);
|
|
49
|
+
if (stats.size >= MAX_FILE_SIZE) {
|
|
50
|
+
this.rotate();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// File may not exist yet
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
rotate() {
|
|
58
|
+
// Delete oldest: gmab.9.log
|
|
59
|
+
const oldest = join(this.dir, `gmab.${MAX_FILES}.log`);
|
|
60
|
+
try {
|
|
61
|
+
if (existsSync(oldest))
|
|
62
|
+
unlinkSync(oldest);
|
|
63
|
+
}
|
|
64
|
+
catch { /* noop */ }
|
|
65
|
+
// Shift: gmab.8.log -> gmab.9.log, ..., gmab.1.log -> gmab.2.log
|
|
66
|
+
for (let i = MAX_FILES - 1; i >= 1; i--) {
|
|
67
|
+
const from = join(this.dir, `gmab.${i}.log`);
|
|
68
|
+
const to = join(this.dir, `gmab.${i + 1}.log`);
|
|
69
|
+
try {
|
|
70
|
+
renameSync(from, to);
|
|
71
|
+
}
|
|
72
|
+
catch { /* noop */ }
|
|
73
|
+
}
|
|
74
|
+
// Current -> gmab.1.log
|
|
75
|
+
try {
|
|
76
|
+
renameSync(this.filePath, join(this.dir, "gmab.1.log"));
|
|
77
|
+
}
|
|
78
|
+
catch { /* noop */ }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let writer = null;
|
|
82
|
+
let logsDir = "";
|
|
83
|
+
/** Initialize file logging. Call once at startup. */
|
|
84
|
+
export function initLogFile(dir) {
|
|
85
|
+
logsDir = dir;
|
|
86
|
+
writer = new LogFileWriter(dir);
|
|
87
|
+
}
|
|
88
|
+
/** Returns the logs directory path (empty string if not initialized). */
|
|
89
|
+
export function getLogsDir() {
|
|
90
|
+
return logsDir;
|
|
91
|
+
}
|
|
92
|
+
export function createLogger(tag) {
|
|
93
|
+
const shouldLog = (level) => LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[globalLevel];
|
|
94
|
+
return {
|
|
95
|
+
debug: (msg, ...args) => {
|
|
96
|
+
if (shouldLog("debug")) {
|
|
97
|
+
const line = fmt("debug", tag, msg);
|
|
98
|
+
console.debug(line, ...args);
|
|
99
|
+
writer?.append(line);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
info: (msg, ...args) => {
|
|
103
|
+
if (shouldLog("info")) {
|
|
104
|
+
const line = fmt("info", tag, msg);
|
|
105
|
+
console.log(line, ...args);
|
|
106
|
+
writer?.append(line);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
warn: (msg, ...args) => {
|
|
110
|
+
if (shouldLog("warn")) {
|
|
111
|
+
const line = fmt("warn", tag, msg);
|
|
112
|
+
console.warn(line, ...args);
|
|
113
|
+
writer?.append(line);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
error: (msg, ...args) => {
|
|
117
|
+
if (shouldLog("error")) {
|
|
118
|
+
const line = fmt("error", tag, msg);
|
|
119
|
+
console.error(line, ...args);
|
|
120
|
+
writer?.append(line);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type RoleRef = {
|
|
2
|
+
role: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
/** Index used only when role+name duplicates exist. */
|
|
5
|
+
nth?: number;
|
|
6
|
+
};
|
|
7
|
+
export type RoleRefMap = Record<string, RoleRef>;
|
|
8
|
+
export type RoleSnapshotStats = {
|
|
9
|
+
lines: number;
|
|
10
|
+
chars: number;
|
|
11
|
+
refs: number;
|
|
12
|
+
interactive: number;
|
|
13
|
+
};
|
|
14
|
+
export type RoleSnapshotOptions = {
|
|
15
|
+
/** Only include interactive elements (buttons, links, inputs, etc.). */
|
|
16
|
+
interactive?: boolean;
|
|
17
|
+
/** Maximum depth to include (0 = root only). */
|
|
18
|
+
maxDepth?: number;
|
|
19
|
+
/** Remove unnamed structural elements and empty branches. */
|
|
20
|
+
compact?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare function getRoleSnapshotStats(snapshot: string, refs: RoleRefMap): RoleSnapshotStats;
|
|
23
|
+
export declare function parseRoleRef(raw: string): string | null;
|
|
24
|
+
export declare function buildRoleSnapshotFromAriaSnapshot(ariaSnapshot: string, options?: RoleSnapshotOptions): {
|
|
25
|
+
snapshot: string;
|
|
26
|
+
refs: RoleRefMap;
|
|
27
|
+
};
|
|
28
|
+
export declare function buildRoleSnapshotFromAiSnapshot(aiSnapshot: string, options?: RoleSnapshotOptions): {
|
|
29
|
+
snapshot: string;
|
|
30
|
+
refs: RoleRefMap;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=pw-role-snapshot.d.ts.map
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
const INTERACTIVE_ROLES = new Set([
|
|
2
|
+
"button",
|
|
3
|
+
"link",
|
|
4
|
+
"textbox",
|
|
5
|
+
"checkbox",
|
|
6
|
+
"radio",
|
|
7
|
+
"combobox",
|
|
8
|
+
"listbox",
|
|
9
|
+
"menuitem",
|
|
10
|
+
"menuitemcheckbox",
|
|
11
|
+
"menuitemradio",
|
|
12
|
+
"option",
|
|
13
|
+
"searchbox",
|
|
14
|
+
"slider",
|
|
15
|
+
"spinbutton",
|
|
16
|
+
"switch",
|
|
17
|
+
"tab",
|
|
18
|
+
"treeitem",
|
|
19
|
+
]);
|
|
20
|
+
const CONTENT_ROLES = new Set([
|
|
21
|
+
"heading",
|
|
22
|
+
"cell",
|
|
23
|
+
"gridcell",
|
|
24
|
+
"columnheader",
|
|
25
|
+
"rowheader",
|
|
26
|
+
"listitem",
|
|
27
|
+
"article",
|
|
28
|
+
"region",
|
|
29
|
+
"main",
|
|
30
|
+
"navigation",
|
|
31
|
+
]);
|
|
32
|
+
const STRUCTURAL_ROLES = new Set([
|
|
33
|
+
"generic",
|
|
34
|
+
"group",
|
|
35
|
+
"list",
|
|
36
|
+
"table",
|
|
37
|
+
"row",
|
|
38
|
+
"rowgroup",
|
|
39
|
+
"grid",
|
|
40
|
+
"treegrid",
|
|
41
|
+
"menu",
|
|
42
|
+
"menubar",
|
|
43
|
+
"toolbar",
|
|
44
|
+
"tablist",
|
|
45
|
+
"tree",
|
|
46
|
+
"directory",
|
|
47
|
+
"document",
|
|
48
|
+
"application",
|
|
49
|
+
"presentation",
|
|
50
|
+
"none",
|
|
51
|
+
]);
|
|
52
|
+
export function getRoleSnapshotStats(snapshot, refs) {
|
|
53
|
+
const interactive = Object.values(refs).filter((r) => INTERACTIVE_ROLES.has(r.role)).length;
|
|
54
|
+
return {
|
|
55
|
+
lines: snapshot.split("\n").length,
|
|
56
|
+
chars: snapshot.length,
|
|
57
|
+
refs: Object.keys(refs).length,
|
|
58
|
+
interactive,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function getIndentLevel(line) {
|
|
62
|
+
const match = line.match(/^(\s*)/);
|
|
63
|
+
return match ? Math.floor(match[1].length / 2) : 0;
|
|
64
|
+
}
|
|
65
|
+
function createRoleNameTracker() {
|
|
66
|
+
const counts = new Map();
|
|
67
|
+
const refsByKey = new Map();
|
|
68
|
+
return {
|
|
69
|
+
counts,
|
|
70
|
+
refsByKey,
|
|
71
|
+
getKey(role, name) {
|
|
72
|
+
return `${role}:${name ?? ""}`;
|
|
73
|
+
},
|
|
74
|
+
getNextIndex(role, name) {
|
|
75
|
+
const key = this.getKey(role, name);
|
|
76
|
+
const current = counts.get(key) ?? 0;
|
|
77
|
+
counts.set(key, current + 1);
|
|
78
|
+
return current;
|
|
79
|
+
},
|
|
80
|
+
trackRef(role, name, ref) {
|
|
81
|
+
const key = this.getKey(role, name);
|
|
82
|
+
const list = refsByKey.get(key) ?? [];
|
|
83
|
+
list.push(ref);
|
|
84
|
+
refsByKey.set(key, list);
|
|
85
|
+
},
|
|
86
|
+
getDuplicateKeys() {
|
|
87
|
+
const out = new Set();
|
|
88
|
+
for (const [key, refs] of refsByKey) {
|
|
89
|
+
if (refs.length > 1) {
|
|
90
|
+
out.add(key);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function removeNthFromNonDuplicates(refs, tracker) {
|
|
98
|
+
const duplicates = tracker.getDuplicateKeys();
|
|
99
|
+
for (const [ref, data] of Object.entries(refs)) {
|
|
100
|
+
const key = tracker.getKey(data.role, data.name);
|
|
101
|
+
if (!duplicates.has(key)) {
|
|
102
|
+
delete refs[ref]?.nth;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function compactTree(tree) {
|
|
107
|
+
const lines = tree.split("\n");
|
|
108
|
+
const result = [];
|
|
109
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
110
|
+
const line = lines[i];
|
|
111
|
+
if (line.includes("[ref=")) {
|
|
112
|
+
result.push(line);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (line.includes(":") && !line.trimEnd().endsWith(":")) {
|
|
116
|
+
result.push(line);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const currentIndent = getIndentLevel(line);
|
|
120
|
+
let hasRelevantChildren = false;
|
|
121
|
+
for (let j = i + 1; j < lines.length; j += 1) {
|
|
122
|
+
const childIndent = getIndentLevel(lines[j]);
|
|
123
|
+
if (childIndent <= currentIndent) {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
if (lines[j]?.includes("[ref=")) {
|
|
127
|
+
hasRelevantChildren = true;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (hasRelevantChildren) {
|
|
132
|
+
result.push(line);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result.join("\n");
|
|
136
|
+
}
|
|
137
|
+
function processLine(line, refs, options, tracker, nextRef) {
|
|
138
|
+
const depth = getIndentLevel(line);
|
|
139
|
+
if (options.maxDepth !== undefined && depth > options.maxDepth) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/);
|
|
143
|
+
if (!match) {
|
|
144
|
+
return options.interactive ? null : line;
|
|
145
|
+
}
|
|
146
|
+
const [, prefix, roleRaw, name, suffix] = match;
|
|
147
|
+
if (roleRaw.startsWith("/")) {
|
|
148
|
+
return options.interactive ? null : line;
|
|
149
|
+
}
|
|
150
|
+
const role = roleRaw.toLowerCase();
|
|
151
|
+
const isInteractive = INTERACTIVE_ROLES.has(role);
|
|
152
|
+
const isContent = CONTENT_ROLES.has(role);
|
|
153
|
+
const isStructural = STRUCTURAL_ROLES.has(role);
|
|
154
|
+
if (options.interactive && !isInteractive) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
if (options.compact && isStructural && !name) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
const shouldHaveRef = isInteractive || (isContent && name);
|
|
161
|
+
if (!shouldHaveRef) {
|
|
162
|
+
return line;
|
|
163
|
+
}
|
|
164
|
+
const ref = nextRef();
|
|
165
|
+
const nth = tracker.getNextIndex(role, name);
|
|
166
|
+
tracker.trackRef(role, name, ref);
|
|
167
|
+
refs[ref] = {
|
|
168
|
+
role,
|
|
169
|
+
name,
|
|
170
|
+
nth,
|
|
171
|
+
};
|
|
172
|
+
let enhanced = `${prefix}${roleRaw}`;
|
|
173
|
+
if (name) {
|
|
174
|
+
enhanced += ` "${name}"`;
|
|
175
|
+
}
|
|
176
|
+
enhanced += ` [ref=${ref}]`;
|
|
177
|
+
if (nth > 0) {
|
|
178
|
+
enhanced += ` [nth=${nth}]`;
|
|
179
|
+
}
|
|
180
|
+
if (suffix) {
|
|
181
|
+
enhanced += suffix;
|
|
182
|
+
}
|
|
183
|
+
return enhanced;
|
|
184
|
+
}
|
|
185
|
+
export function parseRoleRef(raw) {
|
|
186
|
+
const trimmed = raw.trim();
|
|
187
|
+
if (!trimmed) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
const normalized = trimmed.startsWith("@")
|
|
191
|
+
? trimmed.slice(1)
|
|
192
|
+
: trimmed.startsWith("ref=")
|
|
193
|
+
? trimmed.slice(4)
|
|
194
|
+
: trimmed;
|
|
195
|
+
return /^e\d+$/.test(normalized) ? normalized : null;
|
|
196
|
+
}
|
|
197
|
+
export function buildRoleSnapshotFromAriaSnapshot(ariaSnapshot, options = {}) {
|
|
198
|
+
const lines = ariaSnapshot.split("\n");
|
|
199
|
+
const refs = {};
|
|
200
|
+
const tracker = createRoleNameTracker();
|
|
201
|
+
let counter = 0;
|
|
202
|
+
const nextRef = () => {
|
|
203
|
+
counter += 1;
|
|
204
|
+
return `e${counter}`;
|
|
205
|
+
};
|
|
206
|
+
if (options.interactive) {
|
|
207
|
+
const result = [];
|
|
208
|
+
for (const line of lines) {
|
|
209
|
+
const depth = getIndentLevel(line);
|
|
210
|
+
if (options.maxDepth !== undefined && depth > options.maxDepth) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/);
|
|
214
|
+
if (!match) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const [, , roleRaw, name, suffix] = match;
|
|
218
|
+
if (roleRaw.startsWith("/")) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const role = roleRaw.toLowerCase();
|
|
222
|
+
if (!INTERACTIVE_ROLES.has(role)) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const ref = nextRef();
|
|
226
|
+
const nth = tracker.getNextIndex(role, name);
|
|
227
|
+
tracker.trackRef(role, name, ref);
|
|
228
|
+
refs[ref] = {
|
|
229
|
+
role,
|
|
230
|
+
name,
|
|
231
|
+
nth,
|
|
232
|
+
};
|
|
233
|
+
let enhanced = `- ${roleRaw}`;
|
|
234
|
+
if (name) {
|
|
235
|
+
enhanced += ` "${name}"`;
|
|
236
|
+
}
|
|
237
|
+
enhanced += ` [ref=${ref}]`;
|
|
238
|
+
if (nth > 0) {
|
|
239
|
+
enhanced += ` [nth=${nth}]`;
|
|
240
|
+
}
|
|
241
|
+
if (suffix.includes("[")) {
|
|
242
|
+
enhanced += suffix;
|
|
243
|
+
}
|
|
244
|
+
result.push(enhanced);
|
|
245
|
+
}
|
|
246
|
+
removeNthFromNonDuplicates(refs, tracker);
|
|
247
|
+
return {
|
|
248
|
+
snapshot: result.join("\n") || "(no interactive elements)",
|
|
249
|
+
refs,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const result = [];
|
|
253
|
+
for (const line of lines) {
|
|
254
|
+
const processed = processLine(line, refs, options, tracker, nextRef);
|
|
255
|
+
if (processed !== null) {
|
|
256
|
+
result.push(processed);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
removeNthFromNonDuplicates(refs, tracker);
|
|
260
|
+
const tree = result.join("\n") || "(empty)";
|
|
261
|
+
return {
|
|
262
|
+
snapshot: options.compact ? compactTree(tree) : tree,
|
|
263
|
+
refs,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function parseAiSnapshotRef(suffix) {
|
|
267
|
+
const match = suffix.match(/\[ref=(e\d+)\]/i);
|
|
268
|
+
return match ? match[1] : null;
|
|
269
|
+
}
|
|
270
|
+
export function buildRoleSnapshotFromAiSnapshot(aiSnapshot, options = {}) {
|
|
271
|
+
const lines = String(aiSnapshot ?? "").split("\n");
|
|
272
|
+
const refs = {};
|
|
273
|
+
if (options.interactive) {
|
|
274
|
+
const out = [];
|
|
275
|
+
for (const line of lines) {
|
|
276
|
+
const depth = getIndentLevel(line);
|
|
277
|
+
if (options.maxDepth !== undefined && depth > options.maxDepth) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/);
|
|
281
|
+
if (!match) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const [, , roleRaw, name, suffix] = match;
|
|
285
|
+
if (roleRaw.startsWith("/")) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const role = roleRaw.toLowerCase();
|
|
289
|
+
if (!INTERACTIVE_ROLES.has(role)) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const ref = parseAiSnapshotRef(suffix);
|
|
293
|
+
if (!ref) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
refs[ref] = { role, ...(name ? { name } : {}) };
|
|
297
|
+
out.push(`- ${roleRaw}${name ? ` "${name}"` : ""}${suffix}`);
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
snapshot: out.join("\n") || "(no interactive elements)",
|
|
301
|
+
refs,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
const out = [];
|
|
305
|
+
for (const line of lines) {
|
|
306
|
+
const depth = getIndentLevel(line);
|
|
307
|
+
if (options.maxDepth !== undefined && depth > options.maxDepth) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/);
|
|
311
|
+
if (!match) {
|
|
312
|
+
out.push(line);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const [, , roleRaw, name, suffix] = match;
|
|
316
|
+
if (roleRaw.startsWith("/")) {
|
|
317
|
+
out.push(line);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const role = roleRaw.toLowerCase();
|
|
321
|
+
const isStructural = STRUCTURAL_ROLES.has(role);
|
|
322
|
+
if (options.compact && isStructural && !name) {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const ref = parseAiSnapshotRef(suffix);
|
|
326
|
+
if (ref) {
|
|
327
|
+
refs[ref] = { role, ...(name ? { name } : {}) };
|
|
328
|
+
}
|
|
329
|
+
out.push(line);
|
|
330
|
+
}
|
|
331
|
+
const tree = out.join("\n") || "(empty)";
|
|
332
|
+
return {
|
|
333
|
+
snapshot: options.compact ? compactTree(tree) : tree,
|
|
334
|
+
refs,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=pw-role-snapshot.js.map
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { BrowserContext, Page, Request } from "playwright-core";
|
|
2
|
+
export type BrowserConsoleMessage = {
|
|
3
|
+
type: string;
|
|
4
|
+
text: string;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
location?: {
|
|
7
|
+
url?: string;
|
|
8
|
+
lineNumber?: number;
|
|
9
|
+
columnNumber?: number;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type BrowserPageError = {
|
|
13
|
+
message: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
stack?: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
};
|
|
18
|
+
export type BrowserNetworkRequest = {
|
|
19
|
+
id: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
method: string;
|
|
22
|
+
url: string;
|
|
23
|
+
resourceType?: string;
|
|
24
|
+
status?: number;
|
|
25
|
+
ok?: boolean;
|
|
26
|
+
failureText?: string;
|
|
27
|
+
};
|
|
28
|
+
type SnapshotForAIResult = {
|
|
29
|
+
full: string;
|
|
30
|
+
incremental?: string;
|
|
31
|
+
};
|
|
32
|
+
type SnapshotForAIOptions = {
|
|
33
|
+
timeout?: number;
|
|
34
|
+
track?: string;
|
|
35
|
+
};
|
|
36
|
+
export type WithSnapshotForAI = {
|
|
37
|
+
_snapshotForAI?: (options?: SnapshotForAIOptions) => Promise<SnapshotForAIResult>;
|
|
38
|
+
};
|
|
39
|
+
type PageState = {
|
|
40
|
+
console: BrowserConsoleMessage[];
|
|
41
|
+
errors: BrowserPageError[];
|
|
42
|
+
requests: BrowserNetworkRequest[];
|
|
43
|
+
requestIds: WeakMap<Request, string>;
|
|
44
|
+
nextRequestId: number;
|
|
45
|
+
armIdUpload: number;
|
|
46
|
+
armIdDialog: number;
|
|
47
|
+
armIdDownload: number;
|
|
48
|
+
roleRefs?: Record<string, {
|
|
49
|
+
role: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
nth?: number;
|
|
52
|
+
}>;
|
|
53
|
+
roleRefsMode?: "role" | "aria";
|
|
54
|
+
roleRefsFrameSelector?: string;
|
|
55
|
+
};
|
|
56
|
+
type RoleRefs = NonNullable<PageState["roleRefs"]>;
|
|
57
|
+
type ContextState = {
|
|
58
|
+
traceActive: boolean;
|
|
59
|
+
};
|
|
60
|
+
export declare function rememberRoleRefsForTarget(opts: {
|
|
61
|
+
cdpUrl: string;
|
|
62
|
+
targetId: string;
|
|
63
|
+
refs: RoleRefs;
|
|
64
|
+
frameSelector?: string;
|
|
65
|
+
mode?: NonNullable<PageState["roleRefsMode"]>;
|
|
66
|
+
}): void;
|
|
67
|
+
export declare function storeRoleRefsForTarget(opts: {
|
|
68
|
+
page: Page;
|
|
69
|
+
cdpUrl: string;
|
|
70
|
+
targetId?: string;
|
|
71
|
+
refs: RoleRefs;
|
|
72
|
+
frameSelector?: string;
|
|
73
|
+
mode: NonNullable<PageState["roleRefsMode"]>;
|
|
74
|
+
}): void;
|
|
75
|
+
export declare function restoreRoleRefsForTarget(opts: {
|
|
76
|
+
cdpUrl: string;
|
|
77
|
+
targetId?: string;
|
|
78
|
+
page: Page;
|
|
79
|
+
}): void;
|
|
80
|
+
export declare function ensurePageState(page: Page): PageState;
|
|
81
|
+
export declare function ensureContextState(context: BrowserContext): ContextState;
|
|
82
|
+
export declare function getPageForTargetId(opts: {
|
|
83
|
+
cdpUrl: string;
|
|
84
|
+
targetId?: string;
|
|
85
|
+
}): Promise<Page>;
|
|
86
|
+
export declare function refLocator(page: Page, ref: string): import("playwright-core").Locator;
|
|
87
|
+
export declare function closePlaywrightBrowserConnection(): Promise<void>;
|
|
88
|
+
export declare function forceDisconnectPlaywrightForTarget(opts: {
|
|
89
|
+
cdpUrl: string;
|
|
90
|
+
targetId?: string;
|
|
91
|
+
reason?: string;
|
|
92
|
+
}): Promise<void>;
|
|
93
|
+
export declare function listPagesViaPlaywright(opts: {
|
|
94
|
+
cdpUrl: string;
|
|
95
|
+
}): Promise<Array<{
|
|
96
|
+
targetId: string;
|
|
97
|
+
title: string;
|
|
98
|
+
url: string;
|
|
99
|
+
type: string;
|
|
100
|
+
}>>;
|
|
101
|
+
export declare function createPageViaPlaywright(opts: {
|
|
102
|
+
cdpUrl: string;
|
|
103
|
+
url: string;
|
|
104
|
+
}): Promise<{
|
|
105
|
+
targetId: string;
|
|
106
|
+
title: string;
|
|
107
|
+
url: string;
|
|
108
|
+
type: string;
|
|
109
|
+
}>;
|
|
110
|
+
export declare function closePageByTargetIdViaPlaywright(opts: {
|
|
111
|
+
cdpUrl: string;
|
|
112
|
+
targetId: string;
|
|
113
|
+
}): Promise<void>;
|
|
114
|
+
export declare function focusPageByTargetIdViaPlaywright(opts: {
|
|
115
|
+
cdpUrl: string;
|
|
116
|
+
targetId: string;
|
|
117
|
+
}): Promise<void>;
|
|
118
|
+
export {};
|
|
119
|
+
//# sourceMappingURL=pw-session.d.ts.map
|