@midscene/web 1.10.4-beta-20260715034325.0 → 1.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/cli.mjs CHANGED
@@ -18,7 +18,7 @@ Promise.resolve().then(()=>{
18
18
  return runToolsCLI(tools, 'midscene-web', {
19
19
  stripPrefix: 'web_',
20
20
  argv: parsedOptions.argv,
21
- version: "1.10.4-beta-20260715034325.0",
21
+ version: "1.10.4",
22
22
  extraCommands: createReportCliCommands()
23
23
  });
24
24
  }).catch((e)=>{
@@ -33,9 +33,10 @@ var __webpack_require__ = {};
33
33
  var __webpack_exports__ = {};
34
34
  __webpack_require__.r(__webpack_exports__);
35
35
  __webpack_require__.d(__webpack_exports__, {
36
- PUPPETEER_ENDPOINT_FILE: ()=>PUPPETEER_ENDPOINT_FILE,
37
36
  WebPuppeteerMidsceneTools: ()=>WebPuppeteerMidsceneTools,
38
- buildDetachedChromeArgs: ()=>buildDetachedChromeArgs
37
+ PUPPETEER_ENDPOINT_FILE: ()=>PUPPETEER_ENDPOINT_FILE,
38
+ buildDetachedChromeArgs: ()=>buildDetachedChromeArgs,
39
+ waitForDetachedChromeEndpoint: ()=>waitForDetachedChromeEndpoint
39
40
  });
40
41
  const external_node_child_process_namespaceObject = require("node:child_process");
41
42
  const external_node_fs_namespaceObject = require("node:fs");
@@ -46,6 +47,7 @@ const core_namespaceObject = require("@midscene/core");
46
47
  const agent_behavior_init_args_namespaceObject = require("@midscene/shared/agent-tools/agent-behavior-init-args");
47
48
  const base_tools_namespaceObject = require("@midscene/shared/agent-tools/base-tools");
48
49
  const chrome_path_namespaceObject = require("@midscene/shared/agent-tools/chrome-path");
50
+ const logger_namespaceObject = require("@midscene/shared/logger");
49
51
  const external_puppeteer_core_namespaceObject = require("puppeteer-core");
50
52
  var external_puppeteer_core_default = /*#__PURE__*/ __webpack_require__.n(external_puppeteer_core_namespaceObject);
51
53
  const external_agent_init_args_js_namespaceObject = require("./agent-init-args.js");
@@ -64,7 +66,10 @@ function _define_property(obj, key, value) {
64
66
  }
65
67
  const ENDPOINT_FILE = (0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), 'midscene-puppeteer-endpoint');
66
68
  const USER_DATA_DIR = (0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), 'midscene-puppeteer-profile');
69
+ const TARGET_ID_FILE = (0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.tmpdir)(), 'midscene-puppeteer-target-id');
67
70
  const DETACHED_CHROME_LAUNCH_TIMEOUT_MS = 30000;
71
+ const DETACHED_CHROME_ENDPOINT_POLL_INTERVAL_MS = 25;
72
+ const debug = (0, logger_namespaceObject.getDebug)('agent-tools:puppeteer');
68
73
  const PUPPETEER_ENDPOINT_FILE = ENDPOINT_FILE;
69
74
  function buildDetachedChromeArgs(options) {
70
75
  const viewport = options.viewport ?? viewport_js_namespaceObject.defaultPuppeteerWindowViewportSize;
@@ -94,6 +99,67 @@ function terminateDetachedChrome(proc) {
94
99
  proc.kill('SIGKILL');
95
100
  } catch {}
96
101
  }
