@midscene/web 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/bridge-mode/io-client.mjs +1 -1
- package/dist/es/bridge-mode/io-server.mjs +2 -2
- package/dist/es/bridge-mode/page-browser-side.mjs +1 -1
- package/dist/es/cli.mjs +1 -1
- package/dist/es/mcp-server.mjs +1 -1
- package/dist/es/static/static-page.mjs +23 -27
- package/dist/es/static/static-page.mjs.map +1 -1
- package/dist/es/web-page.mjs +109 -146
- package/dist/es/web-page.mjs.map +1 -1
- package/dist/lib/bridge-mode/io-client.js +1 -1
- package/dist/lib/bridge-mode/io-server.js +2 -2
- package/dist/lib/bridge-mode/page-browser-side.js +1 -1
- package/dist/lib/cli.js +1 -1
- package/dist/lib/mcp-server.js +1 -1
- package/dist/lib/static/static-page.js +22 -26
- package/dist/lib/static/static-page.js.map +1 -1
- package/dist/lib/web-page.js +111 -155
- package/dist/lib/web-page.js.map +1 -1
- package/dist/types/static/static-page.d.ts +2 -0
- package/dist/types/web-page.d.ts +2 -1
- package/package.json +4 -4
|
@@ -86,7 +86,7 @@ class BridgeServer {
|
|
|
86
86
|
logMsg('one client connected');
|
|
87
87
|
this.socket = socket;
|
|
88
88
|
const clientVersion = socket.handshake.query.version;
|
|
89
|
-
logMsg(`Bridge connected, cli-side version v1.8.
|
|
89
|
+
logMsg(`Bridge connected, cli-side version v1.8.1, browser-side version v${clientVersion}`);
|
|
90
90
|
socket.on(BridgeEvent.CallResponse, (params)=>{
|
|
91
91
|
const id = params.id;
|
|
92
92
|
const response = params.response;
|
|
@@ -110,7 +110,7 @@ class BridgeServer {
|
|
|
110
110
|
setTimeout(()=>{
|
|
111
111
|
this.onConnect?.();
|
|
112
112
|
const payload = {
|
|
113
|
-
version: "1.8.
|
|
113
|
+
version: "1.8.1"
|
|
114
114
|
};
|
|
115
115
|
socket.emit(BridgeEvent.Connected, payload);
|
|
116
116
|
Promise.resolve().then(()=>{
|
|
@@ -65,7 +65,7 @@ class ExtensionBridgePageBrowserSide extends page {
|
|
|
65
65
|
throw new Error('Connection denied by user');
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.8.
|
|
68
|
+
this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.8.1`, 'log');
|
|
69
69
|
}
|
|
70
70
|
async connect() {
|
|
71
71
|
return await this.setupBridgeClient();
|
package/dist/es/cli.mjs
CHANGED
package/dist/es/mcp-server.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineActionsFromInputPrimitives } from "@midscene/core/device";
|
|
2
2
|
import { ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED } from "@midscene/shared/common";
|
|
3
3
|
function _define_property(obj, key, value) {
|
|
4
4
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -15,32 +15,9 @@ const ThrowNotImplemented = (methodName)=>{
|
|
|
15
15
|
};
|
|
16
16
|
class StaticPage {
|
|
17
17
|
actionSpace() {
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}),
|
|
22
|
-
defineActionRightClick(async (param)=>{
|
|
23
|
-
ThrowNotImplemented('RightClick');
|
|
24
|
-
}),
|
|
25
|
-
defineActionHover(async (param)=>{
|
|
26
|
-
ThrowNotImplemented('Hover');
|
|
27
|
-
}),
|
|
28
|
-
defineActionInput(async (param)=>{
|
|
29
|
-
ThrowNotImplemented('Input');
|
|
30
|
-
}),
|
|
31
|
-
defineActionKeyboardPress(async (param)=>{
|
|
32
|
-
ThrowNotImplemented('KeyboardPress');
|
|
33
|
-
}),
|
|
34
|
-
defineActionScroll(async (param)=>{
|
|
35
|
-
ThrowNotImplemented('Scroll');
|
|
36
|
-
}),
|
|
37
|
-
defineActionDragAndDrop(async (param)=>{
|
|
38
|
-
ThrowNotImplemented('DragAndDrop');
|
|
39
|
-
}),
|
|
40
|
-
defineActionSwipe(async (param)=>{
|
|
41
|
-
ThrowNotImplemented('Swipe');
|
|
42
|
-
})
|
|
43
|
-
];
|
|
18
|
+
return defineActionsFromInputPrimitives(this.inputPrimitives, {
|
|
19
|
+
size: ()=>this.size()
|
|
20
|
+
});
|
|
44
21
|
}
|
|
45
22
|
async evaluateJavaScript(script) {
|
|
46
23
|
return ThrowNotImplemented('evaluateJavaScript');
|
|
@@ -104,6 +81,25 @@ class StaticPage {
|
|
|
104
81
|
constructor(uiContext){
|
|
105
82
|
_define_property(this, "interfaceType", 'static');
|
|
106
83
|
_define_property(this, "uiContext", void 0);
|
|
84
|
+
_define_property(this, "inputPrimitives", {
|
|
85
|
+
pointer: {
|
|
86
|
+
tap: async ()=>ThrowNotImplemented('Tap'),
|
|
87
|
+
rightClick: async ()=>ThrowNotImplemented('RightClick'),
|
|
88
|
+
hover: async ()=>ThrowNotImplemented('Hover'),
|
|
89
|
+
dragAndDrop: async ()=>ThrowNotImplemented('DragAndDrop')
|
|
90
|
+
},
|
|
91
|
+
keyboard: {
|
|
92
|
+
typeText: async ()=>ThrowNotImplemented('Input'),
|
|
93
|
+
keyboardPress: async ()=>ThrowNotImplemented('KeyboardPress'),
|
|
94
|
+
clearInput: async ()=>ThrowNotImplemented('ClearInput')
|
|
95
|
+
},
|
|
96
|
+
touch: {
|
|
97
|
+
swipe: async ()=>ThrowNotImplemented('Swipe')
|
|
98
|
+
},
|
|
99
|
+
scroll: {
|
|
100
|
+
scroll: async ()=>ThrowNotImplemented('Scroll')
|
|
101
|
+
}
|
|
102
|
+
});
|
|
107
103
|
_define_property(this, "mouse", {
|
|
108
104
|
click: ThrowNotImplemented.bind(null, 'mouse.click'),
|
|
109
105
|
wheel: ThrowNotImplemented.bind(null, 'mouse.wheel'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static/static-page.mjs","sources":["../../../src/static/static-page.ts"],"sourcesContent":["import type { DeviceAction, Point, UIContext } from '@midscene/core';\nimport type { AbstractInterface } from '@midscene/core/device';\nimport {\n
|
|
1
|
+
{"version":3,"file":"static/static-page.mjs","sources":["../../../src/static/static-page.ts"],"sourcesContent":["import type { DeviceAction, Point, UIContext } from '@midscene/core';\nimport type { AbstractInterface } from '@midscene/core/device';\nimport {\n type InputPrimitives,\n defineActionsFromInputPrimitives,\n} from '@midscene/core/device';\nimport { ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED } from '@midscene/shared/common';\n\nconst ThrowNotImplemented = (methodName: string) => {\n throw new Error(\n `The method \"${methodName}\" is not implemented as designed since this is a static UI context. (${ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED})`,\n );\n};\n\ntype StaticPageUIContext = Omit<UIContext, 'deprecatedDpr'>;\n\nexport default class StaticPage implements AbstractInterface {\n interfaceType = 'static';\n\n private uiContext: StaticPageUIContext;\n readonly inputPrimitives: InputPrimitives = {\n pointer: {\n tap: async () => ThrowNotImplemented('Tap'),\n rightClick: async () => ThrowNotImplemented('RightClick'),\n hover: async () => ThrowNotImplemented('Hover'),\n dragAndDrop: async () => ThrowNotImplemented('DragAndDrop'),\n },\n keyboard: {\n typeText: async () => ThrowNotImplemented('Input'),\n keyboardPress: async () => ThrowNotImplemented('KeyboardPress'),\n clearInput: async () => ThrowNotImplemented('ClearInput'),\n },\n touch: {\n swipe: async () => ThrowNotImplemented('Swipe'),\n },\n scroll: {\n scroll: async () => ThrowNotImplemented('Scroll'),\n },\n };\n\n constructor(uiContext: StaticPageUIContext) {\n this.uiContext = uiContext;\n }\n\n actionSpace(): DeviceAction[] {\n // Return available actions for static page - they will throw \"not implemented\" errors when executed\n // but need to be available for planning phase\n return defineActionsFromInputPrimitives(this.inputPrimitives, {\n size: () => this.size(),\n });\n }\n\n async evaluateJavaScript<T = unknown>(script: string): Promise<T> {\n return ThrowNotImplemented('evaluateJavaScript');\n }\n\n // @deprecated\n async getElementsInfo() {\n return ThrowNotImplemented('getElementsInfo');\n }\n\n async getElementsNodeTree() {\n return ThrowNotImplemented('getElementsNodeTree');\n }\n\n async getXpathsByPoint(point: Point) {\n return ThrowNotImplemented('getXpathsByPoint');\n }\n\n async getElementInfoByXpath(xpath: string) {\n return ThrowNotImplemented('getElementInfoByXpath');\n }\n\n async size() {\n return {\n ...this.uiContext.shotSize,\n };\n }\n\n async screenshotBase64() {\n const screenshot = this.uiContext.screenshot;\n if (typeof screenshot === 'object' && 'base64' in screenshot) {\n return (screenshot as { base64: string }).base64;\n }\n return screenshot as unknown as string;\n }\n\n async url() {\n return Promise.resolve('https://static_page_without_url');\n }\n\n async scrollUntilTop(startingPoint?: Point) {\n return ThrowNotImplemented('scrollUntilTop');\n }\n\n async scrollUntilBottom(startingPoint?: Point) {\n return ThrowNotImplemented('scrollUntilBottom');\n }\n\n async scrollUntilLeft(startingPoint?: Point) {\n return ThrowNotImplemented('scrollUntilLeft');\n }\n\n async scrollUntilRight(startingPoint?: Point) {\n return ThrowNotImplemented('scrollUntilRight');\n }\n\n async scrollUp(distance?: number, startingPoint?: Point) {\n return ThrowNotImplemented('scrollUp');\n }\n\n async scrollDown(distance?: number, startingPoint?: Point) {\n return ThrowNotImplemented('scrollDown');\n }\n\n async scrollLeft(distance?: number, startingPoint?: Point) {\n return ThrowNotImplemented('scrollLeft');\n }\n\n async scrollRight(distance?: number, startingPoint?: Point) {\n return ThrowNotImplemented('scrollRight');\n }\n\n async clearInput() {\n return ThrowNotImplemented('clearInput');\n }\n\n mouse = {\n click: ThrowNotImplemented.bind(null, 'mouse.click'),\n wheel: ThrowNotImplemented.bind(null, 'mouse.wheel'),\n move: ThrowNotImplemented.bind(null, 'mouse.move'),\n drag: ThrowNotImplemented.bind(null, 'mouse.drag'),\n };\n\n keyboard = {\n type: ThrowNotImplemented.bind(null, 'keyboard.type'),\n press: ThrowNotImplemented.bind(null, 'keyboard.press'),\n };\n\n async destroy(): Promise<void> {\n //\n }\n\n updateContext(newContext: StaticPageUIContext): void {\n this.uiContext = newContext;\n }\n}\n"],"names":["ThrowNotImplemented","methodName","Error","ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED","StaticPage","defineActionsFromInputPrimitives","script","point","xpath","screenshot","Promise","startingPoint","distance","newContext","uiContext"],"mappings":";;;;;;;;;;;;AAQA,MAAMA,sBAAsB,CAACC;IAC3B,MAAM,IAAIC,MACR,CAAC,YAAY,EAAED,WAAW,qEAAqE,EAAEE,uCAAuC,CAAC,CAAC;AAE9I;AAIe,MAAMC;IA4BnB,cAA8B;QAG5B,OAAOC,iCAAiC,IAAI,CAAC,eAAe,EAAE;YAC5D,MAAM,IAAM,IAAI,CAAC,IAAI;QACvB;IACF;IAEA,MAAM,mBAAgCC,MAAc,EAAc;QAChE,OAAON,oBAAoB;IAC7B;IAGA,MAAM,kBAAkB;QACtB,OAAOA,oBAAoB;IAC7B;IAEA,MAAM,sBAAsB;QAC1B,OAAOA,oBAAoB;IAC7B;IAEA,MAAM,iBAAiBO,KAAY,EAAE;QACnC,OAAOP,oBAAoB;IAC7B;IAEA,MAAM,sBAAsBQ,KAAa,EAAE;QACzC,OAAOR,oBAAoB;IAC7B;IAEA,MAAM,OAAO;QACX,OAAO;YACL,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ;QAC5B;IACF;IAEA,MAAM,mBAAmB;QACvB,MAAMS,aAAa,IAAI,CAAC,SAAS,CAAC,UAAU;QAC5C,IAAI,AAAsB,YAAtB,OAAOA,cAA2B,YAAYA,YAChD,OAAQA,WAAkC,MAAM;QAElD,OAAOA;IACT;IAEA,MAAM,MAAM;QACV,OAAOC,QAAQ,OAAO,CAAC;IACzB;IAEA,MAAM,eAAeC,aAAqB,EAAE;QAC1C,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,kBAAkBW,aAAqB,EAAE;QAC7C,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,gBAAgBW,aAAqB,EAAE;QAC3C,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,iBAAiBW,aAAqB,EAAE;QAC5C,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,SAASY,QAAiB,EAAED,aAAqB,EAAE;QACvD,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,WAAWY,QAAiB,EAAED,aAAqB,EAAE;QACzD,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,WAAWY,QAAiB,EAAED,aAAqB,EAAE;QACzD,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,YAAYY,QAAiB,EAAED,aAAqB,EAAE;QAC1D,OAAOX,oBAAoB;IAC7B;IAEA,MAAM,aAAa;QACjB,OAAOA,oBAAoB;IAC7B;IAcA,MAAM,UAAyB,CAE/B;IAEA,cAAca,UAA+B,EAAQ;QACnD,IAAI,CAAC,SAAS,GAAGA;IACnB;IAzGA,YAAYC,SAA8B,CAAE;QAvB5C,wCAAgB;QAEhB,uBAAQ,aAAR;QACA,uBAAS,mBAAmC;YAC1C,SAAS;gBACP,KAAK,UAAYd,oBAAoB;gBACrC,YAAY,UAAYA,oBAAoB;gBAC5C,OAAO,UAAYA,oBAAoB;gBACvC,aAAa,UAAYA,oBAAoB;YAC/C;YACA,UAAU;gBACR,UAAU,UAAYA,oBAAoB;gBAC1C,eAAe,UAAYA,oBAAoB;gBAC/C,YAAY,UAAYA,oBAAoB;YAC9C;YACA,OAAO;gBACL,OAAO,UAAYA,oBAAoB;YACzC;YACA,QAAQ;gBACN,QAAQ,UAAYA,oBAAoB;YAC1C;QACF;QAyFA,gCAAQ;YACN,OAAOA,oBAAoB,IAAI,CAAC,MAAM;YACtC,OAAOA,oBAAoB,IAAI,CAAC,MAAM;YACtC,MAAMA,oBAAoB,IAAI,CAAC,MAAM;YACrC,MAAMA,oBAAoB,IAAI,CAAC,MAAM;QACvC;QAEA,mCAAW;YACT,MAAMA,oBAAoB,IAAI,CAAC,MAAM;YACrC,OAAOA,oBAAoB,IAAI,CAAC,MAAM;QACxC;QAhGE,IAAI,CAAC,SAAS,GAAGc;IACnB;AAwGF"}
|
package/dist/es/web-page.mjs
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import node_assert from "node:assert";
|
|
2
1
|
import { z } from "@midscene/core";
|
|
3
|
-
import { AbstractInterface, defineAction,
|
|
2
|
+
import { AbstractInterface, defineAction, defineActionsFromInputPrimitives } from "@midscene/core/device";
|
|
4
3
|
import { sleep } from "@midscene/core/utils";
|
|
5
|
-
import { getDebug } from "@midscene/shared/logger";
|
|
6
4
|
import { transformHotkeyInput } from "@midscene/shared/us-keyboard-layout";
|
|
7
|
-
const debug = getDebug('web:page');
|
|
8
5
|
const navigateParamSchema = z.object({
|
|
9
6
|
url: z.string().describe('The URL to navigate to. Must start with https://, file://, or a similar protocol.')
|
|
10
7
|
});
|
|
@@ -85,152 +82,117 @@ class AbstractWebPage extends AbstractInterface {
|
|
|
85
82
|
}
|
|
86
83
|
async clearInput(element) {}
|
|
87
84
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
button: 'left'
|
|
94
|
-
});
|
|
95
|
-
}),
|
|
96
|
-
defineActionRightClick(async (param)=>{
|
|
97
|
-
const element = param.locate;
|
|
98
|
-
node_assert(element, 'Element not found, cannot right click');
|
|
99
|
-
await page.mouse.click(element.center[0], element.center[1], {
|
|
100
|
-
button: 'right'
|
|
101
|
-
});
|
|
102
|
-
}),
|
|
103
|
-
defineActionDoubleClick(async (param)=>{
|
|
104
|
-
const element = param.locate;
|
|
105
|
-
node_assert(element, 'Element not found, cannot double click');
|
|
106
|
-
await page.mouse.click(element.center[0], element.center[1], {
|
|
107
|
-
button: 'left',
|
|
108
|
-
count: 2
|
|
109
|
-
});
|
|
110
|
-
}),
|
|
111
|
-
defineActionHover(async (param)=>{
|
|
112
|
-
const element = param.locate;
|
|
113
|
-
node_assert(element, 'Element not found, cannot hover');
|
|
114
|
-
await page.mouse.move(element.center[0], element.center[1]);
|
|
115
|
-
}),
|
|
116
|
-
defineActionInput(async (param)=>{
|
|
117
|
-
const element = param.locate;
|
|
118
|
-
if (element && 'typeOnly' !== param.mode) await page.clearInput(element);
|
|
119
|
-
else if (element && 'typeOnly' === param.mode) {
|
|
120
|
-
await page.mouse.click(element.center[0], element.center[1], {
|
|
85
|
+
function createWebInputPrimitives(page) {
|
|
86
|
+
return {
|
|
87
|
+
pointer: {
|
|
88
|
+
tap: async ({ x, y })=>{
|
|
89
|
+
await page.mouse.click(x, y, {
|
|
121
90
|
button: 'left'
|
|
122
91
|
});
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
92
|
+
},
|
|
93
|
+
rightClick: async ({ x, y })=>{
|
|
94
|
+
await page.mouse.click(x, y, {
|
|
95
|
+
button: 'right'
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
doubleClick: async ({ x, y })=>{
|
|
99
|
+
await page.mouse.click(x, y, {
|
|
100
|
+
button: 'left',
|
|
101
|
+
count: 2
|
|
102
|
+
});
|
|
103
|
+
},
|
|
104
|
+
hover: async ({ x, y })=>{
|
|
105
|
+
await page.mouse.move(x, y);
|
|
106
|
+
},
|
|
107
|
+
dragAndDrop: async (from, to)=>{
|
|
108
|
+
await page.mouse.drag(from, to);
|
|
109
|
+
},
|
|
110
|
+
longPress: async ({ x, y }, opts)=>{
|
|
111
|
+
await page.longPress(x, y, opts?.duration);
|
|
128
112
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
await page.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
]
|
|
152
|
-
|
|
113
|
+
},
|
|
114
|
+
keyboard: {
|
|
115
|
+
typeText: async (value, opts)=>{
|
|
116
|
+
const element = opts?.target;
|
|
117
|
+
if (element && opts?.replace !== false) await page.clearInput(element);
|
|
118
|
+
else if (element) {
|
|
119
|
+
const target = element;
|
|
120
|
+
await page.mouse.click(target.center[0], target.center[1], {
|
|
121
|
+
button: 'left'
|
|
122
|
+
});
|
|
123
|
+
await page.keyboard.press([
|
|
124
|
+
{
|
|
125
|
+
key: 'End'
|
|
126
|
+
}
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
if (opts?.focusOnly) return;
|
|
130
|
+
await page.keyboard.type(value);
|
|
131
|
+
await page.flushPendingVisualUpdate?.();
|
|
132
|
+
},
|
|
133
|
+
keyboardPress: async (keyName, opts)=>{
|
|
134
|
+
const element = opts?.target;
|
|
135
|
+
if (element) await page.mouse.click(element.center[0], element.center[1], {
|
|
136
|
+
button: 'left'
|
|
137
|
+
});
|
|
138
|
+
const keys = getKeyCommands(keyName);
|
|
139
|
+
await page.keyboard.press(keys);
|
|
140
|
+
await page.flushPendingVisualUpdate?.();
|
|
141
|
+
},
|
|
142
|
+
cursorMove: async (direction, times = 1)=>{
|
|
143
|
+
const arrowKey = 'left' === direction ? 'ArrowLeft' : 'ArrowRight';
|
|
144
|
+
for(let i = 0; i < times; i++){
|
|
145
|
+
await page.keyboard.press([
|
|
146
|
+
{
|
|
147
|
+
key: arrowKey
|
|
148
|
+
}
|
|
149
|
+
]);
|
|
150
|
+
await sleep(100);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
clearInput: async (target)=>{
|
|
154
|
+
await page.clearInput(target);
|
|
153
155
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const scrollToEventName = param?.scrollType;
|
|
162
|
-
if ('scrollToTop' === scrollToEventName) await page.scrollUntilTop(startingPoint);
|
|
163
|
-
else if ('scrollToBottom' === scrollToEventName) await page.scrollUntilBottom(startingPoint);
|
|
164
|
-
else if ('scrollToRight' === scrollToEventName) await page.scrollUntilRight(startingPoint);
|
|
165
|
-
else if ('scrollToLeft' === scrollToEventName) await page.scrollUntilLeft(startingPoint);
|
|
166
|
-
else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
|
|
167
|
-
else {
|
|
168
|
-
if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await page.scrollUp(param.distance || void 0, startingPoint);
|
|
169
|
-
else if ('left' === param.direction) await page.scrollLeft(param.distance || void 0, startingPoint);
|
|
170
|
-
else if ('right' === param.direction) await page.scrollRight(param.distance || void 0, startingPoint);
|
|
171
|
-
else throw new Error(`Unknown scroll direction: ${param.direction}`);
|
|
172
|
-
else await page.scrollDown(param?.distance || void 0, startingPoint);
|
|
173
|
-
await sleep(500);
|
|
156
|
+
},
|
|
157
|
+
touch: {
|
|
158
|
+
pinch: async ({ x, y }, opts)=>{
|
|
159
|
+
await page.pinch(x, y, opts.startDistance, opts.endDistance, opts.duration);
|
|
160
|
+
},
|
|
161
|
+
swipe: async (from, to, opts)=>{
|
|
162
|
+
await page.swipe(from, to, opts?.duration);
|
|
174
163
|
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
x: width / 2,
|
|
208
|
-
y: height / 2
|
|
209
|
-
};
|
|
210
|
-
let endPoint;
|
|
211
|
-
if (end) endPoint = {
|
|
212
|
-
x: end.center[0],
|
|
213
|
-
y: end.center[1]
|
|
214
|
-
};
|
|
215
|
-
else if (param.distance) {
|
|
216
|
-
const direction = param.direction;
|
|
217
|
-
if (!direction) throw new Error('direction is required for swipe gesture');
|
|
218
|
-
endPoint = {
|
|
219
|
-
x: startPoint.x + ('right' === direction ? param.distance : 'left' === direction ? -param.distance : 0),
|
|
220
|
-
y: startPoint.y + ('down' === direction ? param.distance : 'up' === direction ? -param.distance : 0)
|
|
221
|
-
};
|
|
222
|
-
} else throw new Error('Either end or distance must be specified for swipe gesture');
|
|
223
|
-
endPoint.x = Math.max(0, Math.min(endPoint.x, width));
|
|
224
|
-
endPoint.y = Math.max(0, Math.min(endPoint.y, height));
|
|
225
|
-
const duration = param.duration;
|
|
226
|
-
debug(`swipe from ${startPoint.x}, ${startPoint.y} to ${endPoint.x}, ${endPoint.y} with duration ${duration}ms, repeat is set to ${param.repeat}`);
|
|
227
|
-
let repeat = 'number' == typeof param.repeat ? param.repeat : 1;
|
|
228
|
-
if (0 === repeat) repeat = 10;
|
|
229
|
-
for(let i = 0; i < repeat; i++)await page.swipe(startPoint, endPoint, duration);
|
|
230
|
-
})
|
|
231
|
-
] : [],
|
|
232
|
-
defineActionClearInput(async (param)=>{
|
|
233
|
-
await page.clearInput(param.locate);
|
|
164
|
+
},
|
|
165
|
+
scroll: {
|
|
166
|
+
scroll: async (param)=>{
|
|
167
|
+
const element = param.locate;
|
|
168
|
+
const startingPoint = element ? {
|
|
169
|
+
left: element.center[0],
|
|
170
|
+
top: element.center[1]
|
|
171
|
+
} : void 0;
|
|
172
|
+
const scrollToEventName = param?.scrollType;
|
|
173
|
+
if ('scrollToTop' === scrollToEventName) await page.scrollUntilTop(startingPoint);
|
|
174
|
+
else if ('scrollToBottom' === scrollToEventName) await page.scrollUntilBottom(startingPoint);
|
|
175
|
+
else if ('scrollToRight' === scrollToEventName) await page.scrollUntilRight(startingPoint);
|
|
176
|
+
else if ('scrollToLeft' === scrollToEventName) await page.scrollUntilLeft(startingPoint);
|
|
177
|
+
else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
|
|
178
|
+
else {
|
|
179
|
+
if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await page.scrollUp(param.distance || void 0, startingPoint);
|
|
180
|
+
else if ('left' === param.direction) await page.scrollLeft(param.distance || void 0, startingPoint);
|
|
181
|
+
else if ('right' === param.direction) await page.scrollRight(param.distance || void 0, startingPoint);
|
|
182
|
+
else throw new Error(`Unknown scroll direction: ${param.direction}`);
|
|
183
|
+
else await page.scrollDown(param?.distance || void 0, startingPoint);
|
|
184
|
+
await sleep(500);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const commonWebActionsForWebPage = (page, includeTouchEvents = false)=>{
|
|
191
|
+
const input = createWebInputPrimitives(page);
|
|
192
|
+
return [
|
|
193
|
+
...defineActionsFromInputPrimitives(input, {
|
|
194
|
+
size: ()=>page.size(),
|
|
195
|
+
includeSwipe: includeTouchEvents
|
|
234
196
|
}),
|
|
235
197
|
defineAction({
|
|
236
198
|
name: 'Navigate',
|
|
@@ -269,6 +231,7 @@ const commonWebActionsForWebPage = (page, includeTouchEvents = false)=>[
|
|
|
269
231
|
}
|
|
270
232
|
})
|
|
271
233
|
];
|
|
272
|
-
|
|
234
|
+
};
|
|
235
|
+
export { AbstractWebPage, commonWebActionsForWebPage, createWebInputPrimitives, getKeyCommands };
|
|
273
236
|
|
|
274
237
|
//# sourceMappingURL=web-page.mjs.map
|
package/dist/es/web-page.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-page.mjs","sources":["../../src/web-page.ts"],"sourcesContent":["import assert from 'node:assert';\nimport type { Point } from '@midscene/core';\nimport { z } from '@midscene/core';\nimport {\n AbstractInterface,\n type DeviceAction,\n defineAction,\n defineActionClearInput,\n defineActionCursorMove,\n defineActionDoubleClick,\n defineActionDragAndDrop,\n defineActionHover,\n defineActionInput,\n defineActionKeyboardPress,\n defineActionLongPress,\n defineActionPinch,\n defineActionRightClick,\n defineActionScroll,\n defineActionSwipe,\n defineActionTap,\n normalizePinchParam,\n} from '@midscene/core/device';\n\nimport { sleep } from '@midscene/core/utils';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { getDebug } from '@midscene/shared/logger';\nimport { transformHotkeyInput } from '@midscene/shared/us-keyboard-layout';\n\nconst debug = getDebug('web:page');\n\nconst navigateParamSchema = z.object({\n url: z\n .string()\n .describe(\n 'The URL to navigate to. Must start with https://, file://, or a similar protocol.',\n ),\n});\n\nfunction normalizeKeyInputs(value: string | string[]): string[] {\n const inputs = Array.isArray(value) ? value : [value];\n const result: string[] = [];\n\n for (const input of inputs) {\n if (typeof input !== 'string') {\n result.push(input as unknown as string);\n continue;\n }\n\n const trimmed = input.trim();\n if (!trimmed) {\n result.push(input);\n continue;\n }\n\n let normalized = trimmed;\n if (normalized.length > 1 && normalized.includes('+')) {\n normalized = normalized.replace(/\\s*\\+\\s*/g, ' ');\n }\n if (/\\s/.test(normalized)) {\n normalized = normalized.replace(/\\s+/g, ' ');\n }\n\n const transformed = transformHotkeyInput(normalized);\n if (transformed.length === 1 && transformed[0] === '' && trimmed !== '') {\n result.push(input);\n continue;\n }\n if (transformed.length === 0) {\n result.push(input);\n continue;\n }\n\n result.push(...transformed);\n }\n\n return result;\n}\n\nexport function getKeyCommands(\n value: string | string[],\n): Array<{ key: string; command?: string }> {\n const keys = normalizeKeyInputs(value);\n\n return keys.reduce((acc: Array<{ key: string; command?: string }>, k) => {\n const includeMeta = keys.includes('Meta') || keys.includes('Control');\n if (includeMeta && (k === 'a' || k === 'A')) {\n return acc.concat([{ key: k, command: 'SelectAll' }]);\n }\n if (includeMeta && (k === 'c' || k === 'C')) {\n return acc.concat([{ key: k, command: 'Copy' }]);\n }\n if (includeMeta && (k === 'v' || k === 'V')) {\n return acc.concat([{ key: k, command: 'Paste' }]);\n }\n return acc.concat([{ key: k }]);\n }, []);\n}\n\n// this is copied from puppeteer, but we don't want to import puppeteer here\nexport declare type KeyInput =\n | '0'\n | '1'\n | '2'\n | '3'\n | '4'\n | '5'\n | '6'\n | '7'\n | '8'\n | '9'\n | 'Power'\n | 'Eject'\n | 'Abort'\n | 'Help'\n | 'Backspace'\n | 'Tab'\n | 'Numpad5'\n | 'NumpadEnter'\n | 'Enter'\n | '\\r'\n | '\\n'\n | 'ShiftLeft'\n | 'ShiftRight'\n | 'ControlLeft'\n | 'ControlRight'\n | 'AltLeft'\n | 'AltRight'\n | 'Pause'\n | 'CapsLock'\n | 'Escape'\n | 'Convert'\n | 'NonConvert'\n | 'Space'\n | 'Numpad9'\n | 'PageUp'\n | 'Numpad3'\n | 'PageDown'\n | 'End'\n | 'Numpad1'\n | 'Home'\n | 'Numpad7'\n | 'ArrowLeft'\n | 'Numpad4'\n | 'Numpad8'\n | 'ArrowUp'\n | 'ArrowRight'\n | 'Numpad6'\n | 'Numpad2'\n | 'ArrowDown'\n | 'Select'\n | 'Open'\n | 'PrintScreen'\n | 'Insert'\n | 'Numpad0'\n | 'Delete'\n | 'NumpadDecimal'\n | 'Digit0'\n | 'Digit1'\n | 'Digit2'\n | 'Digit3'\n | 'Digit4'\n | 'Digit5'\n | 'Digit6'\n | 'Digit7'\n | 'Digit8'\n | 'Digit9'\n | 'KeyA'\n | 'KeyB'\n | 'KeyC'\n | 'KeyD'\n | 'KeyE'\n | 'KeyF'\n | 'KeyG'\n | 'KeyH'\n | 'KeyI'\n | 'KeyJ'\n | 'KeyK'\n | 'KeyL'\n | 'KeyM'\n | 'KeyN'\n | 'KeyO'\n | 'KeyP'\n | 'KeyQ'\n | 'KeyR'\n | 'KeyS'\n | 'KeyT'\n | 'KeyU'\n | 'KeyV'\n | 'KeyW'\n | 'KeyX'\n | 'KeyY'\n | 'KeyZ'\n | 'MetaLeft'\n | 'MetaRight'\n | 'ContextMenu'\n | 'NumpadMultiply'\n | 'NumpadAdd'\n | 'NumpadSubtract'\n | 'NumpadDivide'\n | 'F1'\n | 'F2'\n | 'F3'\n | 'F4'\n | 'F5'\n | 'F6'\n | 'F7'\n | 'F8'\n | 'F9'\n | 'F10'\n | 'F11'\n | 'F12'\n | 'F13'\n | 'F14'\n | 'F15'\n | 'F16'\n | 'F17'\n | 'F18'\n | 'F19'\n | 'F20'\n | 'F21'\n | 'F22'\n | 'F23'\n | 'F24'\n | 'NumLock'\n | 'ScrollLock'\n | 'AudioVolumeMute'\n | 'AudioVolumeDown'\n | 'AudioVolumeUp'\n | 'MediaTrackNext'\n | 'MediaTrackPrevious'\n | 'MediaStop'\n | 'MediaPlayPause'\n | 'Semicolon'\n | 'Equal'\n | 'NumpadEqual'\n | 'Comma'\n | 'Minus'\n | 'Period'\n | 'Slash'\n | 'Backquote'\n | 'BracketLeft'\n | 'Backslash'\n | 'BracketRight'\n | 'Quote'\n | 'AltGraph'\n | 'Props'\n | 'Cancel'\n | 'Clear'\n | 'Shift'\n | 'Control'\n | 'Alt'\n | 'Accept'\n | 'ModeChange'\n | ' '\n | 'Print'\n | 'Execute'\n | '\\u0000'\n | 'a'\n | 'b'\n | 'c'\n | 'd'\n | 'e'\n | 'f'\n | 'g'\n | 'h'\n | 'i'\n | 'j'\n | 'k'\n | 'l'\n | 'm'\n | 'n'\n | 'o'\n | 'p'\n | 'q'\n | 'r'\n | 's'\n | 't'\n | 'u'\n | 'v'\n | 'w'\n | 'x'\n | 'y'\n | 'z'\n | 'Meta'\n | '*'\n | '+'\n | '-'\n | '/'\n | ';'\n | '='\n | ','\n | '.'\n | '`'\n | '['\n | '\\\\'\n | ']'\n | \"'\"\n | 'Attn'\n | 'CrSel'\n | 'ExSel'\n | 'EraseEof'\n | 'Play'\n | 'ZoomOut'\n | ')'\n | '!'\n | '@'\n | '#'\n | '$'\n | '%'\n | '^'\n | '&'\n | '('\n | 'A'\n | 'B'\n | 'C'\n | 'D'\n | 'E'\n | 'F'\n | 'G'\n | 'H'\n | 'I'\n | 'J'\n | 'K'\n | 'L'\n | 'M'\n | 'N'\n | 'O'\n | 'P'\n | 'Q'\n | 'R'\n | 'S'\n | 'T'\n | 'U'\n | 'V'\n | 'W'\n | 'X'\n | 'Y'\n | 'Z'\n | ':'\n | '<'\n | '_'\n | '>'\n | '?'\n | '~'\n | '{'\n | '|'\n | '}'\n | '\"'\n | 'SoftLeft'\n | 'SoftRight'\n | 'Camera'\n | 'Call'\n | 'EndCall'\n | 'VolumeDown'\n | 'VolumeUp';\n\nexport type MouseButton = 'left' | 'right' | 'middle';\n\nexport interface MouseAction {\n click: (\n x: number,\n y: number,\n options: { button: MouseButton; count?: number },\n ) => Promise<void>;\n wheel: (deltaX: number, deltaY: number) => Promise<void>;\n move: (x: number, y: number) => Promise<void>;\n drag: (\n from: { x: number; y: number },\n to: { x: number; y: number },\n ) => Promise<void>;\n}\n\nexport interface KeyboardAction {\n type: (text: string) => Promise<void>;\n press: (\n action:\n | { key: KeyInput; command?: string }\n | { key: KeyInput; command?: string }[],\n ) => Promise<void>;\n}\n\nexport interface ChromePageDestroyOptions {\n closeTab?: boolean; // should close the tab when the page object is destroyed\n}\n\nexport abstract class AbstractWebPage extends AbstractInterface {\n navigate?(url: string): Promise<void>;\n reload?(): Promise<void>;\n goBack?(): Promise<void>;\n goForward?(): Promise<void>;\n stopLoading?(): Promise<void>;\n navigationState?(): Promise<{ isLoading: boolean }>;\n flushPendingVisualUpdate?(): Promise<void>;\n\n get mouse(): MouseAction {\n return {\n click: async (\n x: number,\n y: number,\n options: { button: MouseButton },\n ) => {},\n wheel: async (deltaX: number, deltaY: number) => {},\n move: async (x: number, y: number) => {},\n drag: async (\n from: { x: number; y: number },\n to: { x: number; y: number },\n ) => {},\n };\n }\n\n get keyboard(): KeyboardAction {\n return {\n type: async (text: string) => {},\n press: async (\n action:\n | { key: KeyInput; command?: string }\n | { key: KeyInput; command?: string }[],\n ) => {},\n };\n }\n\n async clearInput(element?: ElementInfo): Promise<void> {}\n\n abstract scrollUntilTop(startingPoint?: Point): Promise<void>;\n abstract scrollUntilBottom(startingPoint?: Point): Promise<void>;\n abstract scrollUntilLeft(startingPoint?: Point): Promise<void>;\n abstract scrollUntilRight(startingPoint?: Point): Promise<void>;\n abstract scrollUp(distance?: number, startingPoint?: Point): Promise<void>;\n abstract scrollDown(distance?: number, startingPoint?: Point): Promise<void>;\n abstract scrollLeft(distance?: number, startingPoint?: Point): Promise<void>;\n abstract scrollRight(distance?: number, startingPoint?: Point): Promise<void>;\n abstract longPress(x: number, y: number, duration?: number): Promise<void>;\n abstract swipe(\n from: { x: number; y: number },\n to: { x: number; y: number },\n duration?: number,\n ): Promise<void>;\n abstract pinch(\n centerX: number,\n centerY: number,\n startDistance: number,\n endDistance: number,\n duration?: number,\n ): Promise<void>;\n}\n\nexport const commonWebActionsForWebPage = <T extends AbstractWebPage>(\n page: T,\n includeTouchEvents = false,\n): DeviceAction<any>[] => [\n defineActionTap(async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot tap');\n\n // Pure tap action - file handling is done at Page layer via setFileChooserHandler\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n }),\n defineActionRightClick(async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot right click');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'right',\n });\n }),\n defineActionDoubleClick(async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot double click');\n\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n count: 2,\n });\n }),\n defineActionHover(async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot hover');\n await page.mouse.move(element.center[0], element.center[1]);\n }),\n defineActionInput(async (param) => {\n const element = param.locate;\n if (element && param.mode !== 'typeOnly') {\n await page.clearInput(element as unknown as ElementInfo);\n } else if (element && param.mode === 'typeOnly') {\n // typeOnly mode: click to focus and move cursor to end, but don't clear\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n await page.keyboard.press([{ key: 'End' }]);\n }\n\n if (param.mode === 'clear') {\n return;\n }\n\n if (!param || !param.value) {\n return;\n }\n\n // Note: there is another implementation in AndroidDevicePage, which is more complex\n await page.keyboard.type(param.value);\n await page.flushPendingVisualUpdate?.();\n }),\n defineActionKeyboardPress(async (param) => {\n const element = param.locate;\n if (element) {\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n }\n\n const keys = getKeyCommands(param.keyName);\n await page.keyboard.press(keys as any); // TODO: fix this type error\n await page.flushPendingVisualUpdate?.();\n }),\n defineActionCursorMove(async (param) => {\n const arrowKey = param.direction === 'left' ? 'ArrowLeft' : 'ArrowRight';\n const times = param.times ?? 1;\n for (let i = 0; i < times; i++) {\n await page.keyboard.press([{ key: arrowKey as any }]);\n await sleep(100);\n }\n }),\n defineActionScroll(async (param) => {\n const element = param.locate;\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = param?.scrollType;\n if (scrollToEventName === 'scrollToTop') {\n await page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'scrollToBottom') {\n await page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'scrollToRight') {\n await page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'scrollToLeft') {\n await page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'singleAction' || !scrollToEventName) {\n if (param?.direction === 'down' || !param || !param.direction) {\n await page.scrollDown(param?.distance || undefined, startingPoint);\n } else if (param.direction === 'up') {\n await page.scrollUp(param.distance || undefined, startingPoint);\n } else if (param.direction === 'left') {\n await page.scrollLeft(param.distance || undefined, startingPoint);\n } else if (param.direction === 'right') {\n await page.scrollRight(param.distance || undefined, startingPoint);\n } else {\n throw new Error(`Unknown scroll direction: ${param.direction}`);\n }\n // until mouse event is done\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(\n param,\n )}`,\n );\n }\n }),\n defineActionDragAndDrop(async (param) => {\n const from = param.from;\n const to = param.to;\n assert(from, 'missing \"from\" param for drag and drop');\n assert(to, 'missing \"to\" param for drag and drop');\n await page.mouse.drag(\n {\n x: from.center[0],\n y: from.center[1],\n },\n {\n x: to.center[0],\n y: to.center[1],\n },\n );\n }),\n\n defineActionLongPress(async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot long press');\n const duration = param?.duration;\n await page.longPress(element.center[0], element.center[1], duration);\n }),\n\n defineActionPinch(async (param) => {\n const { centerX, centerY, startDistance, endDistance, duration } =\n normalizePinchParam(param, await page.size());\n\n await page.pinch(centerX, centerY, startDistance, endDistance, duration);\n }),\n\n ...(includeTouchEvents\n ? [\n defineActionSwipe(async (param) => {\n const { width, height } = await page.size();\n const { start, end } = param;\n\n const startPoint = start\n ? {\n x: start.center[0],\n y: start.center[1],\n }\n : {\n x: width / 2,\n y: height / 2,\n };\n\n let endPoint: {\n x: number;\n y: number;\n };\n\n if (end) {\n endPoint = {\n x: end.center[0],\n y: end.center[1],\n };\n } else if (param.distance) {\n const direction = param.direction;\n if (!direction) {\n throw new Error('direction is required for swipe gesture');\n }\n\n endPoint = {\n x:\n startPoint.x +\n (direction === 'right'\n ? param.distance\n : direction === 'left'\n ? -param.distance\n : 0),\n y:\n startPoint.y +\n (direction === 'down'\n ? param.distance\n : direction === 'up'\n ? -param.distance\n : 0),\n };\n } else {\n throw new Error(\n 'Either end or distance must be specified for swipe gesture',\n );\n }\n\n // Ensure end coordinates are within bounds\n endPoint.x = Math.max(0, Math.min(endPoint.x, width));\n endPoint.y = Math.max(0, Math.min(endPoint.y, height));\n\n const duration = param.duration;\n\n debug(\n `swipe from ${startPoint.x}, ${startPoint.y} to ${endPoint.x}, ${endPoint.y} with duration ${duration}ms, repeat is set to ${param.repeat}`,\n );\n let repeat = typeof param.repeat === 'number' ? param.repeat : 1;\n if (repeat === 0) {\n repeat = 10; // 10 times is enough for infinite swipe\n }\n for (let i = 0; i < repeat; i++) {\n await page.swipe(startPoint, endPoint, duration);\n }\n }),\n ]\n : []),\n\n defineActionClearInput(async (param) => {\n await page.clearInput(param.locate as ElementInfo | undefined);\n }),\n\n defineAction<typeof navigateParamSchema, { url: string }>({\n name: 'Navigate',\n description:\n 'Navigate the browser to a specified URL. Opens the URL in the current tab.',\n paramSchema: navigateParamSchema,\n sample: {\n url: 'https://www.example.com',\n },\n call: async (param) => {\n if (!page.navigate) {\n throw new Error(\n 'Navigate operation is not supported on this page type',\n );\n }\n await page.navigate(param.url);\n },\n }),\n\n defineAction({\n name: 'Reload',\n description: 'Reload the current page',\n call: async () => {\n if (!page.reload) {\n throw new Error('Reload operation is not supported on this page type');\n }\n await page.reload();\n },\n }),\n\n defineAction({\n name: 'GoBack',\n description: 'Navigate back in browser history',\n call: async () => {\n if (!page.goBack) {\n throw new Error('GoBack operation is not supported on this page type');\n }\n await page.goBack();\n },\n }),\n defineAction({\n name: 'GoForward',\n description: 'Navigate forward in browser history',\n call: async () => {\n if (!page.goForward) {\n throw new Error(\n 'GoForward operation is not supported on this page type',\n );\n }\n await page.goForward();\n },\n }),\n];\n"],"names":["debug","getDebug","navigateParamSchema","z","normalizeKeyInputs","value","inputs","Array","result","input","trimmed","normalized","transformed","transformHotkeyInput","getKeyCommands","keys","acc","k","includeMeta","AbstractWebPage","AbstractInterface","x","y","options","deltaX","deltaY","from","to","text","action","element","commonWebActionsForWebPage","page","includeTouchEvents","defineActionTap","param","assert","defineActionRightClick","defineActionDoubleClick","defineActionHover","defineActionInput","defineActionKeyboardPress","defineActionCursorMove","arrowKey","times","i","sleep","defineActionScroll","startingPoint","undefined","scrollToEventName","Error","JSON","defineActionDragAndDrop","defineActionLongPress","duration","defineActionPinch","centerX","centerY","startDistance","endDistance","normalizePinchParam","defineActionSwipe","width","height","start","end","startPoint","endPoint","direction","Math","repeat","defineActionClearInput","defineAction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"web-page.mjs","sources":["../../src/web-page.ts"],"sourcesContent":["import type { Point } from '@midscene/core';\nimport { z } from '@midscene/core';\nimport {\n AbstractInterface,\n type BrowserInputPrimitives,\n type DeviceAction,\n defineAction,\n defineActionsFromInputPrimitives,\n} from '@midscene/core/device';\n\nimport { sleep } from '@midscene/core/utils';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { transformHotkeyInput } from '@midscene/shared/us-keyboard-layout';\n\nconst navigateParamSchema = z.object({\n url: z\n .string()\n .describe(\n 'The URL to navigate to. Must start with https://, file://, or a similar protocol.',\n ),\n});\n\nfunction normalizeKeyInputs(value: string | string[]): string[] {\n const inputs = Array.isArray(value) ? value : [value];\n const result: string[] = [];\n\n for (const input of inputs) {\n if (typeof input !== 'string') {\n result.push(input as unknown as string);\n continue;\n }\n\n const trimmed = input.trim();\n if (!trimmed) {\n result.push(input);\n continue;\n }\n\n let normalized = trimmed;\n if (normalized.length > 1 && normalized.includes('+')) {\n normalized = normalized.replace(/\\s*\\+\\s*/g, ' ');\n }\n if (/\\s/.test(normalized)) {\n normalized = normalized.replace(/\\s+/g, ' ');\n }\n\n const transformed = transformHotkeyInput(normalized);\n if (transformed.length === 1 && transformed[0] === '' && trimmed !== '') {\n result.push(input);\n continue;\n }\n if (transformed.length === 0) {\n result.push(input);\n continue;\n }\n\n result.push(...transformed);\n }\n\n return result;\n}\n\nexport function getKeyCommands(\n value: string | string[],\n): Array<{ key: string; command?: string }> {\n const keys = normalizeKeyInputs(value);\n\n return keys.reduce((acc: Array<{ key: string; command?: string }>, k) => {\n const includeMeta = keys.includes('Meta') || keys.includes('Control');\n if (includeMeta && (k === 'a' || k === 'A')) {\n return acc.concat([{ key: k, command: 'SelectAll' }]);\n }\n if (includeMeta && (k === 'c' || k === 'C')) {\n return acc.concat([{ key: k, command: 'Copy' }]);\n }\n if (includeMeta && (k === 'v' || k === 'V')) {\n return acc.concat([{ key: k, command: 'Paste' }]);\n }\n return acc.concat([{ key: k }]);\n }, []);\n}\n\n// this is copied from puppeteer, but we don't want to import puppeteer here\nexport declare type KeyInput =\n | '0'\n | '1'\n | '2'\n | '3'\n | '4'\n | '5'\n | '6'\n | '7'\n | '8'\n | '9'\n | 'Power'\n | 'Eject'\n | 'Abort'\n | 'Help'\n | 'Backspace'\n | 'Tab'\n | 'Numpad5'\n | 'NumpadEnter'\n | 'Enter'\n | '\\r'\n | '\\n'\n | 'ShiftLeft'\n | 'ShiftRight'\n | 'ControlLeft'\n | 'ControlRight'\n | 'AltLeft'\n | 'AltRight'\n | 'Pause'\n | 'CapsLock'\n | 'Escape'\n | 'Convert'\n | 'NonConvert'\n | 'Space'\n | 'Numpad9'\n | 'PageUp'\n | 'Numpad3'\n | 'PageDown'\n | 'End'\n | 'Numpad1'\n | 'Home'\n | 'Numpad7'\n | 'ArrowLeft'\n | 'Numpad4'\n | 'Numpad8'\n | 'ArrowUp'\n | 'ArrowRight'\n | 'Numpad6'\n | 'Numpad2'\n | 'ArrowDown'\n | 'Select'\n | 'Open'\n | 'PrintScreen'\n | 'Insert'\n | 'Numpad0'\n | 'Delete'\n | 'NumpadDecimal'\n | 'Digit0'\n | 'Digit1'\n | 'Digit2'\n | 'Digit3'\n | 'Digit4'\n | 'Digit5'\n | 'Digit6'\n | 'Digit7'\n | 'Digit8'\n | 'Digit9'\n | 'KeyA'\n | 'KeyB'\n | 'KeyC'\n | 'KeyD'\n | 'KeyE'\n | 'KeyF'\n | 'KeyG'\n | 'KeyH'\n | 'KeyI'\n | 'KeyJ'\n | 'KeyK'\n | 'KeyL'\n | 'KeyM'\n | 'KeyN'\n | 'KeyO'\n | 'KeyP'\n | 'KeyQ'\n | 'KeyR'\n | 'KeyS'\n | 'KeyT'\n | 'KeyU'\n | 'KeyV'\n | 'KeyW'\n | 'KeyX'\n | 'KeyY'\n | 'KeyZ'\n | 'MetaLeft'\n | 'MetaRight'\n | 'ContextMenu'\n | 'NumpadMultiply'\n | 'NumpadAdd'\n | 'NumpadSubtract'\n | 'NumpadDivide'\n | 'F1'\n | 'F2'\n | 'F3'\n | 'F4'\n | 'F5'\n | 'F6'\n | 'F7'\n | 'F8'\n | 'F9'\n | 'F10'\n | 'F11'\n | 'F12'\n | 'F13'\n | 'F14'\n | 'F15'\n | 'F16'\n | 'F17'\n | 'F18'\n | 'F19'\n | 'F20'\n | 'F21'\n | 'F22'\n | 'F23'\n | 'F24'\n | 'NumLock'\n | 'ScrollLock'\n | 'AudioVolumeMute'\n | 'AudioVolumeDown'\n | 'AudioVolumeUp'\n | 'MediaTrackNext'\n | 'MediaTrackPrevious'\n | 'MediaStop'\n | 'MediaPlayPause'\n | 'Semicolon'\n | 'Equal'\n | 'NumpadEqual'\n | 'Comma'\n | 'Minus'\n | 'Period'\n | 'Slash'\n | 'Backquote'\n | 'BracketLeft'\n | 'Backslash'\n | 'BracketRight'\n | 'Quote'\n | 'AltGraph'\n | 'Props'\n | 'Cancel'\n | 'Clear'\n | 'Shift'\n | 'Control'\n | 'Alt'\n | 'Accept'\n | 'ModeChange'\n | ' '\n | 'Print'\n | 'Execute'\n | '\\u0000'\n | 'a'\n | 'b'\n | 'c'\n | 'd'\n | 'e'\n | 'f'\n | 'g'\n | 'h'\n | 'i'\n | 'j'\n | 'k'\n | 'l'\n | 'm'\n | 'n'\n | 'o'\n | 'p'\n | 'q'\n | 'r'\n | 's'\n | 't'\n | 'u'\n | 'v'\n | 'w'\n | 'x'\n | 'y'\n | 'z'\n | 'Meta'\n | '*'\n | '+'\n | '-'\n | '/'\n | ';'\n | '='\n | ','\n | '.'\n | '`'\n | '['\n | '\\\\'\n | ']'\n | \"'\"\n | 'Attn'\n | 'CrSel'\n | 'ExSel'\n | 'EraseEof'\n | 'Play'\n | 'ZoomOut'\n | ')'\n | '!'\n | '@'\n | '#'\n | '$'\n | '%'\n | '^'\n | '&'\n | '('\n | 'A'\n | 'B'\n | 'C'\n | 'D'\n | 'E'\n | 'F'\n | 'G'\n | 'H'\n | 'I'\n | 'J'\n | 'K'\n | 'L'\n | 'M'\n | 'N'\n | 'O'\n | 'P'\n | 'Q'\n | 'R'\n | 'S'\n | 'T'\n | 'U'\n | 'V'\n | 'W'\n | 'X'\n | 'Y'\n | 'Z'\n | ':'\n | '<'\n | '_'\n | '>'\n | '?'\n | '~'\n | '{'\n | '|'\n | '}'\n | '\"'\n | 'SoftLeft'\n | 'SoftRight'\n | 'Camera'\n | 'Call'\n | 'EndCall'\n | 'VolumeDown'\n | 'VolumeUp';\n\nexport type MouseButton = 'left' | 'right' | 'middle';\n\nexport interface MouseAction {\n click: (\n x: number,\n y: number,\n options: { button: MouseButton; count?: number },\n ) => Promise<void>;\n wheel: (deltaX: number, deltaY: number) => Promise<void>;\n move: (x: number, y: number) => Promise<void>;\n drag: (\n from: { x: number; y: number },\n to: { x: number; y: number },\n ) => Promise<void>;\n}\n\nexport interface KeyboardAction {\n type: (text: string) => Promise<void>;\n press: (\n action:\n | { key: KeyInput; command?: string }\n | { key: KeyInput; command?: string }[],\n ) => Promise<void>;\n}\n\nexport interface ChromePageDestroyOptions {\n closeTab?: boolean; // should close the tab when the page object is destroyed\n}\n\nexport abstract class AbstractWebPage extends AbstractInterface {\n navigate?(url: string): Promise<void>;\n reload?(): Promise<void>;\n goBack?(): Promise<void>;\n goForward?(): Promise<void>;\n stopLoading?(): Promise<void>;\n navigationState?(): Promise<{ isLoading: boolean }>;\n flushPendingVisualUpdate?(): Promise<void>;\n\n get mouse(): MouseAction {\n return {\n click: async (\n x: number,\n y: number,\n options: { button: MouseButton },\n ) => {},\n wheel: async (deltaX: number, deltaY: number) => {},\n move: async (x: number, y: number) => {},\n drag: async (\n from: { x: number; y: number },\n to: { x: number; y: number },\n ) => {},\n };\n }\n\n get keyboard(): KeyboardAction {\n return {\n type: async (text: string) => {},\n press: async (\n action:\n | { key: KeyInput; command?: string }\n | { key: KeyInput; command?: string }[],\n ) => {},\n };\n }\n\n async clearInput(element?: ElementInfo): Promise<void> {}\n\n abstract scrollUntilTop(startingPoint?: Point): Promise<void>;\n abstract scrollUntilBottom(startingPoint?: Point): Promise<void>;\n abstract scrollUntilLeft(startingPoint?: Point): Promise<void>;\n abstract scrollUntilRight(startingPoint?: Point): Promise<void>;\n abstract scrollUp(distance?: number, startingPoint?: Point): Promise<void>;\n abstract scrollDown(distance?: number, startingPoint?: Point): Promise<void>;\n abstract scrollLeft(distance?: number, startingPoint?: Point): Promise<void>;\n abstract scrollRight(distance?: number, startingPoint?: Point): Promise<void>;\n abstract longPress(x: number, y: number, duration?: number): Promise<void>;\n abstract swipe(\n from: { x: number; y: number },\n to: { x: number; y: number },\n duration?: number,\n ): Promise<void>;\n abstract pinch(\n centerX: number,\n centerY: number,\n startDistance: number,\n endDistance: number,\n duration?: number,\n ): Promise<void>;\n}\n\nexport function createWebInputPrimitives(\n page: AbstractWebPage,\n): BrowserInputPrimitives {\n return {\n pointer: {\n tap: async ({ x, y }) => {\n await page.mouse.click(x, y, { button: 'left' });\n },\n rightClick: async ({ x, y }) => {\n await page.mouse.click(x, y, { button: 'right' });\n },\n doubleClick: async ({ x, y }) => {\n await page.mouse.click(x, y, { button: 'left', count: 2 });\n },\n hover: async ({ x, y }) => {\n await page.mouse.move(x, y);\n },\n dragAndDrop: async (from, to) => {\n await page.mouse.drag(from, to);\n },\n longPress: async ({ x, y }, opts) => {\n await page.longPress(x, y, opts?.duration);\n },\n },\n keyboard: {\n typeText: async (value, opts) => {\n const element = opts?.target;\n if (element && opts?.replace !== false) {\n await page.clearInput(element as ElementInfo);\n } else if (element) {\n const target = element as ElementInfo;\n await page.mouse.click(target.center[0], target.center[1], {\n button: 'left',\n });\n await page.keyboard.press([{ key: 'End' }]);\n }\n\n if (opts?.focusOnly) {\n return;\n }\n\n await page.keyboard.type(value);\n await page.flushPendingVisualUpdate?.();\n },\n keyboardPress: async (keyName, opts) => {\n const element = opts?.target as\n | { center: [number, number] }\n | undefined;\n if (element) {\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n }\n\n const keys = getKeyCommands(keyName);\n await page.keyboard.press(keys as any);\n await page.flushPendingVisualUpdate?.();\n },\n cursorMove: async (direction, times = 1) => {\n const arrowKey = direction === 'left' ? 'ArrowLeft' : 'ArrowRight';\n for (let i = 0; i < times; i++) {\n await page.keyboard.press([{ key: arrowKey as any }]);\n await sleep(100);\n }\n },\n clearInput: async (target) => {\n await page.clearInput(target as ElementInfo | undefined);\n },\n },\n touch: {\n pinch: async ({ x, y }, opts) => {\n await page.pinch(\n x,\n y,\n opts.startDistance,\n opts.endDistance,\n opts.duration,\n );\n },\n swipe: async (from, to, opts) => {\n await page.swipe(from, to, opts?.duration);\n },\n },\n scroll: {\n scroll: async (param) => {\n const element = param.locate;\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = param?.scrollType;\n if (scrollToEventName === 'scrollToTop') {\n await page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'scrollToBottom') {\n await page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'scrollToRight') {\n await page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'scrollToLeft') {\n await page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'singleAction' || !scrollToEventName) {\n if (param?.direction === 'down' || !param || !param.direction) {\n await page.scrollDown(param?.distance || undefined, startingPoint);\n } else if (param.direction === 'up') {\n await page.scrollUp(param.distance || undefined, startingPoint);\n } else if (param.direction === 'left') {\n await page.scrollLeft(param.distance || undefined, startingPoint);\n } else if (param.direction === 'right') {\n await page.scrollRight(param.distance || undefined, startingPoint);\n } else {\n throw new Error(`Unknown scroll direction: ${param.direction}`);\n }\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(\n param,\n )}`,\n );\n }\n },\n },\n };\n}\n\nexport const commonWebActionsForWebPage = <T extends AbstractWebPage>(\n page: T,\n includeTouchEvents = false,\n): DeviceAction<any>[] => {\n const input = createWebInputPrimitives(page);\n return [\n ...defineActionsFromInputPrimitives(input, {\n size: () => page.size(),\n includeSwipe: includeTouchEvents,\n }),\n\n defineAction<typeof navigateParamSchema, { url: string }>({\n name: 'Navigate',\n description:\n 'Navigate the browser to a specified URL. Opens the URL in the current tab.',\n paramSchema: navigateParamSchema,\n sample: {\n url: 'https://www.example.com',\n },\n call: async (param) => {\n if (!page.navigate) {\n throw new Error(\n 'Navigate operation is not supported on this page type',\n );\n }\n await page.navigate(param.url);\n },\n }),\n\n defineAction({\n name: 'Reload',\n description: 'Reload the current page',\n call: async () => {\n if (!page.reload) {\n throw new Error(\n 'Reload operation is not supported on this page type',\n );\n }\n await page.reload();\n },\n }),\n\n defineAction({\n name: 'GoBack',\n description: 'Navigate back in browser history',\n call: async () => {\n if (!page.goBack) {\n throw new Error(\n 'GoBack operation is not supported on this page type',\n );\n }\n await page.goBack();\n },\n }),\n defineAction({\n name: 'GoForward',\n description: 'Navigate forward in browser history',\n call: async () => {\n if (!page.goForward) {\n throw new Error(\n 'GoForward operation is not supported on this page type',\n );\n }\n await page.goForward();\n },\n }),\n ];\n};\n"],"names":["navigateParamSchema","z","normalizeKeyInputs","value","inputs","Array","result","input","trimmed","normalized","transformed","transformHotkeyInput","getKeyCommands","keys","acc","k","includeMeta","AbstractWebPage","AbstractInterface","x","y","options","deltaX","deltaY","from","to","text","action","element","createWebInputPrimitives","page","opts","target","keyName","direction","times","arrowKey","i","sleep","param","startingPoint","undefined","scrollToEventName","Error","JSON","commonWebActionsForWebPage","includeTouchEvents","defineActionsFromInputPrimitives","defineAction"],"mappings":"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"}
|
|
@@ -115,7 +115,7 @@ class BridgeServer {
|
|
|
115
115
|
(0, shared_utils_namespaceObject.logMsg)('one client connected');
|
|
116
116
|
this.socket = socket;
|
|
117
117
|
const clientVersion = socket.handshake.query.version;
|
|
118
|
-
(0, shared_utils_namespaceObject.logMsg)(`Bridge connected, cli-side version v1.8.
|
|
118
|
+
(0, shared_utils_namespaceObject.logMsg)(`Bridge connected, cli-side version v1.8.1, browser-side version v${clientVersion}`);
|
|
119
119
|
socket.on(external_common_js_namespaceObject.BridgeEvent.CallResponse, (params)=>{
|
|
120
120
|
const id = params.id;
|
|
121
121
|
const response = params.response;
|
|
@@ -139,7 +139,7 @@ class BridgeServer {
|
|
|
139
139
|
setTimeout(()=>{
|
|
140
140
|
this.onConnect?.();
|
|
141
141
|
const payload = {
|
|
142
|
-
version: "1.8.
|
|
142
|
+
version: "1.8.1"
|
|
143
143
|
};
|
|
144
144
|
socket.emit(external_common_js_namespaceObject.BridgeEvent.Connected, payload);
|
|
145
145
|
Promise.resolve().then(()=>{
|
|
@@ -103,7 +103,7 @@ class ExtensionBridgePageBrowserSide extends page_js_default() {
|
|
|
103
103
|
throw new Error('Connection denied by user');
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.8.
|
|
106
|
+
this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.8.1`, 'log');
|
|
107
107
|
}
|
|
108
108
|
async connect() {
|
|
109
109
|
return await this.setupBridgeClient();
|