@donggui/web 1.5.5-donggui.3
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/README.md +9 -0
- package/bin/midscene-playground +3 -0
- package/bin/midscene-web +2 -0
- package/dist/es/bin.mjs +23 -0
- package/dist/es/bin.mjs.map +1 -0
- package/dist/es/bridge-mode/agent-cli-side.mjs +137 -0
- package/dist/es/bridge-mode/agent-cli-side.mjs.map +1 -0
- package/dist/es/bridge-mode/browser.mjs +2 -0
- package/dist/es/bridge-mode/common.mjs +43 -0
- package/dist/es/bridge-mode/common.mjs.map +1 -0
- package/dist/es/bridge-mode/index.mjs +4 -0
- package/dist/es/bridge-mode/io-client.mjs +101 -0
- package/dist/es/bridge-mode/io-client.mjs.map +1 -0
- package/dist/es/bridge-mode/io-server.mjs +210 -0
- package/dist/es/bridge-mode/io-server.mjs.map +1 -0
- package/dist/es/bridge-mode/page-browser-side.mjs +118 -0
- package/dist/es/bridge-mode/page-browser-side.mjs.map +1 -0
- package/dist/es/chrome-extension/agent.mjs +9 -0
- package/dist/es/chrome-extension/agent.mjs.map +1 -0
- package/dist/es/chrome-extension/cdpInput.mjs +174 -0
- package/dist/es/chrome-extension/cdpInput.mjs.LICENSE.txt +5 -0
- package/dist/es/chrome-extension/cdpInput.mjs.map +1 -0
- package/dist/es/chrome-extension/dynamic-scripts.mjs +38 -0
- package/dist/es/chrome-extension/dynamic-scripts.mjs.map +1 -0
- package/dist/es/chrome-extension/index.mjs +5 -0
- package/dist/es/chrome-extension/page.mjs +651 -0
- package/dist/es/chrome-extension/page.mjs.map +1 -0
- package/dist/es/cli.mjs +16 -0
- package/dist/es/cli.mjs.map +1 -0
- package/dist/es/common/cache-helper.mjs +28 -0
- package/dist/es/common/cache-helper.mjs.map +1 -0
- package/dist/es/index.mjs +6 -0
- package/dist/es/mcp-server.mjs +35 -0
- package/dist/es/mcp-server.mjs.map +1 -0
- package/dist/es/mcp-tools-puppeteer.mjs +215 -0
- package/dist/es/mcp-tools-puppeteer.mjs.map +1 -0
- package/dist/es/mcp-tools.mjs +78 -0
- package/dist/es/mcp-tools.mjs.map +1 -0
- package/dist/es/playwright/ai-fixture.mjs +367 -0
- package/dist/es/playwright/ai-fixture.mjs.map +1 -0
- package/dist/es/playwright/index.mjs +40 -0
- package/dist/es/playwright/index.mjs.map +1 -0
- package/dist/es/playwright/page.mjs +44 -0
- package/dist/es/playwright/page.mjs.map +1 -0
- package/dist/es/playwright/reporter/index.mjs +216 -0
- package/dist/es/playwright/reporter/index.mjs.map +1 -0
- package/dist/es/puppeteer/agent-launcher.mjs +185 -0
- package/dist/es/puppeteer/agent-launcher.mjs.map +1 -0
- package/dist/es/puppeteer/base-page.mjs +564 -0
- package/dist/es/puppeteer/base-page.mjs.map +1 -0
- package/dist/es/puppeteer/index.mjs +34 -0
- package/dist/es/puppeteer/index.mjs.map +1 -0
- package/dist/es/puppeteer/page.mjs +9 -0
- package/dist/es/puppeteer/page.mjs.map +1 -0
- package/dist/es/static/index.mjs +3 -0
- package/dist/es/static/static-agent.mjs +12 -0
- package/dist/es/static/static-agent.mjs.map +1 -0
- package/dist/es/static/static-page.mjs +122 -0
- package/dist/es/static/static-page.mjs.map +1 -0
- package/dist/es/utils.mjs +8 -0
- package/dist/es/utils.mjs.map +1 -0
- package/dist/es/web-element.mjs +59 -0
- package/dist/es/web-element.mjs.map +1 -0
- package/dist/es/web-page.mjs +260 -0
- package/dist/es/web-page.mjs.map +1 -0
- package/dist/lib/bin.js +29 -0
- package/dist/lib/bin.js.map +1 -0
- package/dist/lib/bridge-mode/agent-cli-side.js +174 -0
- package/dist/lib/bridge-mode/agent-cli-side.js.map +1 -0
- package/dist/lib/bridge-mode/browser.js +38 -0
- package/dist/lib/bridge-mode/browser.js.map +1 -0
- package/dist/lib/bridge-mode/common.js +107 -0
- package/dist/lib/bridge-mode/common.js.map +1 -0
- package/dist/lib/bridge-mode/index.js +46 -0
- package/dist/lib/bridge-mode/index.js.map +1 -0
- package/dist/lib/bridge-mode/io-client.js +135 -0
- package/dist/lib/bridge-mode/io-client.js.map +1 -0
- package/dist/lib/bridge-mode/io-server.js +247 -0
- package/dist/lib/bridge-mode/io-server.js.map +1 -0
- package/dist/lib/bridge-mode/page-browser-side.js +162 -0
- package/dist/lib/bridge-mode/page-browser-side.js.map +1 -0
- package/dist/lib/chrome-extension/agent.js +43 -0
- package/dist/lib/chrome-extension/agent.js.map +1 -0
- package/dist/lib/chrome-extension/cdpInput.js +208 -0
- package/dist/lib/chrome-extension/cdpInput.js.LICENSE.txt +5 -0
- package/dist/lib/chrome-extension/cdpInput.js.map +1 -0
- package/dist/lib/chrome-extension/dynamic-scripts.js +88 -0
- package/dist/lib/chrome-extension/dynamic-scripts.js.map +1 -0
- package/dist/lib/chrome-extension/index.js +60 -0
- package/dist/lib/chrome-extension/index.js.map +1 -0
- package/dist/lib/chrome-extension/page.js +685 -0
- package/dist/lib/chrome-extension/page.js.map +1 -0
- package/dist/lib/cli.js +22 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/common/cache-helper.js +68 -0
- package/dist/lib/common/cache-helper.js.map +1 -0
- package/dist/lib/index.js +60 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/mcp-server.js +75 -0
- package/dist/lib/mcp-server.js.map +1 -0
- package/dist/lib/mcp-tools-puppeteer.js +259 -0
- package/dist/lib/mcp-tools-puppeteer.js.map +1 -0
- package/dist/lib/mcp-tools.js +112 -0
- package/dist/lib/mcp-tools.js.map +1 -0
- package/dist/lib/playwright/ai-fixture.js +404 -0
- package/dist/lib/playwright/ai-fixture.js.map +1 -0
- package/dist/lib/playwright/index.js +93 -0
- package/dist/lib/playwright/index.js.map +1 -0
- package/dist/lib/playwright/page.js +78 -0
- package/dist/lib/playwright/page.js.map +1 -0
- package/dist/lib/playwright/reporter/index.js +250 -0
- package/dist/lib/playwright/reporter/index.js.map +1 -0
- package/dist/lib/puppeteer/agent-launcher.js +253 -0
- package/dist/lib/puppeteer/agent-launcher.js.map +1 -0
- package/dist/lib/puppeteer/base-page.js +607 -0
- package/dist/lib/puppeteer/base-page.js.map +1 -0
- package/dist/lib/puppeteer/index.js +84 -0
- package/dist/lib/puppeteer/index.js.map +1 -0
- package/dist/lib/puppeteer/page.js +43 -0
- package/dist/lib/puppeteer/page.js.map +1 -0
- package/dist/lib/static/index.js +52 -0
- package/dist/lib/static/index.js.map +1 -0
- package/dist/lib/static/static-agent.js +46 -0
- package/dist/lib/static/static-agent.js.map +1 -0
- package/dist/lib/static/static-page.js +156 -0
- package/dist/lib/static/static-page.js.map +1 -0
- package/dist/lib/utils.js +40 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/web-element.js +96 -0
- package/dist/lib/web-element.js.map +1 -0
- package/dist/lib/web-page.js +310 -0
- package/dist/lib/web-page.js.map +1 -0
- package/dist/types/bin.d.ts +1 -0
- package/dist/types/bridge-mode/agent-cli-side.d.ts +49 -0
- package/dist/types/bridge-mode/browser.d.ts +2 -0
- package/dist/types/bridge-mode/common.d.ts +74 -0
- package/dist/types/bridge-mode/index.d.ts +4 -0
- package/dist/types/bridge-mode/io-client.d.ts +10 -0
- package/dist/types/bridge-mode/io-server.d.ts +27 -0
- package/dist/types/bridge-mode/page-browser-side.d.ts +21 -0
- package/dist/types/chrome-extension/agent.d.ts +5 -0
- package/dist/types/chrome-extension/cdpInput.d.ts +52 -0
- package/dist/types/chrome-extension/dynamic-scripts.d.ts +3 -0
- package/dist/types/chrome-extension/index.d.ts +5 -0
- package/dist/types/chrome-extension/page.d.ts +110 -0
- package/dist/types/cli.d.ts +1 -0
- package/dist/types/common/cache-helper.d.ts +20 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/mcp-server.d.ts +26 -0
- package/dist/types/mcp-tools-puppeteer.d.ts +13 -0
- package/dist/types/mcp-tools.d.ts +12 -0
- package/dist/types/playwright/ai-fixture.d.ts +131 -0
- package/dist/types/playwright/index.d.ts +13 -0
- package/dist/types/playwright/page.d.ts +11 -0
- package/dist/types/playwright/reporter/index.d.ts +42 -0
- package/dist/types/puppeteer/agent-launcher.d.ts +61 -0
- package/dist/types/puppeteer/base-page.d.ts +106 -0
- package/dist/types/puppeteer/index.d.ts +10 -0
- package/dist/types/puppeteer/page.d.ts +6 -0
- package/dist/types/static/index.d.ts +2 -0
- package/dist/types/static/static-agent.d.ts +5 -0
- package/dist/types/static/static-page.d.ts +42 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/types/web-element.d.ts +48 -0
- package/dist/types/web-page.d.ts +62 -0
- package/package.json +166 -0
package/README.md
ADDED
package/bin/midscene-web
ADDED
package/dist/es/bin.mjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { playgroundForAgent } from "@midscene/playground";
|
|
2
|
+
import { StaticPage, StaticPageAgent } from "./static/index.mjs";
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import { ScreenshotItem } from "@midscene/core";
|
|
5
|
+
async function startServer() {
|
|
6
|
+
const page = new StaticPage({
|
|
7
|
+
shotSize: {
|
|
8
|
+
width: 800,
|
|
9
|
+
height: 600
|
|
10
|
+
},
|
|
11
|
+
screenshot: ScreenshotItem.create('', Date.now()),
|
|
12
|
+
shrunkShotToLogicalRatio: 1
|
|
13
|
+
});
|
|
14
|
+
const agent = new StaticPageAgent(page);
|
|
15
|
+
const { server } = await playgroundForAgent(agent).launch({
|
|
16
|
+
openBrowser: false,
|
|
17
|
+
verbose: false
|
|
18
|
+
});
|
|
19
|
+
console.log(`Midscene playground server is running on http://localhost:${server.port}`);
|
|
20
|
+
}
|
|
21
|
+
startServer().catch(console.error);
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=bin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.mjs","sources":["../../src/bin.ts"],"sourcesContent":["import { playgroundForAgent } from '@midscene/playground';\nimport { StaticPage, StaticPageAgent } from './static';\nimport 'dotenv/config';\nimport { ScreenshotItem } from '@midscene/core';\n\nasync function startServer() {\n // Create page and agent instances with minimal valid data\n // Use screenshotBase64 field for empty screenshot\n const page = new StaticPage({\n shotSize: { width: 800, height: 600 },\n screenshot: ScreenshotItem.create('', Date.now()),\n shrunkShotToLogicalRatio: 1,\n });\n const agent = new StaticPageAgent(page);\n\n const { server } = await playgroundForAgent(agent).launch({\n openBrowser: false,\n verbose: false,\n });\n console.log(\n `Midscene playground server is running on http://localhost:${server.port}`,\n );\n}\n\nstartServer().catch(console.error);\n"],"names":["startServer","page","StaticPage","ScreenshotItem","Date","agent","StaticPageAgent","server","playgroundForAgent","console"],"mappings":";;;;AAKA,eAAeA;IAGb,MAAMC,OAAO,IAAIC,WAAW;QAC1B,UAAU;YAAE,OAAO;YAAK,QAAQ;QAAI;QACpC,YAAYC,eAAe,MAAM,CAAC,IAAIC,KAAK,GAAG;QAC9C,0BAA0B;IAC5B;IACA,MAAMC,QAAQ,IAAIC,gBAAgBL;IAElC,MAAM,EAAEM,MAAM,EAAE,GAAG,MAAMC,mBAAmBH,OAAO,MAAM,CAAC;QACxD,aAAa;QACb,SAAS;IACX;IACAI,QAAQ,GAAG,CACT,CAAC,0DAA0D,EAAEF,OAAO,IAAI,EAAE;AAE9E;AAEAP,cAAc,KAAK,CAACS,QAAQ,KAAK"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Agent } from "@midscene/core/agent";
|
|
2
|
+
import { assert } from "@midscene/shared/utils";
|
|
3
|
+
import { commonWebActionsForWebPage } from "../web-page.mjs";
|
|
4
|
+
import { BridgeEvent, BridgePageType, DefaultBridgeServerHost, DefaultBridgeServerPort, KeyboardEvent, MouseEvent, getBridgeServerHost } from "./common.mjs";
|
|
5
|
+
import { BridgeServer } from "./io-server.mjs";
|
|
6
|
+
function _define_property(obj, key, value) {
|
|
7
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
8
|
+
value: value,
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true
|
|
12
|
+
});
|
|
13
|
+
else obj[key] = value;
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
const sleep = (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
|
|
17
|
+
const getBridgePageInCliSide = (options)=>{
|
|
18
|
+
const host = options?.host || DefaultBridgeServerHost;
|
|
19
|
+
const port = options?.port || DefaultBridgeServerPort;
|
|
20
|
+
const server = new BridgeServer(host, port, void 0, void 0, options?.closeConflictServer);
|
|
21
|
+
server.listen({
|
|
22
|
+
timeout: options?.timeout
|
|
23
|
+
});
|
|
24
|
+
const bridgeCaller = (method, timeout)=>async (...args)=>{
|
|
25
|
+
const response = await server.call(method, args, timeout);
|
|
26
|
+
return response;
|
|
27
|
+
};
|
|
28
|
+
const page = {
|
|
29
|
+
showStatusMessage: async (message)=>{
|
|
30
|
+
await server.call(BridgeEvent.UpdateAgentStatus, [
|
|
31
|
+
message
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const proxyPage = new Proxy(page, {
|
|
36
|
+
get (target, prop, receiver) {
|
|
37
|
+
assert('string' == typeof prop, 'prop must be a string');
|
|
38
|
+
if ('toJSON' === prop) return ()=>({
|
|
39
|
+
interfaceType: BridgePageType
|
|
40
|
+
});
|
|
41
|
+
if ('interfaceType' === prop) return BridgePageType;
|
|
42
|
+
if ('actionSpace' === prop) return ()=>commonWebActionsForWebPage(proxyPage);
|
|
43
|
+
if (Object.keys(page).includes(prop)) return page[prop];
|
|
44
|
+
if ('mouse' === prop) {
|
|
45
|
+
const mouse = {
|
|
46
|
+
click: bridgeCaller(MouseEvent.Click),
|
|
47
|
+
wheel: bridgeCaller(MouseEvent.Wheel),
|
|
48
|
+
move: bridgeCaller(MouseEvent.Move),
|
|
49
|
+
drag: bridgeCaller(MouseEvent.Drag)
|
|
50
|
+
};
|
|
51
|
+
return mouse;
|
|
52
|
+
}
|
|
53
|
+
if ('keyboard' === prop) {
|
|
54
|
+
const keyboard = {
|
|
55
|
+
type: bridgeCaller(KeyboardEvent.Type),
|
|
56
|
+
press: bridgeCaller(KeyboardEvent.Press)
|
|
57
|
+
};
|
|
58
|
+
return keyboard;
|
|
59
|
+
}
|
|
60
|
+
if ('destroy' === prop) return async (...args)=>{
|
|
61
|
+
try {
|
|
62
|
+
const caller = bridgeCaller('destroy');
|
|
63
|
+
await caller(...args);
|
|
64
|
+
} catch (e) {}
|
|
65
|
+
return server.close();
|
|
66
|
+
};
|
|
67
|
+
if ('connectNewTabWithUrl' === prop) return async (url, options)=>{
|
|
68
|
+
const timeout = options?.timeout;
|
|
69
|
+
const caller = bridgeCaller(prop, timeout);
|
|
70
|
+
return await caller(url, options);
|
|
71
|
+
};
|
|
72
|
+
if ('connectCurrentTab' === prop) return async (options)=>{
|
|
73
|
+
const timeout = options?.timeout;
|
|
74
|
+
const caller = bridgeCaller(prop, timeout);
|
|
75
|
+
return await caller(options);
|
|
76
|
+
};
|
|
77
|
+
return bridgeCaller(prop);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return proxyPage;
|
|
81
|
+
};
|
|
82
|
+
class AgentOverChromeBridge extends Agent {
|
|
83
|
+
async setDestroyOptionsAfterConnect() {
|
|
84
|
+
if (this.destroyAfterDisconnectFlag) this.page.setDestroyOptions({
|
|
85
|
+
closeTab: true
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async connectNewTabWithUrl(url, options) {
|
|
89
|
+
await this.page.connectNewTabWithUrl(url, options);
|
|
90
|
+
await sleep(500);
|
|
91
|
+
await this.setDestroyOptionsAfterConnect();
|
|
92
|
+
}
|
|
93
|
+
async getBrowserTabList() {
|
|
94
|
+
return await this.page.getBrowserTabList();
|
|
95
|
+
}
|
|
96
|
+
async setActiveTabId(tabId) {
|
|
97
|
+
return await this.page.setActiveTabId(Number.parseInt(tabId));
|
|
98
|
+
}
|
|
99
|
+
async connectCurrentTab(options) {
|
|
100
|
+
await this.page.connectCurrentTab(options);
|
|
101
|
+
await sleep(500);
|
|
102
|
+
await this.setDestroyOptionsAfterConnect();
|
|
103
|
+
}
|
|
104
|
+
async aiAct(prompt, options) {
|
|
105
|
+
if (options) console.warn('the `options` parameter of aiAct is not supported in cli side');
|
|
106
|
+
return await super.aiAct(prompt);
|
|
107
|
+
}
|
|
108
|
+
async destroy(closeNewTabsAfterDisconnect) {
|
|
109
|
+
if ('boolean' == typeof closeNewTabsAfterDisconnect) await this.page.setDestroyOptions({
|
|
110
|
+
closeTab: closeNewTabsAfterDisconnect
|
|
111
|
+
});
|
|
112
|
+
await super.destroy();
|
|
113
|
+
}
|
|
114
|
+
constructor(opts){
|
|
115
|
+
const host = getBridgeServerHost({
|
|
116
|
+
host: opts?.host,
|
|
117
|
+
allowRemoteAccess: opts?.allowRemoteAccess
|
|
118
|
+
});
|
|
119
|
+
const page = getBridgePageInCliSide({
|
|
120
|
+
host,
|
|
121
|
+
port: opts?.port,
|
|
122
|
+
timeout: opts?.serverListeningTimeout,
|
|
123
|
+
closeConflictServer: opts?.closeConflictServer
|
|
124
|
+
});
|
|
125
|
+
const originalOnTaskStartTip = opts?.onTaskStartTip;
|
|
126
|
+
super(page, Object.assign(opts || {}, {
|
|
127
|
+
onTaskStartTip: (tip)=>{
|
|
128
|
+
this.page.showStatusMessage(tip);
|
|
129
|
+
if (originalOnTaskStartTip) originalOnTaskStartTip?.call(this, tip);
|
|
130
|
+
}
|
|
131
|
+
})), _define_property(this, "destroyAfterDisconnectFlag", void 0);
|
|
132
|
+
this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export { AgentOverChromeBridge, getBridgePageInCliSide };
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=agent-cli-side.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-mode/agent-cli-side.mjs","sources":["../../../src/bridge-mode/agent-cli-side.ts"],"sourcesContent":["import { Agent, type AgentOpt } from '@midscene/core/agent';\nimport { assert } from '@midscene/shared/utils';\nimport { commonWebActionsForWebPage } from '../web-page';\nimport type { KeyboardAction, MouseAction } from '../web-page';\nimport {\n type BridgeConnectTabOptions,\n BridgeEvent,\n BridgePageType,\n DefaultBridgeServerHost,\n DefaultBridgeServerPort,\n KeyboardEvent,\n MouseEvent,\n getBridgeServerHost,\n} from './common';\nimport { BridgeServer } from './io-server';\nimport type { ExtensionBridgePageBrowserSide } from './page-browser-side';\n\ninterface ChromeExtensionPageCliSide extends ExtensionBridgePageBrowserSide {\n showStatusMessage: (message: string) => Promise<void>;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n// actually, this is a proxy to the page in browser side\nexport const getBridgePageInCliSide = (options?: {\n host?: string;\n port?: number;\n timeout?: number | false;\n closeConflictServer?: boolean;\n}): ChromeExtensionPageCliSide => {\n const host = options?.host || DefaultBridgeServerHost;\n const port = options?.port || DefaultBridgeServerPort;\n const server = new BridgeServer(\n host,\n port,\n undefined,\n undefined,\n options?.closeConflictServer,\n );\n server.listen({\n timeout: options?.timeout,\n });\n const bridgeCaller = (method: string, timeout?: number) => {\n return async (...args: any[]) => {\n const response = await server.call(method, args, timeout);\n return response;\n };\n };\n const page = {\n showStatusMessage: async (message: string) => {\n await server.call(BridgeEvent.UpdateAgentStatus, [message]);\n },\n };\n\n const proxyPage = new Proxy(page, {\n get(target, prop, receiver) {\n assert(typeof prop === 'string', 'prop must be a string');\n\n if (prop === 'toJSON') {\n return () => {\n return {\n interfaceType: BridgePageType,\n };\n };\n }\n\n if (prop === 'interfaceType') {\n return BridgePageType;\n }\n\n if (prop === 'actionSpace') {\n return () => commonWebActionsForWebPage(proxyPage);\n }\n\n if (Object.keys(page).includes(prop)) {\n return page[prop as keyof typeof page];\n }\n\n if (prop === 'mouse') {\n const mouse: MouseAction = {\n click: bridgeCaller(MouseEvent.Click),\n wheel: bridgeCaller(MouseEvent.Wheel),\n move: bridgeCaller(MouseEvent.Move),\n drag: bridgeCaller(MouseEvent.Drag),\n };\n return mouse;\n }\n\n if (prop === 'keyboard') {\n const keyboard: KeyboardAction = {\n type: bridgeCaller(KeyboardEvent.Type),\n press: bridgeCaller(KeyboardEvent.Press),\n };\n return keyboard;\n }\n\n if (prop === 'destroy') {\n return async (...args: any[]) => {\n try {\n const caller = bridgeCaller('destroy');\n await caller(...args);\n } catch (e) {\n // console.error('error calling destroy', e);\n }\n return server.close();\n };\n }\n\n // Special handling for methods that support timeout in options\n if (prop === 'connectNewTabWithUrl') {\n return async (url: string, options?: BridgeConnectTabOptions) => {\n const timeout = options?.timeout;\n const caller = bridgeCaller(prop, timeout);\n return await caller(url, options);\n };\n }\n\n if (prop === 'connectCurrentTab') {\n return async (options?: BridgeConnectTabOptions) => {\n const timeout = options?.timeout;\n const caller = bridgeCaller(prop, timeout);\n return await caller(options);\n };\n }\n\n return bridgeCaller(prop);\n },\n }) as ChromeExtensionPageCliSide;\n\n return proxyPage;\n};\n\nexport class AgentOverChromeBridge extends Agent<ChromeExtensionPageCliSide> {\n private destroyAfterDisconnectFlag?: boolean;\n\n constructor(\n opts?: AgentOpt & {\n /**\n * Enable remote access to the bridge server.\n * - false (default): Only localhost can connect (most secure)\n * - true: Allow remote machines to connect (binds to 0.0.0.0)\n */\n allowRemoteAccess?: boolean;\n /**\n * Custom host to bind the bridge server to.\n * Overrides allowRemoteAccess if specified.\n */\n host?: string;\n /**\n * Custom port for the bridge server.\n * @default 3766\n */\n port?: number;\n closeNewTabsAfterDisconnect?: boolean;\n serverListeningTimeout?: number | false;\n closeConflictServer?: boolean;\n },\n ) {\n const host = getBridgeServerHost({\n host: opts?.host,\n allowRemoteAccess: opts?.allowRemoteAccess,\n });\n const page = getBridgePageInCliSide({\n host,\n port: opts?.port,\n timeout: opts?.serverListeningTimeout,\n closeConflictServer: opts?.closeConflictServer,\n });\n const originalOnTaskStartTip = opts?.onTaskStartTip;\n super(\n page,\n Object.assign(opts || {}, {\n onTaskStartTip: (tip: string) => {\n this.page.showStatusMessage(tip);\n if (originalOnTaskStartTip) {\n originalOnTaskStartTip?.call(this, tip);\n }\n },\n }),\n );\n this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;\n }\n\n async setDestroyOptionsAfterConnect() {\n if (this.destroyAfterDisconnectFlag) {\n this.page.setDestroyOptions({\n closeTab: true,\n });\n }\n }\n\n async connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions) {\n await this.page.connectNewTabWithUrl(url, options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async getBrowserTabList() {\n return await this.page.getBrowserTabList();\n }\n\n async setActiveTabId(tabId: string) {\n return await this.page.setActiveTabId(Number.parseInt(tabId));\n }\n\n async connectCurrentTab(options?: BridgeConnectTabOptions) {\n await this.page.connectCurrentTab(options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async aiAct(prompt: string, options?: any) {\n if (options) {\n console.warn(\n 'the `options` parameter of aiAct is not supported in cli side',\n );\n }\n return await super.aiAct(prompt);\n }\n\n async destroy(closeNewTabsAfterDisconnect?: boolean) {\n if (typeof closeNewTabsAfterDisconnect === 'boolean') {\n await this.page.setDestroyOptions({\n closeTab: closeNewTabsAfterDisconnect,\n });\n }\n await super.destroy();\n }\n}\n"],"names":["sleep","ms","Promise","resolve","setTimeout","getBridgePageInCliSide","options","host","DefaultBridgeServerHost","port","DefaultBridgeServerPort","server","BridgeServer","undefined","bridgeCaller","method","timeout","args","response","page","message","BridgeEvent","proxyPage","Proxy","target","prop","receiver","assert","BridgePageType","commonWebActionsForWebPage","Object","mouse","MouseEvent","keyboard","KeyboardEvent","caller","e","url","AgentOverChromeBridge","Agent","tabId","Number","prompt","console","closeNewTabsAfterDisconnect","opts","getBridgeServerHost","originalOnTaskStartTip","tip"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const DefaultBridgeServerHost = '127.0.0.1';
|
|
2
|
+
const DefaultBridgeServerPort = 3766;
|
|
3
|
+
const DefaultLocalEndpoint = `http://${DefaultBridgeServerHost}:${DefaultBridgeServerPort}`;
|
|
4
|
+
const BridgeCallTimeout = 30000;
|
|
5
|
+
function getBridgeServerHost(options) {
|
|
6
|
+
if (options?.host) return options.host;
|
|
7
|
+
if (options?.allowRemoteAccess) return '0.0.0.0';
|
|
8
|
+
return DefaultBridgeServerHost;
|
|
9
|
+
}
|
|
10
|
+
var common_BridgeEvent = /*#__PURE__*/ function(BridgeEvent) {
|
|
11
|
+
BridgeEvent["Call"] = "bridge-call";
|
|
12
|
+
BridgeEvent["CallResponse"] = "bridge-call-response";
|
|
13
|
+
BridgeEvent["UpdateAgentStatus"] = "bridge-update-agent-status";
|
|
14
|
+
BridgeEvent["Message"] = "bridge-message";
|
|
15
|
+
BridgeEvent["Connected"] = "bridge-connected";
|
|
16
|
+
BridgeEvent["Refused"] = "bridge-refused";
|
|
17
|
+
BridgeEvent["ConnectNewTabWithUrl"] = "connectNewTabWithUrl";
|
|
18
|
+
BridgeEvent["ConnectCurrentTab"] = "connectCurrentTab";
|
|
19
|
+
BridgeEvent["GetBrowserTabList"] = "getBrowserTabList";
|
|
20
|
+
BridgeEvent["SetDestroyOptions"] = "setDestroyOptions";
|
|
21
|
+
BridgeEvent["SetActiveTabId"] = "setActiveTabId";
|
|
22
|
+
return BridgeEvent;
|
|
23
|
+
}({});
|
|
24
|
+
const BridgeSignalKill = 'MIDSCENE_BRIDGE_SIGNAL_KILL';
|
|
25
|
+
var common_MouseEvent = /*#__PURE__*/ function(MouseEvent) {
|
|
26
|
+
MouseEvent["PREFIX"] = "mouse.";
|
|
27
|
+
MouseEvent["Click"] = "mouse.click";
|
|
28
|
+
MouseEvent["Wheel"] = "mouse.wheel";
|
|
29
|
+
MouseEvent["Move"] = "mouse.move";
|
|
30
|
+
MouseEvent["Drag"] = "mouse.drag";
|
|
31
|
+
return MouseEvent;
|
|
32
|
+
}({});
|
|
33
|
+
var common_KeyboardEvent = /*#__PURE__*/ function(KeyboardEvent) {
|
|
34
|
+
KeyboardEvent["PREFIX"] = "keyboard.";
|
|
35
|
+
KeyboardEvent["Type"] = "keyboard.type";
|
|
36
|
+
KeyboardEvent["Press"] = "keyboard.press";
|
|
37
|
+
return KeyboardEvent;
|
|
38
|
+
}({});
|
|
39
|
+
const BridgePageType = 'page-over-chrome-extension-bridge';
|
|
40
|
+
const BridgeErrorCodeNoClientConnected = 'no-client-connected';
|
|
41
|
+
export { BridgeCallTimeout, BridgeErrorCodeNoClientConnected, common_BridgeEvent as BridgeEvent, BridgePageType, BridgeSignalKill, DefaultBridgeServerHost, DefaultBridgeServerPort, DefaultLocalEndpoint, common_KeyboardEvent as KeyboardEvent, common_MouseEvent as MouseEvent, getBridgeServerHost };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=common.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-mode/common.mjs","sources":["../../../src/bridge-mode/common.ts"],"sourcesContent":["export const DefaultBridgeServerHost = '127.0.0.1';\nexport const DefaultBridgeServerPort = 3766;\nexport const DefaultLocalEndpoint = `http://${DefaultBridgeServerHost}:${DefaultBridgeServerPort}`;\nexport const BridgeCallTimeout = 30000;\n\n/**\n * Get the server host based on configuration options.\n * Priority: explicit host > allowRemoteAccess > default (127.0.0.1)\n */\nexport function getBridgeServerHost(options?: {\n host?: string;\n allowRemoteAccess?: boolean;\n}): string {\n if (options?.host) {\n return options.host;\n }\n if (options?.allowRemoteAccess) {\n return '0.0.0.0';\n }\n return DefaultBridgeServerHost;\n}\n\nexport enum BridgeEvent {\n Call = 'bridge-call',\n CallResponse = 'bridge-call-response',\n UpdateAgentStatus = 'bridge-update-agent-status',\n Message = 'bridge-message',\n Connected = 'bridge-connected',\n Refused = 'bridge-refused',\n ConnectNewTabWithUrl = 'connectNewTabWithUrl',\n ConnectCurrentTab = 'connectCurrentTab',\n GetBrowserTabList = 'getBrowserTabList',\n SetDestroyOptions = 'setDestroyOptions',\n SetActiveTabId = 'setActiveTabId',\n}\n\nexport const BridgeSignalKill = 'MIDSCENE_BRIDGE_SIGNAL_KILL';\n\nexport interface BridgeConnectTabOptions {\n /**\n * If true, the page will always track the active tab.\n * @default true\n */\n forceSameTabNavigation?: boolean;\n /**\n * Custom timeout for connecting to the tab in milliseconds.\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n}\n\nexport enum MouseEvent {\n PREFIX = 'mouse.',\n Click = 'mouse.click',\n Wheel = 'mouse.wheel',\n Move = 'mouse.move',\n Drag = 'mouse.drag',\n}\n\nexport enum KeyboardEvent {\n PREFIX = 'keyboard.',\n Type = 'keyboard.type',\n Press = 'keyboard.press',\n}\n\nexport const BridgePageType = 'page-over-chrome-extension-bridge';\n\nexport const BridgeErrorCodeNoClientConnected = 'no-client-connected';\n\nexport interface BridgeCall {\n method: string;\n args: any[];\n response: any;\n callTime: number;\n responseTime: number;\n callback: (error: Error | undefined, response: any) => void;\n error?: Error;\n}\n\nexport interface BridgeCallRequest {\n id: string;\n method: string;\n args: any[];\n}\n\nexport interface BridgeCallResponse {\n id: string;\n response: any;\n error?: any;\n}\n\nexport interface BridgeConnectedEventPayload {\n version: string;\n}\n"],"names":["DefaultBridgeServerHost","DefaultBridgeServerPort","DefaultLocalEndpoint","BridgeCallTimeout","getBridgeServerHost","options","BridgeEvent","BridgeSignalKill","MouseEvent","KeyboardEvent","BridgePageType","BridgeErrorCodeNoClientConnected"],"mappings":"AAAO,MAAMA,0BAA0B;AAChC,MAAMC,0BAA0B;AAChC,MAAMC,uBAAuB,CAAC,OAAO,EAAEF,wBAAwB,CAAC,EAAEC,yBAAyB;AAC3F,MAAME,oBAAoB;AAM1B,SAASC,oBAAoBC,OAGnC;IACC,IAAIA,SAAS,MACX,OAAOA,QAAQ,IAAI;IAErB,IAAIA,SAAS,mBACX,OAAO;IAET,OAAOL;AACT;AAEO,IAAKM,qBAAWA,WAAAA,GAAAA,SAAXA,WAAW;;;;;;;;;;;;WAAXA;;AAcL,MAAMC,mBAAmB;AAezB,IAAKC,oBAAUA,WAAAA,GAAAA,SAAVA,UAAU;;;;;;WAAVA;;AAQL,IAAKC,uBAAaA,WAAAA,GAAAA,SAAbA,aAAa;;;;WAAbA;;AAML,MAAMC,iBAAiB;AAEvB,MAAMC,mCAAmC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { assert } from "@midscene/shared/utils";
|
|
2
|
+
import { io } from "socket.io-client";
|
|
3
|
+
import { BridgeEvent } from "./common.mjs";
|
|
4
|
+
function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
6
|
+
value: value,
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true
|
|
10
|
+
});
|
|
11
|
+
else obj[key] = value;
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
class BridgeClient {
|
|
15
|
+
async connect() {
|
|
16
|
+
return new Promise((resolve, reject)=>{
|
|
17
|
+
const forceWebSocket = 'undefined' == typeof XMLHttpRequest;
|
|
18
|
+
this.socket = io(this.endpoint, {
|
|
19
|
+
reconnection: false,
|
|
20
|
+
...forceWebSocket ? {
|
|
21
|
+
transports: [
|
|
22
|
+
'websocket'
|
|
23
|
+
]
|
|
24
|
+
} : {},
|
|
25
|
+
query: {
|
|
26
|
+
version: "1.5.5-donggui.3"
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const timeout = setTimeout(()=>{
|
|
30
|
+
try {
|
|
31
|
+
this.socket?.offAny();
|
|
32
|
+
this.socket?.close();
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.warn('got error when offing socket', e);
|
|
35
|
+
}
|
|
36
|
+
this.socket = null;
|
|
37
|
+
reject(new Error('failed to connect to bridge server after timeout'));
|
|
38
|
+
}, 5000);
|
|
39
|
+
this.socket.on('disconnect', (reason)=>{
|
|
40
|
+
this.socket = null;
|
|
41
|
+
this.onDisconnect?.();
|
|
42
|
+
});
|
|
43
|
+
this.socket.on('connect_error', (e)=>{
|
|
44
|
+
console.error('bridge-connect-error', e);
|
|
45
|
+
reject(new Error(e || 'bridge connect error'));
|
|
46
|
+
});
|
|
47
|
+
this.socket.on(BridgeEvent.Connected, (payload)=>{
|
|
48
|
+
clearTimeout(timeout);
|
|
49
|
+
this.serverVersion = payload?.version || 'unknown';
|
|
50
|
+
resolve(this.socket);
|
|
51
|
+
});
|
|
52
|
+
this.socket.on(BridgeEvent.Refused, (e)=>{
|
|
53
|
+
console.error('bridge-refused', e);
|
|
54
|
+
try {
|
|
55
|
+
this.socket?.disconnect();
|
|
56
|
+
} catch (e) {}
|
|
57
|
+
reject(new Error(e || 'bridge refused'));
|
|
58
|
+
});
|
|
59
|
+
this.socket.on(BridgeEvent.Call, (call)=>{
|
|
60
|
+
const id = call.id;
|
|
61
|
+
assert(void 0 !== id, 'call id is required');
|
|
62
|
+
(async ()=>{
|
|
63
|
+
let response;
|
|
64
|
+
try {
|
|
65
|
+
response = await this.onBridgeCall(call.method, call.args);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
const errorContent = `Error from bridge client when calling, method: ${call.method}, args: ${call.args}, error: ${e?.message || e}\n${e?.stack || ''}`;
|
|
68
|
+
console.error(errorContent);
|
|
69
|
+
return this.socket?.emit(BridgeEvent.CallResponse, {
|
|
70
|
+
id,
|
|
71
|
+
error: errorContent
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
this.socket?.emit(BridgeEvent.CallResponse, {
|
|
75
|
+
id,
|
|
76
|
+
response
|
|
77
|
+
});
|
|
78
|
+
})();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
disconnect() {
|
|
83
|
+
this.socket?.disconnect();
|
|
84
|
+
this.socket = null;
|
|
85
|
+
}
|
|
86
|
+
constructor(endpoint, onBridgeCall, onDisconnect){
|
|
87
|
+
_define_property(this, "endpoint", void 0);
|
|
88
|
+
_define_property(this, "onBridgeCall", void 0);
|
|
89
|
+
_define_property(this, "onDisconnect", void 0);
|
|
90
|
+
_define_property(this, "socket", void 0);
|
|
91
|
+
_define_property(this, "serverVersion", void 0);
|
|
92
|
+
this.endpoint = endpoint;
|
|
93
|
+
this.onBridgeCall = onBridgeCall;
|
|
94
|
+
this.onDisconnect = onDisconnect;
|
|
95
|
+
this.socket = null;
|
|
96
|
+
this.serverVersion = null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export { BridgeClient };
|
|
100
|
+
|
|
101
|
+
//# sourceMappingURL=io-client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-mode/io-client.mjs","sources":["../../../src/bridge-mode/io-client.ts"],"sourcesContent":["import { assert } from '@midscene/shared/utils';\nimport { io as ClientIO, type Socket as ClientSocket } from 'socket.io-client';\nimport {\n type BridgeCallRequest,\n type BridgeCallResponse,\n type BridgeConnectedEventPayload,\n BridgeEvent,\n} from './common';\n\ndeclare const __VERSION__: string;\n\n// ws client, this is where the request is processed\nexport class BridgeClient {\n private socket: ClientSocket | null = null;\n public serverVersion: string | null = null;\n constructor(\n public endpoint: string,\n public onBridgeCall: (method: string, args: any[]) => Promise<any>,\n public onDisconnect?: () => void,\n ) {}\n\n async connect() {\n return new Promise((resolve, reject) => {\n // Force WebSocket if XMLHttpRequest is not available (e.g., Service Worker)\n const forceWebSocket = typeof XMLHttpRequest === 'undefined';\n\n this.socket = ClientIO(this.endpoint, {\n reconnection: false,\n // Force WebSocket in environments without XHR (Service Worker)\n ...(forceWebSocket ? { transports: ['websocket'] } : {}),\n query: {\n version: __VERSION__,\n },\n });\n\n const timeout = setTimeout(() => {\n try {\n this.socket?.offAny();\n this.socket?.close();\n } catch (e) {\n console.warn('got error when offing socket', e);\n }\n this.socket = null;\n reject(new Error('failed to connect to bridge server after timeout'));\n }, 5 * 1000);\n\n // on disconnect\n this.socket.on('disconnect', (reason: string) => {\n // console.log('bridge-disconnected, reason:', reason);\n this.socket = null;\n this.onDisconnect?.();\n });\n\n this.socket.on('connect_error', (e: any) => {\n console.error('bridge-connect-error', e);\n reject(new Error(e || 'bridge connect error'));\n });\n\n this.socket.on(\n BridgeEvent.Connected,\n (payload: BridgeConnectedEventPayload) => {\n clearTimeout(timeout);\n this.serverVersion = payload?.version || 'unknown';\n resolve(this.socket);\n },\n );\n this.socket.on(BridgeEvent.Refused, (e: any) => {\n console.error('bridge-refused', e);\n try {\n this.socket?.disconnect();\n } catch (e) {\n // console.warn('got error when disconnecting socket', e);\n }\n reject(new Error(e || 'bridge refused'));\n });\n this.socket.on(BridgeEvent.Call, (call: BridgeCallRequest) => {\n const id = call.id;\n assert(typeof id !== 'undefined', 'call id is required');\n (async () => {\n let response: any;\n try {\n response = await this.onBridgeCall(call.method, call.args);\n } catch (e: any) {\n const errorContent = `Error from bridge client when calling, method: ${call.method}, args: ${call.args}, error: ${e?.message || e}\\n${e?.stack || ''}`;\n console.error(errorContent);\n return this.socket?.emit(BridgeEvent.CallResponse, {\n id,\n error: errorContent,\n } as BridgeCallResponse);\n }\n this.socket?.emit(BridgeEvent.CallResponse, {\n id,\n response,\n } as BridgeCallResponse);\n })();\n });\n });\n }\n\n disconnect() {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n"],"names":["BridgeClient","Promise","resolve","reject","forceWebSocket","XMLHttpRequest","ClientIO","__VERSION__","timeout","setTimeout","e","console","Error","reason","BridgeEvent","payload","clearTimeout","call","id","assert","response","errorContent","endpoint","onBridgeCall","onDisconnect"],"mappings":";;;;;;;;;;;;;AAYO,MAAMA;IASX,MAAM,UAAU;QACd,OAAO,IAAIC,QAAQ,CAACC,SAASC;YAE3B,MAAMC,iBAAiB,AAA0B,eAA1B,OAAOC;YAE9B,IAAI,CAAC,MAAM,GAAGC,GAAS,IAAI,CAAC,QAAQ,EAAE;gBACpC,cAAc;gBAEd,GAAIF,iBAAiB;oBAAE,YAAY;wBAAC;qBAAY;gBAAC,IAAI,CAAC,CAAC;gBACvD,OAAO;oBACL,SAASG;gBACX;YACF;YAEA,MAAMC,UAAUC,WAAW;gBACzB,IAAI;oBACF,IAAI,CAAC,MAAM,EAAE;oBACb,IAAI,CAAC,MAAM,EAAE;gBACf,EAAE,OAAOC,GAAG;oBACVC,QAAQ,IAAI,CAAC,gCAAgCD;gBAC/C;gBACA,IAAI,CAAC,MAAM,GAAG;gBACdP,OAAO,IAAIS,MAAM;YACnB,GAAG;YAGH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,CAACC;gBAE5B,IAAI,CAAC,MAAM,GAAG;gBACd,IAAI,CAAC,YAAY;YACnB;YAEA,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,iBAAiB,CAACH;gBAC/BC,QAAQ,KAAK,CAAC,wBAAwBD;gBACtCP,OAAO,IAAIS,MAAMF,KAAK;YACxB;YAEA,IAAI,CAAC,MAAM,CAAC,EAAE,CACZI,YAAY,SAAS,EACrB,CAACC;gBACCC,aAAaR;gBACb,IAAI,CAAC,aAAa,GAAGO,SAAS,WAAW;gBACzCb,QAAQ,IAAI,CAAC,MAAM;YACrB;YAEF,IAAI,CAAC,MAAM,CAAC,EAAE,CAACY,YAAY,OAAO,EAAE,CAACJ;gBACnCC,QAAQ,KAAK,CAAC,kBAAkBD;gBAChC,IAAI;oBACF,IAAI,CAAC,MAAM,EAAE;gBACf,EAAE,OAAOA,GAAG,CAEZ;gBACAP,OAAO,IAAIS,MAAMF,KAAK;YACxB;YACA,IAAI,CAAC,MAAM,CAAC,EAAE,CAACI,YAAY,IAAI,EAAE,CAACG;gBAChC,MAAMC,KAAKD,KAAK,EAAE;gBAClBE,OAAO,AAAc,WAAPD,IAAoB;gBACjC;oBACC,IAAIE;oBACJ,IAAI;wBACFA,WAAW,MAAM,IAAI,CAAC,YAAY,CAACH,KAAK,MAAM,EAAEA,KAAK,IAAI;oBAC3D,EAAE,OAAOP,GAAQ;wBACf,MAAMW,eAAe,CAAC,+CAA+C,EAAEJ,KAAK,MAAM,CAAC,QAAQ,EAAEA,KAAK,IAAI,CAAC,SAAS,EAAEP,GAAG,WAAWA,EAAE,EAAE,EAAEA,GAAG,SAAS,IAAI;wBACtJC,QAAQ,KAAK,CAACU;wBACd,OAAO,IAAI,CAAC,MAAM,EAAE,KAAKP,YAAY,YAAY,EAAE;4BACjDI;4BACA,OAAOG;wBACT;oBACF;oBACA,IAAI,CAAC,MAAM,EAAE,KAAKP,YAAY,YAAY,EAAE;wBAC1CI;wBACAE;oBACF;gBACF;YACF;QACF;IACF;IAEA,aAAa;QACX,IAAI,CAAC,MAAM,EAAE;QACb,IAAI,CAAC,MAAM,GAAG;IAChB;IAvFA,YACSE,QAAgB,EAChBC,YAA2D,EAC3DC,YAAyB,CAChC;;;;QANF,uBAAQ,UAAR;QACA,uBAAO,iBAAP;aAESF,QAAQ,GAARA;aACAC,YAAY,GAAZA;aACAC,YAAY,GAAZA;aALD,MAAM,GAAwB;aAC/B,aAAa,GAAkB;IAKnC;AAoFL"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { sleep } from "@midscene/core/utils";
|
|
3
|
+
import { logMsg } from "@midscene/shared/utils";
|
|
4
|
+
import { Server } from "socket.io";
|
|
5
|
+
import { io } from "socket.io-client";
|
|
6
|
+
import { BridgeCallTimeout, BridgeErrorCodeNoClientConnected, BridgeEvent, BridgeSignalKill, DefaultBridgeServerPort } from "./common.mjs";
|
|
7
|
+
function _define_property(obj, key, value) {
|
|
8
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
9
|
+
value: value,
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true
|
|
13
|
+
});
|
|
14
|
+
else obj[key] = value;
|
|
15
|
+
return obj;
|
|
16
|
+
}
|
|
17
|
+
const killRunningServer = async (port, host = 'localhost')=>{
|
|
18
|
+
try {
|
|
19
|
+
const client = io(`ws://${host}:${port || DefaultBridgeServerPort}`, {
|
|
20
|
+
query: {
|
|
21
|
+
[BridgeSignalKill]: 1
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
await sleep(100);
|
|
25
|
+
await client.close();
|
|
26
|
+
} catch (e) {}
|
|
27
|
+
};
|
|
28
|
+
class BridgeServer {
|
|
29
|
+
async listen(opts = {}) {
|
|
30
|
+
const { timeout = 30000 } = opts;
|
|
31
|
+
if (this.closeConflictServer) await killRunningServer(this.port, this.host);
|
|
32
|
+
return new Promise((resolve, reject)=>{
|
|
33
|
+
if (this.listeningTimerFlag) return reject(new Error('already listening'));
|
|
34
|
+
this.listeningTimerFlag = true;
|
|
35
|
+
this.listeningTimeoutId = timeout ? setTimeout(()=>{
|
|
36
|
+
reject(new Error(`no extension connected after ${timeout}ms (${BridgeErrorCodeNoClientConnected})`));
|
|
37
|
+
}, timeout) : null;
|
|
38
|
+
this.connectionTipTimer = !timeout || timeout > 3000 ? setTimeout(()=>{
|
|
39
|
+
logMsg('waiting for bridge to connect...');
|
|
40
|
+
}, 2000) : null;
|
|
41
|
+
const httpServer = createServer();
|
|
42
|
+
httpServer.once('listening', ()=>{
|
|
43
|
+
resolve();
|
|
44
|
+
});
|
|
45
|
+
httpServer.once('error', (err)=>{
|
|
46
|
+
reject(new Error(`Bridge Listening Error: ${err.message}`));
|
|
47
|
+
});
|
|
48
|
+
if ('127.0.0.1' === this.host) httpServer.listen(this.port);
|
|
49
|
+
else httpServer.listen(this.port, this.host);
|
|
50
|
+
this.io = new Server(httpServer, {
|
|
51
|
+
maxHttpBufferSize: 104857600
|
|
52
|
+
});
|
|
53
|
+
this.io.use((socket, next)=>{
|
|
54
|
+
if (this.socket) next(new Error('server already connected by another client'));
|
|
55
|
+
next();
|
|
56
|
+
});
|
|
57
|
+
this.io.on('connection', (socket)=>{
|
|
58
|
+
const url = socket.handshake.url;
|
|
59
|
+
if (url.includes(BridgeSignalKill)) {
|
|
60
|
+
console.warn('kill signal received, closing bridge server');
|
|
61
|
+
return this.close();
|
|
62
|
+
}
|
|
63
|
+
this.connectionLost = false;
|
|
64
|
+
this.connectionLostReason = '';
|
|
65
|
+
this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);
|
|
66
|
+
this.listeningTimeoutId = null;
|
|
67
|
+
this.connectionTipTimer && clearTimeout(this.connectionTipTimer);
|
|
68
|
+
this.connectionTipTimer = null;
|
|
69
|
+
if (this.socket) {
|
|
70
|
+
socket.emit(BridgeEvent.Refused);
|
|
71
|
+
socket.disconnect();
|
|
72
|
+
return reject(new Error('server already connected by another client'));
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
logMsg('one client connected');
|
|
76
|
+
this.socket = socket;
|
|
77
|
+
const clientVersion = socket.handshake.query.version;
|
|
78
|
+
logMsg(`Bridge connected, cli-side version v1.5.5-donggui.3, browser-side version v${clientVersion}`);
|
|
79
|
+
socket.on(BridgeEvent.CallResponse, (params)=>{
|
|
80
|
+
const id = params.id;
|
|
81
|
+
const response = params.response;
|
|
82
|
+
const error = params.error;
|
|
83
|
+
this.triggerCallResponseCallback(id, error, response);
|
|
84
|
+
});
|
|
85
|
+
socket.on('disconnect', (reason)=>{
|
|
86
|
+
this.connectionLost = true;
|
|
87
|
+
this.connectionLostReason = reason;
|
|
88
|
+
try {
|
|
89
|
+
this.io?.close();
|
|
90
|
+
} catch (e) {}
|
|
91
|
+
for(const id in this.calls){
|
|
92
|
+
const call = this.calls[id];
|
|
93
|
+
if (!call.responseTime) {
|
|
94
|
+
const errorMessage = this.connectionLostErrorMsg();
|
|
95
|
+
this.triggerCallResponseCallback(id, new Error(errorMessage), null);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
this.onDisconnect?.(reason);
|
|
99
|
+
});
|
|
100
|
+
setTimeout(()=>{
|
|
101
|
+
this.onConnect?.();
|
|
102
|
+
const payload = {
|
|
103
|
+
version: "1.5.5-donggui.3"
|
|
104
|
+
};
|
|
105
|
+
socket.emit(BridgeEvent.Connected, payload);
|
|
106
|
+
Promise.resolve().then(()=>{
|
|
107
|
+
for(const id in this.calls)if (0 === this.calls[id].callTime) this.emitCall(id);
|
|
108
|
+
});
|
|
109
|
+
}, 0);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.error('failed to handle connection event', e);
|
|
112
|
+
reject(e);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
this.io.on('close', ()=>{
|
|
116
|
+
this.close();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async triggerCallResponseCallback(id, error, response) {
|
|
121
|
+
const call = this.calls[id];
|
|
122
|
+
if (!call) throw new Error(`call ${id} not found`);
|
|
123
|
+
call.error = error || void 0;
|
|
124
|
+
call.response = response;
|
|
125
|
+
call.responseTime = Date.now();
|
|
126
|
+
call.callback(call.error, response);
|
|
127
|
+
}
|
|
128
|
+
async emitCall(id) {
|
|
129
|
+
const call = this.calls[id];
|
|
130
|
+
if (!call) throw new Error(`call ${id} not found`);
|
|
131
|
+
if (this.connectionLost) {
|
|
132
|
+
const message = `Connection lost, reason: ${this.connectionLostReason}`;
|
|
133
|
+
call.callback(new Error(message), null);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (this.socket) {
|
|
137
|
+
this.socket.emit(BridgeEvent.Call, {
|
|
138
|
+
id,
|
|
139
|
+
method: call.method,
|
|
140
|
+
args: call.args
|
|
141
|
+
});
|
|
142
|
+
call.callTime = Date.now();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async call(method, args, timeout = BridgeCallTimeout) {
|
|
146
|
+
const id = `${this.callId++}`;
|
|
147
|
+
return new Promise((resolve, reject)=>{
|
|
148
|
+
const timeoutId = setTimeout(()=>{
|
|
149
|
+
logMsg(`bridge call timeout, id=${id}, method=${method}, args=`, args);
|
|
150
|
+
this.calls[id].error = new Error(`Bridge call timeout after ${timeout}ms: ${method}`);
|
|
151
|
+
reject(this.calls[id].error);
|
|
152
|
+
}, timeout);
|
|
153
|
+
this.calls[id] = {
|
|
154
|
+
method,
|
|
155
|
+
args,
|
|
156
|
+
response: null,
|
|
157
|
+
callTime: 0,
|
|
158
|
+
responseTime: 0,
|
|
159
|
+
callback: (error, response)=>{
|
|
160
|
+
clearTimeout(timeoutId);
|
|
161
|
+
if (error) reject(error);
|
|
162
|
+
else resolve(response);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
this.emitCall(id);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
async close() {
|
|
169
|
+
this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);
|
|
170
|
+
this.connectionTipTimer && clearTimeout(this.connectionTipTimer);
|
|
171
|
+
const closeProcess = this.io?.close();
|
|
172
|
+
this.io = null;
|
|
173
|
+
return closeProcess;
|
|
174
|
+
}
|
|
175
|
+
constructor(host, port, onConnect, onDisconnect, closeConflictServer){
|
|
176
|
+
_define_property(this, "host", void 0);
|
|
177
|
+
_define_property(this, "port", void 0);
|
|
178
|
+
_define_property(this, "onConnect", void 0);
|
|
179
|
+
_define_property(this, "onDisconnect", void 0);
|
|
180
|
+
_define_property(this, "closeConflictServer", void 0);
|
|
181
|
+
_define_property(this, "callId", void 0);
|
|
182
|
+
_define_property(this, "io", void 0);
|
|
183
|
+
_define_property(this, "socket", void 0);
|
|
184
|
+
_define_property(this, "listeningTimeoutId", void 0);
|
|
185
|
+
_define_property(this, "listeningTimerFlag", void 0);
|
|
186
|
+
_define_property(this, "connectionTipTimer", void 0);
|
|
187
|
+
_define_property(this, "calls", void 0);
|
|
188
|
+
_define_property(this, "connectionLost", void 0);
|
|
189
|
+
_define_property(this, "connectionLostReason", void 0);
|
|
190
|
+
_define_property(this, "connectionLostErrorMsg", void 0);
|
|
191
|
+
this.host = host;
|
|
192
|
+
this.port = port;
|
|
193
|
+
this.onConnect = onConnect;
|
|
194
|
+
this.onDisconnect = onDisconnect;
|
|
195
|
+
this.closeConflictServer = closeConflictServer;
|
|
196
|
+
this.callId = 0;
|
|
197
|
+
this.io = null;
|
|
198
|
+
this.socket = null;
|
|
199
|
+
this.listeningTimeoutId = null;
|
|
200
|
+
this.listeningTimerFlag = false;
|
|
201
|
+
this.connectionTipTimer = null;
|
|
202
|
+
this.calls = {};
|
|
203
|
+
this.connectionLost = false;
|
|
204
|
+
this.connectionLostReason = '';
|
|
205
|
+
this.connectionLostErrorMsg = ()=>`Connection lost, reason: ${this.connectionLostReason}`;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export { BridgeServer, killRunningServer };
|
|
209
|
+
|
|
210
|
+
//# sourceMappingURL=io-server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-mode/io-server.mjs","sources":["../../../src/bridge-mode/io-server.ts"],"sourcesContent":["import { createServer } from 'node:http';\nimport { sleep } from '@midscene/core/utils';\nimport { logMsg } from '@midscene/shared/utils';\nimport { Server, type Socket as ServerSocket } from 'socket.io';\nimport { io as ClientIO } from 'socket.io-client';\n\nimport {\n type BridgeCall,\n type BridgeCallResponse,\n BridgeCallTimeout,\n type BridgeConnectedEventPayload,\n BridgeErrorCodeNoClientConnected,\n BridgeEvent,\n BridgeSignalKill,\n DefaultBridgeServerPort,\n} from './common';\n\ndeclare const __VERSION__: string;\n\nexport const killRunningServer = async (port?: number, host = 'localhost') => {\n try {\n const client = ClientIO(`ws://${host}:${port || DefaultBridgeServerPort}`, {\n query: {\n [BridgeSignalKill]: 1,\n },\n });\n await sleep(100);\n await client.close();\n } catch (e) {\n // console.error('failed to kill port', e);\n }\n};\n\n// ws server, this is where the request is sent\nexport class BridgeServer {\n private callId = 0;\n private io: Server | null = null;\n private socket: ServerSocket | null = null;\n private listeningTimeoutId: NodeJS.Timeout | null = null;\n private listeningTimerFlag = false;\n private connectionTipTimer: NodeJS.Timeout | null = null;\n public calls: Record<string, BridgeCall> = {};\n\n private connectionLost = false;\n private connectionLostReason = '';\n\n constructor(\n public host: string,\n public port: number,\n public onConnect?: () => void,\n public onDisconnect?: (reason: string) => void,\n public closeConflictServer?: boolean,\n ) {}\n\n async listen(\n opts: {\n timeout?: number | false;\n } = {},\n ): Promise<void> {\n const { timeout = 30000 } = opts;\n\n if (this.closeConflictServer) {\n await killRunningServer(this.port, this.host);\n }\n\n return new Promise((resolve, reject) => {\n if (this.listeningTimerFlag) {\n return reject(new Error('already listening'));\n }\n this.listeningTimerFlag = true;\n\n this.listeningTimeoutId = timeout\n ? setTimeout(() => {\n reject(\n new Error(\n `no extension connected after ${timeout}ms (${BridgeErrorCodeNoClientConnected})`,\n ),\n );\n }, timeout)\n : null;\n\n this.connectionTipTimer =\n !timeout || timeout > 3000\n ? setTimeout(() => {\n logMsg('waiting for bridge to connect...');\n }, 2000)\n : null;\n\n // Create HTTP server and start listening on the specified host and port\n const httpServer = createServer();\n\n // Set up HTTP server event listeners FIRST\n httpServer.once('listening', () => {\n resolve();\n });\n\n httpServer.once('error', (err: Error) => {\n reject(new Error(`Bridge Listening Error: ${err.message}`));\n });\n\n // Start listening BEFORE creating Socket.IO Server\n // When host is 127.0.0.1 (default), don't specify host to listen on all local interfaces (IPv4 + IPv6)\n // This ensures localhost resolves correctly in both IPv4 and IPv6 environments\n if (this.host === '127.0.0.1') {\n httpServer.listen(this.port);\n } else {\n httpServer.listen(this.port, this.host);\n }\n\n // Now create Socket.IO Server attached to the already-listening HTTP server\n this.io = new Server(httpServer, {\n maxHttpBufferSize: 100 * 1024 * 1024, // 100MB\n });\n\n this.io.use((socket, next) => {\n if (this.socket) {\n next(new Error('server already connected by another client'));\n }\n next();\n });\n\n this.io.on('connection', (socket) => {\n // check the connection url\n const url = socket.handshake.url;\n if (url.includes(BridgeSignalKill)) {\n console.warn('kill signal received, closing bridge server');\n return this.close();\n }\n\n this.connectionLost = false;\n this.connectionLostReason = '';\n this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);\n this.listeningTimeoutId = null;\n this.connectionTipTimer && clearTimeout(this.connectionTipTimer);\n this.connectionTipTimer = null;\n if (this.socket) {\n socket.emit(BridgeEvent.Refused);\n // close the socket\n socket.disconnect();\n\n return reject(\n new Error('server already connected by another client'),\n );\n }\n\n try {\n logMsg('one client connected');\n this.socket = socket;\n\n const clientVersion = socket.handshake.query.version;\n logMsg(\n `Bridge connected, cli-side version v${__VERSION__}, browser-side version v${clientVersion}`,\n );\n\n socket.on(BridgeEvent.CallResponse, (params: BridgeCallResponse) => {\n const id = params.id;\n const response = params.response;\n const error = params.error;\n\n this.triggerCallResponseCallback(id, error, response);\n });\n\n socket.on('disconnect', (reason: string) => {\n this.connectionLost = true;\n this.connectionLostReason = reason;\n\n try {\n this.io?.close();\n } catch (e) {\n // ignore\n }\n\n // flush all pending calls as error\n for (const id in this.calls) {\n const call = this.calls[id];\n\n if (!call.responseTime) {\n const errorMessage = this.connectionLostErrorMsg();\n this.triggerCallResponseCallback(\n id,\n new Error(errorMessage),\n null,\n );\n }\n }\n\n this.onDisconnect?.(reason);\n });\n\n setTimeout(() => {\n this.onConnect?.();\n\n const payload = {\n version: __VERSION__,\n } as BridgeConnectedEventPayload;\n socket.emit(BridgeEvent.Connected, payload);\n Promise.resolve().then(() => {\n for (const id in this.calls) {\n if (this.calls[id].callTime === 0) {\n this.emitCall(id);\n }\n }\n });\n }, 0);\n } catch (e) {\n console.error('failed to handle connection event', e);\n reject(e);\n }\n });\n\n this.io.on('close', () => {\n this.close();\n });\n });\n }\n\n private connectionLostErrorMsg = () => {\n return `Connection lost, reason: ${this.connectionLostReason}`;\n };\n\n private async triggerCallResponseCallback(\n id: string | number,\n error: Error | null,\n response: any,\n ) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n call.error = error || undefined;\n call.response = response;\n call.responseTime = Date.now();\n\n call.callback(call.error, response);\n }\n\n private async emitCall(id: string) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n\n if (this.connectionLost) {\n const message = `Connection lost, reason: ${this.connectionLostReason}`;\n call.callback(new Error(message), null);\n return;\n }\n\n if (this.socket) {\n this.socket.emit(BridgeEvent.Call, {\n id,\n method: call.method,\n args: call.args,\n });\n call.callTime = Date.now();\n }\n }\n\n async call<T = any>(\n method: string,\n args: any[],\n timeout = BridgeCallTimeout,\n ): Promise<T> {\n const id = `${this.callId++}`;\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n logMsg(`bridge call timeout, id=${id}, method=${method}, args=`, args);\n this.calls[id].error = new Error(\n `Bridge call timeout after ${timeout}ms: ${method}`,\n );\n reject(this.calls[id].error);\n }, timeout);\n\n this.calls[id] = {\n method,\n args,\n response: null,\n callTime: 0,\n responseTime: 0,\n callback: (error: Error | undefined, response: any) => {\n clearTimeout(timeoutId);\n if (error) {\n reject(error);\n } else {\n resolve(response);\n }\n },\n };\n\n this.emitCall(id);\n });\n }\n\n // do NOT restart after close\n async close() {\n this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);\n this.connectionTipTimer && clearTimeout(this.connectionTipTimer);\n const closeProcess = this.io?.close();\n this.io = null;\n\n return closeProcess;\n }\n}\n"],"names":["killRunningServer","port","host","client","ClientIO","DefaultBridgeServerPort","BridgeSignalKill","sleep","e","BridgeServer","opts","timeout","Promise","resolve","reject","Error","setTimeout","BridgeErrorCodeNoClientConnected","logMsg","httpServer","createServer","err","Server","socket","next","url","console","clearTimeout","BridgeEvent","clientVersion","params","id","response","error","reason","call","errorMessage","payload","__VERSION__","undefined","Date","message","method","args","BridgeCallTimeout","timeoutId","closeProcess","onConnect","onDisconnect","closeConflictServer"],"mappings":"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"}
|