102
+ function getTargetId(page) {
103
+ return page.target()._targetId;
104
+ }
105
+ function waitForDetachedChromeEndpoint(proc, stderrFile, timeoutMs = DETACHED_CHROME_LAUNCH_TIMEOUT_MS) {
106
+ return new Promise((resolve, reject)=>{
107
+ let output = '';
108
+ let settled = false;
109
+ let exited = false;
110
+ let pollTimer;
111
+ const cleanup = ()=>{
112
+ clearTimeout(timeout);
113
+ if (pollTimer) clearTimeout(pollTimer);
114
+ proc.removeListener('exit', onExit);
115
+ proc.removeListener('error', onError);
116
+ };
117
+ const resolveOnce = (value)=>{
118
+ if (settled) return;
119
+ settled = true;
120
+ cleanup();
121
+ resolve(value);
122
+ };
123
+ const rejectOnce = (error, terminate = false)=>{
124
+ if (settled) return;
125
+ settled = true;
126
+ if (terminate) terminateDetachedChrome(proc);
127
+ cleanup();
128
+ reject(error);
129
+ };
130
+ const onExit = (code, signal)=>{
131
+ exited = true;
132
+ (0, promises_namespaceObject.readFile)(stderrFile, 'utf-8').catch(()=>output).then((latestOutput)=>{
133
+ output = latestOutput;
134
+ rejectOnce(new Error(`Chrome exited with code ${code ?? signal} before DevTools was ready.\nChrome stderr: ${output}\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`));
135
+ });
136
+ };
137
+ const onError = (error)=>{
138
+ rejectOnce(new Error(`Failed to launch Chrome. Stderr log: "${stderrFile}".`, {
139
+ cause: error
140
+ }), true);
141
+ };
142
+ const pollForEndpoint = async ()=>{
143
+ if (settled || exited) return;
144
+ try {
145
+ output = await (0, promises_namespaceObject.readFile)(stderrFile, 'utf-8');
146
+ } catch (error) {
147
+ rejectOnce(new Error(`Failed to read Chrome stderr log "${stderrFile}".`, {
148
+ cause: error
149
+ }), true);
150
+ return;
151
+ }
152
+ if (settled || exited) return;
153
+ const match = output.match(/DevTools listening on (ws:\/\/[^\s]+)/);
154
+ if (match) return void resolveOnce(match[1]);
155
+ pollTimer = setTimeout(()=>void pollForEndpoint(), DETACHED_CHROME_ENDPOINT_POLL_INTERVAL_MS);
156
+ };
157
+ const timeout = setTimeout(()=>rejectOnce(new Error(`Chrome launch timeout.\nChrome stderr: ${output}\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`), true), timeoutMs);
158
+ proc.on('exit', onExit);
159
+ proc.on('error', onError);
160
+ pollForEndpoint();
161
+ });
162
+ }
97
163
  class PuppeteerBrowserManager {
98
164
  get endpointFile() {
99
165
  return this.persistence.endpointFile || ENDPOINT_FILE;
@@ -101,6 +167,53 @@ class PuppeteerBrowserManager {
101
167
  get userDataDir() {
102
168
  return this.persistence.userDataDir || USER_DATA_DIR;
103
169
  }
170
+ get targetIdFile() {
171
+ return this.persistence.targetIdFile || TARGET_ID_FILE;
172
+ }
173
+ get chromeStderrFile() {
174
+ return (0, external_node_path_namespaceObject.join)(this.userDataDir, 'chrome-stderr.log');
175
+ }
176
+ async readSavedTargetId() {
177
+ let content;
178
+ try {
179
+ content = await (0, promises_namespaceObject.readFile)(this.targetIdFile, 'utf-8');
180
+ } catch (error) {
181
+ if ('ENOENT' === error.code) return null;
182
+ throw new Error(`Failed to read Puppeteer targetId from "${this.targetIdFile}".`, {
183
+ cause: error
184
+ });
185
+ }
186
+ const targetId = content.trim();
187
+ if (!targetId) throw new Error(`Puppeteer targetId file "${this.targetIdFile}" is empty.`);
188
+ return targetId;
189
+ }
190
+ async saveTargetId(targetId) {
191
+ try {
192
+ await (0, promises_namespaceObject.writeFile)(this.targetIdFile, targetId, 'utf-8');
193
+ debug('Saved Puppeteer targetId: %s', targetId);
194
+ } catch (error) {
195
+ throw new Error(`Failed to save Puppeteer targetId to "${this.targetIdFile}".`, {
196
+ cause: error
197
+ });
198
+ }
199
+ }
200
+ async cleanupTargetIdFile() {
201
+ try {
202
+ await (0, promises_namespaceObject.unlink)(this.targetIdFile);
203
+ } catch (error) {
204
+ if ('ENOENT' === error.code) return;
205
+ throw new Error(`Failed to remove Puppeteer targetId file "${this.targetIdFile}".`, {
206
+ cause: error
207
+ });
208
+ }
209
+ }
210
+ async cleanupChromeStderrFile() {
211
+ try {
212
+ await (0, promises_namespaceObject.unlink)(this.chromeStderrFile);
213
+ } catch (error) {
214
+ if ('ENOENT' !== error.code) debug('Failed to clean Chrome stderr log: %s', error);
215
+ }
216
+ }
104
217
  async getOrLaunch(viewport) {
105
218
  const endpointFile = this.endpointFile;
106
219
  if ((0, external_node_fs_namespaceObject.existsSync)(endpointFile)) try {
@@ -113,11 +226,14 @@ class PuppeteerBrowserManager {
113
226
  browser,
114
227
  reused: true
115
228
  };
116
- } catch {
229
+ } catch (error) {
230
+ debug('Failed to reuse persisted Puppeteer endpoint: %s', error);
117
231
  try {
118
232
  await (0, promises_namespaceObject.unlink)(endpointFile);
119
233
  } catch {}
234
+ await this.cleanupTargetIdFile();
120
235
  }
236
+ await this.cleanupTargetIdFile();
121
237
  const wsEndpoint = await this.launchDetachedChrome(viewport);
122
238
  await (0, promises_namespaceObject.writeFile)(endpointFile, wsEndpoint);
123
239
  const browser = await external_puppeteer_core_default().connect({
@@ -131,17 +247,20 @@ class PuppeteerBrowserManager {
131
247
  }
132
248
  async closeBrowser() {
133
249
  const endpointFile = this.endpointFile;
134
- if (!(0, external_node_fs_namespaceObject.existsSync)(endpointFile)) return;
135
- try {
250
+ if ((0, external_node_fs_namespaceObject.existsSync)(endpointFile)) try {
136
251
  const endpoint = (await (0, promises_namespaceObject.readFile)(endpointFile, 'utf-8')).trim();
137
252
  const browser = await external_puppeteer_core_default().connect({
138
253
  browserWSEndpoint: endpoint
139
254
  });
140
255
  await browser.close();
141
- } catch {}
256
+ } catch (error) {
257
+ debug('Failed to close persisted Puppeteer browser: %s', error);
258
+ }
142
259
  try {
143
- await (0, promises_namespaceObject.unlink)(endpointFile);
260
+ if ((0, external_node_fs_namespaceObject.existsSync)(endpointFile)) await (0, promises_namespaceObject.unlink)(endpointFile);
144
261
  } catch {}
262
+ await this.cleanupTargetIdFile();
263
+ await this.cleanupChromeStderrFile();
145
264
  }
146
265
  disconnect() {
147
266
  if (this.activeBrowser) {
@@ -159,48 +278,34 @@ class PuppeteerBrowserManager {
159
278
  userDataDir,
160
279
  viewport
161
280
  });
162
- const proc = (0, external_node_child_process_namespaceObject.spawn)(chromePath, args, {
163
- detached: true,
164
- stdio: [
165
- 'ignore',
166
- 'ignore',
167
- 'pipe'
168
- ]
169
- });
281
+ const stderrFile = this.chromeStderrFile;
282
+ const stderrHandle = await (0, promises_namespaceObject.open)(stderrFile, 'w');
283
+ let proc;
284
+ try {
285
+ proc = (0, external_node_child_process_namespaceObject.spawn)(chromePath, args, {
286
+ detached: true,
287
+ stdio: [
288
+ 'ignore',
289
+ 'ignore',
290
+ stderrHandle.fd
291
+ ]
292
+ });
293
+ } catch (error) {
294
+ await stderrHandle.close();
295
+ throw error;
296
+ }
297
+ const endpointPromise = waitForDetachedChromeEndpoint(proc, stderrFile);
170
298
  proc.unref();
171
- return new Promise((resolve, reject)=>{
172
- let output = '';
173
- let settled = false;
174
- const cleanup = ()=>{
175
- clearTimeout(timeout);
176
- proc.stderr.removeListener('data', onData);
177
- proc.removeListener('exit', onExit);
178
- };
179
- const resolveOnce = (value)=>{
180
- if (settled) return;
181
- settled = true;
182
- cleanup();
183
- resolve(value);
184
- };
185
- const rejectOnce = (error, terminate = false)=>{
186
- if (settled) return;
187
- settled = true;
188
- if (terminate) terminateDetachedChrome(proc);
189
- cleanup();
190
- reject(error);
191
- };
192
- const onData = (data)=>{
193
- output += data.toString();
194
- const match = output.match(/DevTools listening on (ws:\/\/[^\s]+)/);
195
- if (match) resolveOnce(match[1]);
196
- };
197
- proc.stderr.on('data', onData);
198
- const onExit = (code, signal)=>{
199
- rejectOnce(new Error(`Chrome exited with code ${code ?? signal} before DevTools was ready.\nChrome stderr: ${output}\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`));
200
- };
201
- proc.on('exit', onExit);
202
- const timeout = setTimeout(()=>rejectOnce(new Error(`Chrome launch timeout.\nChrome stderr: ${output}\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`), true), DETACHED_CHROME_LAUNCH_TIMEOUT_MS);
203
- });
299
+ try {
300
+ await stderrHandle.close();
301
+ } catch (error) {
302
+ terminateDetachedChrome(proc);
303
+ await endpointPromise.catch(()=>void 0);
304
+ throw new Error(`Failed to close Chrome stderr log "${stderrFile}".`, {
305
+ cause: error
306
+ });
307
+ }
308
+ return endpointPromise;
204
309
  }
205
310
  constructor(persistence = {}){
206
311
  _define_property(this, "persistence", void 0);
@@ -244,11 +349,16 @@ class WebPuppeteerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneT
244
349
  waitUntil: 'domcontentloaded'
245
350
  });
246
351
  } else {
352
+ const savedTargetId = await this.browserManager.readSavedTargetId();
353
+ const matchedPage = savedTargetId ? pages.find((candidate)=>getTargetId(candidate) === savedTargetId) : void 0;
247
354
  const webPages = pages.filter((p)=>/^https?:\/\//.test(p.url()));
248
- page = webPages.length > 0 ? webPages[webPages.length - 1] : pages[pages.length - 1] || await browser.newPage();
355
+ page = matchedPage ?? (webPages.length > 0 ? webPages[webPages.length - 1] : pages[pages.length - 1] || await browser.newPage());
249
356
  if (reused) await page.bringToFront();
250
357
  if (this.viewport) await page.setViewport(this.viewport);
251
358
  }
359
+ const targetId = getTargetId(page);
360
+ if (!targetId) throw new Error('Failed to persist Puppeteer page session because Puppeteer did not expose a Chrome targetId.');
361
+ await this.browserManager.saveTargetId(targetId);
252
362
  const reportOptions = this.readCliReportAgentOptions();
253
363
  this.agent = new index_js_namespaceObject.PuppeteerAgent(page, {
254
364
  ...(0, agent_behavior_init_args_namespaceObject.extractAgentBehaviorInitArgs)(initArgs) ?? {},
@@ -307,6 +417,7 @@ class WebPuppeteerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneT
307
417
  this.lastInitArgsSignature = void 0;
308
418
  }
309
419
  this.browserManager.disconnect();
420
+ await this.browserManager.cleanupTargetIdFile();
310
421
  return this.buildTextResult('Disconnected from web page (browser still running)');
311
422
  }
312
423
  },
@@ -346,10 +457,12 @@ class WebPuppeteerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneT
346
457
  exports.PUPPETEER_ENDPOINT_FILE = __webpack_exports__.PUPPETEER_ENDPOINT_FILE;
347
458
  exports.WebPuppeteerMidsceneTools = __webpack_exports__.WebPuppeteerMidsceneTools;
348
459
  exports.buildDetachedChromeArgs = __webpack_exports__.buildDetachedChromeArgs;
460
+ exports.waitForDetachedChromeEndpoint = __webpack_exports__.waitForDetachedChromeEndpoint;
349
461
  for(var __rspack_i in __webpack_exports__)if (-1 === [
350
462
  "PUPPETEER_ENDPOINT_FILE",
351
463
  "WebPuppeteerMidsceneTools",
352
- "buildDetachedChromeArgs"
464
+ "buildDetachedChromeArgs",
465
+ "waitForDetachedChromeEndpoint"
353
466
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
354
467
  Object.defineProperty(exports, '__esModule', {
355
468
  value: true
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tools-puppeteer.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/agent-tools-puppeteer.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { type ChildProcess, spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { ScreenshotItem } from '@midscene/core';\nimport {\n extractAgentBehaviorInitArgs,\n getAgentInitArgsSignature,\n shouldRebuildAgentForInitArgs,\n} from '@midscene/shared/agent-tools/agent-behavior-init-args';\nimport {\n BaseMidsceneTools,\n type InitArgSpec,\n} from '@midscene/shared/agent-tools/base-tools';\nimport { resolveChromePath } from '@midscene/shared/agent-tools/chrome-path';\nimport type { ToolDefinition } from '@midscene/shared/agent-tools/types';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport puppeteer from 'puppeteer-core';\nimport type { Browser, Page } from 'puppeteer-core';\nimport {\n type WebAgentInitArgs,\n adaptWebAgentInitArgs,\n webAgentInitArgShape,\n} from './agent-init-args';\nimport {\n type ViewportSize,\n defaultPuppeteerWindowViewportSize,\n defaultStaticPageViewportSize,\n} from './common/viewport';\nimport { PuppeteerAgent } from './puppeteer';\nimport { StaticPage } from './static';\n\nconst ENDPOINT_FILE = join(tmpdir(), 'midscene-puppeteer-endpoint');\nconst USER_DATA_DIR = join(tmpdir(), 'midscene-puppeteer-profile');\nconst DETACHED_CHROME_LAUNCH_TIMEOUT_MS = 30_000;\n\nexport const PUPPETEER_ENDPOINT_FILE = ENDPOINT_FILE;\n\nexport interface PuppeteerPersistenceOptions {\n endpointFile?: string;\n userDataDir?: string;\n}\n\nexport interface WebPuppeteerMidsceneToolsOptions {\n persistence?: PuppeteerPersistenceOptions;\n}\n\nexport function buildDetachedChromeArgs(options: {\n userDataDir: string;\n viewport?: ViewportSize;\n}): string[] {\n const viewport = options.viewport ?? defaultPuppeteerWindowViewportSize;\n\n return [\n '--headless=new',\n `--user-data-dir=${options.userDataDir}`,\n '--remote-debugging-port=0',\n '--no-first-run',\n '--no-default-browser-check',\n '--disable-extensions',\n '--disable-default-apps',\n '--disable-sync',\n '--disable-background-networking',\n '--password-store=basic',\n '--use-mock-keychain',\n `--window-size=${viewport.width},${viewport.height}`,\n '--force-color-profile=srgb',\n ];\n}\n\nfunction terminateDetachedChrome(proc: ChildProcess): void {\n if (proc.killed || proc.exitCode !== null || proc.signalCode !== null) {\n return;\n }\n\n if (process.platform !== 'win32' && proc.pid) {\n try {\n process.kill(-proc.pid, 'SIGKILL');\n return;\n } catch {}\n }\n\n try {\n proc.kill('SIGKILL');\n } catch {}\n}\n\n/**\n * Persistent Puppeteer browser manager.\n * Launches a detached Chrome and persists the WS endpoint across CLI calls.\n */\nclass PuppeteerBrowserManager {\n activeBrowser: Browser | null = null;\n\n constructor(private readonly persistence: PuppeteerPersistenceOptions = {}) {}\n\n private get endpointFile() {\n return this.persistence.endpointFile || ENDPOINT_FILE;\n }\n\n private get userDataDir() {\n return this.persistence.userDataDir || USER_DATA_DIR;\n }\n\n async getOrLaunch(\n viewport?: ViewportSize,\n ): Promise<{ browser: Browser; reused: boolean }> {\n const endpointFile = this.endpointFile;\n if (existsSync(endpointFile)) {\n try {\n const endpoint = (await readFile(endpointFile, 'utf-8')).trim();\n const browser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n defaultViewport: null,\n });\n return { browser, reused: true };\n } catch {\n try {\n await unlink(endpointFile);\n } catch {}\n }\n }\n\n const wsEndpoint = await this.launchDetachedChrome(viewport);\n await writeFile(endpointFile, wsEndpoint);\n\n const browser = await puppeteer.connect({\n browserWSEndpoint: wsEndpoint,\n defaultViewport: null,\n });\n return { browser, reused: false };\n }\n\n async closeBrowser(): Promise<void> {\n const endpointFile = this.endpointFile;\n if (!existsSync(endpointFile)) return;\n try {\n const endpoint = (await readFile(endpointFile, 'utf-8')).trim();\n const browser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n });\n await browser.close();\n } catch {}\n try {\n await unlink(endpointFile);\n } catch {}\n }\n\n disconnect(): void {\n if (this.activeBrowser) {\n this.activeBrowser.disconnect();\n this.activeBrowser = null;\n }\n }\n\n async launchDetachedChrome(viewport?: ViewportSize): Promise<string> {\n const chromePath = resolveChromePath();\n const userDataDir = this.userDataDir;\n\n await mkdir(userDataDir, { recursive: true });\n\n const args = buildDetachedChromeArgs({\n userDataDir,\n viewport,\n });\n\n const proc = spawn(chromePath, args, {\n detached: true,\n stdio: ['ignore', 'ignore', 'pipe'],\n });\n proc.unref();\n\n return new Promise<string>((resolve, reject) => {\n let output = '';\n let settled = false;\n const cleanup = () => {\n clearTimeout(timeout);\n proc.stderr!.removeListener('data', onData);\n proc.removeListener('exit', onExit);\n };\n const resolveOnce = (value: string) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n const rejectOnce = (error: Error, terminate = false) => {\n if (settled) return;\n settled = true;\n if (terminate) {\n terminateDetachedChrome(proc);\n }\n cleanup();\n reject(error);\n };\n const onData = (data: Buffer) => {\n output += data.toString();\n const match = output.match(/DevTools listening on (ws:\\/\\/[^\\s]+)/);\n if (match) {\n resolveOnce(match[1]);\n }\n };\n proc.stderr!.on('data', onData);\n\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n rejectOnce(\n new Error(\n `Chrome exited with code ${code ?? signal} before DevTools was ready.\\nChrome stderr: ${output}\\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`,\n ),\n );\n };\n proc.on('exit', onExit);\n\n const timeout = setTimeout(\n () =>\n rejectOnce(\n new Error(\n `Chrome launch timeout.\\nChrome stderr: ${output}\\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`,\n ),\n true,\n ),\n DETACHED_CHROME_LAUNCH_TIMEOUT_MS,\n );\n });\n }\n}\n\nconst defaultBrowserManager = new PuppeteerBrowserManager();\n\n/**\n * Tools manager for Web Puppeteer mode.\n * Uses a persistent headless Chrome browser that survives across CLI calls.\n */\nexport class WebPuppeteerMidsceneTools extends BaseMidsceneTools<\n PuppeteerAgent,\n WebAgentInitArgs\n> {\n private readonly viewport?: ViewportSize;\n private readonly browserManager: PuppeteerBrowserManager;\n private lastInitArgsSignature?: string;\n\n constructor(\n viewport?: ViewportSize,\n options: WebPuppeteerMidsceneToolsOptions = {},\n ) {\n super();\n this.viewport = viewport ? { ...viewport } : undefined;\n this.browserManager = options.persistence\n ? new PuppeteerBrowserManager(options.persistence)\n : defaultBrowserManager;\n }\n\n protected getCliReportSessionName() {\n return 'midscene-web';\n }\n\n protected readonly initArgSpec: InitArgSpec<WebAgentInitArgs> = {\n namespace: 'web',\n shape: webAgentInitArgShape,\n cli: {\n preferBareKeys: true,\n },\n adapt: adaptWebAgentInitArgs,\n };\n\n protected createTemporaryDevice() {\n return new StaticPage({\n screenshot: ScreenshotItem.create('', Date.now()),\n shotSize: this.viewport ?? defaultStaticPageViewportSize,\n shrunkShotToLogicalRatio: 1,\n });\n }\n\n protected async ensureAgent(\n initArgs?: WebAgentInitArgs,\n ): Promise<PuppeteerAgent> {\n const navigateToUrl = initArgs?.url;\n const nextSignature = getAgentInitArgsSignature(initArgs);\n const shouldOpenUrl = typeof navigateToUrl === 'string';\n\n if (\n this.agent &&\n (shouldOpenUrl ||\n shouldRebuildAgentForInitArgs(\n this.lastInitArgsSignature,\n nextSignature,\n ))\n ) {\n try {\n await this.agent?.destroy?.();\n } catch {}\n this.agent = undefined;\n }\n\n if (this.agent) return this.agent;\n\n const { browser, reused } = await this.browserManager.getOrLaunch(\n this.viewport,\n );\n this.browserManager.activeBrowser = browser;\n\n const pages = await browser.pages();\n let page: Page;\n\n if (navigateToUrl) {\n page = await browser.newPage();\n if (this.viewport) {\n await page.setViewport(this.viewport);\n }\n await page.goto(navigateToUrl, {\n timeout: 30000,\n waitUntil: 'domcontentloaded',\n });\n } else {\n // Reuse the last web page\n const webPages = pages.filter((p) => /^https?:\\/\\//.test(p.url()));\n page =\n webPages.length > 0\n ? webPages[webPages.length - 1]\n : pages[pages.length - 1] || (await browser.newPage());\n\n if (reused) {\n await page.bringToFront();\n }\n if (this.viewport) {\n await page.setViewport(this.viewport);\n }\n }\n\n const reportOptions = this.readCliReportAgentOptions();\n this.agent = new PuppeteerAgent(page as unknown as PuppeteerPage, {\n ...(extractAgentBehaviorInitArgs(initArgs) ?? {}),\n ...(reportOptions ?? {}),\n });\n this.lastInitArgsSignature = nextSignature;\n return this.agent;\n }\n\n public async destroy(): Promise<void> {\n await super.destroy();\n this.browserManager.disconnect();\n }\n\n protected preparePlatformTools(): ToolDefinition[] {\n return [\n {\n name: 'web_connect',\n description:\n 'Connect to a web page. Opens a new tab with the given URL, or reuses the current page.',\n schema: this.getAgentInitArgSchema(),\n cli: this.getAgentInitArgCliMetadata(),\n handler: async (args) => {\n const initArgs = this.extractAgentInitParam(args);\n const url = initArgs?.url;\n\n // Explicit connect always starts a fresh page session.\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n\n const reportSession = this.createNewCliReportSession(\n url ?? 'current-page',\n );\n this.commitCliReportSession(reportSession);\n this.agent = await this.ensureAgent(initArgs);\n\n const screenshot = await this.agent.page?.screenshotBase64();\n const label = url ?? 'current page';\n\n return {\n content: [\n { type: 'text', text: `Connected to: ${label}` },\n ...(screenshot ? this.buildScreenshotContent(screenshot) : []),\n ],\n };\n },\n },\n {\n name: 'web_disconnect',\n description:\n 'Disconnect from current web page. The browser stays running for future calls.',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n this.browserManager.disconnect();\n return this.buildTextResult(\n 'Disconnected from web page (browser still running)',\n );\n },\n },\n {\n name: 'web_close',\n description: 'Close the browser completely and release all resources.',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n await this.browserManager.closeBrowser();\n return this.buildTextResult('Browser closed');\n },\n },\n ];\n }\n}\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","ENDPOINT_FILE","join","tmpdir","USER_DATA_DIR","DETACHED_CHROME_LAUNCH_TIMEOUT_MS","PUPPETEER_ENDPOINT_FILE","buildDetachedChromeArgs","options","viewport","defaultPuppeteerWindowViewportSize","terminateDetachedChrome","proc","process","PuppeteerBrowserManager","endpointFile","existsSync","endpoint","readFile","browser","puppeteer","unlink","wsEndpoint","writeFile","chromePath","resolveChromePath","userDataDir","mkdir","args","spawn","Promise","resolve","reject","output","settled","cleanup","clearTimeout","timeout","onData","onExit","resolveOnce","value","rejectOnce","error","terminate","data","match","code","signal","Error","setTimeout","persistence","defaultBrowserManager","WebPuppeteerMidsceneTools","BaseMidsceneTools","StaticPage","ScreenshotItem","Date","defaultStaticPageViewportSize","initArgs","navigateToUrl","nextSignature","getAgentInitArgsSignature","shouldOpenUrl","shouldRebuildAgentForInitArgs","undefined","reused","pages","page","webPages","p","reportOptions","PuppeteerAgent","extractAgentBehaviorInitArgs","url","reportSession","screenshot","label","webAgentInitArgShape","adaptWebAgentInitArgs"],"mappings":"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"}
1
+ {"version":3,"file":"agent-tools-puppeteer.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/agent-tools-puppeteer.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { type ChildProcess, spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, open, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { ScreenshotItem } from '@midscene/core';\nimport {\n extractAgentBehaviorInitArgs,\n getAgentInitArgsSignature,\n shouldRebuildAgentForInitArgs,\n} from '@midscene/shared/agent-tools/agent-behavior-init-args';\nimport {\n BaseMidsceneTools,\n type InitArgSpec,\n} from '@midscene/shared/agent-tools/base-tools';\nimport { resolveChromePath } from '@midscene/shared/agent-tools/chrome-path';\nimport type { ToolDefinition } from '@midscene/shared/agent-tools/types';\nimport { getDebug } from '@midscene/shared/logger';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport puppeteer from 'puppeteer-core';\nimport type { Browser, Page } from 'puppeteer-core';\nimport {\n type WebAgentInitArgs,\n adaptWebAgentInitArgs,\n webAgentInitArgShape,\n} from './agent-init-args';\nimport {\n type ViewportSize,\n defaultPuppeteerWindowViewportSize,\n defaultStaticPageViewportSize,\n} from './common/viewport';\nimport { PuppeteerAgent } from './puppeteer';\nimport { StaticPage } from './static';\n\nconst ENDPOINT_FILE = join(tmpdir(), 'midscene-puppeteer-endpoint');\nconst USER_DATA_DIR = join(tmpdir(), 'midscene-puppeteer-profile');\nconst TARGET_ID_FILE = join(tmpdir(), 'midscene-puppeteer-target-id');\nconst DETACHED_CHROME_LAUNCH_TIMEOUT_MS = 30_000;\nconst DETACHED_CHROME_ENDPOINT_POLL_INTERVAL_MS = 25;\nconst debug = getDebug('agent-tools:puppeteer');\n\nexport const PUPPETEER_ENDPOINT_FILE = ENDPOINT_FILE;\n\nexport interface PuppeteerPersistenceOptions {\n endpointFile?: string;\n userDataDir?: string;\n targetIdFile?: string;\n}\n\nexport interface WebPuppeteerMidsceneToolsOptions {\n persistence?: PuppeteerPersistenceOptions;\n}\n\nexport function buildDetachedChromeArgs(options: {\n userDataDir: string;\n viewport?: ViewportSize;\n}): string[] {\n const viewport = options.viewport ?? defaultPuppeteerWindowViewportSize;\n\n return [\n '--headless=new',\n `--user-data-dir=${options.userDataDir}`,\n '--remote-debugging-port=0',\n '--no-first-run',\n '--no-default-browser-check',\n '--disable-extensions',\n '--disable-default-apps',\n '--disable-sync',\n '--disable-background-networking',\n '--password-store=basic',\n '--use-mock-keychain',\n `--window-size=${viewport.width},${viewport.height}`,\n '--force-color-profile=srgb',\n ];\n}\n\nfunction terminateDetachedChrome(proc: ChildProcess): void {\n if (proc.killed || proc.exitCode !== null || proc.signalCode !== null) {\n return;\n }\n\n if (process.platform !== 'win32' && proc.pid) {\n try {\n process.kill(-proc.pid, 'SIGKILL');\n return;\n } catch {}\n }\n\n try {\n proc.kill('SIGKILL');\n } catch {}\n}\n\nfunction getTargetId(page: Page): string | undefined {\n return (page.target() as unknown as { _targetId?: string })._targetId;\n}\n\nexport function waitForDetachedChromeEndpoint(\n proc: ChildProcess,\n stderrFile: string,\n timeoutMs = DETACHED_CHROME_LAUNCH_TIMEOUT_MS,\n): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n let output = '';\n let settled = false;\n let exited = false;\n let pollTimer: NodeJS.Timeout | undefined;\n const cleanup = () => {\n clearTimeout(timeout);\n if (pollTimer) {\n clearTimeout(pollTimer);\n }\n proc.removeListener('exit', onExit);\n proc.removeListener('error', onError);\n };\n const resolveOnce = (value: string) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n const rejectOnce = (error: Error, terminate = false) => {\n if (settled) return;\n settled = true;\n if (terminate) {\n terminateDetachedChrome(proc);\n }\n cleanup();\n reject(error);\n };\n const onExit = (code: number | null, signal: NodeJS.Signals | null) => {\n exited = true;\n void readFile(stderrFile, 'utf-8')\n .catch(() => output)\n .then((latestOutput) => {\n output = latestOutput;\n rejectOnce(\n new Error(\n `Chrome exited with code ${code ?? signal} before DevTools was ready.\\nChrome stderr: ${output}\\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`,\n ),\n );\n });\n };\n const onError = (error: Error) => {\n rejectOnce(\n new Error(`Failed to launch Chrome. Stderr log: \"${stderrFile}\".`, {\n cause: error,\n }),\n true,\n );\n };\n const pollForEndpoint = async (): Promise<void> => {\n if (settled || exited) return;\n try {\n output = await readFile(stderrFile, 'utf-8');\n } catch (error) {\n rejectOnce(\n new Error(`Failed to read Chrome stderr log \"${stderrFile}\".`, {\n cause: error,\n }),\n true,\n );\n return;\n }\n\n if (settled || exited) return;\n const match = output.match(/DevTools listening on (ws:\\/\\/[^\\s]+)/);\n if (match) {\n resolveOnce(match[1]);\n return;\n }\n pollTimer = setTimeout(\n () => void pollForEndpoint(),\n DETACHED_CHROME_ENDPOINT_POLL_INTERVAL_MS,\n );\n };\n const timeout = setTimeout(\n () =>\n rejectOnce(\n new Error(\n `Chrome launch timeout.\\nChrome stderr: ${output}\\nTip: if running in a container, launch Chrome with sandbox-compatible arguments.`,\n ),\n true,\n ),\n timeoutMs,\n );\n\n proc.on('exit', onExit);\n proc.on('error', onError);\n void pollForEndpoint();\n });\n}\n\n/**\n * Persistent Puppeteer browser manager.\n * Launches a detached Chrome and persists the WS endpoint across CLI calls.\n */\nclass PuppeteerBrowserManager {\n activeBrowser: Browser | null = null;\n\n constructor(private readonly persistence: PuppeteerPersistenceOptions = {}) {}\n\n private get endpointFile() {\n return this.persistence.endpointFile || ENDPOINT_FILE;\n }\n\n private get userDataDir() {\n return this.persistence.userDataDir || USER_DATA_DIR;\n }\n\n private get targetIdFile() {\n return this.persistence.targetIdFile || TARGET_ID_FILE;\n }\n\n private get chromeStderrFile() {\n return join(this.userDataDir, 'chrome-stderr.log');\n }\n\n async readSavedTargetId(): Promise<string | null> {\n let content: string;\n try {\n content = await readFile(this.targetIdFile, 'utf-8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw new Error(\n `Failed to read Puppeteer targetId from \"${this.targetIdFile}\".`,\n { cause: error },\n );\n }\n\n const targetId = content.trim();\n if (!targetId) {\n throw new Error(\n `Puppeteer targetId file \"${this.targetIdFile}\" is empty.`,\n );\n }\n return targetId;\n }\n\n async saveTargetId(targetId: string): Promise<void> {\n try {\n await writeFile(this.targetIdFile, targetId, 'utf-8');\n debug('Saved Puppeteer targetId: %s', targetId);\n } catch (error) {\n throw new Error(\n `Failed to save Puppeteer targetId to \"${this.targetIdFile}\".`,\n { cause: error },\n );\n }\n }\n\n async cleanupTargetIdFile(): Promise<void> {\n try {\n await unlink(this.targetIdFile);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw new Error(\n `Failed to remove Puppeteer targetId file \"${this.targetIdFile}\".`,\n { cause: error },\n );\n }\n }\n\n async cleanupChromeStderrFile(): Promise<void> {\n try {\n await unlink(this.chromeStderrFile);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n debug('Failed to clean Chrome stderr log: %s', error);\n }\n }\n }\n\n async getOrLaunch(\n viewport?: ViewportSize,\n ): Promise<{ browser: Browser; reused: boolean }> {\n const endpointFile = this.endpointFile;\n if (existsSync(endpointFile)) {\n try {\n const endpoint = (await readFile(endpointFile, 'utf-8')).trim();\n const browser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n defaultViewport: null,\n });\n return { browser, reused: true };\n } catch (error) {\n debug('Failed to reuse persisted Puppeteer endpoint: %s', error);\n try {\n await unlink(endpointFile);\n } catch {}\n await this.cleanupTargetIdFile();\n }\n }\n\n await this.cleanupTargetIdFile();\n const wsEndpoint = await this.launchDetachedChrome(viewport);\n await writeFile(endpointFile, wsEndpoint);\n\n const browser = await puppeteer.connect({\n browserWSEndpoint: wsEndpoint,\n defaultViewport: null,\n });\n return { browser, reused: false };\n }\n\n async closeBrowser(): Promise<void> {\n const endpointFile = this.endpointFile;\n if (existsSync(endpointFile)) {\n try {\n const endpoint = (await readFile(endpointFile, 'utf-8')).trim();\n const browser = await puppeteer.connect({\n browserWSEndpoint: endpoint,\n });\n await browser.close();\n } catch (error) {\n debug('Failed to close persisted Puppeteer browser: %s', error);\n }\n }\n try {\n if (existsSync(endpointFile)) {\n await unlink(endpointFile);\n }\n } catch {}\n await this.cleanupTargetIdFile();\n await this.cleanupChromeStderrFile();\n }\n\n disconnect(): void {\n if (this.activeBrowser) {\n this.activeBrowser.disconnect();\n this.activeBrowser = null;\n }\n }\n\n async launchDetachedChrome(viewport?: ViewportSize): Promise<string> {\n const chromePath = resolveChromePath();\n const userDataDir = this.userDataDir;\n\n await mkdir(userDataDir, { recursive: true });\n\n const args = buildDetachedChromeArgs({\n userDataDir,\n viewport,\n });\n\n const stderrFile = this.chromeStderrFile;\n const stderrHandle = await open(stderrFile, 'w');\n let proc: ChildProcess;\n try {\n proc = spawn(chromePath, args, {\n detached: true,\n stdio: ['ignore', 'ignore', stderrHandle.fd],\n });\n } catch (error) {\n await stderrHandle.close();\n throw error;\n }\n const endpointPromise = waitForDetachedChromeEndpoint(proc, stderrFile);\n proc.unref();\n try {\n await stderrHandle.close();\n } catch (error) {\n terminateDetachedChrome(proc);\n await endpointPromise.catch(() => undefined);\n throw new Error(`Failed to close Chrome stderr log \"${stderrFile}\".`, {\n cause: error,\n });\n }\n\n return endpointPromise;\n }\n}\n\nconst defaultBrowserManager = new PuppeteerBrowserManager();\n\n/**\n * Tools manager for Web Puppeteer mode.\n * Uses a persistent headless Chrome browser that survives across CLI calls.\n */\nexport class WebPuppeteerMidsceneTools extends BaseMidsceneTools<\n PuppeteerAgent,\n WebAgentInitArgs\n> {\n private readonly viewport?: ViewportSize;\n private readonly browserManager: PuppeteerBrowserManager;\n private lastInitArgsSignature?: string;\n\n constructor(\n viewport?: ViewportSize,\n options: WebPuppeteerMidsceneToolsOptions = {},\n ) {\n super();\n this.viewport = viewport ? { ...viewport } : undefined;\n this.browserManager = options.persistence\n ? new PuppeteerBrowserManager(options.persistence)\n : defaultBrowserManager;\n }\n\n protected getCliReportSessionName() {\n return 'midscene-web';\n }\n\n protected readonly initArgSpec: InitArgSpec<WebAgentInitArgs> = {\n namespace: 'web',\n shape: webAgentInitArgShape,\n cli: {\n preferBareKeys: true,\n },\n adapt: adaptWebAgentInitArgs,\n };\n\n protected createTemporaryDevice() {\n return new StaticPage({\n screenshot: ScreenshotItem.create('', Date.now()),\n shotSize: this.viewport ?? defaultStaticPageViewportSize,\n shrunkShotToLogicalRatio: 1,\n });\n }\n\n protected async ensureAgent(\n initArgs?: WebAgentInitArgs,\n ): Promise<PuppeteerAgent> {\n const navigateToUrl = initArgs?.url;\n const nextSignature = getAgentInitArgsSignature(initArgs);\n const shouldOpenUrl = typeof navigateToUrl === 'string';\n\n if (\n this.agent &&\n (shouldOpenUrl ||\n shouldRebuildAgentForInitArgs(\n this.lastInitArgsSignature,\n nextSignature,\n ))\n ) {\n try {\n await this.agent?.destroy?.();\n } catch {}\n this.agent = undefined;\n }\n\n if (this.agent) return this.agent;\n\n const { browser, reused } = await this.browserManager.getOrLaunch(\n this.viewport,\n );\n this.browserManager.activeBrowser = browser;\n\n const pages = await browser.pages();\n let page: Page;\n\n if (navigateToUrl) {\n page = await browser.newPage();\n if (this.viewport) {\n await page.setViewport(this.viewport);\n }\n await page.goto(navigateToUrl, {\n timeout: 30000,\n waitUntil: 'domcontentloaded',\n });\n } else {\n const savedTargetId = await this.browserManager.readSavedTargetId();\n const matchedPage = savedTargetId\n ? pages.find((candidate) => getTargetId(candidate) === savedTargetId)\n : undefined;\n const webPages = pages.filter((p) => /^https?:\\/\\//.test(p.url()));\n page =\n matchedPage ??\n (webPages.length > 0\n ? webPages[webPages.length - 1]\n : pages[pages.length - 1] || (await browser.newPage()));\n\n if (reused) {\n await page.bringToFront();\n }\n if (this.viewport) {\n await page.setViewport(this.viewport);\n }\n }\n\n const targetId = getTargetId(page);\n if (!targetId) {\n throw new Error(\n 'Failed to persist Puppeteer page session because Puppeteer did not expose a Chrome targetId.',\n );\n }\n await this.browserManager.saveTargetId(targetId);\n\n const reportOptions = this.readCliReportAgentOptions();\n this.agent = new PuppeteerAgent(page as unknown as PuppeteerPage, {\n ...(extractAgentBehaviorInitArgs(initArgs) ?? {}),\n ...(reportOptions ?? {}),\n });\n this.lastInitArgsSignature = nextSignature;\n return this.agent;\n }\n\n public async destroy(): Promise<void> {\n await super.destroy();\n this.browserManager.disconnect();\n }\n\n protected preparePlatformTools(): ToolDefinition[] {\n return [\n {\n name: 'web_connect',\n description:\n 'Connect to a web page. Opens a new tab with the given URL, or reuses the current page.',\n schema: this.getAgentInitArgSchema(),\n cli: this.getAgentInitArgCliMetadata(),\n handler: async (args) => {\n const initArgs = this.extractAgentInitParam(args);\n const url = initArgs?.url;\n\n // Explicit connect always starts a fresh page session.\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n\n const reportSession = this.createNewCliReportSession(\n url ?? 'current-page',\n );\n this.commitCliReportSession(reportSession);\n this.agent = await this.ensureAgent(initArgs);\n\n const screenshot = await this.agent.page?.screenshotBase64();\n const label = url ?? 'current page';\n\n return {\n content: [\n { type: 'text', text: `Connected to: ${label}` },\n ...(screenshot ? this.buildScreenshotContent(screenshot) : []),\n ],\n };\n },\n },\n {\n name: 'web_disconnect',\n description:\n 'Disconnect from current web page. The browser stays running for future calls.',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n this.browserManager.disconnect();\n await this.browserManager.cleanupTargetIdFile();\n return this.buildTextResult(\n 'Disconnected from web page (browser still running)',\n );\n },\n },\n {\n name: 'web_close',\n description: 'Close the browser completely and release all resources.',\n schema: {},\n handler: async () => {\n if (this.agent) {\n try {\n await this.agent.destroy?.();\n } catch {}\n this.agent = undefined;\n this.lastInitArgsSignature = undefined;\n }\n await this.browserManager.closeBrowser();\n return this.buildTextResult('Browser closed');\n },\n },\n ];\n }\n}\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","ENDPOINT_FILE","join","tmpdir","USER_DATA_DIR","TARGET_ID_FILE","DETACHED_CHROME_LAUNCH_TIMEOUT_MS","DETACHED_CHROME_ENDPOINT_POLL_INTERVAL_MS","debug","getDebug","PUPPETEER_ENDPOINT_FILE","buildDetachedChromeArgs","options","viewport","defaultPuppeteerWindowViewportSize","terminateDetachedChrome","proc","process","getTargetId","page","waitForDetachedChromeEndpoint","stderrFile","timeoutMs","Promise","resolve","reject","output","settled","exited","pollTimer","cleanup","clearTimeout","timeout","onExit","onError","resolveOnce","value","rejectOnce","error","terminate","code","signal","readFile","latestOutput","Error","pollForEndpoint","match","setTimeout","PuppeteerBrowserManager","content","targetId","writeFile","unlink","endpointFile","existsSync","endpoint","browser","puppeteer","wsEndpoint","chromePath","resolveChromePath","userDataDir","mkdir","args","stderrHandle","open","spawn","endpointPromise","undefined","persistence","defaultBrowserManager","WebPuppeteerMidsceneTools","BaseMidsceneTools","StaticPage","ScreenshotItem","Date","defaultStaticPageViewportSize","initArgs","navigateToUrl","nextSignature","getAgentInitArgsSignature","shouldOpenUrl","shouldRebuildAgentForInitArgs","reused","pages","savedTargetId","matchedPage","candidate","webPages","p","reportOptions","PuppeteerAgent","extractAgentBehaviorInitArgs","url","reportSession","screenshot","label","webAgentInitArgShape","adaptWebAgentInitArgs"],"mappings":"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"}
@@ -51,7 +51,7 @@ class BridgeClient {
51
51
  ]
52
52
  } : {},
53
53
  query: {
54
- version: "1.10.4-beta-20260715034325.0"
54
+ version: "1.10.4"
55
55
  }
56
56
  });
57
57
  const timeout = setTimeout(()=>{
@@ -131,7 +131,7 @@ class BridgeServer {
131
131
  (0, shared_utils_namespaceObject.logMsg)('one client connected');
132
132
  this.socket = socket;
133
133
  const clientVersion = socket.handshake.query.version;
134
- (0, shared_utils_namespaceObject.logMsg)(`Bridge connected, cli-side version v1.10.4-beta-20260715034325.0, browser-side version v${clientVersion}`);
134
+ (0, shared_utils_namespaceObject.logMsg)(`Bridge connected, cli-side version v1.10.4, browser-side version v${clientVersion}`);
135
135
  socket.on(external_common_js_namespaceObject.BridgeEvent.CallResponse, (params)=>{
136
136
  const id = params.id;
137
137
  const response = params.response;
@@ -155,7 +155,7 @@ class BridgeServer {
155
155
  setTimeout(()=>{
156
156
  this.onConnect?.();
157
157
  const payload = {
158
- version: "1.10.4-beta-20260715034325.0"
158
+ version: "1.10.4"
159
159
  };
160
160
  socket.emit(external_common_js_namespaceObject.BridgeEvent.Connected, payload);
161
161
  Promise.resolve().then(()=>{
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-mode/io-server.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/bridge-mode/io-server.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import {\n type IncomingMessage,\n type ServerResponse,\n createServer,\n} from 'node:http';\nimport { sleep } from '@midscene/core/utils';\nimport { getDebug } from '@midscene/shared/logger';\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\nconst debug = getDebug('web:bridge:io-server');\n\ndeclare const __VERSION__: string;\n\n/**\n * Returns true if the given Origin header value is allowed to connect\n * to the bridge server. Trusted origins are:\n * - No Origin header (local Node.js processes like killRunningServer)\n * - chrome-extension:// origins (the Midscene Chrome extension)\n *\n * Browser pages (https://evil.com, etc.) are rejected to prevent\n * Cross-Site WebSocket Hijacking (CSWSH) attacks.\n */\nfunction isTrustedOrigin(origin: string | undefined): boolean {\n if (!origin) return true;\n if (origin.startsWith('chrome-extension://')) return true;\n return false;\n}\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(300);\n await client.close();\n } catch (e) {\n debug('failed to kill port: %O', 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 — no /bridge-auth endpoint needed since we use\n // pure Origin checking in the Socket.IO middleware below.\n const httpServer = createServer(\n (_req: IncomingMessage, res: ServerResponse) => {\n res.writeHead(404);\n res.end();\n },\n );\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 // Increase pingTimeout to tolerate Chrome MV3 Service Worker suspension.\n // The SW keepalive alarm fires every ~24s; default pingTimeout (20s) may\n // be too short if the SW is suspended between alarm pings.\n pingTimeout: 60000,\n });\n\n this.io.use((socket, next) => {\n // Reject connections from untrusted browser origins to prevent\n // Cross-Site WebSocket Hijacking (CSWSH) and unauthorized kill signals.\n // The browser automatically sets the Origin header on WebSocket\n // handshakes, and JavaScript cannot override it.\n const origin = socket.handshake.headers.origin;\n if (!isTrustedOrigin(origin)) {\n debug('connection rejected: untrusted origin=%s', origin);\n return next(new Error('origin not allowed'));\n }\n\n // Allow new connections to replace old ones (reconnection after\n // extension Stop→Start). If the old socket is already disconnected\n // or unresponsive, accept the new connection immediately.\n if (\n socket.handshake.url.includes(BridgeSignalKill) === false &&\n this.socket?.connected\n ) {\n return 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?.connected) {\n socket.emit(BridgeEvent.Refused);\n socket.disconnect();\n logMsg(\n 'refused new connection: server already connected by another client',\n );\n return;\n }\n\n // Clean up stale old socket if it exists but is no longer connected\n if (this.socket) {\n try {\n this.socket.disconnect();\n } catch (e) {\n logMsg(`failed to disconnect stale socket: ${e}`);\n }\n this.socket = null;\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 this.socket = null;\n\n // flush all pending calls as error and clean up completed calls\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 // Clean up completed calls to prevent memory leaks in long-running sessions\n for (const id in this.calls) {\n if (this.calls[id].responseTime) {\n delete this.calls[id];\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 logMsg(`failed to handle connection event: ${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 | string | null,\n response: any,\n ) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n // Ensure error is always an Error object (bridge client may send strings)\n if (error) {\n call.error =\n error instanceof Error\n ? error\n : new Error(typeof error === 'string' ? error : String(error));\n } else {\n call.error = undefined;\n }\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":["__webpack_require__","definition","key","Object","obj","prop","Symbol","debug","getDebug","isTrustedOrigin","origin","killRunningServer","port","host","client","ClientIO","DefaultBridgeServerPort","BridgeSignalKill","sleep","e","BridgeServer","opts","timeout","Promise","resolve","reject","Error","setTimeout","BridgeErrorCodeNoClientConnected","logMsg","httpServer","createServer","_req","res","err","Server","socket","next","url","console","clearTimeout","BridgeEvent","clientVersion","params","id","response","error","reason","call","errorMessage","payload","__VERSION__","String","undefined","Date","message","method","args","BridgeCallTimeout","timeoutId","closeProcess","onConnect","onDisconnect","closeConflictServer"],"mappings":"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"}
1
+ {"version":3,"file":"bridge-mode/io-server.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/bridge-mode/io-server.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import {\n type IncomingMessage,\n type ServerResponse,\n createServer,\n} from 'node:http';\nimport { sleep } from '@midscene/core/utils';\nimport { getDebug } from '@midscene/shared/logger';\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\nconst debug = getDebug('web:bridge:io-server');\n\ndeclare const __VERSION__: string;\n\n/**\n * Returns true if the given Origin header value is allowed to connect\n * to the bridge server. Trusted origins are:\n * - No Origin header (local Node.js processes like killRunningServer)\n * - chrome-extension:// origins (the Midscene Chrome extension)\n *\n * Browser pages (https://evil.com, etc.) are rejected to prevent\n * Cross-Site WebSocket Hijacking (CSWSH) attacks.\n */\nfunction isTrustedOrigin(origin: string | undefined): boolean {\n if (!origin) return true;\n if (origin.startsWith('chrome-extension://')) return true;\n return false;\n}\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(300);\n await client.close();\n } catch (e) {\n debug('failed to kill port: %O', 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 — no /bridge-auth endpoint needed since we use\n // pure Origin checking in the Socket.IO middleware below.\n const httpServer = createServer(\n (_req: IncomingMessage, res: ServerResponse) => {\n res.writeHead(404);\n res.end();\n },\n );\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 // Increase pingTimeout to tolerate Chrome MV3 Service Worker suspension.\n // The SW keepalive alarm fires every ~24s; default pingTimeout (20s) may\n // be too short if the SW is suspended between alarm pings.\n pingTimeout: 60000,\n });\n\n this.io.use((socket, next) => {\n // Reject connections from untrusted browser origins to prevent\n // Cross-Site WebSocket Hijacking (CSWSH) and unauthorized kill signals.\n // The browser automatically sets the Origin header on WebSocket\n // handshakes, and JavaScript cannot override it.\n const origin = socket.handshake.headers.origin;\n if (!isTrustedOrigin(origin)) {\n debug('connection rejected: untrusted origin=%s', origin);\n return next(new Error('origin not allowed'));\n }\n\n // Allow new connections to replace old ones (reconnection after\n // extension Stop→Start). If the old socket is already disconnected\n // or unresponsive, accept the new connection immediately.\n if (\n socket.handshake.url.includes(BridgeSignalKill) === false &&\n this.socket?.connected\n ) {\n return 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?.connected) {\n socket.emit(BridgeEvent.Refused);\n socket.disconnect();\n logMsg(\n 'refused new connection: server already connected by another client',\n );\n return;\n }\n\n // Clean up stale old socket if it exists but is no longer connected\n if (this.socket) {\n try {\n this.socket.disconnect();\n } catch (e) {\n logMsg(`failed to disconnect stale socket: ${e}`);\n }\n this.socket = null;\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 this.socket = null;\n\n // flush all pending calls as error and clean up completed calls\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 // Clean up completed calls to prevent memory leaks in long-running sessions\n for (const id in this.calls) {\n if (this.calls[id].responseTime) {\n delete this.calls[id];\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 logMsg(`failed to handle connection event: ${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 | string | null,\n response: any,\n ) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n // Ensure error is always an Error object (bridge client may send strings)\n if (error) {\n call.error =\n error instanceof Error\n ? error\n : new Error(typeof error === 'string' ? error : String(error));\n } else {\n call.error = undefined;\n }\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":["__webpack_require__","definition","key","Object","obj","prop","Symbol","debug","getDebug","isTrustedOrigin","origin","killRunningServer","port","host","client","ClientIO","DefaultBridgeServerPort","BridgeSignalKill","sleep","e","BridgeServer","opts","timeout","Promise","resolve","reject","Error","setTimeout","BridgeErrorCodeNoClientConnected","logMsg","httpServer","createServer","_req","res","err","Server","socket","next","url","console","clearTimeout","BridgeEvent","clientVersion","params","id","response","error","reason","call","errorMessage","payload","__VERSION__","String","undefined","Date","message","method","args","BridgeCallTimeout","timeoutId","closeProcess","onConnect","onDisconnect","closeConflictServer"],"mappings":"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"}
@@ -138,7 +138,7 @@ class ExtensionBridgePageBrowserSide extends page_js_default() {
138
138
  throw new Error('Connection denied by user');
139
139
  }
140
140
  }
141
- this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.10.4-beta-20260715034325.0`, 'log');
141
+ this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.10.4`, 'log');
142
142
  }
143
143
  async connect() {
144
144
  return await this.setupBridgeClient();