@rpascene/web 0.30.8

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.
Files changed (135) hide show
  1. package/README.md +9 -0
  2. package/bin/midscene-playground +3 -0
  3. package/dist/es/bin.mjs +26 -0
  4. package/dist/es/bin.mjs.map +1 -0
  5. package/dist/es/bridge-mode/agent-cli-side.mjs +117 -0
  6. package/dist/es/bridge-mode/agent-cli-side.mjs.map +1 -0
  7. package/dist/es/bridge-mode/browser.mjs +2 -0
  8. package/dist/es/bridge-mode/common.mjs +37 -0
  9. package/dist/es/bridge-mode/common.mjs.map +1 -0
  10. package/dist/es/bridge-mode/index.mjs +4 -0
  11. package/dist/es/bridge-mode/io-client.mjs +101 -0
  12. package/dist/es/bridge-mode/io-client.mjs.map +1 -0
  13. package/dist/es/bridge-mode/io-server.mjs +208 -0
  14. package/dist/es/bridge-mode/io-server.mjs.map +1 -0
  15. package/dist/es/bridge-mode/page-browser-side.mjs +103 -0
  16. package/dist/es/bridge-mode/page-browser-side.mjs.map +1 -0
  17. package/dist/es/chrome-extension/agent.mjs +9 -0
  18. package/dist/es/chrome-extension/agent.mjs.map +1 -0
  19. package/dist/es/chrome-extension/cdpInput.mjs +174 -0
  20. package/dist/es/chrome-extension/cdpInput.mjs.LICENSE.txt +5 -0
  21. package/dist/es/chrome-extension/cdpInput.mjs.map +1 -0
  22. package/dist/es/chrome-extension/dynamic-scripts.mjs +37 -0
  23. package/dist/es/chrome-extension/dynamic-scripts.mjs.map +1 -0
  24. package/dist/es/chrome-extension/index.mjs +5 -0
  25. package/dist/es/chrome-extension/page.mjs +633 -0
  26. package/dist/es/chrome-extension/page.mjs.map +1 -0
  27. package/dist/es/index.mjs +6 -0
  28. package/dist/es/playwright/ai-fixture.mjs +325 -0
  29. package/dist/es/playwright/ai-fixture.mjs.map +1 -0
  30. package/dist/es/playwright/index.mjs +23 -0
  31. package/dist/es/playwright/index.mjs.map +1 -0
  32. package/dist/es/playwright/page.mjs +9 -0
  33. package/dist/es/playwright/page.mjs.map +1 -0
  34. package/dist/es/playwright/reporter/index.mjs +90 -0
  35. package/dist/es/playwright/reporter/index.mjs.map +1 -0
  36. package/dist/es/puppeteer/agent-launcher.mjs +132 -0
  37. package/dist/es/puppeteer/agent-launcher.mjs.map +1 -0
  38. package/dist/es/puppeteer/base-page.mjs +491 -0
  39. package/dist/es/puppeteer/base-page.mjs.map +1 -0
  40. package/dist/es/puppeteer/index.mjs +17 -0
  41. package/dist/es/puppeteer/index.mjs.map +1 -0
  42. package/dist/es/puppeteer/page.mjs +9 -0
  43. package/dist/es/puppeteer/page.mjs.map +1 -0
  44. package/dist/es/static/index.mjs +3 -0
  45. package/dist/es/static/static-agent.mjs +10 -0
  46. package/dist/es/static/static-agent.mjs.map +1 -0
  47. package/dist/es/static/static-page.mjs +132 -0
  48. package/dist/es/static/static-page.mjs.map +1 -0
  49. package/dist/es/web-element.mjs +96 -0
  50. package/dist/es/web-element.mjs.map +1 -0
  51. package/dist/es/web-page.mjs +206 -0
  52. package/dist/es/web-page.mjs.map +1 -0
  53. package/dist/lib/bin.js +54 -0
  54. package/dist/lib/bin.js.map +1 -0
  55. package/dist/lib/bridge-mode/agent-cli-side.js +154 -0
  56. package/dist/lib/bridge-mode/agent-cli-side.js.map +1 -0
  57. package/dist/lib/bridge-mode/browser.js +38 -0
  58. package/dist/lib/bridge-mode/browser.js.map +1 -0
  59. package/dist/lib/bridge-mode/common.js +95 -0
  60. package/dist/lib/bridge-mode/common.js.map +1 -0
  61. package/dist/lib/bridge-mode/index.js +46 -0
  62. package/dist/lib/bridge-mode/index.js.map +1 -0
  63. package/dist/lib/bridge-mode/io-client.js +135 -0
  64. package/dist/lib/bridge-mode/io-client.js.map +1 -0
  65. package/dist/lib/bridge-mode/io-server.js +245 -0
  66. package/dist/lib/bridge-mode/io-server.js.map +1 -0
  67. package/dist/lib/bridge-mode/page-browser-side.js +147 -0
  68. package/dist/lib/bridge-mode/page-browser-side.js.map +1 -0
  69. package/dist/lib/chrome-extension/agent.js +43 -0
  70. package/dist/lib/chrome-extension/agent.js.map +1 -0
  71. package/dist/lib/chrome-extension/cdpInput.js +208 -0
  72. package/dist/lib/chrome-extension/cdpInput.js.LICENSE.txt +5 -0
  73. package/dist/lib/chrome-extension/cdpInput.js.map +1 -0
  74. package/dist/lib/chrome-extension/dynamic-scripts.js +77 -0
  75. package/dist/lib/chrome-extension/dynamic-scripts.js.map +1 -0
  76. package/dist/lib/chrome-extension/index.js +60 -0
  77. package/dist/lib/chrome-extension/index.js.map +1 -0
  78. package/dist/lib/chrome-extension/page.js +667 -0
  79. package/dist/lib/chrome-extension/page.js.map +1 -0
  80. package/dist/lib/index.js +60 -0
  81. package/dist/lib/index.js.map +1 -0
  82. package/dist/lib/playwright/ai-fixture.js +362 -0
  83. package/dist/lib/playwright/ai-fixture.js.map +1 -0
  84. package/dist/lib/playwright/index.js +66 -0
  85. package/dist/lib/playwright/index.js.map +1 -0
  86. package/dist/lib/playwright/page.js +43 -0
  87. package/dist/lib/playwright/page.js.map +1 -0
  88. package/dist/lib/playwright/reporter/index.js +124 -0
  89. package/dist/lib/playwright/reporter/index.js.map +1 -0
  90. package/dist/lib/puppeteer/agent-launcher.js +194 -0
  91. package/dist/lib/puppeteer/agent-launcher.js.map +1 -0
  92. package/dist/lib/puppeteer/base-page.js +531 -0
  93. package/dist/lib/puppeteer/base-page.js.map +1 -0
  94. package/dist/lib/puppeteer/index.js +57 -0
  95. package/dist/lib/puppeteer/index.js.map +1 -0
  96. package/dist/lib/puppeteer/page.js +43 -0
  97. package/dist/lib/puppeteer/page.js.map +1 -0
  98. package/dist/lib/static/index.js +52 -0
  99. package/dist/lib/static/index.js.map +1 -0
  100. package/dist/lib/static/static-agent.js +44 -0
  101. package/dist/lib/static/static-agent.js.map +1 -0
  102. package/dist/lib/static/static-page.js +166 -0
  103. package/dist/lib/static/static-page.js.map +1 -0
  104. package/dist/lib/web-element.js +136 -0
  105. package/dist/lib/web-element.js.map +1 -0
  106. package/dist/lib/web-page.js +256 -0
  107. package/dist/lib/web-page.js.map +1 -0
  108. package/dist/types/bin.d.ts +1 -0
  109. package/dist/types/bridge-mode/agent-cli-side.d.ts +32 -0
  110. package/dist/types/bridge-mode/browser.d.ts +2 -0
  111. package/dist/types/bridge-mode/common.d.ts +60 -0
  112. package/dist/types/bridge-mode/index.d.ts +4 -0
  113. package/dist/types/bridge-mode/io-client.d.ts +10 -0
  114. package/dist/types/bridge-mode/io-server.d.ts +26 -0
  115. package/dist/types/bridge-mode/page-browser-side.d.ts +18 -0
  116. package/dist/types/chrome-extension/agent.d.ts +5 -0
  117. package/dist/types/chrome-extension/cdpInput.d.ts +52 -0
  118. package/dist/types/chrome-extension/dynamic-scripts.d.ts +3 -0
  119. package/dist/types/chrome-extension/index.d.ts +5 -0
  120. package/dist/types/chrome-extension/page.d.ts +95 -0
  121. package/dist/types/index.d.ts +9 -0
  122. package/dist/types/playwright/ai-fixture.d.ts +117 -0
  123. package/dist/types/playwright/index.d.ts +12 -0
  124. package/dist/types/playwright/page.d.ts +6 -0
  125. package/dist/types/playwright/reporter/index.d.ts +18 -0
  126. package/dist/types/puppeteer/agent-launcher.d.ts +29 -0
  127. package/dist/types/puppeteer/base-page.d.ts +90 -0
  128. package/dist/types/puppeteer/index.d.ts +9 -0
  129. package/dist/types/puppeteer/page.d.ts +6 -0
  130. package/dist/types/static/index.d.ts +2 -0
  131. package/dist/types/static/static-agent.d.ts +5 -0
  132. package/dist/types/static/static-page.d.ts +52 -0
  133. package/dist/types/web-element.d.ts +51 -0
  134. package/dist/types/web-page.d.ts +59 -0
  135. package/package.json +164 -0
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ ## Documentation
2
+
3
+ Automate UI actions, extract data, and perform assertions using AI. It offers JavaScript SDK, Chrome extension, and support for scripting in YAML.
4
+
5
+ See https://rpascenejs.com/ for details.
6
+
7
+ ## License
8
+
9
+ Rpascene is MIT licensed.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../dist/lib/bin.js');
@@ -0,0 +1,26 @@
1
+ import { PlaygroundServer } from "@rpascene/playground";
2
+ import cors from "cors";
3
+ import { StaticPage, StaticPageAgent } from "./static/index.mjs";
4
+ import "dotenv/config";
5
+ const page = new StaticPage({
6
+ tree: {
7
+ node: null,
8
+ children: []
9
+ },
10
+ size: {
11
+ width: 800,
12
+ height: 600
13
+ },
14
+ screenshotBase64: ''
15
+ });
16
+ const agent = new StaticPageAgent(page);
17
+ const server = new PlaygroundServer(agent);
18
+ server.app.use(cors({
19
+ origin: '*',
20
+ credentials: true
21
+ }));
22
+ Promise.resolve().then(()=>server.launch()).then(()=>{
23
+ console.log(`Rpascene playground server is running on http://localhost:${server.port}`);
24
+ });
25
+
26
+ //# sourceMappingURL=bin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.mjs","sources":["webpack://@rpascene/web/./src/bin.ts"],"sourcesContent":["import { PlaygroundServer } from '@rpascene/playground';\nimport cors from 'cors';\nimport { StaticPage, StaticPageAgent } from './static';\nimport 'dotenv/config';\n\n// Create page and agent instances with minimal valid data\nconst page = new StaticPage({\n tree: {\n node: null,\n children: [],\n },\n size: { width: 800, height: 600 },\n screenshotBase64: '',\n});\nconst agent = new StaticPageAgent(page);\n\n// Create server with agent only\nconst server = new PlaygroundServer(agent);\n\n// Register CORS middleware\nserver.app.use(\n cors({\n origin: '*',\n credentials: true,\n }),\n);\n\nPromise.resolve()\n .then(() => server.launch())\n .then(() => {\n console.log(\n `Rpascene playground server is running on http://localhost:${server.port}`,\n );\n });\n"],"names":["page","StaticPage","agent","StaticPageAgent","server","PlaygroundServer","cors","Promise","console"],"mappings":";;;;AAMA,MAAMA,OAAO,IAAIC,WAAW;IAC1B,MAAM;QACJ,MAAM;QACN,UAAU,EAAE;IACd;IACA,MAAM;QAAE,OAAO;QAAK,QAAQ;IAAI;IAChC,kBAAkB;AACpB;AACA,MAAMC,QAAQ,IAAIC,gBAAgBH;AAGlC,MAAMI,SAAS,IAAIC,iBAAiBH;AAGpCE,OAAO,GAAG,CAAC,GAAG,CACZE,KAAK;IACH,QAAQ;IACR,aAAa;AACf;AAGFC,QAAQ,OAAO,GACZ,IAAI,CAAC,IAAMH,OAAO,MAAM,IACxB,IAAI,CAAC;IACJI,QAAQ,GAAG,CACT,CAAC,0DAA0D,EAAEJ,OAAO,IAAI,EAAE;AAE9E"}
@@ -0,0 +1,117 @@
1
+ import { Agent } from "@rpascene/core/agent";
2
+ import { assert } from "@rpascene/shared/utils";
3
+ import { commonWebActionsForWebPage } from "../web-page.mjs";
4
+ import { BridgeEvent, BridgePageType, DefaultBridgeServerPort, KeyboardEvent, MouseEvent } 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 = (timeout, closeConflictServer)=>{
18
+ const server = new BridgeServer(DefaultBridgeServerPort, void 0, void 0, closeConflictServer);
19
+ server.listen({
20
+ timeout
21
+ });
22
+ const bridgeCaller = (method)=>async (...args)=>{
23
+ const response = await server.call(method, args);
24
+ return response;
25
+ };
26
+ const page = {
27
+ showStatusMessage: async (message)=>{
28
+ await server.call(BridgeEvent.UpdateAgentStatus, [
29
+ message
30
+ ]);
31
+ }
32
+ };
33
+ const proxyPage = new Proxy(page, {
34
+ get (target, prop, receiver) {
35
+ assert('string' == typeof prop, 'prop must be a string');
36
+ if ('toJSON' === prop) return ()=>({
37
+ interfaceType: BridgePageType
38
+ });
39
+ if ('getContext' === prop) return;
40
+ if ('interfaceType' === prop) return BridgePageType;
41
+ if ('actionSpace' === prop) return ()=>commonWebActionsForWebPage(proxyPage);
42
+ if (Object.keys(page).includes(prop)) return page[prop];
43
+ if ('mouse' === prop) {
44
+ const mouse = {
45
+ click: bridgeCaller(MouseEvent.Click),
46
+ wheel: bridgeCaller(MouseEvent.Wheel),
47
+ move: bridgeCaller(MouseEvent.Move),
48
+ drag: bridgeCaller(MouseEvent.Drag)
49
+ };
50
+ return mouse;
51
+ }
52
+ if ('keyboard' === prop) {
53
+ const keyboard = {
54
+ type: bridgeCaller(KeyboardEvent.Type),
55
+ press: bridgeCaller(KeyboardEvent.Press)
56
+ };
57
+ return keyboard;
58
+ }
59
+ if ('destroy' === prop) return async (...args)=>{
60
+ try {
61
+ const caller = bridgeCaller('destroy');
62
+ await caller(...args);
63
+ } catch (e) {}
64
+ return server.close();
65
+ };
66
+ return bridgeCaller(prop);
67
+ }
68
+ });
69
+ return proxyPage;
70
+ };
71
+ class AgentOverChromeBridge extends Agent {
72
+ async setDestroyOptionsAfterConnect() {
73
+ if (this.destroyAfterDisconnectFlag) this.page.setDestroyOptions({
74
+ closeTab: true
75
+ });
76
+ }
77
+ async connectNewTabWithUrl(url, options) {
78
+ await this.page.connectNewTabWithUrl(url, options);
79
+ await sleep(500);
80
+ await this.setDestroyOptionsAfterConnect();
81
+ }
82
+ async getBrowserTabList() {
83
+ return await this.page.getBrowserTabList();
84
+ }
85
+ async setActiveTabId(tabId) {
86
+ return await this.page.setActiveTabId(Number.parseInt(tabId));
87
+ }
88
+ async connectCurrentTab(options) {
89
+ await this.page.connectCurrentTab(options);
90
+ await sleep(500);
91
+ await this.setDestroyOptionsAfterConnect();
92
+ }
93
+ async aiAction(prompt, options) {
94
+ if (options) console.warn('the `options` parameter of aiAction is not supported in cli side');
95
+ return await super.aiAction(prompt);
96
+ }
97
+ async destroy(closeNewTabsAfterDisconnect) {
98
+ if ('boolean' == typeof closeNewTabsAfterDisconnect) await this.page.setDestroyOptions({
99
+ closeTab: closeNewTabsAfterDisconnect
100
+ });
101
+ await super.destroy();
102
+ }
103
+ constructor(opts){
104
+ const page = getBridgePageInCliSide(null == opts ? void 0 : opts.serverListeningTimeout);
105
+ const originalOnTaskStartTip = null == opts ? void 0 : opts.onTaskStartTip;
106
+ super(page, Object.assign(opts || {}, {
107
+ onTaskStartTip: (tip)=>{
108
+ this.page.showStatusMessage(tip);
109
+ if (originalOnTaskStartTip) null == originalOnTaskStartTip || originalOnTaskStartTip.call(this, tip);
110
+ }
111
+ })), _define_property(this, "destroyAfterDisconnectFlag", void 0);
112
+ this.destroyAfterDisconnectFlag = null == opts ? void 0 : opts.closeNewTabsAfterDisconnect;
113
+ }
114
+ }
115
+ export { AgentOverChromeBridge, getBridgePageInCliSide };
116
+
117
+ //# sourceMappingURL=agent-cli-side.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-mode\\agent-cli-side.mjs","sources":["webpack://@rpascene/web/./src/bridge-mode/agent-cli-side.ts"],"sourcesContent":["import { Agent, type AgentOpt } from '@rpascene/core/agent';\nimport { assert } from '@rpascene/shared/utils';\nimport { commonWebActionsForWebPage } from '../web-page';\nimport type { KeyboardAction, MouseAction } from '../web-page';\nimport {\n type BridgeConnectTabOptions,\n BridgeEvent,\n BridgePageType,\n DefaultBridgeServerPort,\n KeyboardEvent,\n MouseEvent,\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 = (\n timeout?: number | false,\n closeConflictServer?: boolean,\n): ChromeExtensionPageCliSide => {\n const server = new BridgeServer(\n DefaultBridgeServerPort,\n undefined,\n undefined,\n closeConflictServer,\n );\n server.listen({\n timeout,\n });\n const bridgeCaller = (method: string) => {\n return async (...args: any[]) => {\n const response = await server.call(method, args);\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 === 'getContext') {\n return undefined;\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 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 closeNewTabsAfterDisconnect?: boolean;\n serverListeningTimeout?: number | false;\n closeConflictServer?: boolean;\n },\n ) {\n const page = getBridgePageInCliSide(opts?.serverListeningTimeout);\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 aiAction(prompt: string, options?: any) {\n if (options) {\n console.warn(\n 'the `options` parameter of aiAction is not supported in cli side',\n );\n }\n return await super.aiAction(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","timeout","closeConflictServer","server","BridgeServer","DefaultBridgeServerPort","undefined","bridgeCaller","method","args","response","page","message","BridgeEvent","proxyPage","Proxy","target","prop","receiver","assert","BridgePageType","commonWebActionsForWebPage","Object","mouse","MouseEvent","keyboard","KeyboardEvent","caller","e","AgentOverChromeBridge","Agent","url","options","tabId","Number","prompt","console","closeNewTabsAfterDisconnect","opts","originalOnTaskStartTip","tip"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { ExtensionBridgePageBrowserSide } from "./page-browser-side.mjs";
2
+ export { ExtensionBridgePageBrowserSide };
@@ -0,0 +1,37 @@
1
+ const DefaultBridgeServerPort = 3766;
2
+ const DefaultLocalEndpoint = `http://127.0.0.1:${DefaultBridgeServerPort}`;
3
+ const BridgeCallTimeout = 30000;
4
+ var common_BridgeEvent = /*#__PURE__*/ function(BridgeEvent) {
5
+ BridgeEvent["Call"] = "bridge-call";
6
+ BridgeEvent["CallResponse"] = "bridge-call-response";
7
+ BridgeEvent["UpdateAgentStatus"] = "bridge-update-agent-status";
8
+ BridgeEvent["Message"] = "bridge-message";
9
+ BridgeEvent["Connected"] = "bridge-connected";
10
+ BridgeEvent["Refused"] = "bridge-refused";
11
+ BridgeEvent["ConnectNewTabWithUrl"] = "connectNewTabWithUrl";
12
+ BridgeEvent["ConnectCurrentTab"] = "connectCurrentTab";
13
+ BridgeEvent["GetBrowserTabList"] = "getBrowserTabList";
14
+ BridgeEvent["SetDestroyOptions"] = "setDestroyOptions";
15
+ BridgeEvent["SetActiveTabId"] = "setActiveTabId";
16
+ return BridgeEvent;
17
+ }({});
18
+ const BridgeSignalKill = 'RPASCENE_BRIDGE_SIGNAL_KILL';
19
+ var common_MouseEvent = /*#__PURE__*/ function(MouseEvent) {
20
+ MouseEvent["PREFIX"] = "mouse.";
21
+ MouseEvent["Click"] = "mouse.click";
22
+ MouseEvent["Wheel"] = "mouse.wheel";
23
+ MouseEvent["Move"] = "mouse.move";
24
+ MouseEvent["Drag"] = "mouse.drag";
25
+ return MouseEvent;
26
+ }({});
27
+ var common_KeyboardEvent = /*#__PURE__*/ function(KeyboardEvent) {
28
+ KeyboardEvent["PREFIX"] = "keyboard.";
29
+ KeyboardEvent["Type"] = "keyboard.type";
30
+ KeyboardEvent["Press"] = "keyboard.press";
31
+ return KeyboardEvent;
32
+ }({});
33
+ const BridgePageType = 'page-over-chrome-extension-bridge';
34
+ const BridgeErrorCodeNoClientConnected = 'no-client-connected';
35
+ export { BridgeCallTimeout, BridgeErrorCodeNoClientConnected, common_BridgeEvent as BridgeEvent, BridgePageType, BridgeSignalKill, DefaultBridgeServerPort, DefaultLocalEndpoint, common_KeyboardEvent as KeyboardEvent, common_MouseEvent as MouseEvent };
36
+
37
+ //# sourceMappingURL=common.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-mode\\common.mjs","sources":["webpack://@rpascene/web/./src/bridge-mode/common.ts"],"sourcesContent":["export const DefaultBridgeServerPort = 3766;\nexport const DefaultLocalEndpoint = `http://127.0.0.1:${DefaultBridgeServerPort}`;\nexport const BridgeCallTimeout = 30000;\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 = 'RPASCENE_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\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":["DefaultBridgeServerPort","DefaultLocalEndpoint","BridgeCallTimeout","BridgeEvent","BridgeSignalKill","MouseEvent","KeyboardEvent","BridgePageType","BridgeErrorCodeNoClientConnected"],"mappings":"AAAO,MAAMA,0BAA0B;AAChC,MAAMC,uBAAuB,CAAC,iBAAiB,EAAED,yBAAyB;AAC1E,MAAME,oBAAoB;AAE1B,IAAKC,qBAAWA,WAAAA,GAAAA,SAAXA,WAAW;;;;;;;;;;;;WAAXA;;AAcL,MAAMC,mBAAmB;AAUzB,IAAKC,oBAAUA,WAAAA,GAAAA,SAAVA,UAAU;;;;;;WAAVA;;AAQL,IAAKC,uBAAaA,WAAAA,GAAAA,SAAbA,aAAa;;;;WAAbA;;AAML,MAAMC,iBAAiB;AAEvB,MAAMC,mCAAmC"}
@@ -0,0 +1,4 @@
1
+ import { AgentOverChromeBridge } from "./agent-cli-side.mjs";
2
+ import { overrideAIConfig } from "@rpascene/shared/env";
3
+ import { killRunningServer } from "./io-server.mjs";
4
+ export { AgentOverChromeBridge, killRunningServer, overrideAIConfig };
@@ -0,0 +1,101 @@
1
+ import { assert } from "@rpascene/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
+ this.socket = io(this.endpoint, {
18
+ reconnection: false,
19
+ query: {
20
+ version: "0.30.8"
21
+ }
22
+ });
23
+ const timeout = setTimeout(()=>{
24
+ try {
25
+ var _this_socket, _this_socket1;
26
+ null == (_this_socket = this.socket) || _this_socket.offAny();
27
+ null == (_this_socket1 = this.socket) || _this_socket1.close();
28
+ } catch (e) {
29
+ console.warn('got error when offing socket', e);
30
+ }
31
+ this.socket = null;
32
+ reject(new Error('failed to connect to bridge server after timeout'));
33
+ }, 1000);
34
+ this.socket.on('disconnect', (reason)=>{
35
+ var _this_onDisconnect, _this;
36
+ this.socket = null;
37
+ null == (_this_onDisconnect = (_this = this).onDisconnect) || _this_onDisconnect.call(_this);
38
+ });
39
+ this.socket.on('connect_error', (e)=>{
40
+ console.error('bridge-connect-error', e);
41
+ reject(new Error(e || 'bridge connect error'));
42
+ });
43
+ this.socket.on(BridgeEvent.Connected, (payload)=>{
44
+ clearTimeout(timeout);
45
+ this.serverVersion = (null == payload ? void 0 : payload.version) || 'unknown';
46
+ resolve(this.socket);
47
+ });
48
+ this.socket.on(BridgeEvent.Refused, (e)=>{
49
+ console.error('bridge-refused', e);
50
+ try {
51
+ var _this_socket;
52
+ null == (_this_socket = this.socket) || _this_socket.disconnect();
53
+ } catch (e) {}
54
+ reject(new Error(e || 'bridge refused'));
55
+ });
56
+ this.socket.on(BridgeEvent.Call, (call)=>{
57
+ const id = call.id;
58
+ assert(void 0 !== id, 'call id is required');
59
+ (async ()=>{
60
+ var _this_socket;
61
+ let response;
62
+ try {
63
+ response = await this.onBridgeCall(call.method, call.args);
64
+ } catch (e) {
65
+ var _this_socket1;
66
+ const errorContent = `Error from bridge client when calling, method: ${call.method}, args: ${call.args}, error: ${(null == e ? void 0 : e.message) || e}\n${(null == e ? void 0 : e.stack) || ''}`;
67
+ console.error(errorContent);
68
+ return null == (_this_socket1 = this.socket) ? void 0 : _this_socket1.emit(BridgeEvent.CallResponse, {
69
+ id,
70
+ error: errorContent
71
+ });
72
+ }
73
+ null == (_this_socket = this.socket) || _this_socket.emit(BridgeEvent.CallResponse, {
74
+ id,
75
+ response
76
+ });
77
+ })();
78
+ });
79
+ });
80
+ }
81
+ disconnect() {
82
+ var _this_socket;
83
+ null == (_this_socket = this.socket) || _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":["webpack://@rpascene/web/./src/bridge-mode/io-client.ts"],"sourcesContent":["import { assert } from '@rpascene/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 this.socket = ClientIO(this.endpoint, {\n reconnection: false,\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 }, 1 * 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","ClientIO","__VERSION__","timeout","setTimeout","_this_socket","_this_socket1","e","console","Error","reason","_this","BridgeEvent","payload","clearTimeout","call","id","assert","response","errorContent","endpoint","onBridgeCall","onDisconnect"],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ import { sleep } from "@rpascene/core/utils";
2
+ import { logMsg } from "@rpascene/shared/utils";
3
+ import { Server } from "socket.io";
4
+ import { io } from "socket.io-client";
5
+ import { BridgeCallTimeout, BridgeErrorCodeNoClientConnected, BridgeEvent, BridgeSignalKill, DefaultBridgeServerPort } from "./common.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 killRunningServer = async (port)=>{
17
+ try {
18
+ const client = io(`ws://localhost:${port || DefaultBridgeServerPort}`, {
19
+ query: {
20
+ [BridgeSignalKill]: 1
21
+ }
22
+ });
23
+ await sleep(100);
24
+ await client.close();
25
+ } catch (e) {}
26
+ };
27
+ class BridgeServer {
28
+ async listen(opts = {}) {
29
+ const { timeout = 30000 } = opts;
30
+ if (this.closeConflictServer) await killRunningServer(this.port);
31
+ return new Promise((resolve, reject)=>{
32
+ if (this.listeningTimerFlag) return reject(new Error('already listening'));
33
+ this.listeningTimerFlag = true;
34
+ this.listeningTimeoutId = timeout ? setTimeout(()=>{
35
+ reject(new Error(`no extension connected after ${timeout}ms (${BridgeErrorCodeNoClientConnected})`));
36
+ }, timeout) : null;
37
+ this.connectionTipTimer = !timeout || timeout > 3000 ? setTimeout(()=>{
38
+ logMsg('waiting for bridge to connect...');
39
+ }, 2000) : null;
40
+ this.io = new Server(this.port, {
41
+ maxHttpBufferSize: 104857600
42
+ });
43
+ this.io.httpServer.once('listening', ()=>{
44
+ resolve();
45
+ });
46
+ this.io.httpServer.once('error', (err)=>{
47
+ reject(new Error(`Bridge Listening Error: ${err.message}`));
48
+ });
49
+ this.io.use((socket, next)=>{
50
+ if (this.socket) next(new Error('server already connected by another client'));
51
+ next();
52
+ });
53
+ this.io.on('connection', (socket)=>{
54
+ const url = socket.handshake.url;
55
+ if (url.includes(BridgeSignalKill)) {
56
+ console.warn('kill signal received, closing bridge server');
57
+ return this.close();
58
+ }
59
+ this.connectionLost = false;
60
+ this.connectionLostReason = '';
61
+ this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);
62
+ this.listeningTimeoutId = null;
63
+ this.connectionTipTimer && clearTimeout(this.connectionTipTimer);
64
+ this.connectionTipTimer = null;
65
+ if (this.socket) {
66
+ socket.emit(BridgeEvent.Refused);
67
+ socket.disconnect();
68
+ return reject(new Error('server already connected by another client'));
69
+ }
70
+ try {
71
+ logMsg('one client connected');
72
+ this.socket = socket;
73
+ const clientVersion = socket.handshake.query.version;
74
+ logMsg(`Bridge connected, cli-side version v0.30.8, browser-side version v${clientVersion}`);
75
+ socket.on(BridgeEvent.CallResponse, (params)=>{
76
+ const id = params.id;
77
+ const response = params.response;
78
+ const error = params.error;
79
+ this.triggerCallResponseCallback(id, error, response);
80
+ });
81
+ socket.on('disconnect', (reason)=>{
82
+ var _this_onDisconnect, _this;
83
+ this.connectionLost = true;
84
+ this.connectionLostReason = reason;
85
+ try {
86
+ var _this_io;
87
+ null == (_this_io = this.io) || _this_io.close();
88
+ } catch (e) {}
89
+ for(const id in this.calls){
90
+ const call = this.calls[id];
91
+ if (!call.responseTime) {
92
+ const errorMessage = this.connectionLostErrorMsg();
93
+ this.triggerCallResponseCallback(id, new Error(errorMessage), null);
94
+ }
95
+ }
96
+ null == (_this_onDisconnect = (_this = this).onDisconnect) || _this_onDisconnect.call(_this, reason);
97
+ });
98
+ setTimeout(()=>{
99
+ var _this_onConnect, _this;
100
+ null == (_this_onConnect = (_this = this).onConnect) || _this_onConnect.call(_this);
101
+ const payload = {
102
+ version: "0.30.8"
103
+ };
104
+ socket.emit(BridgeEvent.Connected, payload);
105
+ Promise.resolve().then(()=>{
106
+ for(const id in this.calls)if (0 === this.calls[id].callTime) this.emitCall(id);
107
+ });
108
+ }, 0);
109
+ } catch (e) {
110
+ console.error('failed to handle connection event', e);
111
+ reject(e);
112
+ }
113
+ });
114
+ this.io.on('close', ()=>{
115
+ this.close();
116
+ });
117
+ });
118
+ }
119
+ async triggerCallResponseCallback(id, error, response) {
120
+ const call = this.calls[id];
121
+ if (!call) throw new Error(`call ${id} not found`);
122
+ call.error = error || void 0;
123
+ call.response = response;
124
+ call.responseTime = Date.now();
125
+ call.callback(call.error, response);
126
+ }
127
+ async emitCall(id) {
128
+ const call = this.calls[id];
129
+ if (!call) throw new Error(`call ${id} not found`);
130
+ if (this.connectionLost) {
131
+ const message = `Connection lost, reason: ${this.connectionLostReason}`;
132
+ call.callback(new Error(message), null);
133
+ return;
134
+ }
135
+ if (this.socket) {
136
+ this.socket.emit(BridgeEvent.Call, {
137
+ id,
138
+ method: call.method,
139
+ args: call.args
140
+ });
141
+ call.callTime = Date.now();
142
+ }
143
+ }
144
+ async call(method, args, timeout = BridgeCallTimeout) {
145
+ const id = `${this.callId++}`;
146
+ return new Promise((resolve, reject)=>{
147
+ const timeoutId = setTimeout(()=>{
148
+ logMsg(`bridge call timeout, id=${id}, method=${method}, args=`, args);
149
+ this.calls[id].error = new Error(`Bridge call timeout after ${timeout}ms: ${method}`);
150
+ reject(this.calls[id].error);
151
+ }, timeout);
152
+ this.calls[id] = {
153
+ method,
154
+ args,
155
+ response: null,
156
+ callTime: 0,
157
+ responseTime: 0,
158
+ callback: (error, response)=>{
159
+ clearTimeout(timeoutId);
160
+ if (error) reject(error);
161
+ else resolve(response);
162
+ }
163
+ };
164
+ this.emitCall(id);
165
+ });
166
+ }
167
+ async close() {
168
+ var _this_io;
169
+ this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);
170
+ this.connectionTipTimer && clearTimeout(this.connectionTipTimer);
171
+ const closeProcess = null == (_this_io = this.io) ? void 0 : _this_io.close();
172
+ this.io = null;
173
+ return closeProcess;
174
+ }
175
+ constructor(port, onConnect, onDisconnect, closeConflictServer){
176
+ _define_property(this, "port", void 0);
177
+ _define_property(this, "onConnect", void 0);
178
+ _define_property(this, "onDisconnect", void 0);
179
+ _define_property(this, "closeConflictServer", void 0);
180
+ _define_property(this, "callId", void 0);
181
+ _define_property(this, "io", void 0);
182
+ _define_property(this, "socket", void 0);
183
+ _define_property(this, "listeningTimeoutId", void 0);
184
+ _define_property(this, "listeningTimerFlag", void 0);
185
+ _define_property(this, "connectionTipTimer", void 0);
186
+ _define_property(this, "calls", void 0);
187
+ _define_property(this, "connectionLost", void 0);
188
+ _define_property(this, "connectionLostReason", void 0);
189
+ _define_property(this, "connectionLostErrorMsg", void 0);
190
+ this.port = port;
191
+ this.onConnect = onConnect;
192
+ this.onDisconnect = onDisconnect;
193
+ this.closeConflictServer = closeConflictServer;
194
+ this.callId = 0;
195
+ this.io = null;
196
+ this.socket = null;
197
+ this.listeningTimeoutId = null;
198
+ this.listeningTimerFlag = false;
199
+ this.connectionTipTimer = null;
200
+ this.calls = {};
201
+ this.connectionLost = false;
202
+ this.connectionLostReason = '';
203
+ this.connectionLostErrorMsg = ()=>`Connection lost, reason: ${this.connectionLostReason}`;
204
+ }
205
+ }
206
+ export { BridgeServer, killRunningServer };
207
+
208
+ //# sourceMappingURL=io-server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-mode\\io-server.mjs","sources":["webpack://@rpascene/web/./src/bridge-mode/io-server.ts"],"sourcesContent":["import { sleep } from '@rpascene/core/utils';\nimport { logMsg } from '@rpascene/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) => {\n try {\n const client = ClientIO(\n `ws://localhost:${port || DefaultBridgeServerPort}`,\n {\n query: {\n [BridgeSignalKill]: 1,\n },\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 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);\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 this.io = new Server(this.port, {\n maxHttpBufferSize: 100 * 1024 * 1024, // 100MB\n });\n\n // Listen for the native HTTP server 'listening' event\n this.io.httpServer.once('listening', () => {\n resolve();\n });\n\n this.io.httpServer.once('error', (err: Error) => {\n reject(new Error(`Bridge Listening Error: ${err.message}`));\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","client","ClientIO","DefaultBridgeServerPort","BridgeSignalKill","sleep","e","BridgeServer","opts","timeout","Promise","resolve","reject","Error","setTimeout","BridgeErrorCodeNoClientConnected","logMsg","Server","err","socket","next","url","console","clearTimeout","BridgeEvent","clientVersion","params","id","response","error","reason","_this","_this_io","call","errorMessage","payload","__VERSION__","undefined","Date","message","method","args","BridgeCallTimeout","timeoutId","closeProcess","onConnect","onDisconnect","closeConflictServer"],"mappings":"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"}