@aiscene/aiserver 1.7.0 → 1.7.2
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/core/adb.d.ts +10 -0
- package/dist/core/adb.d.ts.map +1 -0
- package/dist/core/adb.js +25 -0
- package/dist/core/adb.js.map +1 -0
- package/dist/core/android-identifiers.d.ts +3 -0
- package/dist/core/android-identifiers.d.ts.map +1 -0
- package/dist/core/android-identifiers.js +21 -0
- package/dist/core/android-identifiers.js.map +1 -0
- package/dist/core/native-swipe.d.ts.map +1 -1
- package/dist/core/native-swipe.js +3 -6
- package/dist/core/native-swipe.js.map +1 -1
- package/dist/core/types.d.ts +13 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/debug/report-group-name.d.ts +14 -0
- package/dist/debug/report-group-name.d.ts.map +1 -0
- package/dist/debug/report-group-name.js +30 -0
- package/dist/debug/report-group-name.js.map +1 -0
- package/dist/debug/types.d.ts +55 -31
- package/dist/debug/types.d.ts.map +1 -1
- package/dist/debug/websocket-server.d.ts +1 -0
- package/dist/debug/websocket-server.d.ts.map +1 -1
- package/dist/debug/websocket-server.js +142 -9
- package/dist/debug/websocket-server.js.map +1 -1
- package/dist/device/detector.d.ts.map +1 -1
- package/dist/device/detector.js +2 -1
- package/dist/device/detector.js.map +1 -1
- package/dist/device/heartbeat.d.ts.map +1 -1
- package/dist/device/heartbeat.js +2 -4
- package/dist/device/heartbeat.js.map +1 -1
- package/dist/executor/action-executor.d.ts.map +1 -1
- package/dist/executor/action-executor.js +20 -22
- package/dist/executor/action-executor.js.map +1 -1
- package/dist/executor/android-executor.d.ts.map +1 -1
- package/dist/executor/android-executor.js +22 -19
- package/dist/executor/android-executor.js.map +1 -1
- package/dist/executor/cli-executor.d.ts.map +1 -1
- package/dist/executor/cli-executor.js +9 -0
- package/dist/executor/cli-executor.js.map +1 -1
- package/dist/login/android-login-context.d.ts +29 -0
- package/dist/login/android-login-context.d.ts.map +1 -0
- package/dist/login/android-login-context.js +165 -0
- package/dist/login/android-login-context.js.map +1 -0
- package/dist/recorder/android-login-replay.d.ts +11 -0
- package/dist/recorder/android-login-replay.d.ts.map +1 -0
- package/dist/recorder/android-login-replay.js +70 -0
- package/dist/recorder/android-login-replay.js.map +1 -0
- package/dist/recorder/android-login-script.d.ts +50 -0
- package/dist/recorder/android-login-script.d.ts.map +1 -0
- package/dist/recorder/android-login-script.js +2 -0
- package/dist/recorder/android-login-script.js.map +1 -0
- package/dist/recorder/android-recording-manager.d.ts +23 -0
- package/dist/recorder/android-recording-manager.d.ts.map +1 -0
- package/dist/recorder/android-recording-manager.js +180 -0
- package/dist/recorder/android-recording-manager.js.map +1 -0
- package/dist/recorder/android-ui-hierarchy.d.ts +45 -0
- package/dist/recorder/android-ui-hierarchy.d.ts.map +1 -0
- package/dist/recorder/android-ui-hierarchy.js +183 -0
- package/dist/recorder/android-ui-hierarchy.js.map +1 -0
- package/dist/recorder/web-login-replay.d.ts +9 -0
- package/dist/recorder/web-login-replay.d.ts.map +1 -0
- package/dist/recorder/web-login-replay.js +39 -0
- package/dist/recorder/web-login-replay.js.map +1 -0
- package/dist/recorder/web-login-script.d.ts +36 -0
- package/dist/recorder/web-login-script.d.ts.map +1 -0
- package/dist/recorder/web-login-script.js +2 -0
- package/dist/recorder/web-login-script.js.map +1 -0
- package/dist/recorder/web-recording-manager.d.ts +41 -0
- package/dist/recorder/web-recording-manager.d.ts.map +1 -0
- package/dist/recorder/web-recording-manager.js +226 -0
- package/dist/recorder/web-recording-manager.js.map +1 -0
- package/dist/scrcpy/server.d.ts.map +1 -1
- package/dist/scrcpy/server.js +213 -11
- package/dist/scrcpy/server.js.map +1 -1
- package/dist/task/execution-params.d.ts +5 -0
- package/dist/task/execution-params.d.ts.map +1 -0
- package/dist/task/execution-params.js +41 -0
- package/dist/task/execution-params.js.map +1 -0
- package/dist/task/poller.d.ts.map +1 -1
- package/dist/task/poller.js +8 -1
- package/dist/task/poller.js.map +1 -1
- package/dist/task/scheduler.d.ts.map +1 -1
- package/dist/task/scheduler.js +67 -8
- package/dist/task/scheduler.js.map +1 -1
- package/dist/task/types.d.ts.map +1 -1
- package/dist/task/types.js +35 -1
- package/dist/task/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
function decodeXml(value) {
|
|
6
|
+
return value
|
|
7
|
+
.replace(/"/g, '"')
|
|
8
|
+
.replace(/'/g, "'")
|
|
9
|
+
.replace(/</g, '<')
|
|
10
|
+
.replace(/>/g, '>')
|
|
11
|
+
.replace(/&/g, '&');
|
|
12
|
+
}
|
|
13
|
+
function parseAttributes(source) {
|
|
14
|
+
const result = {};
|
|
15
|
+
const pattern = /([\w-]+)="([^"]*)"/g;
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = pattern.exec(source))) {
|
|
18
|
+
result[match[1]] = decodeXml(match[2]);
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
function parseBounds(value) {
|
|
23
|
+
if (!value)
|
|
24
|
+
return null;
|
|
25
|
+
const match = value.match(/^\[(\d+),(\d+)]\[(\d+),(\d+)]$/);
|
|
26
|
+
if (!match)
|
|
27
|
+
return null;
|
|
28
|
+
return [Number(match[1]), Number(match[2]), Number(match[3]), Number(match[4])];
|
|
29
|
+
}
|
|
30
|
+
export function parseAndroidUiNodes(xml) {
|
|
31
|
+
const nodes = [];
|
|
32
|
+
const pattern = /<node\b([^>]*)\/?>/g;
|
|
33
|
+
let match;
|
|
34
|
+
while ((match = pattern.exec(xml))) {
|
|
35
|
+
const attrs = parseAttributes(match[1]);
|
|
36
|
+
const bounds = parseBounds(attrs.bounds);
|
|
37
|
+
if (!bounds)
|
|
38
|
+
continue;
|
|
39
|
+
const selector = {};
|
|
40
|
+
if (attrs['resource-id'])
|
|
41
|
+
selector.resourceId = attrs['resource-id'];
|
|
42
|
+
if (attrs['content-desc'])
|
|
43
|
+
selector.contentDescription = attrs['content-desc'];
|
|
44
|
+
if (attrs.text)
|
|
45
|
+
selector.text = attrs.text;
|
|
46
|
+
if (attrs.class)
|
|
47
|
+
selector.className = attrs.class;
|
|
48
|
+
nodes.push({
|
|
49
|
+
id: `node-${nodes.length}`,
|
|
50
|
+
selector,
|
|
51
|
+
focused: attrs.focused === 'true',
|
|
52
|
+
clickable: attrs.clickable === 'true',
|
|
53
|
+
checkable: attrs.checkable === 'true',
|
|
54
|
+
editable: attrs.class === 'android.widget.EditText' ||
|
|
55
|
+
attrs.focusable === 'true' ||
|
|
56
|
+
attrs['long-clickable'] === 'true',
|
|
57
|
+
password: attrs.password === 'true',
|
|
58
|
+
enabled: attrs.enabled !== 'false',
|
|
59
|
+
bounds,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return nodes;
|
|
63
|
+
}
|
|
64
|
+
async function runAdbBuffer(deviceId, args, timeout = 10000) {
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const child = spawn('adb', ['-s', deviceId, ...args], {
|
|
67
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
68
|
+
});
|
|
69
|
+
const stdout = [];
|
|
70
|
+
const stderr = [];
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
child.kill('SIGKILL');
|
|
73
|
+
reject(new Error(`ADB command timed out after ${timeout}ms`));
|
|
74
|
+
}, timeout);
|
|
75
|
+
child.stdout.on('data', (chunk) => stdout.push(chunk));
|
|
76
|
+
child.stderr.on('data', (chunk) => stderr.push(chunk));
|
|
77
|
+
child.once('error', (error) => {
|
|
78
|
+
clearTimeout(timer);
|
|
79
|
+
reject(error);
|
|
80
|
+
});
|
|
81
|
+
child.once('close', (code) => {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
if (code === 0) {
|
|
84
|
+
resolve(Buffer.concat(stdout));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
reject(new Error(Buffer.concat(stderr).toString('utf8') || `ADB exited with ${code}`));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async function runAdb(deviceId, args, timeout = 10000) {
|
|
93
|
+
const { stdout } = await execFileAsync('adb', ['-s', deviceId, ...args], {
|
|
94
|
+
timeout,
|
|
95
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
96
|
+
});
|
|
97
|
+
return stdout;
|
|
98
|
+
}
|
|
99
|
+
export async function resetAndLaunchAndroidApp(deviceId, packageName) {
|
|
100
|
+
await runAdb(deviceId, ['shell', 'pm', 'clear', packageName], 20000);
|
|
101
|
+
await runAdb(deviceId, ['shell', 'monkey', '-p', packageName, '-c', 'android.intent.category.LAUNCHER', '1'], 20000);
|
|
102
|
+
}
|
|
103
|
+
export async function captureAndroidUiHierarchy(deviceId) {
|
|
104
|
+
const remotePath = `/sdcard/aiserver-window-${Date.now()}.xml`;
|
|
105
|
+
try {
|
|
106
|
+
await runAdb(deviceId, ['shell', 'uiautomator', 'dump', remotePath], 15000);
|
|
107
|
+
return await runAdb(deviceId, ['shell', 'cat', remotePath], 10000);
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
runAdb(deviceId, ['shell', 'rm', '-f', remotePath], 5000).catch(() => { });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export async function getAndroidScreenSize(deviceId) {
|
|
114
|
+
const output = await runAdb(deviceId, ['shell', 'wm', 'size'], 5000);
|
|
115
|
+
const matches = [...output.matchAll(/(\d+)x(\d+)/g)];
|
|
116
|
+
const match = matches[matches.length - 1];
|
|
117
|
+
return match
|
|
118
|
+
? { width: Number(match[1]), height: Number(match[2]) }
|
|
119
|
+
: { width: 1080, height: 1920 };
|
|
120
|
+
}
|
|
121
|
+
export async function captureAndroidScreen(deviceId) {
|
|
122
|
+
return runAdbBuffer(deviceId, ['exec-out', 'screencap', '-p'], 15000);
|
|
123
|
+
}
|
|
124
|
+
export async function captureAndroidScreenshotState(deviceId) {
|
|
125
|
+
const screenshot = await captureAndroidScreen(deviceId);
|
|
126
|
+
return {
|
|
127
|
+
screenshotBase64: screenshot.toString('base64'),
|
|
128
|
+
width: screenshot.length >= 24 ? screenshot.readUInt32BE(16) : 0,
|
|
129
|
+
height: screenshot.length >= 24 ? screenshot.readUInt32BE(20) : 0,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export async function captureAndroidElementState(deviceId) {
|
|
133
|
+
const xml = await captureAndroidUiHierarchy(deviceId);
|
|
134
|
+
return {
|
|
135
|
+
xml,
|
|
136
|
+
nodes: parseAndroidUiNodes(xml),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export async function captureAndroidScreenState(deviceId) {
|
|
140
|
+
const [screenshot, elements] = await Promise.all([
|
|
141
|
+
captureAndroidScreenshotState(deviceId),
|
|
142
|
+
captureAndroidElementState(deviceId),
|
|
143
|
+
]);
|
|
144
|
+
return {
|
|
145
|
+
...screenshot,
|
|
146
|
+
...elements,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
export function findSelectorAtPoint(xml, x, y) {
|
|
150
|
+
const candidates = parseAndroidUiNodes(xml)
|
|
151
|
+
.filter(({ bounds }) => x >= bounds[0] && x <= bounds[2] && y >= bounds[1] && y <= bounds[3])
|
|
152
|
+
.sort((a, b) => {
|
|
153
|
+
const areaA = (a.bounds[2] - a.bounds[0]) * (a.bounds[3] - a.bounds[1]);
|
|
154
|
+
const areaB = (b.bounds[2] - b.bounds[0]) * (b.bounds[3] - b.bounds[1]);
|
|
155
|
+
return areaA - areaB;
|
|
156
|
+
});
|
|
157
|
+
return candidates.find((node) => Object.keys(node.selector).length > 1)?.selector;
|
|
158
|
+
}
|
|
159
|
+
export function findFocusedSelector(xml) {
|
|
160
|
+
return parseAndroidUiNodes(xml).find((node) => node.focused && Object.keys(node.selector).length > 1)?.selector;
|
|
161
|
+
}
|
|
162
|
+
export function findPointBySelector(xml, selector) {
|
|
163
|
+
const node = parseAndroidUiNodes(xml).find(({ selector: candidate }) => {
|
|
164
|
+
if (selector.resourceId && candidate.resourceId !== selector.resourceId)
|
|
165
|
+
return false;
|
|
166
|
+
if (selector.contentDescription &&
|
|
167
|
+
candidate.contentDescription !== selector.contentDescription)
|
|
168
|
+
return false;
|
|
169
|
+
if (selector.text && candidate.text !== selector.text)
|
|
170
|
+
return false;
|
|
171
|
+
if (selector.className && candidate.className !== selector.className)
|
|
172
|
+
return false;
|
|
173
|
+
return true;
|
|
174
|
+
});
|
|
175
|
+
if (!node)
|
|
176
|
+
return undefined;
|
|
177
|
+
return {
|
|
178
|
+
x: Math.round((node.bounds[0] + node.bounds[2]) / 2),
|
|
179
|
+
y: Math.round((node.bounds[1] + node.bounds[3]) / 2),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
export { runAdb };
|
|
183
|
+
//# sourceMappingURL=android-ui-hierarchy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"android-ui-hierarchy.js","sourceRoot":"","sources":["../../src/recorder/android-ui-hierarchy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { WebLoginScript, WebLoginStep } from './web-login-script.js';
|
|
3
|
+
export declare function replayWebLoginScript(options: {
|
|
4
|
+
page: Page;
|
|
5
|
+
script: WebLoginScript;
|
|
6
|
+
variables?: Record<string, string>;
|
|
7
|
+
onStep?: (index: number, step: WebLoginStep) => void;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=web-login-replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-login-replay.d.ts","sourceRoot":"","sources":["../../src/recorder/web-login-replay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAuC1E,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CACtD,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function resolveValue(value, variables) {
|
|
2
|
+
return value.replace(/\{\{(\w+)}}/g, (_, key) => variables[key] ?? '');
|
|
3
|
+
}
|
|
4
|
+
async function executeStep(page, step, variables) {
|
|
5
|
+
if (step.type === 'goto') {
|
|
6
|
+
await page.goto(step.url, { waitUntil: 'domcontentloaded' });
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (step.type === 'wait') {
|
|
10
|
+
await page.waitForTimeout(step.duration);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const locator = page.locator(step.selector).first();
|
|
14
|
+
await locator.waitFor({ state: 'visible', timeout: step.timeout || 10000 });
|
|
15
|
+
if (step.type === 'click') {
|
|
16
|
+
await locator.click();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (step.type === 'check') {
|
|
20
|
+
await locator.check();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const value = resolveValue(step.value, variables);
|
|
24
|
+
if (step.clearBeforeInput !== false) {
|
|
25
|
+
await locator.fill(value);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
await locator.pressSequentially(value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function replayWebLoginScript(options) {
|
|
32
|
+
for (let index = 0; index < options.script.steps.length; index += 1) {
|
|
33
|
+
const step = options.script.steps[index];
|
|
34
|
+
options.onStep?.(index, step);
|
|
35
|
+
await executeStep(options.page, step, options.variables || {});
|
|
36
|
+
await options.page.waitForTimeout(200);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=web-login-replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-login-replay.js","sourceRoot":"","sources":["../../src/recorder/web-login-replay.ts"],"names":[],"mappings":"AAGA,SAAS,YAAY,CAAC,KAAa,EAAE,SAAiC;IACpE,OAAO,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,GAAW,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACjF,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,IAAU,EACV,IAAkB,EAClB,SAAiC;IAEjC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;IACpD,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC;IAC5E,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,gBAAgB,KAAK,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAK1C;IACC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type WebLoginStep = {
|
|
2
|
+
id: string;
|
|
3
|
+
type: 'goto';
|
|
4
|
+
url: string;
|
|
5
|
+
} | {
|
|
6
|
+
id: string;
|
|
7
|
+
type: 'click';
|
|
8
|
+
selector: string;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
} | {
|
|
11
|
+
id: string;
|
|
12
|
+
type: 'input';
|
|
13
|
+
selector: string;
|
|
14
|
+
value: string;
|
|
15
|
+
secret?: boolean;
|
|
16
|
+
clearBeforeInput?: boolean;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
} | {
|
|
19
|
+
id: string;
|
|
20
|
+
type: 'check';
|
|
21
|
+
selector: string;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
} | {
|
|
24
|
+
id: string;
|
|
25
|
+
type: 'wait';
|
|
26
|
+
duration: number;
|
|
27
|
+
};
|
|
28
|
+
export interface WebLoginScript {
|
|
29
|
+
schemaVersion: 1;
|
|
30
|
+
platform: 'web';
|
|
31
|
+
name: string;
|
|
32
|
+
targetUrl: string;
|
|
33
|
+
steps: WebLoginStep[];
|
|
34
|
+
createdAt: string;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=web-login-script.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-login-script.d.ts","sourceRoot":"","sources":["../../src/recorder/web-login-script.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACjE;IACE,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,CAAC,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-login-script.js","sourceRoot":"","sources":["../../src/recorder/web-login-script.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { WebLoginScript } from './web-login-script.js';
|
|
2
|
+
export declare class WebRecordingManager {
|
|
3
|
+
private sessions;
|
|
4
|
+
start(clientId: string, options: {
|
|
5
|
+
name?: string;
|
|
6
|
+
targetUrl: string;
|
|
7
|
+
}): Promise<WebLoginScript>;
|
|
8
|
+
snapshot(clientId: string): Promise<{
|
|
9
|
+
screenshotBase64: string;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
nodes: Record<string, unknown>[];
|
|
13
|
+
}>;
|
|
14
|
+
select(clientId: string, x: number, y: number): Promise<{
|
|
15
|
+
step: {
|
|
16
|
+
id: string;
|
|
17
|
+
type: "click";
|
|
18
|
+
selector: string;
|
|
19
|
+
timeout?: number;
|
|
20
|
+
};
|
|
21
|
+
passwordField: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
input(clientId: string, text: string, recordingValue: string, secret: boolean): Promise<{
|
|
24
|
+
id: string;
|
|
25
|
+
type: "input";
|
|
26
|
+
selector: string;
|
|
27
|
+
value: string;
|
|
28
|
+
secret?: boolean;
|
|
29
|
+
clearBeforeInput?: boolean;
|
|
30
|
+
timeout?: number;
|
|
31
|
+
}>;
|
|
32
|
+
stop(clientId: string): Promise<WebLoginScript>;
|
|
33
|
+
replay(options: {
|
|
34
|
+
script: WebLoginScript;
|
|
35
|
+
variables?: Record<string, string>;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
cancel(clientId: string): Promise<void>;
|
|
38
|
+
private requireSession;
|
|
39
|
+
}
|
|
40
|
+
export declare const webRecordingManager: WebRecordingManager;
|
|
41
|
+
//# sourceMappingURL=web-recording-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-recording-manager.d.ts","sourceRoot":"","sources":["../../src/recorder/web-recording-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AA+G1E,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAA0C;IAEpD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAmBrE,QAAQ,CAAC,QAAQ,EAAE,MAAM;;;;;;IAgCzB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;;;;;;;;;IA8B7C,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,OAAO;;;;;;;;;IAmBX,IAAI,CAAC,QAAQ,EAAE,MAAM;IAOrB,MAAM,CAAC,OAAO,EAAE;QACpB,MAAM,EAAE,cAAc,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC;IAWK,MAAM,CAAC,QAAQ,EAAE,MAAM;IAM7B,OAAO,CAAC,cAAc;CAKvB;AAED,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { chromium } from 'playwright';
|
|
3
|
+
import { replayWebLoginScript } from './web-login-replay.js';
|
|
4
|
+
const selectorHelper = `
|
|
5
|
+
const cssEscape = globalThis.CSS && globalThis.CSS.escape
|
|
6
|
+
? globalThis.CSS.escape
|
|
7
|
+
: function(value) { return value; };
|
|
8
|
+
const escapeValue = function(value) {
|
|
9
|
+
return value.replace(/\\\\/g, '\\\\\\\\').replace(/"/g, '\\\\"');
|
|
10
|
+
};
|
|
11
|
+
const selectorFor = function(element) {
|
|
12
|
+
if (element.id) return '#' + cssEscape(element.id);
|
|
13
|
+
for (const attr of ['data-testid', 'data-test', 'name', 'aria-label', 'placeholder']) {
|
|
14
|
+
const value = element.getAttribute(attr);
|
|
15
|
+
if (value) {
|
|
16
|
+
return element.tagName.toLowerCase() + '[' + attr + '="' + escapeValue(value) + '"]';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const text = (element.innerText || element.textContent || '').trim().replace(/\\s+/g, ' ');
|
|
20
|
+
if (text && text.length <= 40 && isInteractive(element)) {
|
|
21
|
+
return element.tagName.toLowerCase() + ':has-text("' + escapeValue(text) + '")';
|
|
22
|
+
}
|
|
23
|
+
const parts = [];
|
|
24
|
+
let current = element;
|
|
25
|
+
while (current && current !== document.body && parts.length < 5) {
|
|
26
|
+
const siblings = Array.from(
|
|
27
|
+
current.parentElement ? current.parentElement.children : [],
|
|
28
|
+
).filter(function(item) { return item.tagName === current.tagName; });
|
|
29
|
+
parts.unshift(
|
|
30
|
+
current.tagName.toLowerCase() + ':nth-of-type(' + (siblings.indexOf(current) + 1) + ')',
|
|
31
|
+
);
|
|
32
|
+
current = current.parentElement;
|
|
33
|
+
}
|
|
34
|
+
return 'body > ' + parts.join(' > ');
|
|
35
|
+
};
|
|
36
|
+
const loginWords = /登录|登陆|账号|账户|密码|短信|验证码|手机|下一步|继续|同意|login|sign[ -]?in|password|sms|verify|mobile/i;
|
|
37
|
+
const interactiveTags = ['INPUT', 'TEXTAREA', 'BUTTON', 'A', 'SELECT', 'OPTION', 'LABEL'];
|
|
38
|
+
const isVisible = function(element) {
|
|
39
|
+
const rect = element.getBoundingClientRect();
|
|
40
|
+
const style = getComputedStyle(element);
|
|
41
|
+
return rect.width >= 4 && rect.height >= 4 &&
|
|
42
|
+
rect.bottom > 0 && rect.right > 0 &&
|
|
43
|
+
rect.top < innerHeight && rect.left < innerWidth &&
|
|
44
|
+
style.display !== 'none' && style.visibility !== 'hidden' &&
|
|
45
|
+
Number(style.opacity || 1) > 0;
|
|
46
|
+
};
|
|
47
|
+
const isEditable = function(element) {
|
|
48
|
+
return ['INPUT', 'TEXTAREA', 'SELECT'].includes(element.tagName) ||
|
|
49
|
+
element.isContentEditable;
|
|
50
|
+
};
|
|
51
|
+
const isStrongInteractive = function(element) {
|
|
52
|
+
if (!element || !isVisible(element)) return false;
|
|
53
|
+
const role = (element.getAttribute('role') || '').toLowerCase();
|
|
54
|
+
const style = getComputedStyle(element);
|
|
55
|
+
return interactiveTags.includes(element.tagName) ||
|
|
56
|
+
isEditable(element) ||
|
|
57
|
+
element.hasAttribute('onclick') ||
|
|
58
|
+
typeof element.onclick === 'function' ||
|
|
59
|
+
['button', 'link', 'tab', 'checkbox', 'radio', 'switch', 'option'].includes(role) ||
|
|
60
|
+
element.tabIndex >= 0 ||
|
|
61
|
+
style.cursor === 'pointer';
|
|
62
|
+
};
|
|
63
|
+
const isInteractive = function(element) {
|
|
64
|
+
if (isStrongInteractive(element)) return true;
|
|
65
|
+
if (!element || !isVisible(element)) return false;
|
|
66
|
+
const classAndId = (element.className || '') + ' ' + (element.id || '');
|
|
67
|
+
const text = (
|
|
68
|
+
element.innerText || element.textContent ||
|
|
69
|
+
element.getAttribute('aria-label') || element.getAttribute('placeholder') || ''
|
|
70
|
+
).trim().replace(/\\s+/g, ' ');
|
|
71
|
+
return loginWords.test(text) ||
|
|
72
|
+
/(login|signin|password|pwd|sms|verify|captcha|account|mobile|phone|tab|button|btn)/i.test(classAndId);
|
|
73
|
+
};
|
|
74
|
+
const interactiveAncestor = function(element) {
|
|
75
|
+
let current = element;
|
|
76
|
+
let fallback = null;
|
|
77
|
+
while (current && current !== document.body) {
|
|
78
|
+
if (isStrongInteractive(current)) return current;
|
|
79
|
+
if (!fallback && isInteractive(current)) fallback = current;
|
|
80
|
+
current = current.parentElement;
|
|
81
|
+
}
|
|
82
|
+
return fallback || element;
|
|
83
|
+
};
|
|
84
|
+
`;
|
|
85
|
+
function createScript(session) {
|
|
86
|
+
return {
|
|
87
|
+
schemaVersion: 1,
|
|
88
|
+
platform: 'web',
|
|
89
|
+
name: session.name,
|
|
90
|
+
targetUrl: session.targetUrl,
|
|
91
|
+
steps: session.steps,
|
|
92
|
+
createdAt: new Date().toISOString(),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export class WebRecordingManager {
|
|
96
|
+
sessions = new Map();
|
|
97
|
+
async start(clientId, options) {
|
|
98
|
+
await this.cancel(clientId);
|
|
99
|
+
const targetUrl = new URL(options.targetUrl).toString();
|
|
100
|
+
const browser = await chromium.launch({ headless: true });
|
|
101
|
+
const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });
|
|
102
|
+
const page = await context.newPage();
|
|
103
|
+
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
|
|
104
|
+
const session = {
|
|
105
|
+
browser,
|
|
106
|
+
context,
|
|
107
|
+
page,
|
|
108
|
+
name: options.name?.trim() || 'Web 登录',
|
|
109
|
+
targetUrl,
|
|
110
|
+
steps: [{ id: randomUUID(), type: 'goto', url: targetUrl }],
|
|
111
|
+
};
|
|
112
|
+
this.sessions.set(clientId, session);
|
|
113
|
+
return createScript(session);
|
|
114
|
+
}
|
|
115
|
+
async snapshot(clientId) {
|
|
116
|
+
const session = this.requireSession(clientId);
|
|
117
|
+
const screenshotBase64 = (await session.page.screenshot({ type: 'png' })).toString('base64');
|
|
118
|
+
const viewport = session.page.viewportSize() || { width: 1280, height: 800 };
|
|
119
|
+
const nodes = await session.page.evaluate(`(() => {
|
|
120
|
+
${selectorHelper}
|
|
121
|
+
const seen = new Set();
|
|
122
|
+
return Array.from(document.querySelectorAll('*')).map(function(source, index) {
|
|
123
|
+
const element = interactiveAncestor(source);
|
|
124
|
+
if (!isInteractive(element) || seen.has(element)) return null;
|
|
125
|
+
seen.add(element);
|
|
126
|
+
const rect = element.getBoundingClientRect();
|
|
127
|
+
return {
|
|
128
|
+
id: 'web-' + index,
|
|
129
|
+
bounds: [rect.left, rect.top, rect.right, rect.bottom],
|
|
130
|
+
selector: selectorFor(element),
|
|
131
|
+
editable: isEditable(element),
|
|
132
|
+
password: element.type === 'password',
|
|
133
|
+
text: (
|
|
134
|
+
element.innerText || element.textContent ||
|
|
135
|
+
element.placeholder || element.name || element.getAttribute('aria-label') || ''
|
|
136
|
+
).trim().replace(/\\s+/g, ' ').slice(0, 80),
|
|
137
|
+
};
|
|
138
|
+
}).filter(Boolean).sort(function(a, b) {
|
|
139
|
+
const areaA = (a.bounds[2] - a.bounds[0]) * (a.bounds[3] - a.bounds[1]);
|
|
140
|
+
const areaB = (b.bounds[2] - b.bounds[0]) * (b.bounds[3] - b.bounds[1]);
|
|
141
|
+
return areaA - areaB;
|
|
142
|
+
});
|
|
143
|
+
})()`);
|
|
144
|
+
return { screenshotBase64, width: viewport.width, height: viewport.height, nodes };
|
|
145
|
+
}
|
|
146
|
+
async select(clientId, x, y) {
|
|
147
|
+
const session = this.requireSession(clientId);
|
|
148
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) {
|
|
149
|
+
throw new Error('Invalid element coordinates');
|
|
150
|
+
}
|
|
151
|
+
const element = await session.page.evaluate(`(() => {
|
|
152
|
+
${selectorHelper}
|
|
153
|
+
const source = document.elementFromPoint(${JSON.stringify(x)}, ${JSON.stringify(y)});
|
|
154
|
+
if (!source) return null;
|
|
155
|
+
const target = interactiveAncestor(source);
|
|
156
|
+
return {
|
|
157
|
+
selector: selectorFor(target),
|
|
158
|
+
editable: isEditable(target),
|
|
159
|
+
password: target.type === 'password',
|
|
160
|
+
};
|
|
161
|
+
})()`);
|
|
162
|
+
if (!element)
|
|
163
|
+
throw new Error('No element found at selected point');
|
|
164
|
+
const locator = session.page.locator(element.selector).first();
|
|
165
|
+
await locator.click();
|
|
166
|
+
session.focusedSelector = element.selector;
|
|
167
|
+
const step = {
|
|
168
|
+
id: randomUUID(),
|
|
169
|
+
type: 'click',
|
|
170
|
+
selector: element.selector,
|
|
171
|
+
timeout: 10000,
|
|
172
|
+
};
|
|
173
|
+
session.steps.push(step);
|
|
174
|
+
return { step, passwordField: element.editable ? element.password : false };
|
|
175
|
+
}
|
|
176
|
+
async input(clientId, text, recordingValue, secret) {
|
|
177
|
+
const session = this.requireSession(clientId);
|
|
178
|
+
if (!text)
|
|
179
|
+
throw new Error('Input text is empty');
|
|
180
|
+
if (!session.focusedSelector)
|
|
181
|
+
throw new Error('Please select an input element first');
|
|
182
|
+
await session.page.locator(session.focusedSelector).first().fill(text);
|
|
183
|
+
const step = {
|
|
184
|
+
id: randomUUID(),
|
|
185
|
+
type: 'input',
|
|
186
|
+
selector: session.focusedSelector,
|
|
187
|
+
value: recordingValue,
|
|
188
|
+
secret,
|
|
189
|
+
clearBeforeInput: true,
|
|
190
|
+
timeout: 10000,
|
|
191
|
+
};
|
|
192
|
+
session.steps.push(step);
|
|
193
|
+
return step;
|
|
194
|
+
}
|
|
195
|
+
async stop(clientId) {
|
|
196
|
+
const session = this.requireSession(clientId);
|
|
197
|
+
const script = createScript(session);
|
|
198
|
+
await this.cancel(clientId);
|
|
199
|
+
return script;
|
|
200
|
+
}
|
|
201
|
+
async replay(options) {
|
|
202
|
+
const browser = await chromium.launch({ headless: true });
|
|
203
|
+
try {
|
|
204
|
+
const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });
|
|
205
|
+
const page = await context.newPage();
|
|
206
|
+
await replayWebLoginScript({ page, script: options.script, variables: options.variables });
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
await browser.close();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async cancel(clientId) {
|
|
213
|
+
const session = this.sessions.get(clientId);
|
|
214
|
+
this.sessions.delete(clientId);
|
|
215
|
+
if (session)
|
|
216
|
+
await session.browser.close().catch(() => undefined);
|
|
217
|
+
}
|
|
218
|
+
requireSession(clientId) {
|
|
219
|
+
const session = this.sessions.get(clientId);
|
|
220
|
+
if (!session)
|
|
221
|
+
throw new Error('No active Web recording session');
|
|
222
|
+
return session;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export const webRecordingManager = new WebRecordingManager();
|
|
226
|
+
//# sourceMappingURL=web-recording-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-recording-manager.js","sourceRoot":"","sources":["../../src/recorder/web-recording-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/scrcpy/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/scrcpy/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAYH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAsBxD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAiGD,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,kBAAkB,CAA+B;IACzD,OAAO,CAAC,kBAAkB,CAAM;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,iCAAiC;IACjC,OAAO,CAAC,QAAQ,CAAiD;gBAErD,MAAM,EAAE,YAAY;YAmBlB,iBAAiB;YA6CjB,YAAY;YA2BZ,cAAc;YAuBd,MAAM;YAqCN,gBAAgB;YA2BhB,WAAW;IAwEzB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,oBAAoB;IA4B5B,OAAO,CAAC,sBAAsB;YAyBhB,iBAAiB;IAa/B,wDAAwD;YAC1C,cAAc;IAqB5B,OAAO,CAAC,oBAAoB;IAyqB5B,OAAO,CAAC,qBAAqB;IAYvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA6B7B"}
|