@godscene/web 1.7.11

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 (129) hide show
  1. package/README.md +7 -0
  2. package/bin/midscene-playground +3 -0
  3. package/bin/midscene-web +2 -0
  4. package/dist/es/bin.mjs +14 -0
  5. package/dist/es/bridge-mode/agent-cli-side.mjs +135 -0
  6. package/dist/es/bridge-mode/browser.mjs +2 -0
  7. package/dist/es/bridge-mode/common.mjs +41 -0
  8. package/dist/es/bridge-mode/index.mjs +4 -0
  9. package/dist/es/bridge-mode/io-client.mjs +99 -0
  10. package/dist/es/bridge-mode/io-server.mjs +218 -0
  11. package/dist/es/bridge-mode/page-browser-side.mjs +119 -0
  12. package/dist/es/cdp-proxy-constants.mjs +7 -0
  13. package/dist/es/cdp-proxy-manager.mjs +217 -0
  14. package/dist/es/cdp-proxy.mjs +151 -0
  15. package/dist/es/cdp-target-store.mjs +26 -0
  16. package/dist/es/chrome-extension/agent.mjs +8 -0
  17. package/dist/es/chrome-extension/cdpInput.mjs +172 -0
  18. package/dist/es/chrome-extension/cdpInput.mjs.LICENSE.txt +5 -0
  19. package/dist/es/chrome-extension/dynamic-scripts.mjs +36 -0
  20. package/dist/es/chrome-extension/index.mjs +5 -0
  21. package/dist/es/chrome-extension/page.mjs +733 -0
  22. package/dist/es/cli-options.mjs +97 -0
  23. package/dist/es/cli.mjs +26 -0
  24. package/dist/es/common/cache-helper.mjs +26 -0
  25. package/dist/es/common/viewport.mjs +36 -0
  26. package/dist/es/index.mjs +8 -0
  27. package/dist/es/mcp-server.mjs +33 -0
  28. package/dist/es/mcp-tools-cdp.mjs +164 -0
  29. package/dist/es/mcp-tools-puppeteer.mjs +246 -0
  30. package/dist/es/mcp-tools.mjs +81 -0
  31. package/dist/es/platform.mjs +37 -0
  32. package/dist/es/playwright/ai-fixture.mjs +364 -0
  33. package/dist/es/playwright/index.mjs +36 -0
  34. package/dist/es/playwright/page.mjs +42 -0
  35. package/dist/es/playwright/reporter/index.mjs +178 -0
  36. package/dist/es/puppeteer/agent-launcher.mjs +172 -0
  37. package/dist/es/puppeteer/base-page.mjs +830 -0
  38. package/dist/es/puppeteer/index.mjs +35 -0
  39. package/dist/es/puppeteer/page.mjs +7 -0
  40. package/dist/es/static/index.mjs +3 -0
  41. package/dist/es/static/static-agent.mjs +10 -0
  42. package/dist/es/static/static-page.mjs +123 -0
  43. package/dist/es/utils.mjs +6 -0
  44. package/dist/es/web-element.mjs +57 -0
  45. package/dist/es/web-page.mjs +272 -0
  46. package/dist/lib/bin.js +20 -0
  47. package/dist/lib/bridge-mode/agent-cli-side.js +172 -0
  48. package/dist/lib/bridge-mode/browser.js +36 -0
  49. package/dist/lib/bridge-mode/common.js +105 -0
  50. package/dist/lib/bridge-mode/index.js +44 -0
  51. package/dist/lib/bridge-mode/io-client.js +133 -0
  52. package/dist/lib/bridge-mode/io-server.js +255 -0
  53. package/dist/lib/bridge-mode/page-browser-side.js +163 -0
  54. package/dist/lib/cdp-proxy-constants.js +50 -0
  55. package/dist/lib/cdp-proxy-manager.js +273 -0
  56. package/dist/lib/cdp-proxy.js +179 -0
  57. package/dist/lib/cdp-target-store.js +66 -0
  58. package/dist/lib/chrome-extension/agent.js +42 -0
  59. package/dist/lib/chrome-extension/cdpInput.js +206 -0
  60. package/dist/lib/chrome-extension/cdpInput.js.LICENSE.txt +5 -0
  61. package/dist/lib/chrome-extension/dynamic-scripts.js +86 -0
  62. package/dist/lib/chrome-extension/index.js +58 -0
  63. package/dist/lib/chrome-extension/page.js +767 -0
  64. package/dist/lib/cli-options.js +131 -0
  65. package/dist/lib/cli.js +54 -0
  66. package/dist/lib/common/cache-helper.js +66 -0
  67. package/dist/lib/common/viewport.js +88 -0
  68. package/dist/lib/index.js +66 -0
  69. package/dist/lib/mcp-server.js +73 -0
  70. package/dist/lib/mcp-tools-cdp.js +208 -0
  71. package/dist/lib/mcp-tools-puppeteer.js +296 -0
  72. package/dist/lib/mcp-tools.js +115 -0
  73. package/dist/lib/platform.js +71 -0
  74. package/dist/lib/playwright/ai-fixture.js +401 -0
  75. package/dist/lib/playwright/index.js +89 -0
  76. package/dist/lib/playwright/page.js +76 -0
  77. package/dist/lib/playwright/reporter/index.js +212 -0
  78. package/dist/lib/puppeteer/agent-launcher.js +240 -0
  79. package/dist/lib/puppeteer/base-page.js +876 -0
  80. package/dist/lib/puppeteer/index.js +85 -0
  81. package/dist/lib/puppeteer/page.js +41 -0
  82. package/dist/lib/static/index.js +50 -0
  83. package/dist/lib/static/static-agent.js +44 -0
  84. package/dist/lib/static/static-page.js +157 -0
  85. package/dist/lib/utils.js +38 -0
  86. package/dist/lib/web-element.js +94 -0
  87. package/dist/lib/web-page.js +322 -0
  88. package/dist/types/bin.d.ts +1 -0
  89. package/dist/types/bridge-mode/agent-cli-side.d.ts +49 -0
  90. package/dist/types/bridge-mode/browser.d.ts +2 -0
  91. package/dist/types/bridge-mode/common.d.ts +74 -0
  92. package/dist/types/bridge-mode/index.d.ts +4 -0
  93. package/dist/types/bridge-mode/io-client.d.ts +10 -0
  94. package/dist/types/bridge-mode/io-server.d.ts +27 -0
  95. package/dist/types/bridge-mode/page-browser-side.d.ts +21 -0
  96. package/dist/types/cdp-proxy-constants.d.ts +4 -0
  97. package/dist/types/cdp-proxy-manager.d.ts +53 -0
  98. package/dist/types/cdp-proxy.d.ts +37 -0
  99. package/dist/types/cdp-target-store.d.ts +26 -0
  100. package/dist/types/chrome-extension/agent.d.ts +4 -0
  101. package/dist/types/chrome-extension/cdpInput.d.ts +52 -0
  102. package/dist/types/chrome-extension/dynamic-scripts.d.ts +3 -0
  103. package/dist/types/chrome-extension/index.d.ts +5 -0
  104. package/dist/types/chrome-extension/page.d.ts +120 -0
  105. package/dist/types/cli-options.d.ts +8 -0
  106. package/dist/types/cli.d.ts +1 -0
  107. package/dist/types/common/cache-helper.d.ts +20 -0
  108. package/dist/types/common/viewport.d.ts +17 -0
  109. package/dist/types/index.d.ts +9 -0
  110. package/dist/types/mcp-server.d.ts +26 -0
  111. package/dist/types/mcp-tools-cdp.d.ts +23 -0
  112. package/dist/types/mcp-tools-puppeteer.d.ts +23 -0
  113. package/dist/types/mcp-tools.d.ts +14 -0
  114. package/dist/types/platform.d.ts +10 -0
  115. package/dist/types/playwright/ai-fixture.d.ts +133 -0
  116. package/dist/types/playwright/index.d.ts +13 -0
  117. package/dist/types/playwright/page.d.ts +11 -0
  118. package/dist/types/playwright/reporter/index.d.ts +28 -0
  119. package/dist/types/puppeteer/agent-launcher.d.ts +59 -0
  120. package/dist/types/puppeteer/base-page.d.ts +123 -0
  121. package/dist/types/puppeteer/index.d.ts +11 -0
  122. package/dist/types/puppeteer/page.d.ts +6 -0
  123. package/dist/types/static/index.d.ts +2 -0
  124. package/dist/types/static/static-agent.d.ts +5 -0
  125. package/dist/types/static/static-page.d.ts +46 -0
  126. package/dist/types/utils.d.ts +6 -0
  127. package/dist/types/web-element.d.ts +48 -0
  128. package/dist/types/web-page.d.ts +69 -0
  129. package/package.json +173 -0
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ commonWebActionsForWebPage: ()=>commonWebActionsForWebPage,
37
+ getKeyCommands: ()=>getKeyCommands,
38
+ AbstractWebPage: ()=>AbstractWebPage
39
+ });
40
+ const external_node_assert_namespaceObject = require("node:assert");
41
+ var external_node_assert_default = /*#__PURE__*/ __webpack_require__.n(external_node_assert_namespaceObject);
42
+ const core_namespaceObject = require("@godscene/core");
43
+ const device_namespaceObject = require("@godscene/core/device");
44
+ const utils_namespaceObject = require("@godscene/core/utils");
45
+ const logger_namespaceObject = require("@godscene/shared/logger");
46
+ const us_keyboard_layout_namespaceObject = require("@godscene/shared/us-keyboard-layout");
47
+ const debug = (0, logger_namespaceObject.getDebug)('web:page');
48
+ const navigateParamSchema = core_namespaceObject.z.object({
49
+ url: core_namespaceObject.z.string().describe('The URL to navigate to. Must start with https://, file://, or a similar protocol.')
50
+ });
51
+ function normalizeKeyInputs(value) {
52
+ const inputs = Array.isArray(value) ? value : [
53
+ value
54
+ ];
55
+ const result = [];
56
+ for (const input of inputs){
57
+ if ('string' != typeof input) {
58
+ result.push(input);
59
+ continue;
60
+ }
61
+ const trimmed = input.trim();
62
+ if (!trimmed) {
63
+ result.push(input);
64
+ continue;
65
+ }
66
+ let normalized = trimmed;
67
+ if (normalized.length > 1 && normalized.includes('+')) normalized = normalized.replace(/\s*\+\s*/g, ' ');
68
+ if (/\s/.test(normalized)) normalized = normalized.replace(/\s+/g, ' ');
69
+ const transformed = (0, us_keyboard_layout_namespaceObject.transformHotkeyInput)(normalized);
70
+ if (1 === transformed.length && '' === transformed[0] && '' !== trimmed) {
71
+ result.push(input);
72
+ continue;
73
+ }
74
+ if (0 === transformed.length) {
75
+ result.push(input);
76
+ continue;
77
+ }
78
+ result.push(...transformed);
79
+ }
80
+ return result;
81
+ }
82
+ function getKeyCommands(value) {
83
+ const keys = normalizeKeyInputs(value);
84
+ return keys.reduce((acc, k)=>{
85
+ const includeMeta = keys.includes('Meta') || keys.includes('Control');
86
+ if (includeMeta && ('a' === k || 'A' === k)) return acc.concat([
87
+ {
88
+ key: k,
89
+ command: 'SelectAll'
90
+ }
91
+ ]);
92
+ if (includeMeta && ('c' === k || 'C' === k)) return acc.concat([
93
+ {
94
+ key: k,
95
+ command: 'Copy'
96
+ }
97
+ ]);
98
+ if (includeMeta && ('v' === k || 'V' === k)) return acc.concat([
99
+ {
100
+ key: k,
101
+ command: 'Paste'
102
+ }
103
+ ]);
104
+ return acc.concat([
105
+ {
106
+ key: k
107
+ }
108
+ ]);
109
+ }, []);
110
+ }
111
+ class AbstractWebPage extends device_namespaceObject.AbstractInterface {
112
+ get mouse() {
113
+ return {
114
+ click: async (x, y, options)=>{},
115
+ wheel: async (deltaX, deltaY)=>{},
116
+ move: async (x, y)=>{},
117
+ drag: async (from, to)=>{}
118
+ };
119
+ }
120
+ get keyboard() {
121
+ return {
122
+ type: async (text)=>{},
123
+ press: async (action)=>{}
124
+ };
125
+ }
126
+ async clearInput(element) {}
127
+ }
128
+ const commonWebActionsForWebPage = (page, includeTouchEvents = false)=>[
129
+ (0, device_namespaceObject.defineActionTap)(async (param)=>{
130
+ const element = param.locate;
131
+ external_node_assert_default()(element, 'Element not found, cannot tap');
132
+ await page.mouse.click(element.center[0], element.center[1], {
133
+ button: 'left'
134
+ });
135
+ }),
136
+ (0, device_namespaceObject.defineActionRightClick)(async (param)=>{
137
+ const element = param.locate;
138
+ external_node_assert_default()(element, 'Element not found, cannot right click');
139
+ await page.mouse.click(element.center[0], element.center[1], {
140
+ button: 'right'
141
+ });
142
+ }),
143
+ (0, device_namespaceObject.defineActionDoubleClick)(async (param)=>{
144
+ const element = param.locate;
145
+ external_node_assert_default()(element, 'Element not found, cannot double click');
146
+ await page.mouse.click(element.center[0], element.center[1], {
147
+ button: 'left',
148
+ count: 2
149
+ });
150
+ }),
151
+ (0, device_namespaceObject.defineActionHover)(async (param)=>{
152
+ const element = param.locate;
153
+ external_node_assert_default()(element, 'Element not found, cannot hover');
154
+ await page.mouse.move(element.center[0], element.center[1]);
155
+ }),
156
+ (0, device_namespaceObject.defineActionInput)(async (param)=>{
157
+ const element = param.locate;
158
+ if (element && 'typeOnly' !== param.mode) await page.clearInput(element);
159
+ else if (element && 'typeOnly' === param.mode) {
160
+ await page.mouse.click(element.center[0], element.center[1], {
161
+ button: 'left'
162
+ });
163
+ await page.keyboard.press([
164
+ {
165
+ key: 'End'
166
+ }
167
+ ]);
168
+ }
169
+ if ('clear' === param.mode) return;
170
+ if (!param || !param.value) return;
171
+ await page.keyboard.type(param.value);
172
+ await page.flushPendingVisualUpdate?.();
173
+ }),
174
+ (0, device_namespaceObject.defineActionKeyboardPress)(async (param)=>{
175
+ const element = param.locate;
176
+ if (element) await page.mouse.click(element.center[0], element.center[1], {
177
+ button: 'left'
178
+ });
179
+ const keys = getKeyCommands(param.keyName);
180
+ await page.keyboard.press(keys);
181
+ await page.flushPendingVisualUpdate?.();
182
+ }),
183
+ (0, device_namespaceObject.defineActionCursorMove)(async (param)=>{
184
+ const arrowKey = 'left' === param.direction ? 'ArrowLeft' : 'ArrowRight';
185
+ const times = param.times ?? 1;
186
+ for(let i = 0; i < times; i++){
187
+ await page.keyboard.press([
188
+ {
189
+ key: arrowKey
190
+ }
191
+ ]);
192
+ await (0, utils_namespaceObject.sleep)(100);
193
+ }
194
+ }),
195
+ (0, device_namespaceObject.defineActionScroll)(async (param)=>{
196
+ const element = param.locate;
197
+ const startingPoint = element ? {
198
+ left: element.center[0],
199
+ top: element.center[1]
200
+ } : void 0;
201
+ const scrollToEventName = param?.scrollType;
202
+ if ('scrollToTop' === scrollToEventName) await page.scrollUntilTop(startingPoint);
203
+ else if ('scrollToBottom' === scrollToEventName) await page.scrollUntilBottom(startingPoint);
204
+ else if ('scrollToRight' === scrollToEventName) await page.scrollUntilRight(startingPoint);
205
+ else if ('scrollToLeft' === scrollToEventName) await page.scrollUntilLeft(startingPoint);
206
+ else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
207
+ else {
208
+ if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await page.scrollUp(param.distance || void 0, startingPoint);
209
+ else if ('left' === param.direction) await page.scrollLeft(param.distance || void 0, startingPoint);
210
+ else if ('right' === param.direction) await page.scrollRight(param.distance || void 0, startingPoint);
211
+ else throw new Error(`Unknown scroll direction: ${param.direction}`);
212
+ else await page.scrollDown(param?.distance || void 0, startingPoint);
213
+ await (0, utils_namespaceObject.sleep)(500);
214
+ }
215
+ }),
216
+ (0, device_namespaceObject.defineActionDragAndDrop)(async (param)=>{
217
+ const from = param.from;
218
+ const to = param.to;
219
+ external_node_assert_default()(from, 'missing "from" param for drag and drop');
220
+ external_node_assert_default()(to, 'missing "to" param for drag and drop');
221
+ await page.mouse.drag({
222
+ x: from.center[0],
223
+ y: from.center[1]
224
+ }, {
225
+ x: to.center[0],
226
+ y: to.center[1]
227
+ });
228
+ }),
229
+ (0, device_namespaceObject.defineActionLongPress)(async (param)=>{
230
+ const element = param.locate;
231
+ external_node_assert_default()(element, 'Element not found, cannot long press');
232
+ const duration = param?.duration;
233
+ await page.longPress(element.center[0], element.center[1], duration);
234
+ }),
235
+ (0, device_namespaceObject.defineActionPinch)(async (param)=>{
236
+ const { centerX, centerY, startDistance, endDistance, duration } = (0, device_namespaceObject.normalizePinchParam)(param, await page.size());
237
+ await page.pinch(centerX, centerY, startDistance, endDistance, duration);
238
+ }),
239
+ ...includeTouchEvents ? [
240
+ (0, device_namespaceObject.defineActionSwipe)(async (param)=>{
241
+ const { width, height } = await page.size();
242
+ const { start, end } = param;
243
+ const startPoint = start ? {
244
+ x: start.center[0],
245
+ y: start.center[1]
246
+ } : {
247
+ x: width / 2,
248
+ y: height / 2
249
+ };
250
+ let endPoint;
251
+ if (end) endPoint = {
252
+ x: end.center[0],
253
+ y: end.center[1]
254
+ };
255
+ else if (param.distance) {
256
+ const direction = param.direction;
257
+ if (!direction) throw new Error('direction is required for swipe gesture');
258
+ endPoint = {
259
+ x: startPoint.x + ('right' === direction ? param.distance : 'left' === direction ? -param.distance : 0),
260
+ y: startPoint.y + ('down' === direction ? param.distance : 'up' === direction ? -param.distance : 0)
261
+ };
262
+ } else throw new Error('Either end or distance must be specified for swipe gesture');
263
+ endPoint.x = Math.max(0, Math.min(endPoint.x, width));
264
+ endPoint.y = Math.max(0, Math.min(endPoint.y, height));
265
+ const duration = param.duration;
266
+ debug(`swipe from ${startPoint.x}, ${startPoint.y} to ${endPoint.x}, ${endPoint.y} with duration ${duration}ms, repeat is set to ${param.repeat}`);
267
+ let repeat = 'number' == typeof param.repeat ? param.repeat : 1;
268
+ if (0 === repeat) repeat = 10;
269
+ for(let i = 0; i < repeat; i++)await page.swipe(startPoint, endPoint, duration);
270
+ })
271
+ ] : [],
272
+ (0, device_namespaceObject.defineActionClearInput)(async (param)=>{
273
+ await page.clearInput(param.locate);
274
+ }),
275
+ (0, device_namespaceObject.defineAction)({
276
+ name: 'Navigate',
277
+ description: 'Navigate the browser to a specified URL. Opens the URL in the current tab.',
278
+ paramSchema: navigateParamSchema,
279
+ sample: {
280
+ url: 'https://www.example.com'
281
+ },
282
+ call: async (param)=>{
283
+ if (!page.navigate) throw new Error('Navigate operation is not supported on this page type');
284
+ await page.navigate(param.url);
285
+ }
286
+ }),
287
+ (0, device_namespaceObject.defineAction)({
288
+ name: 'Reload',
289
+ description: 'Reload the current page',
290
+ call: async ()=>{
291
+ if (!page.reload) throw new Error('Reload operation is not supported on this page type');
292
+ await page.reload();
293
+ }
294
+ }),
295
+ (0, device_namespaceObject.defineAction)({
296
+ name: 'GoBack',
297
+ description: 'Navigate back in browser history',
298
+ call: async ()=>{
299
+ if (!page.goBack) throw new Error('GoBack operation is not supported on this page type');
300
+ await page.goBack();
301
+ }
302
+ }),
303
+ (0, device_namespaceObject.defineAction)({
304
+ name: 'GoForward',
305
+ description: 'Navigate forward in browser history',
306
+ call: async ()=>{
307
+ if (!page.goForward) throw new Error('GoForward operation is not supported on this page type');
308
+ await page.goForward();
309
+ }
310
+ })
311
+ ];
312
+ exports.AbstractWebPage = __webpack_exports__.AbstractWebPage;
313
+ exports.commonWebActionsForWebPage = __webpack_exports__.commonWebActionsForWebPage;
314
+ exports.getKeyCommands = __webpack_exports__.getKeyCommands;
315
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
316
+ "AbstractWebPage",
317
+ "commonWebActionsForWebPage",
318
+ "getKeyCommands"
319
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
320
+ Object.defineProperty(exports, '__esModule', {
321
+ value: true
322
+ });
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1,49 @@
1
+ import { Agent, type AgentOpt } from '@godscene/core/agent';
2
+ import { type BridgeConnectTabOptions } from './common';
3
+ import type { ExtensionBridgePageBrowserSide } from './page-browser-side';
4
+ interface ChromeExtensionPageCliSide extends ExtensionBridgePageBrowserSide {
5
+ showStatusMessage: (message: string) => Promise<void>;
6
+ }
7
+ export declare const getBridgePageInCliSide: (options?: {
8
+ host?: string;
9
+ port?: number;
10
+ timeout?: number | false;
11
+ closeConflictServer?: boolean;
12
+ }) => ChromeExtensionPageCliSide;
13
+ export declare class AgentOverChromeBridge extends Agent<ChromeExtensionPageCliSide> {
14
+ private destroyAfterDisconnectFlag?;
15
+ constructor(opts?: AgentOpt & {
16
+ /**
17
+ * Enable remote access to the bridge server.
18
+ * - false (default): Only localhost can connect (most secure)
19
+ * - true: Allow remote machines to connect (binds to 0.0.0.0)
20
+ */
21
+ allowRemoteAccess?: boolean;
22
+ /**
23
+ * Custom host to bind the bridge server to.
24
+ * Overrides allowRemoteAccess if specified.
25
+ */
26
+ host?: string;
27
+ /**
28
+ * Custom port for the bridge server.
29
+ * @default 3766
30
+ */
31
+ port?: number;
32
+ closeNewTabsAfterDisconnect?: boolean;
33
+ serverListeningTimeout?: number | false;
34
+ closeConflictServer?: boolean;
35
+ });
36
+ setDestroyOptionsAfterConnect(): Promise<void>;
37
+ connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions): Promise<void>;
38
+ getBrowserTabList(): Promise<{
39
+ id: string;
40
+ title: string;
41
+ url: string;
42
+ currentActiveTab: boolean;
43
+ }[]>;
44
+ setActiveTabId(tabId: string): Promise<void>;
45
+ connectCurrentTab(options?: BridgeConnectTabOptions): Promise<void>;
46
+ aiAct(prompt: string, options?: any): Promise<string | undefined>;
47
+ destroy(closeNewTabsAfterDisconnect?: boolean): Promise<void>;
48
+ }
49
+ export {};
@@ -0,0 +1,2 @@
1
+ import { ExtensionBridgePageBrowserSide } from '../bridge-mode/page-browser-side';
2
+ export { ExtensionBridgePageBrowserSide };
@@ -0,0 +1,74 @@
1
+ export declare const DefaultBridgeServerHost = "127.0.0.1";
2
+ export declare const DefaultBridgeServerPort = 3766;
3
+ export declare const DefaultLocalEndpoint = "http://127.0.0.1:3766";
4
+ export declare const BridgeCallTimeout = 30000;
5
+ /**
6
+ * Get the server host based on configuration options.
7
+ * Priority: explicit host > allowRemoteAccess > default (127.0.0.1)
8
+ */
9
+ export declare function getBridgeServerHost(options?: {
10
+ host?: string;
11
+ allowRemoteAccess?: boolean;
12
+ }): string;
13
+ export declare enum BridgeEvent {
14
+ Call = "bridge-call",
15
+ CallResponse = "bridge-call-response",
16
+ UpdateAgentStatus = "bridge-update-agent-status",
17
+ Message = "bridge-message",
18
+ Connected = "bridge-connected",
19
+ Refused = "bridge-refused",
20
+ ConnectNewTabWithUrl = "connectNewTabWithUrl",
21
+ ConnectCurrentTab = "connectCurrentTab",
22
+ GetBrowserTabList = "getBrowserTabList",
23
+ SetDestroyOptions = "setDestroyOptions",
24
+ SetActiveTabId = "setActiveTabId"
25
+ }
26
+ export declare const BridgeSignalKill = "MIDSCENE_BRIDGE_SIGNAL_KILL";
27
+ export interface BridgeConnectTabOptions {
28
+ /**
29
+ * If true, the page will always track the active tab.
30
+ * @default true
31
+ */
32
+ forceSameTabNavigation?: boolean;
33
+ /**
34
+ * Custom timeout for connecting to the tab in milliseconds.
35
+ * @default 30000 (30 seconds)
36
+ */
37
+ timeout?: number;
38
+ }
39
+ export declare enum MouseEvent {
40
+ PREFIX = "mouse.",
41
+ Click = "mouse.click",
42
+ Wheel = "mouse.wheel",
43
+ Move = "mouse.move",
44
+ Drag = "mouse.drag"
45
+ }
46
+ export declare enum KeyboardEvent {
47
+ PREFIX = "keyboard.",
48
+ Type = "keyboard.type",
49
+ Press = "keyboard.press"
50
+ }
51
+ export declare const BridgePageType = "page-over-chrome-extension-bridge";
52
+ export declare const BridgeErrorCodeNoClientConnected = "no-client-connected";
53
+ export interface BridgeCall {
54
+ method: string;
55
+ args: any[];
56
+ response: any;
57
+ callTime: number;
58
+ responseTime: number;
59
+ callback: (error: Error | undefined, response: any) => void;
60
+ error?: Error;
61
+ }
62
+ export interface BridgeCallRequest {
63
+ id: string;
64
+ method: string;
65
+ args: any[];
66
+ }
67
+ export interface BridgeCallResponse {
68
+ id: string;
69
+ response: any;
70
+ error?: any;
71
+ }
72
+ export interface BridgeConnectedEventPayload {
73
+ version: string;
74
+ }
@@ -0,0 +1,4 @@
1
+ import { AgentOverChromeBridge } from './agent-cli-side';
2
+ export { AgentOverChromeBridge };
3
+ export { overrideAIConfig } from '@godscene/shared/env';
4
+ export { killRunningServer } from './io-server';
@@ -0,0 +1,10 @@
1
+ export declare class BridgeClient {
2
+ endpoint: string;
3
+ onBridgeCall: (method: string, args: any[]) => Promise<any>;
4
+ onDisconnect?: (() => void) | undefined;
5
+ private socket;
6
+ serverVersion: string | null;
7
+ constructor(endpoint: string, onBridgeCall: (method: string, args: any[]) => Promise<any>, onDisconnect?: (() => void) | undefined);
8
+ connect(): Promise<unknown>;
9
+ disconnect(): void;
10
+ }
@@ -0,0 +1,27 @@
1
+ import { type BridgeCall } from './common';
2
+ export declare const killRunningServer: (port?: number, host?: string) => Promise<void>;
3
+ export declare class BridgeServer {
4
+ host: string;
5
+ port: number;
6
+ onConnect?: (() => void) | undefined;
7
+ onDisconnect?: ((reason: string) => void) | undefined;
8
+ closeConflictServer?: boolean | undefined;
9
+ private callId;
10
+ private io;
11
+ private socket;
12
+ private listeningTimeoutId;
13
+ private listeningTimerFlag;
14
+ private connectionTipTimer;
15
+ calls: Record<string, BridgeCall>;
16
+ private connectionLost;
17
+ private connectionLostReason;
18
+ constructor(host: string, port: number, onConnect?: (() => void) | undefined, onDisconnect?: ((reason: string) => void) | undefined, closeConflictServer?: boolean | undefined);
19
+ listen(opts?: {
20
+ timeout?: number | false;
21
+ }): Promise<void>;
22
+ private connectionLostErrorMsg;
23
+ private triggerCallResponseCallback;
24
+ private emitCall;
25
+ call<T = any>(method: string, args: any[], timeout?: number): Promise<T>;
26
+ close(): Promise<void | undefined>;
27
+ }
@@ -0,0 +1,21 @@
1
+ import ChromeExtensionProxyPage from '../chrome-extension/page';
2
+ import type { ChromePageDestroyOptions } from '../web-page';
3
+ import { type BridgeConnectTabOptions } from './common';
4
+ import { BridgeClient } from './io-client';
5
+ export declare class ExtensionBridgePageBrowserSide extends ChromeExtensionProxyPage {
6
+ serverEndpoint?: string | undefined;
7
+ onDisconnect: () => void;
8
+ onLogMessage: (message: string, type: 'log' | 'status') => void;
9
+ onConnectionRequest?: (() => Promise<boolean>) | undefined;
10
+ bridgeClient: BridgeClient | null;
11
+ private destroyOptions?;
12
+ private newlyCreatedTabIds;
13
+ private confirmationPromise;
14
+ constructor(serverEndpoint?: string | undefined, onDisconnect?: () => void, onLogMessage?: (message: string, type: 'log' | 'status') => void, forceSameTabNavigation?: boolean, onConnectionRequest?: (() => Promise<boolean>) | undefined);
15
+ private setupBridgeClient;
16
+ connect(): Promise<void>;
17
+ connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions): Promise<void>;
18
+ connectCurrentTab(options?: BridgeConnectTabOptions): Promise<void>;
19
+ setDestroyOptions(options: ChromePageDestroyOptions): Promise<void>;
20
+ destroy(): Promise<void>;
21
+ }
@@ -0,0 +1,4 @@
1
+ export declare const PROXY_ENDPOINT_FILE: string;
2
+ export declare const PROXY_PID_FILE: string;
3
+ export declare const PROXY_UPSTREAM_FILE: string;
4
+ export declare const TARGET_ID_FILE: string;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * CDP proxy lifecycle manager (parent-side).
3
+ *
4
+ * Owns everything the CLI needs to start, locate, replace and kill the
5
+ * standalone `cdp-proxy.ts` child process — including its on-disk
6
+ * metadata files (PROXY_ENDPOINT_FILE / PROXY_PID_FILE /
7
+ * PROXY_UPSTREAM_FILE). Also handles auto-resolving page-level CDP URLs
8
+ * to browser-level endpoints via `/json/version`, since puppeteer-core
9
+ * cannot connect to page-level URLs directly.
10
+ *
11
+ * Other modules (notably `mcp-tools-cdp.ts`) use this through the
12
+ * `getProxyEndpoint()` entry point and never touch the metadata files
13
+ * themselves. The cross-command targetId is a separate concern owned by
14
+ * `cdp-target-store.ts`.
15
+ */
16
+ /**
17
+ * True if the previously spawned proxy process is still running.
18
+ */
19
+ export declare function isProxyAlive(): boolean;
20
+ /**
21
+ * The local WebSocket URL the running proxy is serving, or null.
22
+ */
23
+ export declare function readProxyEndpoint(): string | null;
24
+ /**
25
+ * The Chrome endpoint the running proxy is connected to, or null.
26
+ */
27
+ export declare function readProxyUpstream(): string | null;
28
+ /**
29
+ * Stop the running proxy and discard the cross-command targetId.
30
+ *
31
+ * Sends SIGTERM and waits for the proxy's own SIGTERM handler to remove
32
+ * its PROXY_*_FILE metadata via `cleanupIfOwned()`. When the PID file
33
+ * disappears we know the next `spawnProxy()` can safely take over
34
+ * without tripping the duplicate-proxy guard. Falls back to SIGKILL +
35
+ * manual sweep if the proxy is unresponsive within `PROXY_TERM_GRACE_MS`.
36
+ *
37
+ * The targetId file is cleared regardless of the proxy's state because
38
+ * it points into the outgoing Chrome's tab list.
39
+ */
40
+ export declare function killProxy(): Promise<void>;
41
+ /**
42
+ * Resolve the proxy endpoint to use for the given Chrome endpoint.
43
+ *
44
+ * - Page-level URLs are auto-resolved to browser-level via /json/version.
45
+ * - If a proxy is already running and connected to the same upstream,
46
+ * reuse it.
47
+ * - If a proxy is running but pointed at a different upstream, kill it
48
+ * and start a fresh one.
49
+ * - If spawning the proxy fails, fall back to the raw Chrome endpoint
50
+ * (the caller will hit Chrome's permission popup directly but at
51
+ * least the command does not fail outright).
52
+ */
53
+ export declare function getProxyEndpoint(chromeEndpoint: string): Promise<string>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * CDP WebSocket Proxy — standalone process.
3
+ *
4
+ * Holds a persistent WebSocket connection to Chrome's CDP endpoint and
5
+ * exposes a local WebSocket server. Midscene CLI processes connect to the
6
+ * proxy instead of Chrome directly, so Chrome's "Allow remote debugging"
7
+ * permission popup only fires once (when the proxy connects).
8
+ *
9
+ * Lifecycle notes:
10
+ * - When all downstream clients disconnect the proxy stays running but
11
+ * marks the upstream as needing reconnection. The actual reconnect is
12
+ * deferred to the moment the next client connects, so Chrome's CDP
13
+ * state (notably Target.setDiscoverTargets) is reset and the new
14
+ * client receives all targetCreated events.
15
+ * - On startup, if another proxy is already alive the new instance
16
+ * announces "duplicate proxy detected" on stderr and exits 0 without
17
+ * touching the existing metadata files.
18
+ *
19
+ * Exit conditions:
20
+ * 1. Upstream Chrome connection closes or errors.
21
+ * 2. No downstream client message for IDLE_TIMEOUT_MS (default 5 min).
22
+ * 3. SIGTERM / SIGINT.
23
+ * 4. Duplicate proxy detected on startup (exits 0 with stderr notice).
24
+ *
25
+ * Usage (spawned by mcp-tools-cdp.ts):
26
+ * node cdp-proxy.js <chrome-ws-endpoint>
27
+ *
28
+ * On startup, prints the proxy endpoint to stdout as a single JSON line:
29
+ * {"endpoint":"ws://127.0.0.1:<port>/devtools/browser"}
30
+ * and writes:
31
+ * - PROXY_ENDPOINT_FILE — the local proxy URL above
32
+ * - PROXY_PID_FILE — this process's pid
33
+ * - PROXY_UPSTREAM_FILE — the Chrome endpoint the proxy is connected to,
34
+ * so callers can detect when the requested
35
+ * upstream has changed and replace the proxy.
36
+ */
37
+ export {};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Persistent store for the CDP-mode "current tab" targetId.
3
+ *
4
+ * The Midscene CLI runs each command as a fresh Node process, so anything
5
+ * the previous command knew about which tab was being driven must survive
6
+ * across processes. This store writes the chosen targetId to a temp file
7
+ * after `connect`/`act`/etc. succeed, and the next command reads it back
8
+ * to bind to the exact same tab — even when Chrome holds 14 of them.
9
+ *
10
+ * Owns nothing else. The CDP proxy lifecycle and its own metadata files
11
+ * live in `cdp-proxy-manager.ts`.
12
+ */
13
+ /**
14
+ * Read the saved targetId, or null if no command has stored one yet.
15
+ */
16
+ export declare function readSavedTargetId(): string | null;
17
+ /**
18
+ * Save a targetId so the next CLI command can rebind to the same tab.
19
+ */
20
+ export declare function saveTargetId(targetId: string): void;
21
+ /**
22
+ * Discard the saved targetId — call when disconnecting or when the
23
+ * upstream Chrome changes (the targetId would point into the old
24
+ * browser's tab list).
25
+ */
26
+ export declare function cleanupTargetIdFile(): void;
@@ -0,0 +1,4 @@
1
+ import { Agent as PageAgent } from '@godscene/core/agent';
2
+ export declare class ChromeExtensionProxyPageAgent extends PageAgent {
3
+ protected isRetryableContextError(error: unknown): boolean;
4
+ }