@one2x/playwright 1.57.0-alpha.1 → 1.57.0-alpha.2

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 (155) hide show
  1. package/package.json +2 -2
  2. package/lib/agents/generateAgents.js.map +0 -7
  3. package/lib/common/config.js.map +0 -7
  4. package/lib/common/configLoader.js.map +0 -7
  5. package/lib/common/esmLoaderHost.js.map +0 -7
  6. package/lib/common/expectBundle.js.map +0 -7
  7. package/lib/common/expectBundleImpl.js.map +0 -7
  8. package/lib/common/fixtures.js.map +0 -7
  9. package/lib/common/globals.js.map +0 -7
  10. package/lib/common/ipc.js.map +0 -7
  11. package/lib/common/poolBuilder.js.map +0 -7
  12. package/lib/common/process.js.map +0 -7
  13. package/lib/common/suiteUtils.js.map +0 -7
  14. package/lib/common/test.js.map +0 -7
  15. package/lib/common/testLoader.js.map +0 -7
  16. package/lib/common/testType.js.map +0 -7
  17. package/lib/common/validators.js.map +0 -7
  18. package/lib/fsWatcher.js.map +0 -7
  19. package/lib/index.js.map +0 -7
  20. package/lib/internalsForTest.js.map +0 -7
  21. package/lib/isomorphic/events.js.map +0 -7
  22. package/lib/isomorphic/folders.js.map +0 -7
  23. package/lib/isomorphic/stringInternPool.js.map +0 -7
  24. package/lib/isomorphic/teleReceiver.js.map +0 -7
  25. package/lib/isomorphic/teleSuiteUpdater.js.map +0 -7
  26. package/lib/isomorphic/testServerConnection.js.map +0 -7
  27. package/lib/isomorphic/testServerInterface.js.map +0 -7
  28. package/lib/isomorphic/testTree.js.map +0 -7
  29. package/lib/isomorphic/types.d.js.map +0 -7
  30. package/lib/loader/loaderMain.js.map +0 -7
  31. package/lib/matchers/expect.js.map +0 -7
  32. package/lib/matchers/matcherHint.js.map +0 -7
  33. package/lib/matchers/matchers.js.map +0 -7
  34. package/lib/matchers/toBeTruthy.js.map +0 -7
  35. package/lib/matchers/toEqual.js.map +0 -7
  36. package/lib/matchers/toHaveURL.js.map +0 -7
  37. package/lib/matchers/toMatchAriaSnapshot.js.map +0 -7
  38. package/lib/matchers/toMatchSnapshot.js.map +0 -7
  39. package/lib/matchers/toMatchText.js.map +0 -7
  40. package/lib/mcp/browser/actions.d.js.map +0 -7
  41. package/lib/mcp/browser/browserContextFactory.js.map +0 -7
  42. package/lib/mcp/browser/browserServerBackend.js.map +0 -7
  43. package/lib/mcp/browser/codegen.js.map +0 -7
  44. package/lib/mcp/browser/config.js.map +0 -7
  45. package/lib/mcp/browser/context.js.map +0 -7
  46. package/lib/mcp/browser/response.js.map +0 -7
  47. package/lib/mcp/browser/sessionLog.js.map +0 -7
  48. package/lib/mcp/browser/tab.js.map +0 -7
  49. package/lib/mcp/browser/tools/actionRetry.js.map +0 -7
  50. package/lib/mcp/browser/tools/common.js.map +0 -7
  51. package/lib/mcp/browser/tools/console.js.map +0 -7
  52. package/lib/mcp/browser/tools/dialogs.js.map +0 -7
  53. package/lib/mcp/browser/tools/evaluate.js.map +0 -7
  54. package/lib/mcp/browser/tools/files.js.map +0 -7
  55. package/lib/mcp/browser/tools/form.js.map +0 -7
  56. package/lib/mcp/browser/tools/install.js.map +0 -7
  57. package/lib/mcp/browser/tools/keyboard.js.map +0 -7
  58. package/lib/mcp/browser/tools/mouse.js.map +0 -7
  59. package/lib/mcp/browser/tools/navigate.js.map +0 -7
  60. package/lib/mcp/browser/tools/network.js.map +0 -7
  61. package/lib/mcp/browser/tools/pdf.js.map +0 -7
  62. package/lib/mcp/browser/tools/screenshot.js.map +0 -7
  63. package/lib/mcp/browser/tools/snapshot.js.map +0 -7
  64. package/lib/mcp/browser/tools/tabs.js.map +0 -7
  65. package/lib/mcp/browser/tools/tool.js.map +0 -7
  66. package/lib/mcp/browser/tools/tracing.js.map +0 -7
  67. package/lib/mcp/browser/tools/utils.js.map +0 -7
  68. package/lib/mcp/browser/tools/verify.js.map +0 -7
  69. package/lib/mcp/browser/tools/wait.js.map +0 -7
  70. package/lib/mcp/browser/tools.js.map +0 -7
  71. package/lib/mcp/browser/watchdog.js.map +0 -7
  72. package/lib/mcp/config.d.js.map +0 -7
  73. package/lib/mcp/extension/cdpRelay.js.map +0 -7
  74. package/lib/mcp/extension/extensionContextFactory.js.map +0 -7
  75. package/lib/mcp/extension/protocol.js.map +0 -7
  76. package/lib/mcp/index.js.map +0 -7
  77. package/lib/mcp/log.js.map +0 -7
  78. package/lib/mcp/program.js.map +0 -7
  79. package/lib/mcp/sdk/bundle.js.map +0 -7
  80. package/lib/mcp/sdk/exports.js.map +0 -7
  81. package/lib/mcp/sdk/http.js.map +0 -7
  82. package/lib/mcp/sdk/inProcessTransport.js.map +0 -7
  83. package/lib/mcp/sdk/mdb.js.map +0 -7
  84. package/lib/mcp/sdk/proxyBackend.js.map +0 -7
  85. package/lib/mcp/sdk/server.js.map +0 -7
  86. package/lib/mcp/sdk/tool.js.map +0 -7
  87. package/lib/mcp/test/browserBackend.js.map +0 -7
  88. package/lib/mcp/test/generatorTools.js.map +0 -7
  89. package/lib/mcp/test/plannerTools.js.map +0 -7
  90. package/lib/mcp/test/seed.js.map +0 -7
  91. package/lib/mcp/test/streams.js.map +0 -7
  92. package/lib/mcp/test/testBackend.js.map +0 -7
  93. package/lib/mcp/test/testContext.js.map +0 -7
  94. package/lib/mcp/test/testTool.js.map +0 -7
  95. package/lib/mcp/test/testTools.js.map +0 -7
  96. package/lib/mcpBundleImpl.js.map +0 -7
  97. package/lib/plugins/gitCommitInfoPlugin.js.map +0 -7
  98. package/lib/plugins/index.js.map +0 -7
  99. package/lib/plugins/webServerPlugin.js.map +0 -7
  100. package/lib/program.js.map +0 -7
  101. package/lib/reporters/base.js.map +0 -7
  102. package/lib/reporters/blob.js.map +0 -7
  103. package/lib/reporters/dot.js.map +0 -7
  104. package/lib/reporters/empty.js.map +0 -7
  105. package/lib/reporters/github.js.map +0 -7
  106. package/lib/reporters/html.js.map +0 -7
  107. package/lib/reporters/internalReporter.js.map +0 -7
  108. package/lib/reporters/json.js.map +0 -7
  109. package/lib/reporters/junit.js.map +0 -7
  110. package/lib/reporters/line.js.map +0 -7
  111. package/lib/reporters/list.js.map +0 -7
  112. package/lib/reporters/listModeReporter.js.map +0 -7
  113. package/lib/reporters/markdown.js.map +0 -7
  114. package/lib/reporters/merge.js.map +0 -7
  115. package/lib/reporters/multiplexer.js.map +0 -7
  116. package/lib/reporters/reporterV2.js.map +0 -7
  117. package/lib/reporters/teleEmitter.js.map +0 -7
  118. package/lib/reporters/versions/blobV1.js.map +0 -7
  119. package/lib/runner/dispatcher.js.map +0 -7
  120. package/lib/runner/failureTracker.js.map +0 -7
  121. package/lib/runner/lastRun.js.map +0 -7
  122. package/lib/runner/loadUtils.js.map +0 -7
  123. package/lib/runner/loaderHost.js.map +0 -7
  124. package/lib/runner/processHost.js.map +0 -7
  125. package/lib/runner/projectUtils.js.map +0 -7
  126. package/lib/runner/rebase.js.map +0 -7
  127. package/lib/runner/reporters.js.map +0 -7
  128. package/lib/runner/runner.js +0 -110
  129. package/lib/runner/sigIntWatcher.js.map +0 -7
  130. package/lib/runner/taskRunner.js.map +0 -7
  131. package/lib/runner/tasks.js.map +0 -7
  132. package/lib/runner/testGroups.js.map +0 -7
  133. package/lib/runner/testRunner.js.map +0 -7
  134. package/lib/runner/testServer.js.map +0 -7
  135. package/lib/runner/uiModeReporter.js.map +0 -7
  136. package/lib/runner/vcs.js.map +0 -7
  137. package/lib/runner/watchMode.js.map +0 -7
  138. package/lib/runner/workerHost.js.map +0 -7
  139. package/lib/third_party/pirates.js.map +0 -7
  140. package/lib/third_party/tsconfig-loader.js.map +0 -7
  141. package/lib/transform/babelBundle.js.map +0 -7
  142. package/lib/transform/babelBundleImpl.js.map +0 -7
  143. package/lib/transform/compilationCache.js.map +0 -7
  144. package/lib/transform/esmLoader.js.map +0 -7
  145. package/lib/transform/portTransport.js.map +0 -7
  146. package/lib/transform/transform.js.map +0 -7
  147. package/lib/util.js.map +0 -7
  148. package/lib/utilsBundle.js.map +0 -7
  149. package/lib/utilsBundleImpl.js.map +0 -7
  150. package/lib/worker/fixtureRunner.js.map +0 -7
  151. package/lib/worker/testInfo.js.map +0 -7
  152. package/lib/worker/testTracing.js.map +0 -7
  153. package/lib/worker/timeoutManager.js.map +0 -7
  154. package/lib/worker/util.js.map +0 -7
  155. package/lib/worker/workerMain.js.map +0 -7
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/matchers/toMatchSnapshot.ts"],
4
- "sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { compareBuffersOrStrings, getComparator, isString } from 'playwright-core/lib/utils';\nimport { colors } from 'playwright-core/lib/utils';\nimport { mime } from 'playwright-core/lib/utilsBundle';\n\nimport { addSuffixToFilePath, expectTypes } from '../util';\nimport { callLogText, formatMatcherMessage } from './matcherHint';\nimport { currentTestInfo } from '../common/globals';\n\nimport type { MatcherResult } from './matcherHint';\nimport type { ExpectMatcherStateInternal } from './matchers';\nimport type { FullProjectInternal } from '../common/config';\nimport type { TestInfoImpl, TestStepInfoImpl } from '../worker/testInfo';\nimport type { Locator, Page } from 'playwright-core';\nimport type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page';\nimport type { Comparator, ImageComparatorOptions } from 'playwright-core/lib/utils';\n\ntype NameOrSegments = string | string[];\n\ntype ImageMatcherResult = MatcherResult<string, string> & { diff?: string };\n\ntype ToHaveScreenshotConfigOptions = NonNullable<NonNullable<FullProjectInternal['expect']>['toHaveScreenshot']> & {\n _comparator?: string;\n};\n\ntype ToHaveScreenshotOptions = ToHaveScreenshotConfigOptions & {\n clip?: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n fullPage?: boolean;\n mask?: Array<Locator>;\n maskColor?: string;\n omitBackground?: boolean;\n timeout?: number;\n};\n\n// Keep in sync with above (begin).\nconst NonConfigProperties: (keyof ToHaveScreenshotOptions)[] = [\n 'clip',\n 'fullPage',\n 'mask',\n 'maskColor',\n 'omitBackground',\n 'timeout',\n];\n// Keep in sync with above (end).\n\nclass SnapshotHelper {\n readonly testInfo: TestInfoImpl;\n readonly name: string;\n readonly attachmentBaseName: string;\n readonly legacyExpectedPath: string;\n readonly previousPath: string;\n readonly expectedPath: string;\n readonly actualPath: string;\n readonly diffPath: string;\n readonly mimeType: string;\n readonly kind: 'Screenshot'|'Snapshot';\n readonly updateSnapshots: 'all' | 'changed' | 'missing' | 'none';\n readonly comparator: Comparator;\n readonly options: Omit<ToHaveScreenshotOptions, '_comparator'> & { comparator?: string };\n readonly matcherName: string;\n readonly locator: Locator | undefined;\n\n constructor(\n testInfo: TestInfoImpl,\n matcherName: 'toMatchSnapshot' | 'toHaveScreenshot',\n locator: Locator | undefined,\n anonymousSnapshotExtension: string | undefined,\n configOptions: ToHaveScreenshotConfigOptions,\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions,\n optOptions: ToHaveScreenshotOptions,\n ) {\n let name: NameOrSegments | undefined;\n if (Array.isArray(nameOrOptions) || typeof nameOrOptions === 'string') {\n name = nameOrOptions;\n this.options = { ...optOptions };\n } else {\n const { name: nameFromOptions, ...options } = nameOrOptions;\n this.options = options;\n name = nameFromOptions;\n }\n\n this.name = Array.isArray(name) ? name.join(path.sep) : name || '';\n const resolvedPaths = testInfo._resolveSnapshotPaths(matcherName === 'toHaveScreenshot' ? 'screenshot' : 'snapshot', name, 'updateSnapshotIndex', anonymousSnapshotExtension);\n this.expectedPath = resolvedPaths.absoluteSnapshotPath;\n this.attachmentBaseName = resolvedPaths.relativeOutputPath;\n\n const outputBasePath = testInfo._getOutputPath(resolvedPaths.relativeOutputPath);\n this.legacyExpectedPath = addSuffixToFilePath(outputBasePath, '-expected');\n this.previousPath = addSuffixToFilePath(outputBasePath, '-previous');\n this.actualPath = addSuffixToFilePath(outputBasePath, '-actual');\n this.diffPath = addSuffixToFilePath(outputBasePath, '-diff');\n\n const filteredConfigOptions = { ...configOptions };\n for (const prop of NonConfigProperties)\n delete (filteredConfigOptions as any)[prop];\n this.options = {\n ...filteredConfigOptions,\n ...this.options,\n };\n\n // While comparator is not a part of the public API, it is translated here.\n if ((this.options as any)._comparator) {\n this.options.comparator = (this.options as any)._comparator;\n delete (this.options as any)._comparator;\n }\n\n if (this.options.maxDiffPixels !== undefined && this.options.maxDiffPixels < 0)\n throw new Error('`maxDiffPixels` option value must be non-negative integer');\n\n if (this.options.maxDiffPixelRatio !== undefined && (this.options.maxDiffPixelRatio < 0 || this.options.maxDiffPixelRatio > 1))\n throw new Error('`maxDiffPixelRatio` option value must be between 0 and 1');\n\n this.matcherName = matcherName;\n this.locator = locator;\n\n this.updateSnapshots = testInfo.config.updateSnapshots;\n this.mimeType = mime.getType(path.basename(this.expectedPath)) ?? 'application/octet-stream';\n this.comparator = getComparator(this.mimeType);\n\n this.testInfo = testInfo;\n this.kind = this.mimeType.startsWith('image/') ? 'Screenshot' : 'Snapshot';\n }\n\n createMatcherResult(message: string, pass: boolean, log?: string[]): ImageMatcherResult {\n const unfiltered: ImageMatcherResult = {\n name: this.matcherName,\n expected: this.expectedPath,\n actual: this.actualPath,\n diff: this.diffPath,\n pass,\n message: () => message,\n log,\n };\n return Object.fromEntries(Object.entries(unfiltered).filter(([_, v]) => v !== undefined)) as ImageMatcherResult;\n }\n\n handleMissingNegated(): ImageMatcherResult {\n const isWriteMissingMode = this.updateSnapshots !== 'none';\n const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', matchers using \".not\" won\\'t write them automatically.' : '.'}`;\n // NOTE: 'isNot' matcher implies inversed value.\n return this.createMatcherResult(message, true);\n }\n\n handleDifferentNegated(): ImageMatcherResult {\n // NOTE: 'isNot' matcher implies inversed value.\n return this.createMatcherResult('', false);\n }\n\n handleMatchingNegated(): ImageMatcherResult {\n const message = [\n colors.red(`${this.kind} comparison failed:`),\n '',\n indent('Expected result should be different from the actual one.', ' '),\n ].join('\\n');\n // NOTE: 'isNot' matcher implies inversed value.\n return this.createMatcherResult(message, true);\n }\n\n handleMissing(actual: Buffer | string, step: TestStepInfoImpl | undefined): ImageMatcherResult {\n const isWriteMissingMode = this.updateSnapshots !== 'none';\n if (isWriteMissingMode)\n writeFileSync(this.expectedPath, actual);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-expected'), contentType: this.mimeType, path: this.expectedPath });\n writeFileSync(this.actualPath, actual);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-actual'), contentType: this.mimeType, path: this.actualPath });\n const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', writing actual.' : '.'}`;\n if (this.updateSnapshots === 'all' || this.updateSnapshots === 'changed') {\n /* eslint-disable no-console */\n console.log(message);\n return this.createMatcherResult(message, true);\n }\n if (this.updateSnapshots === 'missing') {\n this.testInfo._hasNonRetriableError = true;\n this.testInfo._failWithError(new Error(message));\n return this.createMatcherResult('', true);\n }\n return this.createMatcherResult(message, false);\n }\n\n handleDifferent(\n actual: Buffer | string | undefined,\n expected: Buffer | string | undefined,\n previous: Buffer | string | undefined,\n diff: Buffer | string | undefined,\n header: string,\n diffError: string,\n log: string[] | undefined,\n step: TestStepInfoImpl | undefined): ImageMatcherResult {\n const output = [`${header}${indent(diffError, ' ')}`];\n if (this.name) {\n output.push('');\n output.push(` Snapshot: ${this.name}`);\n }\n if (expected !== undefined) {\n // Copy the expectation inside the `test-results/` folder for backwards compatibility,\n // so that one can upload `test-results/` directory and have all the data inside.\n writeFileSync(this.legacyExpectedPath, expected);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-expected'), contentType: this.mimeType, path: this.expectedPath });\n }\n if (previous !== undefined) {\n writeFileSync(this.previousPath, previous);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-previous'), contentType: this.mimeType, path: this.previousPath });\n }\n if (actual !== undefined) {\n writeFileSync(this.actualPath, actual);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-actual'), contentType: this.mimeType, path: this.actualPath });\n }\n if (diff !== undefined) {\n writeFileSync(this.diffPath, diff);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-diff'), contentType: this.mimeType, path: this.diffPath });\n }\n\n if (log?.length)\n output.push(callLogText(log));\n else\n output.push('');\n\n return this.createMatcherResult(output.join('\\n'), false, log);\n }\n\n handleMatching(): ImageMatcherResult {\n return this.createMatcherResult('', true);\n }\n}\n\nexport function toMatchSnapshot(\n this: ExpectMatcherStateInternal,\n received: Buffer | string,\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ImageComparatorOptions = {},\n optOptions: ImageComparatorOptions = {}\n): MatcherResult<NameOrSegments | { name?: NameOrSegments }, string> {\n const testInfo = currentTestInfo();\n if (!testInfo)\n throw new Error(`toMatchSnapshot() must be called during the test`);\n if (received instanceof Promise)\n throw new Error('An unresolved Promise was passed to toMatchSnapshot(), make sure to resolve it by adding await to it.');\n\n if (testInfo._projectInternal.ignoreSnapshots)\n return { pass: !this.isNot, message: () => '', name: 'toMatchSnapshot', expected: nameOrOptions };\n\n const configOptions = testInfo._projectInternal.expect?.toMatchSnapshot || {};\n const helper = new SnapshotHelper(\n testInfo, 'toMatchSnapshot', undefined, '.' + determineFileExtension(received),\n configOptions, nameOrOptions, optOptions);\n\n if (this.isNot) {\n if (!fs.existsSync(helper.expectedPath))\n return helper.handleMissingNegated();\n const isDifferent = !!helper.comparator(received, fs.readFileSync(helper.expectedPath), helper.options);\n return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated();\n }\n\n if (!fs.existsSync(helper.expectedPath))\n return helper.handleMissing(received, this._stepInfo);\n\n const expected = fs.readFileSync(helper.expectedPath);\n\n if (helper.updateSnapshots === 'all') {\n if (!compareBuffersOrStrings(received, expected))\n return helper.handleMatching();\n writeFileSync(helper.expectedPath, received);\n /* eslint-disable no-console */\n console.log(helper.expectedPath + ' is not the same, writing actual.');\n return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);\n }\n\n if (helper.updateSnapshots === 'changed') {\n const result = helper.comparator(received, expected, helper.options);\n if (!result)\n return helper.handleMatching();\n writeFileSync(helper.expectedPath, received);\n /* eslint-disable no-console */\n console.log(helper.expectedPath + ' does not match, writing actual.');\n return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);\n }\n\n const result = helper.comparator(received, expected, helper.options);\n if (!result)\n return helper.handleMatching();\n\n const header = formatMatcherMessage(this, { matcherName: 'toMatchSnapshot', receiver: isString(received) ? 'string' : 'Buffer', expectation: 'expected' });\n return helper.handleDifferent(received, expected, undefined, result.diff, header, result.errorMessage, undefined, this._stepInfo);\n}\n\nexport function toHaveScreenshotStepTitle(\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {},\n optOptions: ToHaveScreenshotOptions = {}\n): string {\n let name: NameOrSegments | undefined;\n if (typeof nameOrOptions === 'object' && !Array.isArray(nameOrOptions))\n name = nameOrOptions.name;\n else\n name = nameOrOptions;\n return Array.isArray(name) ? name.join(path.sep) : name || '';\n}\n\nexport async function toHaveScreenshot(\n this: ExpectMatcherStateInternal,\n pageOrLocator: Page | Locator,\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {},\n optOptions: ToHaveScreenshotOptions = {}\n): Promise<MatcherResult<NameOrSegments | { name?: NameOrSegments }, string>> {\n const testInfo = currentTestInfo();\n if (!testInfo)\n throw new Error(`toHaveScreenshot() must be called during the test`);\n\n if (testInfo._projectInternal.ignoreSnapshots)\n return { pass: !this.isNot, message: () => '', name: 'toHaveScreenshot', expected: nameOrOptions };\n\n expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot');\n const [page, locator] = pageOrLocator.constructor.name === 'Page' ? [(pageOrLocator as PageEx), undefined] : [(pageOrLocator as Locator).page() as PageEx, pageOrLocator as Locator];\n const configOptions = testInfo._projectInternal.expect?.toHaveScreenshot || {};\n const helper = new SnapshotHelper(testInfo, 'toHaveScreenshot', locator, undefined, configOptions, nameOrOptions, optOptions);\n if (!helper.expectedPath.toLowerCase().endsWith('.png'))\n throw new Error(`Screenshot name \"${path.basename(helper.expectedPath)}\" must have '.png' extension`);\n expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot');\n const style = await loadScreenshotStyles(helper.options.stylePath);\n const timeout = helper.options.timeout ?? this.timeout;\n const expectScreenshotOptions: ExpectScreenshotOptions = {\n locator,\n animations: helper.options.animations ?? 'disabled',\n caret: helper.options.caret ?? 'hide',\n clip: helper.options.clip,\n fullPage: helper.options.fullPage,\n mask: helper.options.mask,\n maskColor: helper.options.maskColor,\n omitBackground: helper.options.omitBackground,\n scale: helper.options.scale ?? 'css',\n style,\n isNot: !!this.isNot,\n timeout,\n comparator: helper.options.comparator,\n maxDiffPixels: helper.options.maxDiffPixels,\n maxDiffPixelRatio: helper.options.maxDiffPixelRatio,\n threshold: helper.options.threshold,\n };\n\n const hasSnapshot = fs.existsSync(helper.expectedPath);\n if (this.isNot) {\n if (!hasSnapshot)\n return helper.handleMissingNegated();\n\n // Having `errorMessage` means we timed out while waiting\n // for screenshots not to match, so screenshots\n // are actually the same in the end.\n expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath);\n const isDifferent = !(await page._expectScreenshot(expectScreenshotOptions)).errorMessage;\n return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated();\n }\n\n // Fast path: there's no screenshot and we don't intend to update it.\n if (helper.updateSnapshots === 'none' && !hasSnapshot)\n return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false);\n\n if (!hasSnapshot) {\n // Regenerate a new screenshot by waiting until two screenshots are the same.\n const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions);\n // We tried re-generating new snapshot but failed.\n // This can be due to e.g. spinning animation, so we want to show it as a diff.\n if (errorMessage) {\n const header = formatMatcherMessage(this, { matcherName: 'toHaveScreenshot', locator, expectation: 'expected', timeout, timedOut });\n return helper.handleDifferent(actual, undefined, previous, diff, header, errorMessage, log, this._stepInfo);\n }\n\n // We successfully generated new screenshot.\n return helper.handleMissing(actual!, this._stepInfo);\n }\n\n // General case:\n // - snapshot exists\n // - regular matcher (i.e. not a `.not`)\n const expected = await fs.promises.readFile(helper.expectedPath);\n expectScreenshotOptions.expected = helper.updateSnapshots === 'all' ? undefined : expected;\n\n const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions);\n const writeFiles = (actualBuffer: Buffer) => {\n writeFileSync(helper.expectedPath, actualBuffer);\n writeFileSync(helper.actualPath, actualBuffer);\n /* eslint-disable no-console */\n console.log(helper.expectedPath + ' is re-generated, writing actual.');\n return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);\n };\n\n if (!errorMessage) {\n // Screenshot is matching, but is not necessarily the same as the expected.\n if (helper.updateSnapshots === 'all' && actual && compareBuffersOrStrings(actual, expected)) {\n console.log(helper.expectedPath + ' is re-generated, writing actual.');\n return writeFiles(actual);\n }\n return helper.handleMatching();\n }\n\n if (helper.updateSnapshots === 'changed' || helper.updateSnapshots === 'all') {\n if (actual)\n return writeFiles(actual);\n let header = formatMatcherMessage(this, { matcherName: 'toHaveScreenshot', locator, expectation: 'expected', timeout, timedOut });\n header += ' Failed to re-generate expected.\\n';\n return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);\n }\n\n const header = formatMatcherMessage(this, { matcherName: 'toHaveScreenshot', locator, expectation: 'expected', timeout, timedOut });\n return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);\n}\n\nfunction writeFileSync(aPath: string, content: Buffer | string) {\n fs.mkdirSync(path.dirname(aPath), { recursive: true });\n fs.writeFileSync(aPath, content);\n}\n\nfunction indent(lines: string, tab: string) {\n return lines.replace(/^(?=.+$)/gm, tab);\n}\n\nfunction determineFileExtension(file: string | Buffer): string {\n if (typeof file === 'string')\n return 'txt';\n if (compareMagicBytes(file, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))\n return 'png';\n if (compareMagicBytes(file, [0xff, 0xd8, 0xff]))\n return 'jpg';\n return 'dat';\n}\n\nfunction compareMagicBytes(file: Buffer, magicBytes: number[]): boolean {\n return Buffer.compare(Buffer.from(magicBytes), file.slice(0, magicBytes.length)) === 0;\n}\n\nasync function loadScreenshotStyles(stylePath?: string | string[]): Promise<string | undefined> {\n if (!stylePath)\n return;\n\n const stylePaths = Array.isArray(stylePath) ? stylePath : [stylePath];\n const styles = await Promise.all(stylePaths.map(async stylePath => {\n const text = await fs.promises.readFile(stylePath, 'utf8');\n return text.trim();\n }));\n return styles.join('\\n').trim() || undefined;\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_utils", "path", "fs", "result", "actual", "previous", "diff", "errorMessage", "log", "timedOut", "header", "stylePath"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/matchers/toMatchText.ts"],
4
- "sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\nimport { expectTypes } from '../util';\nimport {\n printReceivedStringContainExpectedResult,\n printReceivedStringContainExpectedSubstring\n} from './expect';\nimport { formatMatcherMessage } from './matcherHint';\nimport { EXPECTED_COLOR } from '../common/expectBundle';\n\nimport type { MatcherResult } from './matcherHint';\nimport type { ExpectMatcherState } from '../../types/test';\nimport type { Page, Locator } from 'playwright-core';\n\nexport async function toMatchText(\n this: ExpectMatcherState,\n matcherName: string,\n receiver: Locator | Page,\n receiverType: 'Locator' | 'Page',\n query: (isNot: boolean, timeout: number) => Promise<{ matches: boolean, received?: string, log?: string[], timedOut?: boolean, errorMessage?: string }>,\n expected: string | RegExp,\n options: { timeout?: number, matchSubstring?: boolean } = {},\n): Promise<MatcherResult<string | RegExp, string>> {\n expectTypes(receiver, [receiverType], matcherName);\n const locator = receiverType === 'Locator' ? receiver as Locator : undefined;\n\n if (\n !(typeof expected === 'string') &&\n !(expected && typeof expected.test === 'function')\n ) {\n const errorMessage = `Error: ${EXPECTED_COLOR('expected')} value must be a string or regular expression\\n${this.utils.printWithType('Expected', expected, this.utils.printExpected)}`;\n throw new Error(formatMatcherMessage(this, { locator, matcherName, expectation: 'expected', errorMessage }));\n }\n\n const timeout = options.timeout ?? this.timeout;\n\n const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);\n\n if (pass === !this.isNot) {\n return {\n name: matcherName,\n message: () => '',\n pass,\n expected\n };\n }\n\n const expectedSuffix = typeof expected === 'string' ? (options.matchSubstring ? ' substring' : '') : ' pattern';\n const receivedSuffix = typeof expected === 'string' ? (options.matchSubstring ? ' string' : '') : ' string';\n const receivedString = received || '';\n let printedReceived: string | undefined;\n let printedExpected: string | undefined;\n let printedDiff: string | undefined;\n if (pass) {\n if (typeof expected === 'string') {\n printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;\n if (!errorMessage) {\n const formattedReceived = printReceivedStringContainExpectedSubstring(receivedString, receivedString.indexOf(expected), expected.length);\n printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;\n }\n } else {\n printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;\n if (!errorMessage) {\n const formattedReceived = printReceivedStringContainExpectedResult(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null);\n printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;\n }\n }\n } else {\n if (errorMessage)\n printedExpected = `Expected${expectedSuffix}: ${this.utils.printExpected(expected)}`;\n else\n printedDiff = this.utils.printDiffOrStringify(expected, receivedString, `Expected${expectedSuffix}`, `Received${receivedSuffix}`, false);\n }\n\n const message = () => {\n return formatMatcherMessage(this, {\n matcherName,\n expectation: 'expected',\n locator,\n timeout,\n timedOut,\n printedExpected,\n printedReceived,\n printedDiff,\n log,\n errorMessage,\n });\n };\n\n return {\n name: matcherName,\n expected,\n message,\n pass,\n actual: received,\n log,\n timeout: timedOut ? timeout : undefined,\n };\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,kBAA4B;AAC5B,oBAGO;AACP,yBAAqC;AACrC,0BAA+B;AAM/B,eAAsB,YAEpB,aACA,UACA,cACA,OACA,UACA,UAA0D,CAAC,GACV;AACjD,+BAAY,UAAU,CAAC,YAAY,GAAG,WAAW;AACjD,QAAM,UAAU,iBAAiB,YAAY,WAAsB;AAEnE,MACE,EAAE,OAAO,aAAa,aACtB,EAAE,YAAY,OAAO,SAAS,SAAS,aACvC;AACA,UAAMA,gBAAe,cAAU,oCAAe,UAAU,CAAC;AAAA,EAAkD,KAAK,MAAM,cAAc,YAAY,UAAU,KAAK,MAAM,aAAa,CAAC;AACnL,UAAM,IAAI,UAAM,yCAAqB,MAAM,EAAE,SAAS,aAAa,aAAa,YAAY,cAAAA,cAAa,CAAC,CAAC;AAAA,EAC7G;AAEA,QAAM,UAAU,QAAQ,WAAW,KAAK;AAExC,QAAM,EAAE,SAAS,MAAM,UAAU,KAAK,UAAU,aAAa,IAAI,MAAM,MAAM,CAAC,CAAC,KAAK,OAAO,OAAO;AAElG,MAAI,SAAS,CAAC,KAAK,OAAO;AACxB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,aAAa,WAAY,QAAQ,iBAAiB,eAAe,KAAM;AACrG,QAAM,iBAAiB,OAAO,aAAa,WAAY,QAAQ,iBAAiB,YAAY,KAAM;AAClG,QAAM,iBAAiB,YAAY;AACnC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,MAAM;AACR,QAAI,OAAO,aAAa,UAAU;AAChC,wBAAkB,WAAW,cAAc,SAAS,KAAK,MAAM,cAAc,QAAQ,CAAC;AACtF,UAAI,CAAC,cAAc;AACjB,cAAM,wBAAoB,2DAA4C,gBAAgB,eAAe,QAAQ,QAAQ,GAAG,SAAS,MAAM;AACvI,0BAAkB,WAAW,cAAc,KAAK,iBAAiB;AAAA,MACnE;AAAA,IACF,OAAO;AACL,wBAAkB,WAAW,cAAc,SAAS,KAAK,MAAM,cAAc,QAAQ,CAAC;AACtF,UAAI,CAAC,cAAc;AACjB,cAAM,wBAAoB,wDAAyC,gBAAgB,OAAO,SAAS,SAAS,aAAa,SAAS,KAAK,cAAc,IAAI,IAAI;AAC7J,0BAAkB,WAAW,cAAc,KAAK,iBAAiB;AAAA,MACnE;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI;AACF,wBAAkB,WAAW,cAAc,KAAK,KAAK,MAAM,cAAc,QAAQ,CAAC;AAAA;AAElF,oBAAc,KAAK,MAAM,qBAAqB,UAAU,gBAAgB,WAAW,cAAc,IAAI,WAAW,cAAc,IAAI,KAAK;AAAA,EAC3I;AAEA,QAAM,UAAU,MAAM;AACpB,eAAO,yCAAqB,MAAM;AAAA,MAChC;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,SAAS,WAAW,UAAU;AAAA,EAChC;AACF;",
6
- "names": ["errorMessage"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/actions.d.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype Point = { x: number, y: number };\n\nexport type ActionName =\n 'check' |\n 'click' |\n 'closePage' |\n 'fill' |\n 'navigate' |\n 'openPage' |\n 'press' |\n 'select' |\n 'uncheck' |\n 'setInputFiles' |\n 'assertText' |\n 'assertValue' |\n 'assertChecked' |\n 'assertVisible' |\n 'assertSnapshot';\n\nexport type ActionBase = {\n name: ActionName,\n signals: Signal[],\n ariaSnapshot?: string,\n};\n\nexport type ActionWithSelector = ActionBase & {\n selector: string,\n ref?: string,\n};\n\nexport type ClickAction = ActionWithSelector & {\n name: 'click',\n button: 'left' | 'middle' | 'right',\n modifiers: number,\n clickCount: number,\n position?: Point,\n};\n\nexport type CheckAction = ActionWithSelector & {\n name: 'check',\n};\n\nexport type UncheckAction = ActionWithSelector & {\n name: 'uncheck',\n};\n\nexport type FillAction = ActionWithSelector & {\n name: 'fill',\n text: string,\n};\n\nexport type NavigateAction = ActionBase & {\n name: 'navigate',\n url: string,\n};\n\nexport type OpenPageAction = ActionBase & {\n name: 'openPage',\n url: string,\n};\n\nexport type ClosesPageAction = ActionBase & {\n name: 'closePage',\n};\n\nexport type PressAction = ActionWithSelector & {\n name: 'press',\n key: string,\n modifiers: number,\n};\n\nexport type SelectAction = ActionWithSelector & {\n name: 'select',\n options: string[],\n};\n\nexport type SetInputFilesAction = ActionWithSelector & {\n name: 'setInputFiles',\n files: string[],\n};\n\nexport type AssertTextAction = ActionWithSelector & {\n name: 'assertText',\n text: string,\n substring: boolean,\n};\n\nexport type AssertValueAction = ActionWithSelector & {\n name: 'assertValue',\n value: string,\n};\n\nexport type AssertCheckedAction = ActionWithSelector & {\n name: 'assertChecked',\n checked: boolean,\n};\n\nexport type AssertVisibleAction = ActionWithSelector & {\n name: 'assertVisible',\n};\n\nexport type AssertSnapshotAction = ActionWithSelector & {\n name: 'assertSnapshot',\n ariaSnapshot: string,\n};\n\nexport type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageAction | UncheckAction | FillAction | NavigateAction | PressAction | SelectAction | SetInputFilesAction | AssertTextAction | AssertValueAction | AssertCheckedAction | AssertVisibleAction | AssertSnapshotAction;\nexport type AssertAction = AssertCheckedAction | AssertValueAction | AssertTextAction | AssertVisibleAction | AssertSnapshotAction;\nexport type PerformOnRecordAction = ClickAction | CheckAction | UncheckAction | PressAction | SelectAction;\n\n// Signals.\n\nexport type BaseSignal = {\n};\n\nexport type NavigationSignal = BaseSignal & {\n name: 'navigation',\n url: string,\n};\n\nexport type PopupSignal = BaseSignal & {\n name: 'popup',\n popupAlias: string,\n};\n\nexport type DownloadSignal = BaseSignal & {\n name: 'download',\n downloadAlias: string,\n};\n\nexport type DialogSignal = BaseSignal & {\n name: 'dialog',\n dialogAlias: string,\n};\n\nexport type Signal = NavigationSignal | PopupSignal | DownloadSignal | DialogSignal;\n\nexport type FrameDescription = {\n pageGuid: string;\n pageAlias: string;\n framePath: string[];\n};\n\nexport type ActionInContext = {\n frame: FrameDescription;\n description?: string;\n action: Action;\n startTime: number;\n endTime?: number;\n};\n\nexport type SignalInContext = {\n frame: FrameDescription;\n signal: Signal;\n timestamp: number;\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/browserContextFactory.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport net from 'net';\nimport path from 'path';\n\nimport * as playwright from 'playwright-core';\nimport { registryDirectory } from 'playwright-core/lib/server/registry/index';\nimport { startTraceViewerServer } from 'playwright-core/lib/server';\nimport { logUnhandledError, testDebug } from '../log';\nimport { outputFile } from './config';\nimport { firstRootPath } from '../sdk/server';\n\nimport type { FullConfig } from './config';\nimport type { LaunchOptions, BrowserContextOptions } from '../../../../playwright-core/src/client/types';\nimport type { ClientInfo } from '../sdk/server';\n\nexport function contextFactory(config: FullConfig): BrowserContextFactory {\n if (config.sharedBrowserContext)\n return SharedContextFactory.create(config);\n if (config.browser.remoteEndpoint)\n return new RemoteContextFactory(config);\n if (config.browser.cdpEndpoint)\n return new CdpContextFactory(config);\n if (config.browser.isolated)\n return new IsolatedContextFactory(config);\n return new PersistentContextFactory(config);\n}\n\nexport type BrowserContextFactoryResult = {\n browserContext: playwright.BrowserContext;\n close: (afterClose: () => Promise<void>) => Promise<void>;\n};\n\nexport interface BrowserContextFactory {\n createContext(clientInfo: ClientInfo, abortSignal: AbortSignal, toolName: string | undefined): Promise<BrowserContextFactoryResult>;\n}\n\nclass BaseContextFactory implements BrowserContextFactory {\n readonly config: FullConfig;\n private _logName: string;\n private static _cache = new Map<string, Promise<playwright.Browser>>();\n\n constructor(name: string, config: FullConfig) {\n this._logName = name;\n this.config = config;\n }\n\n protected _obtainBrowser(clientInfo: ClientInfo): Promise<playwright.Browser> {\n const key = this._calcFingerprint();\n if (BaseContextFactory._cache.has(key)) {\n return BaseContextFactory._cache.get(key)!;\n }\n testDebug(`obtain browser (${this._logName})`);\n const browserPromise = this._doObtainBrowser(clientInfo);\n void browserPromise.then(browser => {\n browser.on('disconnected', () => {\n BaseContextFactory._cache.delete(key);\n });\n }).catch(() => {\n BaseContextFactory._cache.delete(key);\n });\n BaseContextFactory._cache.set(key, browserPromise);\n return browserPromise;\n }\n\n protected _calcFingerprint(): string {\n const relevantConfig = this._extractRelevantConfig();\n const fingerprintData = {\n name: this._logName,\n config: relevantConfig\n };\n const stableJson = stableStringify(fingerprintData);\n return crypto.createHash('sha256').update(stableJson).digest('hex');\n }\n\n protected _extractRelevantConfig(): any {\n throw new Error('Not implemented');\n }\n\n protected async _doObtainBrowser(clientInfo: ClientInfo): Promise<playwright.Browser> {\n throw new Error('Not implemented');\n }\n\n async createContext(clientInfo: ClientInfo): Promise<BrowserContextFactoryResult> {\n testDebug(`create browser context (${this._logName}), config: ${JSON.stringify(this.config)}`);\n const browser = await this._obtainBrowser(clientInfo);\n const browserContext = await this._doCreateContext(browser);\n await addInitScript(browserContext, this.config.browser.initScript);\n return {\n browserContext,\n close: (afterClose: () => Promise<void>) => this._closeBrowserContext(browserContext, browser, afterClose)\n };\n }\n\n protected async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n throw new Error('Not implemented');\n }\n\n private async _closeBrowserContext(browserContext: playwright.BrowserContext, browser: playwright.Browser, afterClose: () => Promise<void>) {\n testDebug(`close browser context (${this._logName})`);\n if (browser.contexts().length === 1){\n const key = this._calcFingerprint();\n BaseContextFactory._cache.delete(key);\n }\n await browserContext.close().catch(logUnhandledError);\n await afterClose();\n if (browser.contexts().length === 0) {\n testDebug(`close browser (${this._logName})`);\n await browser.close().catch(logUnhandledError);\n }\n }\n}\n\nclass IsolatedContextFactory extends BaseContextFactory {\n constructor(config: FullConfig) {\n super('isolated', config);\n }\n\n protected override async _doObtainBrowser(clientInfo: ClientInfo): Promise<playwright.Browser> {\n const launchOptions = await injectCdpPort(this.config.browser);\n const browserType = playwright[this.config.browser.browserName];\n const tracesDir = await computeTracesDir(this.config, clientInfo);\n if (tracesDir && this.config.saveTrace)\n await startTraceServer(this.config, tracesDir);\n return browserType.launch({\n tracesDir,\n ...launchOptions,\n handleSIGINT: false,\n handleSIGTERM: false,\n }).catch(error => {\n if (error.message.includes('Executable doesn\\'t exist'))\n throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);\n throw error;\n });\n }\n\n protected override _extractRelevantConfig(): any {\n return {\n browserName: this.config.browser.browserName,\n launchOptions: this.config.browser.launchOptions,\n saveTrace: this.config.saveTrace,\n };\n }\n\n protected override async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n\n return browser.newContext(this.config.browser.contextOptions);\n }\n}\n\nclass CdpContextFactory extends BaseContextFactory {\n constructor(config: FullConfig) {\n super('cdp', config);\n }\n\n protected override async _doObtainBrowser(): Promise<playwright.Browser> {\n return playwright.chromium.connectOverCDP(this.config.browser.cdpEndpoint!, { headers: this.config.browser.cdpHeaders });\n }\n\n protected override _extractRelevantConfig(): any {\n return {\n cdpEndpoint: this.config.browser.cdpEndpoint,\n cdpHeaders: this.config.browser.cdpHeaders,\n };\n }\n\n protected override async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n return this.config.browser.isolated ? await browser.newContext() : browser.contexts()[0];\n }\n}\n\nclass RemoteContextFactory extends BaseContextFactory {\n constructor(config: FullConfig) {\n super('remote', config);\n }\n\n protected override async _doObtainBrowser(): Promise<playwright.Browser> {\n const url = new URL(this.config.browser.remoteEndpoint!);\n url.searchParams.set('browser', this.config.browser.browserName);\n if (this.config.browser.launchOptions)\n url.searchParams.set('launch-options', JSON.stringify(this.config.browser.launchOptions));\n return playwright[this.config.browser.browserName].connect(String(url));\n }\n\n protected override _extractRelevantConfig(): any {\n return {\n remoteEndpoint: this.config.browser.remoteEndpoint,\n browserName: this.config.browser.browserName,\n launchOptions: this.config.browser.launchOptions,\n };\n }\n\n protected override async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n return browser.newContext();\n }\n}\n\nclass PersistentContextFactory implements BrowserContextFactory {\n readonly config: FullConfig;\n readonly name = 'persistent';\n readonly description = 'Create a new persistent browser context';\n\n private _userDataDirs = new Set<string>();\n\n constructor(config: FullConfig) {\n this.config = config;\n }\n\n async createContext(clientInfo: ClientInfo): Promise<BrowserContextFactoryResult> {\n const launchOptionsWithCdp = await injectCdpPort(this.config.browser);\n testDebug('create browser context (persistent)');\n const userDataDir = this.config.browser.userDataDir ?? await this._createUserDataDir(clientInfo);\n const tracesDir = await computeTracesDir(this.config, clientInfo);\n if (tracesDir && this.config.saveTrace)\n await startTraceServer(this.config, tracesDir);\n\n this._userDataDirs.add(userDataDir);\n testDebug('lock user data dir', userDataDir);\n\n const browserType = playwright[this.config.browser.browserName];\n for (let i = 0; i < 5; i++) {\n const launchPersistentOptions: LaunchOptions & BrowserContextOptions = {\n tracesDir,\n ...launchOptionsWithCdp,\n ...this.config.browser.contextOptions,\n handleSIGINT: false,\n handleSIGTERM: false,\n ignoreDefaultArgs: [\n '--disable-extensions',\n ],\n assistantMode: true,\n };\n try {\n const browserContext = await browserType.launchPersistentContext(userDataDir, launchPersistentOptions);\n await addInitScript(browserContext, this.config.browser.initScript);\n const close = (afterClose: () => Promise<void>) => this._closeBrowserContext(browserContext, userDataDir, afterClose);\n return { browserContext, close };\n } catch (error: any) {\n if (error.message.includes('Executable doesn\\'t exist'))\n throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);\n if (error.message.includes('ProcessSingleton') || error.message.includes('Invalid URL')) {\n // User data directory is already in use, try again.\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n throw error;\n }\n }\n throw new Error(`Browser is already in use for ${userDataDir}, use --isolated to run multiple instances of the same browser`);\n }\n\n private async _closeBrowserContext(browserContext: playwright.BrowserContext, userDataDir: string, afterClose: () => Promise<void>) {\n testDebug('close browser context (persistent)');\n testDebug('release user data dir', userDataDir);\n await browserContext.close().catch(() => {});\n await afterClose();\n this._userDataDirs.delete(userDataDir);\n testDebug('close browser context complete (persistent)');\n }\n\n private async _createUserDataDir(clientInfo: ClientInfo) {\n const dir = process.env.PWMCP_PROFILES_DIR_FOR_TEST ?? registryDirectory;\n const browserToken = this.config.browser.launchOptions?.channel ?? this.config.browser?.browserName;\n // Hesitant putting hundreds of files into the user's workspace, so using it for hashing instead.\n const rootPath = firstRootPath(clientInfo);\n const rootPathToken = rootPath ? `-${createHash(rootPath)}` : '';\n const result = path.join(dir, `mcp-${browserToken}${rootPathToken}`);\n await fs.promises.mkdir(result, { recursive: true });\n return result;\n }\n}\n\nasync function injectCdpPort(browserConfig: FullConfig['browser']): Promise<any> {\n if (browserConfig.browserName === 'chromium') {\n const cdpPort = await findFreePort();\n return { ...browserConfig.launchOptions, cdpPort };\n }\n return browserConfig.launchOptions;\n}\n\nasync function findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.listen(0, () => {\n const { port } = server.address() as net.AddressInfo;\n server.close(() => resolve(port));\n });\n server.on('error', reject);\n });\n}\n\nasync function startTraceServer(config: FullConfig, tracesDir: string): Promise<string | undefined> {\n if (!config.saveTrace)\n return;\n\n const server = await startTraceViewerServer();\n const urlPrefix = server.urlPrefix('human-readable');\n const url = urlPrefix + '/trace/index.html?trace=' + tracesDir + '/trace.json';\n // eslint-disable-next-line no-console\n console.error('\\nTrace viewer listening on ' + url);\n}\n\nfunction createHash(data: string): string {\n return crypto.createHash('sha256').update(data).digest('hex').slice(0, 7);\n}\n\nasync function addInitScript(browserContext: playwright.BrowserContext, initScript: string[] | undefined) {\n for (const scriptPath of initScript ?? [])\n await browserContext.addInitScript({ path: path.resolve(scriptPath) });\n}\n\nexport class SharedContextFactory implements BrowserContextFactory {\n private _contextPromise: Promise<BrowserContextFactoryResult> | undefined;\n private _baseFactory: BrowserContextFactory;\n private static _instance: SharedContextFactory | undefined;\n\n static create(config: FullConfig) {\n if (SharedContextFactory._instance)\n // throw new Error('SharedContextFactory already exists');\n return SharedContextFactory._instance;;\n const baseConfig = { ...config, sharedBrowserContext: false };\n const baseFactory = contextFactory(baseConfig);\n SharedContextFactory._instance = new SharedContextFactory(baseFactory);\n return SharedContextFactory._instance;\n }\n\n private constructor(baseFactory: BrowserContextFactory) {\n this._baseFactory = baseFactory;\n }\n\n async createContext(clientInfo: ClientInfo, abortSignal: AbortSignal, toolName: string | undefined): Promise<{ browserContext: playwright.BrowserContext, close: () => Promise<void> }> {\n if (!this._contextPromise) {\n testDebug('create shared browser context');\n this._contextPromise = this._baseFactory.createContext(clientInfo, abortSignal, toolName);\n }\n\n const { browserContext } = await this._contextPromise;\n testDebug(`shared context client connected`);\n return {\n browserContext,\n close: async () => {\n testDebug(`shared context client disconnected`);\n },\n };\n }\n\n static async dispose() {\n await SharedContextFactory._instance?._dispose();\n SharedContextFactory._instance = undefined;\n }\n\n private async _dispose() {\n const contextPromise = this._contextPromise;\n this._contextPromise = undefined;\n if (!contextPromise)\n return;\n const { close } = await contextPromise;\n await close(async () => {});\n }\n}\n\nasync function computeTracesDir(config: FullConfig, clientInfo: ClientInfo): Promise<string | undefined> {\n if (!config.saveTrace && !config.capabilities?.includes('tracing'))\n return;\n return await outputFile(config, clientInfo, `traces`, { origin: 'code', reason: 'Collecting trace' });\n}\n\n/**\n * Stable JSON stringify that sorts object keys alphabetically.\n * This ensures that objects with the same properties produce identical strings.\n */\nfunction stableStringify(obj: any): string {\n if (obj === null || obj === undefined) {\n return String(obj);\n }\n\n if (typeof obj !== 'object') {\n return JSON.stringify(obj);\n }\n\n if (Array.isArray(obj)) {\n return '[' + obj.map(item => stableStringify(item)).join(',') + ']';\n }\n\n // Sort object keys for stable output\n const sortedKeys = Object.keys(obj).sort();\n const pairs = sortedKeys.map(key => {\n return JSON.stringify(key) + ':' + stableStringify(obj[key]);\n });\n\n return '{' + pairs.join(',') + '}';\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_server", "crypto", "path", "fs", "net"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/browserServerBackend.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FullConfig } from './config';\nimport { Context } from './context';\nimport { logUnhandledError } from '../log';\nimport { Response } from './response';\nimport { SessionLog } from './sessionLog';\nimport { filteredTools } from './tools';\nimport { toMcpTool } from '../sdk/tool';\n\nimport type { Tool } from './tools/tool';\nimport type { BrowserContextFactory } from './browserContextFactory';\nimport type * as mcpServer from '../sdk/server';\nimport type { ServerBackend } from '../sdk/server';\n\nexport class BrowserServerBackend implements ServerBackend {\n private _tools: Tool[];\n private _context: Context | undefined;\n private _sessionLog: SessionLog | undefined;\n private _config: FullConfig;\n private _browserContextFactory: BrowserContextFactory;\n\n constructor(config: FullConfig, factory: BrowserContextFactory) {\n this._config = config;\n this._browserContextFactory = factory;\n this._tools = filteredTools(config);\n }\n\n async initialize(server: mcpServer.Server, clientInfo: mcpServer.ClientInfo): Promise<void> {\n this._sessionLog = this._config.saveSession ? await SessionLog.create(this._config, clientInfo) : undefined;\n this._context = new Context({\n config: this._config,\n browserContextFactory: this._browserContextFactory,\n sessionLog: this._sessionLog,\n clientInfo,\n });\n }\n\n async listTools(): Promise<mcpServer.Tool[]> {\n return this._tools.map(tool => toMcpTool(tool.schema));\n }\n\n async callTool(name: string, rawArguments: mcpServer.CallToolRequest['params']['arguments']) {\n const tool = this._tools.find(tool => tool.schema.name === name)!;\n if (!tool)\n throw new Error(`Tool \"${name}\" not found`);\n const parsedArguments = tool.schema.inputSchema.parse(rawArguments || {});\n const context = this._context!;\n const response = new Response(context, name, parsedArguments);\n response.logBegin();\n context.setRunningTool(name);\n try {\n await tool.handle(context, parsedArguments, response);\n await response.finish();\n this._sessionLog?.logResponse(response);\n } catch (error: any) {\n response.addError(String(error));\n } finally {\n context.setRunningTool(undefined);\n }\n response.logEnd();\n return response.serialize();\n }\n\n serverClosed() {\n void this._context?.dispose().catch(logUnhandledError);\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,qBAAwB;AACxB,iBAAkC;AAClC,sBAAyB;AACzB,wBAA2B;AAC3B,mBAA8B;AAC9B,kBAA0B;AAOnB,MAAM,qBAA8C;AAAA,EAOzD,YAAY,QAAoB,SAAgC;AAC9D,SAAK,UAAU;AACf,SAAK,yBAAyB;AAC9B,SAAK,aAAS,4BAAc,MAAM;AAAA,EACpC;AAAA,EAEA,MAAM,WAAW,QAA0B,YAAiD;AAC1F,SAAK,cAAc,KAAK,QAAQ,cAAc,MAAM,6BAAW,OAAO,KAAK,SAAS,UAAU,IAAI;AAClG,SAAK,WAAW,IAAI,uBAAQ;AAAA,MAC1B,QAAQ,KAAK;AAAA,MACb,uBAAuB,KAAK;AAAA,MAC5B,YAAY,KAAK;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAAuC;AAC3C,WAAO,KAAK,OAAO,IAAI,cAAQ,uBAAU,KAAK,MAAM,CAAC;AAAA,EACvD;AAAA,EAEA,MAAM,SAAS,MAAc,cAAgE;AAC3F,UAAM,OAAO,KAAK,OAAO,KAAK,CAAAA,UAAQA,MAAK,OAAO,SAAS,IAAI;AAC/D,QAAI,CAAC;AACH,YAAM,IAAI,MAAM,SAAS,IAAI,aAAa;AAC5C,UAAM,kBAAkB,KAAK,OAAO,YAAY,MAAM,gBAAgB,CAAC,CAAC;AACxE,UAAM,UAAU,KAAK;AACrB,UAAM,WAAW,IAAI,yBAAS,SAAS,MAAM,eAAe;AAC5D,aAAS,SAAS;AAClB,YAAQ,eAAe,IAAI;AAC3B,QAAI;AACF,YAAM,KAAK,OAAO,SAAS,iBAAiB,QAAQ;AACpD,YAAM,SAAS,OAAO;AACtB,WAAK,aAAa,YAAY,QAAQ;AAAA,IACxC,SAAS,OAAY;AACnB,eAAS,SAAS,OAAO,KAAK,CAAC;AAAA,IACjC,UAAE;AACA,cAAQ,eAAe,MAAS;AAAA,IAClC;AACA,aAAS,OAAO;AAChB,WAAO,SAAS,UAAU;AAAA,EAC5B;AAAA,EAEA,eAAe;AACb,SAAK,KAAK,UAAU,QAAQ,EAAE,MAAM,4BAAiB;AAAA,EACvD;AACF;",
6
- "names": ["tool"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/codegen.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// adapted from:\n// - https://github.com/microsoft/playwright/blob/76ee48dc9d4034536e3ec5b2c7ce8be3b79418a8/packages/playwright-core/src/utils/isomorphic/stringUtils.ts\n// - https://github.com/microsoft/playwright/blob/76ee48dc9d4034536e3ec5b2c7ce8be3b79418a8/packages/playwright-core/src/server/codegen/javascript.ts\n\n// NOTE: this function should not be used to escape any selectors.\nexport function escapeWithQuotes(text: string, char: string = '\\'') {\n const stringified = JSON.stringify(text);\n const escapedText = stringified.substring(1, stringified.length - 1).replace(/\\\\\"/g, '\"');\n if (char === '\\'')\n return char + escapedText.replace(/[']/g, '\\\\\\'') + char;\n if (char === '\"')\n return char + escapedText.replace(/[\"]/g, '\\\\\"') + char;\n if (char === '`')\n return char + escapedText.replace(/[`]/g, '\\\\`') + char;\n throw new Error('Invalid escape char');\n}\n\nexport function quote(text: string) {\n return escapeWithQuotes(text, '\\'');\n}\n\nexport function formatObject(value: any, indent = ' ', mode: 'multiline' | 'oneline' = 'multiline'): string {\n if (typeof value === 'string')\n return quote(value);\n if (Array.isArray(value))\n return `[${value.map(o => formatObject(o)).join(', ')}]`;\n if (typeof value === 'object') {\n const keys = Object.keys(value).filter(key => value[key] !== undefined).sort();\n if (!keys.length)\n return '{}';\n const tokens: string[] = [];\n for (const key of keys)\n tokens.push(`${key}: ${formatObject(value[key])}`);\n if (mode === 'multiline')\n return `{\\n${tokens.join(`,\\n${indent}`)}\\n}`;\n return `{ ${tokens.join(', ')} }`;\n }\n return String(value);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBO,SAAS,iBAAiB,MAAc,OAAe,KAAM;AAClE,QAAM,cAAc,KAAK,UAAU,IAAI;AACvC,QAAM,cAAc,YAAY,UAAU,GAAG,YAAY,SAAS,CAAC,EAAE,QAAQ,QAAQ,GAAG;AACxF,MAAI,SAAS;AACX,WAAO,OAAO,YAAY,QAAQ,QAAQ,KAAM,IAAI;AACtD,MAAI,SAAS;AACX,WAAO,OAAO,YAAY,QAAQ,QAAQ,KAAK,IAAI;AACrD,MAAI,SAAS;AACX,WAAO,OAAO,YAAY,QAAQ,QAAQ,KAAK,IAAI;AACrD,QAAM,IAAI,MAAM,qBAAqB;AACvC;AAEO,SAAS,MAAM,MAAc;AAClC,SAAO,iBAAiB,MAAM,GAAI;AACpC;AAEO,SAAS,aAAa,OAAY,SAAS,MAAM,OAAgC,aAAqB;AAC3G,MAAI,OAAO,UAAU;AACnB,WAAO,MAAM,KAAK;AACpB,MAAI,MAAM,QAAQ,KAAK;AACrB,WAAO,IAAI,MAAM,IAAI,OAAK,aAAa,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AACvD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,OAAO,OAAO,KAAK,KAAK,EAAE,OAAO,SAAO,MAAM,GAAG,MAAM,MAAS,EAAE,KAAK;AAC7E,QAAI,CAAC,KAAK;AACR,aAAO;AACT,UAAM,SAAmB,CAAC;AAC1B,eAAW,OAAO;AAChB,aAAO,KAAK,GAAG,GAAG,KAAK,aAAa,MAAM,GAAG,CAAC,CAAC,EAAE;AACnD,QAAI,SAAS;AACX,aAAO;AAAA,EAAM,OAAO,KAAK;AAAA,EAAM,MAAM,EAAE,CAAC;AAAA;AAC1C,WAAO,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EAC/B;AACA,SAAO,OAAO,KAAK;AACrB;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/config.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport { devices } from 'playwright-core';\nimport { dotenv, debug } from 'playwright-core/lib/utilsBundle';\nimport { fileExistsAsync } from '../../util';\nimport { firstRootPath } from '../sdk/server';\n\nimport type * as playwright from '../../../types/test';\nimport type { Config, ToolCapability } from '../config';\nimport type { ClientInfo } from '../sdk/server';\n\ntype ViewportSize = { width: number; height: number };\n\nexport type CLIOptions = {\n allowedHosts?: string[];\n allowedOrigins?: string[];\n blockedOrigins?: string[];\n blockServiceWorkers?: boolean;\n browser?: string;\n caps?: string[];\n cdpEndpoint?: string;\n cdpHeader?: Record<string, string>;\n config?: string;\n device?: string;\n executablePath?: string;\n grantPermissions?: string[];\n headless?: boolean;\n host?: string;\n ignoreHttpsErrors?: boolean;\n initScript?: string[];\n isolated?: boolean;\n imageResponses?: 'allow' | 'omit';\n sandbox?: boolean;\n outputDir?: string;\n port?: number;\n proxyBypass?: string;\n proxyServer?: string;\n saveSession?: boolean;\n saveTrace?: boolean;\n saveVideo?: ViewportSize;\n secrets?: Record<string, string>;\n sharedBrowserContext?: boolean;\n storageState?: string;\n testIdAttribute?: string;\n timeoutAction?: number;\n timeoutNavigation?: number;\n userAgent?: string;\n userDataDir?: string;\n viewportSize?: ViewportSize;\n};\n\nexport const defaultConfig: FullConfig = {\n browser: {\n browserName: 'chromium',\n launchOptions: {\n channel: 'chrome',\n headless: os.platform() === 'linux' && !process.env.DISPLAY,\n chromiumSandbox: true,\n },\n contextOptions: {\n viewport: null,\n },\n },\n network: {\n allowedOrigins: undefined,\n blockedOrigins: undefined,\n },\n server: {},\n saveTrace: false,\n timeouts: {\n action: 5000,\n navigation: 60000,\n },\n};\n\ntype BrowserUserConfig = NonNullable<Config['browser']>;\n\nexport type FullConfig = Config & {\n browser: Omit<BrowserUserConfig, 'browserName'> & {\n browserName: 'chromium' | 'firefox' | 'webkit';\n launchOptions: NonNullable<BrowserUserConfig['launchOptions']>;\n contextOptions: NonNullable<BrowserUserConfig['contextOptions']>;\n },\n network: NonNullable<Config['network']>,\n saveTrace: boolean;\n server: NonNullable<Config['server']>,\n timeouts: {\n action: number;\n navigation: number;\n },\n};\n\nexport async function resolveConfig(config: Config): Promise<FullConfig> {\n return mergeConfig(defaultConfig, config);\n}\n\nexport async function resolveCLIConfig(cliOptions: CLIOptions): Promise<FullConfig> {\n const configInFile = await loadConfig(cliOptions.config);\n const envOverrides = configFromEnv();\n const cliOverrides = configFromCLIOptions(cliOptions);\n let result = defaultConfig;\n result = mergeConfig(result, configInFile);\n result = mergeConfig(result, envOverrides);\n result = mergeConfig(result, cliOverrides);\n await validateConfig(result);\n return result;\n}\n\nasync function validateConfig(config: FullConfig): Promise<void> {\n if (config.browser.initScript) {\n for (const script of config.browser.initScript) {\n if (!await fileExistsAsync(script))\n throw new Error(`Init script file does not exist: ${script}`);\n }\n }\n if (config.sharedBrowserContext && config.saveVideo)\n throw new Error('saveVideo is not supported when sharedBrowserContext is true');\n}\n\nexport function configFromCLIOptions(cliOptions: CLIOptions): Config {\n let browserName: 'chromium' | 'firefox' | 'webkit' | undefined;\n let channel: string | undefined;\n switch (cliOptions.browser) {\n case 'chrome':\n case 'chrome-beta':\n case 'chrome-canary':\n case 'chrome-dev':\n case 'chromium':\n case 'msedge':\n case 'msedge-beta':\n case 'msedge-canary':\n case 'msedge-dev':\n browserName = 'chromium';\n channel = cliOptions.browser;\n break;\n case 'firefox':\n browserName = 'firefox';\n break;\n case 'webkit':\n browserName = 'webkit';\n break;\n }\n\n // Launch options\n const launchOptions: playwright.LaunchOptions = {\n channel,\n executablePath: cliOptions.executablePath,\n headless: cliOptions.headless,\n };\n\n // --no-sandbox was passed, disable the sandbox\n if (cliOptions.sandbox === false)\n launchOptions.chromiumSandbox = false;\n\n if (cliOptions.proxyServer) {\n launchOptions.proxy = {\n server: cliOptions.proxyServer\n };\n if (cliOptions.proxyBypass)\n launchOptions.proxy.bypass = cliOptions.proxyBypass;\n }\n\n if (cliOptions.device && cliOptions.cdpEndpoint)\n throw new Error('Device emulation is not supported with cdpEndpoint.');\n\n // Context options\n const contextOptions: playwright.BrowserContextOptions = cliOptions.device ? devices[cliOptions.device] : {};\n if (cliOptions.storageState)\n contextOptions.storageState = cliOptions.storageState;\n\n if (cliOptions.userAgent)\n contextOptions.userAgent = cliOptions.userAgent;\n\n if (cliOptions.viewportSize)\n contextOptions.viewport = cliOptions.viewportSize;\n\n if (cliOptions.ignoreHttpsErrors)\n contextOptions.ignoreHTTPSErrors = true;\n\n if (cliOptions.blockServiceWorkers)\n contextOptions.serviceWorkers = 'block';\n\n if (cliOptions.grantPermissions)\n contextOptions.permissions = cliOptions.grantPermissions;\n\n if (cliOptions.saveVideo) {\n contextOptions.recordVideo = {\n // Videos are moved to output directory on saveAs.\n dir: tmpDir(),\n size: cliOptions.saveVideo,\n };\n }\n\n const result: Config = {\n browser: {\n browserName,\n isolated: cliOptions.isolated,\n userDataDir: cliOptions.userDataDir,\n launchOptions,\n contextOptions,\n cdpEndpoint: cliOptions.cdpEndpoint,\n cdpHeaders: cliOptions.cdpHeader,\n initScript: cliOptions.initScript,\n },\n server: {\n port: cliOptions.port,\n host: cliOptions.host,\n allowedHosts: cliOptions.allowedHosts,\n },\n capabilities: cliOptions.caps as ToolCapability[],\n network: {\n allowedOrigins: cliOptions.allowedOrigins,\n blockedOrigins: cliOptions.blockedOrigins,\n },\n saveSession: cliOptions.saveSession,\n saveTrace: cliOptions.saveTrace,\n saveVideo: cliOptions.saveVideo,\n secrets: cliOptions.secrets,\n sharedBrowserContext: cliOptions.sharedBrowserContext,\n outputDir: cliOptions.outputDir,\n imageResponses: cliOptions.imageResponses,\n testIdAttribute: cliOptions.testIdAttribute,\n timeouts: {\n action: cliOptions.timeoutAction,\n navigation: cliOptions.timeoutNavigation,\n },\n };\n\n return result;\n}\n\nfunction configFromEnv(): Config {\n const options: CLIOptions = {};\n options.allowedHosts = commaSeparatedList(process.env.PLAYWRIGHT_MCP_ALLOWED_HOSTNAMES);\n options.allowedOrigins = semicolonSeparatedList(process.env.PLAYWRIGHT_MCP_ALLOWED_ORIGINS);\n options.blockedOrigins = semicolonSeparatedList(process.env.PLAYWRIGHT_MCP_BLOCKED_ORIGINS);\n options.blockServiceWorkers = envToBoolean(process.env.PLAYWRIGHT_MCP_BLOCK_SERVICE_WORKERS);\n options.browser = envToString(process.env.PLAYWRIGHT_MCP_BROWSER);\n options.caps = commaSeparatedList(process.env.PLAYWRIGHT_MCP_CAPS);\n options.cdpEndpoint = envToString(process.env.PLAYWRIGHT_MCP_CDP_ENDPOINT);\n options.cdpHeader = headerParser(process.env.PLAYWRIGHT_MCP_CDP_HEADERS, {});\n options.config = envToString(process.env.PLAYWRIGHT_MCP_CONFIG);\n options.device = envToString(process.env.PLAYWRIGHT_MCP_DEVICE);\n options.executablePath = envToString(process.env.PLAYWRIGHT_MCP_EXECUTABLE_PATH);\n options.grantPermissions = commaSeparatedList(process.env.PLAYWRIGHT_MCP_GRANT_PERMISSIONS);\n options.headless = envToBoolean(process.env.PLAYWRIGHT_MCP_HEADLESS);\n options.host = envToString(process.env.PLAYWRIGHT_MCP_HOST);\n options.ignoreHttpsErrors = envToBoolean(process.env.PLAYWRIGHT_MCP_IGNORE_HTTPS_ERRORS);\n const initScript = envToString(process.env.PLAYWRIGHT_MCP_INIT_SCRIPT);\n if (initScript)\n options.initScript = [initScript];\n options.isolated = envToBoolean(process.env.PLAYWRIGHT_MCP_ISOLATED);\n if (process.env.PLAYWRIGHT_MCP_IMAGE_RESPONSES === 'omit')\n options.imageResponses = 'omit';\n options.sandbox = envToBoolean(process.env.PLAYWRIGHT_MCP_SANDBOX);\n options.outputDir = envToString(process.env.PLAYWRIGHT_MCP_OUTPUT_DIR);\n options.port = numberParser(process.env.PLAYWRIGHT_MCP_PORT);\n options.proxyBypass = envToString(process.env.PLAYWRIGHT_MCP_PROXY_BYPASS);\n options.proxyServer = envToString(process.env.PLAYWRIGHT_MCP_PROXY_SERVER);\n options.saveTrace = envToBoolean(process.env.PLAYWRIGHT_MCP_SAVE_TRACE);\n options.saveVideo = resolutionParser('--save-video', process.env.PLAYWRIGHT_MCP_SAVE_VIDEO);\n options.secrets = dotenvFileLoader(process.env.PLAYWRIGHT_MCP_SECRETS_FILE);\n options.storageState = envToString(process.env.PLAYWRIGHT_MCP_STORAGE_STATE);\n options.testIdAttribute = envToString(process.env.PLAYWRIGHT_MCP_TEST_ID_ATTRIBUTE);\n options.timeoutAction = numberParser(process.env.PLAYWRIGHT_MCP_TIMEOUT_ACTION);\n options.timeoutNavigation = numberParser(process.env.PLAYWRIGHT_MCP_TIMEOUT_NAVIGATION);\n options.userAgent = envToString(process.env.PLAYWRIGHT_MCP_USER_AGENT);\n options.userDataDir = envToString(process.env.PLAYWRIGHT_MCP_USER_DATA_DIR);\n options.viewportSize = resolutionParser('--viewport-size', process.env.PLAYWRIGHT_MCP_VIEWPORT_SIZE);\n return configFromCLIOptions(options);\n}\n\nasync function loadConfig(configFile: string | undefined): Promise<Config> {\n if (!configFile)\n return {};\n\n try {\n return JSON.parse(await fs.promises.readFile(configFile, 'utf8'));\n } catch (error) {\n throw new Error(`Failed to load config file: ${configFile}, ${error}`);\n }\n}\n\nfunction tmpDir(): string {\n return path.join(process.env.PW_TMPDIR_FOR_TEST ?? os.tmpdir(), 'playwright-mcp-output');\n}\n\nexport function outputDir(config: FullConfig, clientInfo: ClientInfo): string {\n const rootPath = firstRootPath(clientInfo);\n return config.outputDir\n ?? (rootPath ? path.join(rootPath, '.playwright-mcp') : undefined)\n ?? path.join(tmpDir(), String(clientInfo.timestamp));\n}\n\nexport async function outputFile(config: FullConfig, clientInfo: ClientInfo, fileName: string, options: { origin: 'code' | 'llm' | 'web', reason: string }): Promise<string> {\n const file = await resolveFile(config, clientInfo, fileName, options);\n debug('pw:mcp:file')(options.reason, file);\n return file;\n}\n\nasync function resolveFile(config: FullConfig, clientInfo: ClientInfo, fileName: string, options: { origin: 'code' | 'llm' | 'web' }): Promise<string> {\n const dir = outputDir(config, clientInfo);\n\n // Trust code.\n if (options.origin === 'code')\n return path.resolve(dir, fileName);\n\n // Trust llm to use valid characters in file names.\n if (options.origin === 'llm') {\n fileName = fileName.split('\\\\').join('/');\n const resolvedFile = path.resolve(dir, fileName);\n if (!resolvedFile.startsWith(path.resolve(dir) + path.sep))\n throw new Error(`Resolved file path ${resolvedFile} is outside of the output directory ${dir}. Use relative file names to stay within the output directory.`);\n return resolvedFile;\n }\n\n // Do not trust web, at all.\n return path.join(dir, sanitizeForFilePath(fileName));\n}\n\nfunction pickDefined<T extends object>(obj: T | undefined): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj ?? {}).filter(([_, v]) => v !== undefined)\n ) as Partial<T>;\n}\n\nexport function mergeConfig(base: FullConfig, overrides: Config): FullConfig {\n const browser: FullConfig['browser'] = {\n ...pickDefined(base.browser),\n ...pickDefined(overrides.browser),\n browserName: overrides.browser?.browserName ?? base.browser?.browserName ?? 'chromium',\n isolated: overrides.browser?.isolated ?? base.browser?.isolated ?? false,\n launchOptions: {\n ...pickDefined(base.browser?.launchOptions),\n ...pickDefined(overrides.browser?.launchOptions),\n ...{ assistantMode: true },\n },\n contextOptions: {\n ...pickDefined(base.browser?.contextOptions),\n ...pickDefined(overrides.browser?.contextOptions),\n },\n };\n\n if (browser.browserName !== 'chromium' && browser.launchOptions)\n delete browser.launchOptions.channel;\n\n return {\n ...pickDefined(base),\n ...pickDefined(overrides),\n browser,\n network: {\n ...pickDefined(base.network),\n ...pickDefined(overrides.network),\n },\n server: {\n ...pickDefined(base.server),\n ...pickDefined(overrides.server),\n },\n timeouts: {\n ...pickDefined(base.timeouts),\n ...pickDefined(overrides.timeouts),\n },\n } as FullConfig;\n}\n\nexport function semicolonSeparatedList(value: string | undefined): string[] | undefined {\n if (!value)\n return undefined;\n return value.split(';').map(v => v.trim());\n}\n\nexport function commaSeparatedList(value: string | undefined): string[] | undefined {\n if (!value)\n return undefined;\n return value.split(',').map(v => v.trim());\n}\n\nexport function dotenvFileLoader(value: string | undefined): Record<string, string> | undefined {\n if (!value)\n return undefined;\n return dotenv.parse(fs.readFileSync(value, 'utf8'));\n}\n\nexport function numberParser(value: string | undefined): number | undefined {\n if (!value)\n return undefined;\n return +value;\n}\n\nexport function resolutionParser(name: string, value: string | undefined): ViewportSize | undefined {\n if (!value)\n return undefined;\n if (value.includes('x')) {\n const [width, height] = value.split('x').map(v => +v);\n if (isNaN(width) || isNaN(height) || width <= 0 || height <= 0)\n throw new Error(`Invalid resolution format: use ${name}=\"800x600\"`);\n return { width, height };\n }\n\n // Legacy format\n if (value.includes(',')) {\n const [width, height] = value.split(',').map(v => +v);\n if (isNaN(width) || isNaN(height) || width <= 0 || height <= 0)\n throw new Error(`Invalid resolution format: use ${name}=\"800x600\"`);\n return { width, height };\n }\n\n throw new Error(`Invalid resolution format: use ${name}=\"800x600\"`);\n}\n\nexport function headerParser(arg: string | undefined, previous?: Record<string, string>): Record<string, string> {\n if (!arg)\n return previous || {};\n const result: Record<string, string> = previous || {};\n const [name, value] = arg.split(':').map(v => v.trim());\n result[name] = value;\n return result;\n}\n\nfunction envToBoolean(value: string | undefined): boolean | undefined {\n if (value === 'true' || value === '1')\n return true;\n if (value === 'false' || value === '0')\n return false;\n return undefined;\n}\n\nfunction envToString(value: string | undefined): string | undefined {\n return value ? value.trim() : undefined;\n}\n\nfunction sanitizeForFilePath(s: string) {\n const sanitize = (s: string) => s.replace(/[\\x00-\\x2C\\x2E-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7F]+/g, '-');\n const separator = s.lastIndexOf('.');\n if (separator === -1)\n return sanitize(s);\n return sanitize(s.substring(0, separator)) + '.' + sanitize(s.substring(separator + 1));\n}\n\n/**\n * Parse URL query parameters and create config overrides\n * Supports most browser configuration options via URL parameters\n *\n * Excluded parameters (server-level only):\n * - config, host, port, output-dir, save-session, save-trace\n * - executable-path, user-data-dir, extension\n */\nexport function configFromURLParams(url: URL): Config {\n const getParam = (name: string) => url.searchParams.get(name) || undefined;\n\n const options: CLIOptions = {};\n options.allowedOrigins = semicolonSeparatedList(getParam('allowed-origins'));\n options.blockedOrigins = semicolonSeparatedList(getParam('blocked-origins'));\n options.blockServiceWorkers = queryToBoolean(getParam('block-service-workers'));\n options.browser = getParam('browser');\n options.caps = commaSeparatedList(getParam('caps'));\n options.cdpEndpoint = getParam('cdp-endpoint');\n options.device = getParam('device');\n options.headless = queryToBoolean(getParam('headless'));\n options.ignoreHttpsErrors = queryToBoolean(getParam('ignore-https-errors'));\n options.isolated = queryToBoolean(getParam('isolated'));\n const imageResponses = getParam('image-responses');\n if (imageResponses === 'omit' || imageResponses === 'allow')\n options.imageResponses = imageResponses;\n options.sandbox = queryToBoolean(getParam('sandbox'));\n options.proxyBypass = getParam('proxy-bypass');\n options.proxyServer = getParam('proxy-server');\n options.storageState = getParam('storage-state');\n options.userAgent = getParam('user-agent');\n const viewportSize = getParam('viewport-size');\n if (viewportSize)\n options.viewportSize = resolutionParser('--viewport-size', viewportSize);\n\n // If no URL params were actually set, return empty config\n // This ensures empty URLs don't trigger session-specific config in http.ts\n if (!Object.values(options).some(v => v !== undefined)) {\n return {};\n }\n\n return configFromCLIOptions(options);\n}\n\nfunction queryToBoolean(value: string | undefined): boolean | undefined {\n if (value === 'true' || value === '1')\n return true;\n if (value === 'false' || value === '0')\n return false;\n return undefined;\n}\n"],
5
- "mappings": "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",
6
- "names": ["os", "fs", "path", "s"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/context.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { debug } from 'playwright-core/lib/utilsBundle';\nimport { selectors } from 'playwright-core';\n\nimport { logUnhandledError } from '../log';\nimport { Tab } from './tab';\nimport { outputFile } from './config';\nimport * as codegen from './codegen';\nimport { dateAsFileName } from './tools/utils';\n\nimport type * as playwright from '../../../types/test';\nimport type { FullConfig } from './config';\nimport type { BrowserContextFactory, BrowserContextFactoryResult } from './browserContextFactory';\nimport type * as actions from './actions';\nimport type { SessionLog } from './sessionLog';\nimport type { Tracing } from '../../../../playwright-core/src/client/tracing';\nimport type { ClientInfo } from '../sdk/server';\n\nconst testDebug = debug('pw:mcp:test');\n\ntype ContextOptions = {\n config: FullConfig;\n browserContextFactory: BrowserContextFactory;\n sessionLog: SessionLog | undefined;\n clientInfo: ClientInfo;\n};\n\nexport class Context {\n readonly config: FullConfig;\n readonly sessionLog: SessionLog | undefined;\n readonly options: ContextOptions;\n private _browserContextPromise: Promise<BrowserContextFactoryResult> | undefined;\n private _browserContextFactory: BrowserContextFactory;\n private _tabs: Tab[] = [];\n private _currentTab: Tab | undefined;\n private _clientInfo: ClientInfo;\n\n private static _allContexts: Set<Context> = new Set();\n private _closeBrowserContextPromise: Promise<void> | undefined;\n private _runningToolName: string | undefined;\n private _abortController = new AbortController();\n\n constructor(options: ContextOptions) {\n this.config = options.config;\n this.sessionLog = options.sessionLog;\n this.options = options;\n this._browserContextFactory = options.browserContextFactory;\n this._clientInfo = options.clientInfo;\n testDebug('create context');\n Context._allContexts.add(this);\n }\n\n static async disposeAll() {\n await Promise.all([...Context._allContexts].map(context => context.dispose()));\n }\n\n tabs(): Tab[] {\n return this._tabs;\n }\n\n currentTab(): Tab | undefined {\n return this._currentTab;\n }\n\n currentTabOrDie(): Tab {\n if (!this._currentTab)\n throw new Error('No open pages available. Use the \"browser_navigate\" tool to navigate to a page first.');\n return this._currentTab;\n }\n\n async newTab(): Promise<Tab> {\n const { browserContext } = await this._ensureBrowserContext();\n const page = await browserContext.newPage();\n this._currentTab = this._tabs.find(t => t.page === page)!;\n return this._currentTab;\n }\n\n async selectTab(index: number) {\n const tab = this._tabs[index];\n if (!tab)\n throw new Error(`Tab ${index} not found`);\n await tab.page.bringToFront();\n this._currentTab = tab;\n return tab;\n }\n\n async ensureTab(): Promise<Tab> {\n const { browserContext } = await this._ensureBrowserContext();\n if (!this._currentTab)\n await browserContext.newPage();\n return this._currentTab!;\n }\n\n async closeTab(index: number | undefined): Promise<string> {\n const tab = index === undefined ? this._currentTab : this._tabs[index];\n if (!tab)\n throw new Error(`Tab ${index} not found`);\n const url = tab.page.url();\n await tab.page.close();\n return url;\n }\n\n async outputFile(fileName: string, options: { origin: 'code' | 'llm' | 'web', reason: string }): Promise<string> {\n return outputFile(this.config, this._clientInfo, fileName, options);\n }\n\n private _onPageCreated(page: playwright.Page) {\n const tab = new Tab(this, page, tab => this._onPageClosed(tab));\n this._tabs.push(tab);\n if (!this._currentTab)\n this._currentTab = tab;\n }\n\n private _onPageClosed(tab: Tab) {\n const index = this._tabs.indexOf(tab);\n if (index === -1)\n return;\n this._tabs.splice(index, 1);\n\n if (this._currentTab === tab)\n this._currentTab = this._tabs[Math.min(index, this._tabs.length - 1)];\n if (!this._tabs.length)\n void this.closeBrowserContext();\n }\n\n async closeBrowserContext() {\n if (!this._closeBrowserContextPromise)\n this._closeBrowserContextPromise = this._closeBrowserContextImpl().catch(logUnhandledError);\n await this._closeBrowserContextPromise;\n this._closeBrowserContextPromise = undefined;\n }\n\n isRunningTool() {\n return this._runningToolName !== undefined;\n }\n\n setRunningTool(name: string | undefined) {\n this._runningToolName = name;\n }\n\n private async _closeBrowserContextImpl() {\n if (!this._browserContextPromise)\n return;\n\n testDebug('close context');\n\n const promise = this._browserContextPromise;\n this._browserContextPromise = undefined;\n\n await promise.then(async ({ browserContext, close }) => {\n if (this.config.saveTrace)\n await browserContext.tracing.stop();\n const videos = this.config.saveVideo ? browserContext.pages().map(page => page.video()).filter(video => !!video) : [];\n await close(async () => {\n for (const video of videos) {\n const name = await this.outputFile(dateAsFileName('webm'), { origin: 'code', reason: 'Saving video' });\n await fs.promises.mkdir(path.dirname(name), { recursive: true });\n const p = await video.path();\n // video.saveAs() does not work for persistent contexts.\n if (fs.existsSync(p)) {\n try {\n await fs.promises.rename(p, name);\n } catch (e) {\n if (e.code !== 'EXDEV')\n logUnhandledError(e);\n // Retry operation (possibly cross-fs) with copy and unlink\n try {\n await fs.promises.copyFile(p, name);\n await fs.promises.unlink(p);\n } catch (e) {\n logUnhandledError(e);\n }\n }\n }\n }\n });\n });\n }\n\n async dispose() {\n this._abortController.abort('MCP context disposed');\n await this.closeBrowserContext();\n Context._allContexts.delete(this);\n }\n\n private async _setupRequestInterception(context: playwright.BrowserContext) {\n if (this.config.network?.allowedOrigins?.length) {\n await context.route('**', route => route.abort('blockedbyclient'));\n\n for (const origin of this.config.network.allowedOrigins)\n await context.route(originOrHostGlob(origin), route => route.continue());\n }\n\n if (this.config.network?.blockedOrigins?.length) {\n for (const origin of this.config.network.blockedOrigins)\n await context.route(originOrHostGlob(origin), route => route.abort('blockedbyclient'));\n }\n }\n\n async ensureBrowserContext(): Promise<playwright.BrowserContext> {\n const { browserContext } = await this._ensureBrowserContext();\n return browserContext;\n }\n\n private _ensureBrowserContext() {\n if (!this._browserContextPromise) {\n this._browserContextPromise = this._setupBrowserContext();\n this._browserContextPromise.catch(() => {\n this._browserContextPromise = undefined;\n });\n }\n return this._browserContextPromise;\n }\n\n private async _setupBrowserContext(): Promise<BrowserContextFactoryResult> {\n if (this._closeBrowserContextPromise)\n throw new Error('Another browser context is being closed.');\n // TODO: move to the browser context factory to make it based on isolation mode.\n\n if (this.config.testIdAttribute)\n selectors.setTestIdAttribute(this.config.testIdAttribute);\n const result = await this._browserContextFactory.createContext(this._clientInfo, this._abortController.signal, this._runningToolName);\n const { browserContext } = result;\n await this._setupRequestInterception(browserContext);\n if (this.sessionLog)\n await InputRecorder.create(this, browserContext);\n for (const page of browserContext.pages())\n this._onPageCreated(page);\n browserContext.on('page', page => this._onPageCreated(page));\n if (this.config.saveTrace) {\n await (browserContext.tracing as Tracing).start({\n name: 'trace-' + Date.now(),\n screenshots: true,\n snapshots: true,\n _live: true,\n });\n }\n return result;\n }\n\n lookupSecret(secretName: string): { value: string, code: string } {\n if (!this.config.secrets?.[secretName])\n return { value: secretName, code: codegen.quote(secretName) };\n return {\n value: this.config.secrets[secretName]!,\n code: `process.env['${secretName}']`,\n };\n }\n}\n\nfunction originOrHostGlob(originOrHost: string) {\n try {\n const url = new URL(originOrHost);\n // localhost:1234 will parse as protocol 'localhost:' and 'null' origin.\n if (url.origin !== 'null')\n return `${url.origin}/**`;\n } catch {\n }\n // Support for legacy host-only mode.\n return `*://${originOrHost}/**`;\n}\n\nexport class InputRecorder {\n private _context: Context;\n private _browserContext: playwright.BrowserContext;\n\n private constructor(context: Context, browserContext: playwright.BrowserContext) {\n this._context = context;\n this._browserContext = browserContext;\n }\n\n static async create(context: Context, browserContext: playwright.BrowserContext) {\n const recorder = new InputRecorder(context, browserContext);\n await recorder._initialize();\n return recorder;\n }\n\n private async _initialize() {\n const sessionLog = this._context.sessionLog!;\n await (this._browserContext as any)._enableRecorder({\n mode: 'recording',\n recorderMode: 'api',\n }, {\n actionAdded: (page: playwright.Page, data: actions.ActionInContext, code: string) => {\n if (this._context.isRunningTool())\n return;\n const tab = Tab.forPage(page);\n if (tab)\n sessionLog.logUserAction(data.action, tab, code, false);\n },\n actionUpdated: (page: playwright.Page, data: actions.ActionInContext, code: string) => {\n if (this._context.isRunningTool())\n return;\n const tab = Tab.forPage(page);\n if (tab)\n sessionLog.logUserAction(data.action, tab, code, true);\n },\n signalAdded: (page: playwright.Page, data: actions.SignalInContext) => {\n if (this._context.isRunningTool())\n return;\n if (data.signal.name !== 'navigation')\n return;\n const tab = Tab.forPage(page);\n const navigateAction: actions.Action = {\n name: 'navigate',\n url: data.signal.url,\n signals: [],\n };\n if (tab)\n sessionLog.logUserAction(navigateAction, tab, `await page.goto('${data.signal.url}');`, false);\n },\n });\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["tab", "fs", "path", "e"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/response.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { debug } from 'playwright-core/lib/utilsBundle';\nimport { renderModalStates } from './tab';\n\nimport type { Tab, TabSnapshot } from './tab';\nimport type { CallToolResult, ImageContent, TextContent } from '@modelcontextprotocol/sdk/types.js';\nimport type { Context } from './context';\n\nexport const requestDebug = debug('pw:mcp:request');\n\nexport class Response {\n private _result: string[] = [];\n private _code: string[] = [];\n private _images: { contentType: string, data: Buffer }[] = [];\n private _context: Context;\n private _includeSnapshot: 'none' | 'full' | 'incremental' = 'none';\n private _includeTabs = false;\n private _tabSnapshot: TabSnapshot | undefined;\n\n readonly toolName: string;\n readonly toolArgs: Record<string, any>;\n private _isError: boolean | undefined;\n\n constructor(context: Context, toolName: string, toolArgs: Record<string, any>) {\n this._context = context;\n this.toolName = toolName;\n this.toolArgs = toolArgs;\n }\n\n addResult(result: string) {\n this._result.push(result);\n }\n\n addError(error: string) {\n this._result.push(error);\n this._isError = true;\n }\n\n isError() {\n return this._isError;\n }\n\n result() {\n return this._result.join('\\n');\n }\n\n addCode(code: string) {\n this._code.push(code);\n }\n\n code() {\n return this._code.join('\\n');\n }\n\n addImage(image: { contentType: string, data: Buffer }) {\n this._images.push(image);\n }\n\n images() {\n return this._images;\n }\n\n setIncludeSnapshot(full?: 'full') {\n this._includeSnapshot = full ?? 'incremental';\n }\n\n setIncludeTabs() {\n this._includeTabs = true;\n }\n\n async finish() {\n // All the async snapshotting post-action is happening here.\n // Everything below should race against modal states.\n if (this._includeSnapshot !== 'none' && this._context.currentTab())\n this._tabSnapshot = await this._context.currentTabOrDie().captureSnapshot(this._includeSnapshot);\n for (const tab of this._context.tabs())\n await tab.updateTitle();\n }\n\n tabSnapshot(): TabSnapshot | undefined {\n return this._tabSnapshot;\n }\n\n logBegin() {\n if (requestDebug.enabled)\n requestDebug(this.toolName, this.toolArgs);\n }\n\n logEnd() {\n if (requestDebug.enabled)\n requestDebug(this.serialize({ omitSnapshot: true, omitBlobs: true }));\n }\n\n serialize(options: { omitSnapshot?: boolean, omitBlobs?: boolean } = {}): { content: (TextContent | ImageContent)[], isError?: boolean } {\n const response: string[] = [];\n\n // Start with command result.\n if (this._result.length) {\n response.push('### Result');\n response.push(this._result.join('\\n'));\n response.push('');\n }\n\n // Add code if it exists.\n if (this._code.length) {\n response.push(`### Ran Playwright code\n\\`\\`\\`js\n${this._code.join('\\n')}\n\\`\\`\\``);\n response.push('');\n }\n\n // List browser tabs.\n if (this._includeSnapshot !== 'none' || this._includeTabs)\n response.push(...renderTabsMarkdown(this._context.tabs(), this._includeTabs));\n\n // Add snapshot if provided.\n if (this._tabSnapshot?.modalStates.length) {\n response.push(...renderModalStates(this._context, this._tabSnapshot.modalStates));\n response.push('');\n } else if (this._tabSnapshot) {\n response.push(renderTabSnapshot(this._tabSnapshot, options));\n response.push('');\n }\n\n // Main response part\n const content: (TextContent | ImageContent)[] = [\n { type: 'text', text: response.join('\\n') },\n ];\n\n // Image attachments.\n if (this._context.config.imageResponses !== 'omit') {\n for (const image of this._images)\n content.push({ type: 'image', data: options.omitBlobs ? '<blob>' : image.data.toString('base64'), mimeType: image.contentType });\n }\n\n this._redactSecrets(content);\n return { content, isError: this._isError };\n }\n\n private _redactSecrets(content: (TextContent | ImageContent)[]) {\n if (!this._context.config.secrets)\n return;\n\n for (const item of content) {\n if (item.type !== 'text')\n continue;\n for (const [secretName, secretValue] of Object.entries(this._context.config.secrets))\n item.text = item.text.replaceAll(secretValue, `<secret>${secretName}</secret>`);\n }\n }\n}\n\nfunction renderTabSnapshot(tabSnapshot: TabSnapshot, options: { omitSnapshot?: boolean } = {}): string {\n const lines: string[] = [];\n\n if (tabSnapshot.consoleMessages.length) {\n lines.push(`### New console messages`);\n for (const message of tabSnapshot.consoleMessages)\n lines.push(`- ${trim(message.toString(), 100)}`);\n lines.push('');\n }\n\n if (tabSnapshot.downloads.length) {\n lines.push(`### Downloads`);\n for (const entry of tabSnapshot.downloads) {\n if (entry.finished)\n lines.push(`- Downloaded file ${entry.download.suggestedFilename()} to ${entry.outputFile}`);\n else\n lines.push(`- Downloading file ${entry.download.suggestedFilename()} ...`);\n }\n lines.push('');\n }\n\n lines.push(`### Page state`);\n lines.push(`- Page URL: ${tabSnapshot.url}`);\n lines.push(`- Page Title: ${tabSnapshot.title}`);\n lines.push(`- Page Snapshot:`);\n lines.push('```yaml');\n // TODO: perhaps not render page state when there are no changes?\n lines.push(options.omitSnapshot ? '<snapshot>' : (tabSnapshot.ariaSnapshot || '<no changes>'));\n lines.push('```');\n\n return lines.join('\\n');\n}\n\nfunction renderTabsMarkdown(tabs: Tab[], force: boolean = false): string[] {\n if (tabs.length === 1 && !force)\n return [];\n\n if (!tabs.length) {\n return [\n '### Open tabs',\n 'No open tabs. Use the \"browser_navigate\" tool to navigate to a page first.',\n '',\n ];\n }\n\n const lines: string[] = ['### Open tabs'];\n for (let i = 0; i < tabs.length; i++) {\n const tab = tabs[i];\n const current = tab.isCurrentTab() ? ' (current)' : '';\n lines.push(`- ${i}:${current} [${tab.lastTitle()}] (${tab.page.url()})`);\n }\n lines.push('');\n return lines;\n}\n\nfunction trim(text: string, maxLength: number) {\n if (text.length <= maxLength)\n return text;\n return text.slice(0, maxLength) + '...';\n}\n\nfunction parseSections(text: string): Map<string, string> {\n const sections = new Map<string, string>();\n const sectionHeaders = text.split(/^### /m).slice(1); // Remove empty first element\n\n for (const section of sectionHeaders) {\n const firstNewlineIndex = section.indexOf('\\n');\n if (firstNewlineIndex === -1)\n continue;\n\n const sectionName = section.substring(0, firstNewlineIndex);\n const sectionContent = section.substring(firstNewlineIndex + 1).trim();\n sections.set(sectionName, sectionContent);\n }\n\n return sections;\n}\n\nexport function parseResponse(response: CallToolResult) {\n if (response.content?.[0].type !== 'text')\n return undefined;\n const text = response.content[0].text;\n\n const sections = parseSections(text);\n const result = sections.get('Result');\n const code = sections.get('Ran Playwright code');\n const tabs = sections.get('Open tabs');\n const pageState = sections.get('Page state');\n const consoleMessages = sections.get('New console messages');\n const modalState = sections.get('Modal state');\n const downloads = sections.get('Downloads');\n const codeNoFrame = code?.replace(/^```js\\n/, '').replace(/\\n```$/, '');\n const isError = response.isError;\n const attachments = response.content.slice(1);\n\n return {\n result,\n code: codeNoFrame,\n tabs,\n pageState,\n consoleMessages,\n modalState,\n downloads,\n isError,\n attachments,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/sessionLog.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { Response } from './response';\nimport { logUnhandledError } from '../log';\nimport { outputFile } from './config';\n\nimport type { FullConfig } from './config';\nimport type * as actions from './actions';\nimport type { Tab, TabSnapshot } from './tab';\nimport type * as mcpServer from '../sdk/server';\n\ntype LogEntry = {\n timestamp: number;\n toolCall?: {\n toolName: string;\n toolArgs: Record<string, any>;\n result: string;\n isError?: boolean;\n };\n userAction?: actions.Action;\n code: string;\n tabSnapshot?: TabSnapshot;\n};\n\nexport class SessionLog {\n private _folder: string;\n private _file: string;\n private _ordinal = 0;\n private _pendingEntries: LogEntry[] = [];\n private _sessionFileQueue = Promise.resolve();\n private _flushEntriesTimeout: NodeJS.Timeout | undefined;\n\n constructor(sessionFolder: string) {\n this._folder = sessionFolder;\n this._file = path.join(this._folder, 'session.md');\n }\n\n static async create(config: FullConfig, clientInfo: mcpServer.ClientInfo): Promise<SessionLog> {\n const sessionFolder = await outputFile(config, clientInfo, `session-${Date.now()}`, { origin: 'code', reason: 'Saving session' });\n await fs.promises.mkdir(sessionFolder, { recursive: true });\n // eslint-disable-next-line no-console\n console.error(`Session: ${sessionFolder}`);\n return new SessionLog(sessionFolder);\n }\n\n logResponse(response: Response) {\n const entry: LogEntry = {\n timestamp: performance.now(),\n toolCall: {\n toolName: response.toolName,\n toolArgs: response.toolArgs,\n result: response.result(),\n isError: response.isError(),\n },\n code: response.code(),\n tabSnapshot: response.tabSnapshot(),\n };\n this._appendEntry(entry);\n }\n\n logUserAction(action: actions.Action, tab: Tab, code: string, isUpdate: boolean) {\n code = code.trim();\n if (isUpdate) {\n const lastEntry = this._pendingEntries[this._pendingEntries.length - 1];\n if (lastEntry?.userAction?.name === action.name) {\n lastEntry.userAction = action;\n lastEntry.code = code;\n return;\n }\n }\n if (action.name === 'navigate') {\n // Already logged at this location.\n const lastEntry = this._pendingEntries[this._pendingEntries.length - 1];\n if (lastEntry?.tabSnapshot?.url === action.url)\n return;\n }\n const entry: LogEntry = {\n timestamp: performance.now(),\n userAction: action,\n code,\n tabSnapshot: {\n url: tab.page.url(),\n title: '',\n ariaSnapshot: action.ariaSnapshot || '',\n modalStates: [],\n consoleMessages: [],\n downloads: [],\n },\n };\n this._appendEntry(entry);\n }\n\n private _appendEntry(entry: LogEntry) {\n this._pendingEntries.push(entry);\n if (this._flushEntriesTimeout)\n clearTimeout(this._flushEntriesTimeout);\n this._flushEntriesTimeout = setTimeout(() => this._flushEntries(), 1000);\n }\n\n private async _flushEntries() {\n clearTimeout(this._flushEntriesTimeout);\n const entries = this._pendingEntries;\n this._pendingEntries = [];\n const lines: string[] = [''];\n\n for (const entry of entries) {\n const ordinal = (++this._ordinal).toString().padStart(3, '0');\n if (entry.toolCall) {\n lines.push(\n `### Tool call: ${entry.toolCall.toolName}`,\n `- Args`,\n '```json',\n JSON.stringify(entry.toolCall.toolArgs, null, 2),\n '```',\n );\n if (entry.toolCall.result) {\n lines.push(\n entry.toolCall.isError ? `- Error` : `- Result`,\n '```',\n entry.toolCall.result,\n '```',\n );\n }\n }\n\n if (entry.userAction) {\n const actionData = { ...entry.userAction } as any;\n delete actionData.ariaSnapshot;\n delete actionData.selector;\n delete actionData.signals;\n\n lines.push(\n `### User action: ${entry.userAction.name}`,\n `- Args`,\n '```json',\n JSON.stringify(actionData, null, 2),\n '```',\n );\n }\n\n if (entry.code) {\n lines.push(\n `- Code`,\n '```js',\n entry.code,\n '```');\n }\n\n if (entry.tabSnapshot) {\n const fileName = `${ordinal}.snapshot.yml`;\n fs.promises.writeFile(path.join(this._folder, fileName), entry.tabSnapshot.ariaSnapshot).catch(logUnhandledError);\n lines.push(`- Snapshot: ${fileName}`);\n }\n\n lines.push('', '');\n }\n\n this._sessionFileQueue = this._sessionFileQueue.then(() => fs.promises.appendFile(this._file, lines.join('\\n')));\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["path", "fs"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/browser/tab.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EventEmitter } from 'events';\nimport * as playwright from 'playwright-core';\nimport { asLocator, ManualPromise } from 'playwright-core/lib/utils';\n\nimport { callOnPageNoTrace, waitForCompletion } from './tools/utils';\nimport { logUnhandledError } from '../log';\nimport { ModalState } from './tools/tool';\nimport { handleDialog } from './tools/dialogs';\nimport { uploadFile } from './tools/files';\n\nimport type { Context } from './context';\nimport type { Page } from '../../../../playwright-core/src/client/page';\nimport type { Locator } from '../../../../playwright-core/src/client/locator';\n\nexport const TabEvents = {\n modalState: 'modalState'\n};\n\nexport type TabEventsInterface = {\n [TabEvents.modalState]: [modalState: ModalState];\n};\n\nexport type TabSnapshot = {\n url: string;\n title: string;\n ariaSnapshot: string;\n modalStates: ModalState[];\n consoleMessages: ConsoleMessage[];\n downloads: { download: playwright.Download, finished: boolean, outputFile: string }[];\n};\n\nexport class Tab extends EventEmitter<TabEventsInterface> {\n readonly context: Context;\n readonly page: Page;\n private _lastTitle = 'about:blank';\n private _consoleMessages: ConsoleMessage[] = [];\n private _recentConsoleMessages: ConsoleMessage[] = [];\n private _requests: Set<playwright.Request> = new Set();\n private _onPageClose: (tab: Tab) => void;\n private _modalStates: ModalState[] = [];\n private _downloads: { download: playwright.Download, finished: boolean, outputFile: string }[] = [];\n private _initializedPromise: Promise<void>;\n\n constructor(context: Context, page: playwright.Page, onPageClose: (tab: Tab) => void) {\n super();\n this.context = context;\n this.page = page as Page;\n this._onPageClose = onPageClose;\n page.on('console', event => this._handleConsoleMessage(messageToConsoleMessage(event)));\n page.on('pageerror', error => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));\n page.on('request', request => this._requests.add(request));\n page.on('close', () => this._onClose());\n page.on('filechooser', chooser => {\n this.setModalState({\n type: 'fileChooser',\n description: 'File chooser',\n fileChooser: chooser,\n clearedBy: uploadFile.schema.name,\n });\n });\n page.on('dialog', dialog => this._dialogShown(dialog));\n page.on('download', download => {\n void this._downloadStarted(download);\n });\n page.setDefaultNavigationTimeout(this.context.config.timeouts.navigation);\n page.setDefaultTimeout(this.context.config.timeouts.action);\n (page as any)[tabSymbol] = this;\n this._initializedPromise = this._initialize();\n }\n\n static forPage(page: playwright.Page): Tab | undefined {\n return (page as any)[tabSymbol];\n }\n\n static async collectConsoleMessages(page: playwright.Page): Promise<ConsoleMessage[]> {\n const result: ConsoleMessage[] = [];\n const messages = await page.consoleMessages().catch(() => []);\n for (const message of messages)\n result.push(messageToConsoleMessage(message));\n const errors = await page.pageErrors().catch(() => []);\n for (const error of errors)\n result.push(pageErrorToConsoleMessage(error));\n return result;\n }\n\n private async _initialize() {\n for (const message of await Tab.collectConsoleMessages(this.page))\n this._handleConsoleMessage(message);\n const requests = await this.page.requests().catch(() => []);\n for (const request of requests)\n this._requests.add(request);\n }\n\n modalStates(): ModalState[] {\n return this._modalStates;\n }\n\n setModalState(modalState: ModalState) {\n this._modalStates.push(modalState);\n this.emit(TabEvents.modalState, modalState);\n }\n\n clearModalState(modalState: ModalState) {\n this._modalStates = this._modalStates.filter(state => state !== modalState);\n }\n\n modalStatesMarkdown(): string[] {\n return renderModalStates(this.context, this.modalStates());\n }\n\n private _dialogShown(dialog: playwright.Dialog) {\n this.setModalState({\n type: 'dialog',\n description: `\"${dialog.type()}\" dialog with message \"${dialog.message()}\"`,\n dialog,\n clearedBy: handleDialog.schema.name\n });\n }\n\n private async _downloadStarted(download: playwright.Download) {\n const entry = {\n download,\n finished: false,\n outputFile: await this.context.outputFile(download.suggestedFilename(), { origin: 'web', reason: 'Saving download' })\n };\n this._downloads.push(entry);\n await download.saveAs(entry.outputFile);\n entry.finished = true;\n }\n\n private _clearCollectedArtifacts() {\n this._consoleMessages.length = 0;\n this._recentConsoleMessages.length = 0;\n this._requests.clear();\n }\n\n private _handleConsoleMessage(message: ConsoleMessage) {\n this._consoleMessages.push(message);\n this._recentConsoleMessages.push(message);\n }\n\n private _onClose() {\n this._clearCollectedArtifacts();\n this._onPageClose(this);\n }\n\n async updateTitle() {\n await this._raceAgainstModalStates(async () => {\n this._lastTitle = await callOnPageNoTrace(this.page, page => page.title());\n });\n }\n\n lastTitle(): string {\n return this._lastTitle;\n }\n\n isCurrentTab(): boolean {\n return this === this.context.currentTab();\n }\n\n async waitForLoadState(state: 'load', options?: { timeout?: number }): Promise<void> {\n await callOnPageNoTrace(this.page, page => page.waitForLoadState(state, options).catch(logUnhandledError));\n }\n\n async navigate(url: string) {\n this._clearCollectedArtifacts();\n\n const downloadEvent = callOnPageNoTrace(this.page, page => page.waitForEvent('download').catch(logUnhandledError));\n try {\n await this.page.goto(url, { waitUntil: 'domcontentloaded' });\n } catch (_e: unknown) {\n const e = _e as Error;\n const mightBeDownload =\n e.message.includes('net::ERR_ABORTED') // chromium\n || e.message.includes('Download is starting'); // firefox + webkit\n if (!mightBeDownload)\n throw e;\n // on chromium, the download event is fired *after* page.goto rejects, so we wait a lil bit\n const download = await Promise.race([\n downloadEvent,\n new Promise(resolve => setTimeout(resolve, 3000)),\n ]);\n if (!download)\n throw e;\n // Make sure other \"download\" listeners are notified first.\n await new Promise(resolve => setTimeout(resolve, 500));\n return;\n }\n\n // Cap load event to 5 seconds, the page is operational at this point.\n await this.waitForLoadState('load', { timeout: 5000 });\n }\n\n async consoleMessages(type?: 'error'): Promise<ConsoleMessage[]> {\n await this._initializedPromise;\n return this._consoleMessages.filter(message => type ? message.type === type : true);\n }\n\n async requests(): Promise<Set<playwright.Request>> {\n await this._initializedPromise;\n return this._requests;\n }\n\n async captureSnapshot(mode: 'full' | 'incremental'): Promise<TabSnapshot> {\n let tabSnapshot: TabSnapshot | undefined;\n const modalStates = await this._raceAgainstModalStates(async () => {\n const snapshot = await this.page._snapshotForAI({ mode, track: 'response' });\n tabSnapshot = {\n url: this.page.url(),\n title: await this.page.title(),\n ariaSnapshot: snapshot,\n modalStates: [],\n consoleMessages: [],\n downloads: this._downloads,\n };\n });\n if (tabSnapshot) {\n // Assign console message late so that we did not lose any to modal state.\n tabSnapshot.consoleMessages = this._recentConsoleMessages;\n this._recentConsoleMessages = [];\n }\n return tabSnapshot ?? {\n url: this.page.url(),\n title: '',\n ariaSnapshot: '',\n modalStates,\n consoleMessages: [],\n downloads: [],\n };\n }\n\n private _javaScriptBlocked(): boolean {\n return this._modalStates.some(state => state.type === 'dialog');\n }\n\n private async _raceAgainstModalStates(action: () => Promise<void>): Promise<ModalState[]> {\n if (this.modalStates().length)\n return this.modalStates();\n\n const promise = new ManualPromise<ModalState[]>();\n const listener = (modalState: ModalState) => promise.resolve([modalState]);\n this.once(TabEvents.modalState, listener);\n\n return await Promise.race([\n action().then(() => {\n this.off(TabEvents.modalState, listener);\n return [];\n }),\n promise,\n ]);\n }\n\n async waitForCompletion(callback: () => Promise<void>) {\n await this._raceAgainstModalStates(() => waitForCompletion(this, callback));\n }\n\n async refLocator(params: { element: string, ref: string }): Promise<{ locator: Locator, resolved: string }> {\n return (await this.refLocators([params]))[0];\n }\n\n async refLocators(params: { element: string, ref: string }[]): Promise<{ locator: Locator, resolved: string }[]> {\n return Promise.all(params.map(async param => {\n try {\n const locator = this.page.locator(`aria-ref=${param.ref}`).describe(param.element) as Locator;\n const { resolvedSelector } = await locator._resolveSelector();\n return { locator, resolved: asLocator('javascript', resolvedSelector) };\n } catch (e) {\n throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);\n }\n }));\n }\n\n async waitForTimeout(time: number) {\n if (this._javaScriptBlocked()) {\n await new Promise(f => setTimeout(f, time));\n return;\n }\n\n await callOnPageNoTrace(this.page, page => {\n return page.evaluate(() => new Promise(f => setTimeout(f, 1000)));\n });\n }\n}\n\nexport type ConsoleMessage = {\n type: ReturnType<playwright.ConsoleMessage['type']> | undefined;\n text: string;\n toString(): string;\n};\n\nfunction messageToConsoleMessage(message: playwright.ConsoleMessage): ConsoleMessage {\n return {\n type: message.type(),\n text: message.text(),\n toString: () => `[${message.type().toUpperCase()}] ${message.text()} @ ${message.location().url}:${message.location().lineNumber}`,\n };\n}\n\nfunction pageErrorToConsoleMessage(errorOrValue: Error | any): ConsoleMessage {\n if (errorOrValue instanceof Error) {\n return {\n type: 'error',\n text: errorOrValue.message,\n toString: () => errorOrValue.stack || errorOrValue.message,\n };\n }\n return {\n type: 'error',\n text: String(errorOrValue),\n toString: () => String(errorOrValue),\n };\n}\n\nexport function renderModalStates(context: Context, modalStates: ModalState[]): string[] {\n const result: string[] = ['### Modal state'];\n if (modalStates.length === 0)\n result.push('- There is no modal state present');\n for (const state of modalStates)\n result.push(`- [${state.description}]: can be handled by the \"${state.clearedBy}\" tool`);\n return result;\n}\n\nconst tabSymbol = Symbol('tabSymbol');\n"],
5
- "mappings": "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",
6
- "names": ["import_utils"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/actionRetry.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Executes a locator action with automatic retry using allowIntercept option.\n *\n * First attempts the action with the provided options. If the action fails with\n * \"intercepts pointer events\" error, automatically retries with allowIntercept: true.\n *\n * @param action - Function that performs the locator action\n * @param options - Options to pass to the action\n * @returns Object indicating whether allowIntercept was used\n */\nexport async function retryWithAllowIntercept<Options extends Record<string, any>>(\n action: (opts: Options) => Promise<void>,\n options: Options\n): Promise<{ usedAllowIntercept: boolean }> {\n try {\n // First attempt without allowIntercept\n await action(options);\n return { usedAllowIntercept: false };\n } catch (error: any) {\n // Check if error is due to element being intercepted\n if (error?.message?.includes('intercepts pointer events')) {\n // Retry with allowIntercept enabled\n const optionsWithAllowIntercept = { ...options, allowIntercept: true } as Options;\n await action(optionsWithAllowIntercept);\n return { usedAllowIntercept: true };\n }\n // Re-throw other errors\n throw error;\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BA,eAAsB,wBACpB,QACA,SAC0C;AAC1C,MAAI;AAEF,UAAM,OAAO,OAAO;AACpB,WAAO,EAAE,oBAAoB,MAAM;AAAA,EACrC,SAAS,OAAY;AAEnB,QAAI,OAAO,SAAS,SAAS,2BAA2B,GAAG;AAEzD,YAAM,4BAA4B,EAAE,GAAG,SAAS,gBAAgB,KAAK;AACrE,YAAM,OAAO,yBAAyB;AACtC,aAAO,EAAE,oBAAoB,KAAK;AAAA,IACpC;AAEA,UAAM;AAAA,EACR;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/common.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from '../../sdk/bundle';\nimport { defineTabTool, defineTool } from './tool';\n\nconst close = defineTool({\n capability: 'core',\n\n schema: {\n name: 'browser_close',\n title: 'Close browser',\n description: 'Close the page',\n inputSchema: z.object({}),\n type: 'action',\n },\n\n handle: async (context, params, response) => {\n await context.closeBrowserContext();\n response.setIncludeTabs();\n response.addCode(`await page.close()`);\n },\n});\n\nconst resize = defineTabTool({\n capability: 'core',\n schema: {\n name: 'browser_resize',\n title: 'Resize browser window',\n description: 'Resize the browser window',\n inputSchema: z.object({\n width: z.number().describe('Width of the browser window'),\n height: z.number().describe('Height of the browser window'),\n }),\n type: 'action',\n },\n\n handle: async (tab, params, response) => {\n response.addCode(`await page.setViewportSize({ width: ${params.width}, height: ${params.height} });`);\n\n await tab.waitForCompletion(async () => {\n await tab.page.setViewportSize({ width: params.width, height: params.height });\n });\n },\n});\n\nexport default [\n close,\n resize\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,kBAA0C;AAE1C,MAAM,YAAQ,wBAAW;AAAA,EACvB,YAAY;AAAA,EAEZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO,CAAC,CAAC;AAAA,IACxB,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,QAAQ,aAAa;AAC3C,UAAM,QAAQ,oBAAoB;AAClC,aAAS,eAAe;AACxB,aAAS,QAAQ,oBAAoB;AAAA,EACvC;AACF,CAAC;AAED,MAAM,aAAS,2BAAc;AAAA,EAC3B,YAAY;AAAA,EACZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,OAAO,gBAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,MACxD,QAAQ,gBAAE,OAAO,EAAE,SAAS,8BAA8B;AAAA,IAC5D,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,KAAK,QAAQ,aAAa;AACvC,aAAS,QAAQ,uCAAuC,OAAO,KAAK,aAAa,OAAO,MAAM,MAAM;AAEpG,UAAM,IAAI,kBAAkB,YAAY;AACtC,YAAM,IAAI,KAAK,gBAAgB,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC/E,CAAC;AAAA,EACH;AACF,CAAC;AAED,IAAO,iBAAQ;AAAA,EACb;AAAA,EACA;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/console.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from '../../sdk/bundle';\nimport { defineTabTool } from './tool';\n\nconst console = defineTabTool({\n capability: 'core',\n schema: {\n name: 'browser_console_messages',\n title: 'Get console messages',\n description: 'Returns all console messages',\n inputSchema: z.object({\n onlyErrors: z.boolean().optional().describe('Only return error messages'),\n }),\n type: 'readOnly',\n },\n handle: async (tab, params, response) => {\n const messages = await tab.consoleMessages(params.onlyErrors ? 'error' : undefined);\n messages.map(message => response.addResult(message.toString()));\n },\n});\n\nexport default [\n console,\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,kBAA8B;AAE9B,MAAM,cAAU,2BAAc;AAAA,EAC5B,YAAY;AAAA,EACZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,YAAY,gBAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,4BAA4B;AAAA,IAC1E,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EACA,QAAQ,OAAO,KAAK,QAAQ,aAAa;AACvC,UAAM,WAAW,MAAM,IAAI,gBAAgB,OAAO,aAAa,UAAU,MAAS;AAClF,aAAS,IAAI,aAAW,SAAS,UAAU,QAAQ,SAAS,CAAC,CAAC;AAAA,EAChE;AACF,CAAC;AAED,IAAO,kBAAQ;AAAA,EACb;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/dialogs.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from '../../sdk/bundle';\nimport { defineTabTool } from './tool';\n\nexport const handleDialog = defineTabTool({\n capability: 'core',\n\n schema: {\n name: 'browser_handle_dialog',\n title: 'Handle a dialog',\n description: 'Handle a dialog',\n inputSchema: z.object({\n accept: z.boolean().describe('Whether to accept the dialog.'),\n promptText: z.string().optional().describe('The text of the prompt in case of a prompt dialog.'),\n }),\n type: 'action',\n },\n\n handle: async (tab, params, response) => {\n response.setIncludeSnapshot();\n\n const dialogState = tab.modalStates().find(state => state.type === 'dialog');\n if (!dialogState)\n throw new Error('No dialog visible');\n\n tab.clearModalState(dialogState);\n await tab.waitForCompletion(async () => {\n if (params.accept)\n await dialogState.dialog.accept(params.promptText);\n else\n await dialogState.dialog.dismiss();\n });\n },\n\n clearsModalState: 'dialog',\n});\n\nexport default [\n handleDialog,\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,kBAA8B;AAEvB,MAAM,mBAAe,2BAAc;AAAA,EACxC,YAAY;AAAA,EAEZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,QAAQ,gBAAE,QAAQ,EAAE,SAAS,+BAA+B;AAAA,MAC5D,YAAY,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oDAAoD;AAAA,IACjG,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,KAAK,QAAQ,aAAa;AACvC,aAAS,mBAAmB;AAE5B,UAAM,cAAc,IAAI,YAAY,EAAE,KAAK,WAAS,MAAM,SAAS,QAAQ;AAC3E,QAAI,CAAC;AACH,YAAM,IAAI,MAAM,mBAAmB;AAErC,QAAI,gBAAgB,WAAW;AAC/B,UAAM,IAAI,kBAAkB,YAAY;AACtC,UAAI,OAAO;AACT,cAAM,YAAY,OAAO,OAAO,OAAO,UAAU;AAAA;AAEjD,cAAM,YAAY,OAAO,QAAQ;AAAA,IACrC,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB;AACpB,CAAC;AAED,IAAO,kBAAQ;AAAA,EACb;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/evaluate.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from '../../sdk/bundle';\nimport { defineTabTool } from './tool';\nimport * as javascript from '../codegen';\n\nimport type { Tab } from '../tab';\n\nconst evaluateSchema = z.object({\n function: z.string().describe('() => { /* code */ } or (element) => { /* code */ } when element is provided'),\n element: z.string().optional().describe('Human-readable element description used to obtain permission to interact with the element'),\n ref: z.string().optional().describe('Exact target element reference from the page snapshot'),\n});\n\nconst evaluate = defineTabTool({\n capability: 'core',\n schema: {\n name: 'browser_evaluate',\n title: 'Evaluate JavaScript',\n description: 'Evaluate JavaScript expression on page or element',\n inputSchema: evaluateSchema,\n type: 'action',\n },\n\n handle: async (tab, params, response) => {\n response.setIncludeSnapshot();\n\n let locator: Awaited<ReturnType<Tab['refLocator']>> | undefined;\n if (params.ref && params.element) {\n locator = await tab.refLocator({ ref: params.ref, element: params.element });\n response.addCode(`await page.${locator.resolved}.evaluate(${javascript.quote(params.function)});`);\n } else {\n response.addCode(`await page.evaluate(${javascript.quote(params.function)});`);\n }\n\n await tab.waitForCompletion(async () => {\n const receiver = locator?.locator ?? tab.page;\n const result = await receiver._evaluateFunction(params.function);\n response.addResult(JSON.stringify(result, null, 2) || 'undefined');\n });\n },\n});\n\nexport default [\n evaluate,\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,kBAA8B;AAC9B,iBAA4B;AAI5B,MAAM,iBAAiB,gBAAE,OAAO;AAAA,EAC9B,UAAU,gBAAE,OAAO,EAAE,SAAS,8EAA8E;AAAA,EAC5G,SAAS,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2FAA2F;AAAA,EACnI,KAAK,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uDAAuD;AAC7F,CAAC;AAED,MAAM,eAAW,2BAAc;AAAA,EAC7B,YAAY;AAAA,EACZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,KAAK,QAAQ,aAAa;AACvC,aAAS,mBAAmB;AAE5B,QAAI;AACJ,QAAI,OAAO,OAAO,OAAO,SAAS;AAChC,gBAAU,MAAM,IAAI,WAAW,EAAE,KAAK,OAAO,KAAK,SAAS,OAAO,QAAQ,CAAC;AAC3E,eAAS,QAAQ,cAAc,QAAQ,QAAQ,aAAa,WAAW,MAAM,OAAO,QAAQ,CAAC,IAAI;AAAA,IACnG,OAAO;AACL,eAAS,QAAQ,uBAAuB,WAAW,MAAM,OAAO,QAAQ,CAAC,IAAI;AAAA,IAC/E;AAEA,UAAM,IAAI,kBAAkB,YAAY;AACtC,YAAM,WAAW,SAAS,WAAW,IAAI;AACzC,YAAM,SAAS,MAAM,SAAS,kBAAkB,OAAO,QAAQ;AAC/D,eAAS,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,KAAK,WAAW;AAAA,IACnE,CAAC;AAAA,EACH;AACF,CAAC;AAED,IAAO,mBAAQ;AAAA,EACb;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/files.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from '../../sdk/bundle';\nimport { defineTabTool } from './tool';\n\nexport const uploadFile = defineTabTool({\n capability: 'core',\n\n schema: {\n name: 'browser_file_upload',\n title: 'Upload files',\n description: 'Upload one or multiple files',\n inputSchema: z.object({\n paths: z.array(z.string()).optional().describe('The absolute paths to the files to upload. Can be single file or multiple files. If omitted, file chooser is cancelled.'),\n }),\n type: 'action',\n },\n\n handle: async (tab, params, response) => {\n response.setIncludeSnapshot();\n\n const modalState = tab.modalStates().find(state => state.type === 'fileChooser');\n if (!modalState)\n throw new Error('No file chooser visible');\n\n response.addCode(`await fileChooser.setFiles(${JSON.stringify(params.paths)})`);\n\n tab.clearModalState(modalState);\n await tab.waitForCompletion(async () => {\n if (params.paths)\n await modalState.fileChooser.setFiles(params.paths);\n });\n },\n\n clearsModalState: 'fileChooser',\n});\n\nexport default [\n uploadFile,\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,kBAA8B;AAEvB,MAAM,iBAAa,2BAAc;AAAA,EACtC,YAAY;AAAA,EAEZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,OAAO,gBAAE,MAAM,gBAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,yHAAyH;AAAA,IAC1K,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,KAAK,QAAQ,aAAa;AACvC,aAAS,mBAAmB;AAE5B,UAAM,aAAa,IAAI,YAAY,EAAE,KAAK,WAAS,MAAM,SAAS,aAAa;AAC/E,QAAI,CAAC;AACH,YAAM,IAAI,MAAM,yBAAyB;AAE3C,aAAS,QAAQ,8BAA8B,KAAK,UAAU,OAAO,KAAK,CAAC,GAAG;AAE9E,QAAI,gBAAgB,UAAU;AAC9B,UAAM,IAAI,kBAAkB,YAAY;AACtC,UAAI,OAAO;AACT,cAAM,WAAW,YAAY,SAAS,OAAO,KAAK;AAAA,IACtD,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB;AACpB,CAAC;AAED,IAAO,gBAAQ;AAAA,EACb;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/form.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from '../../sdk/bundle';\nimport { defineTabTool } from './tool';\nimport * as codegen from '../codegen';\nimport { retryWithAllowIntercept } from './actionRetry';\n\nconst fillForm = defineTabTool({\n capability: 'core',\n\n schema: {\n name: 'browser_fill_form',\n title: 'Fill form',\n description: 'Fill multiple form fields',\n inputSchema: z.object({\n fields: z.array(z.object({\n name: z.string().describe('Human-readable field name'),\n type: z.enum(['textbox', 'checkbox', 'radio', 'combobox', 'slider']).describe('Type of the field'),\n ref: z.string().describe('Exact target field reference from the page snapshot'),\n value: z.string().describe('Value to fill in the field. If the field is a checkbox, the value should be `true` or `false`. If the field is a combobox, the value should be the text of the option.'),\n })).describe('Fields to fill in'),\n }),\n type: 'input',\n },\n\n handle: async (tab, params, response) => {\n response.setIncludeSnapshot();\n\n for (const field of params.fields) {\n const { locator, resolved } = await tab.refLocator({ element: field.name, ref: field.ref });\n const locatorSource = `await page.${resolved}`;\n if (field.type === 'textbox' || field.type === 'slider') {\n const secret = tab.context.lookupSecret(field.value);\n await locator.fill(secret.value);\n response.addCode(`${locatorSource}.fill(${secret.code});`);\n } else if (field.type === 'checkbox' || field.type === 'radio') {\n // Checkbox and radio can be intercepted by overlays, use retry logic\n const result = await retryWithAllowIntercept(\n async (opts) => await locator.setChecked(field.value === 'true', opts),\n {}\n );\n const optionsAttr = result.usedAllowIntercept ? ', { allowIntercept: true }' : '';\n response.addCode(`${locatorSource}.setChecked(${field.value}${optionsAttr});`);\n } else if (field.type === 'combobox') {\n await locator.selectOption({ label: field.value });\n response.addCode(`${locatorSource}.selectOption(${codegen.quote(field.value)});`);\n }\n }\n },\n});\n\nexport default [\n fillForm,\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,kBAA8B;AAC9B,cAAyB;AACzB,yBAAwC;AAExC,MAAM,eAAW,2BAAc;AAAA,EAC7B,YAAY;AAAA,EAEZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,QAAQ,gBAAE,MAAM,gBAAE,OAAO;AAAA,QACvB,MAAM,gBAAE,OAAO,EAAE,SAAS,2BAA2B;AAAA,QACrD,MAAM,gBAAE,KAAK,CAAC,WAAW,YAAY,SAAS,YAAY,QAAQ,CAAC,EAAE,SAAS,mBAAmB;AAAA,QACjG,KAAK,gBAAE,OAAO,EAAE,SAAS,qDAAqD;AAAA,QAC9E,OAAO,gBAAE,OAAO,EAAE,SAAS,wKAAwK;AAAA,MACrM,CAAC,CAAC,EAAE,SAAS,mBAAmB;AAAA,IAClC,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,KAAK,QAAQ,aAAa;AACvC,aAAS,mBAAmB;AAE5B,eAAW,SAAS,OAAO,QAAQ;AACjC,YAAM,EAAE,SAAS,SAAS,IAAI,MAAM,IAAI,WAAW,EAAE,SAAS,MAAM,MAAM,KAAK,MAAM,IAAI,CAAC;AAC1F,YAAM,gBAAgB,cAAc,QAAQ;AAC5C,UAAI,MAAM,SAAS,aAAa,MAAM,SAAS,UAAU;AACvD,cAAM,SAAS,IAAI,QAAQ,aAAa,MAAM,KAAK;AACnD,cAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,iBAAS,QAAQ,GAAG,aAAa,SAAS,OAAO,IAAI,IAAI;AAAA,MAC3D,WAAW,MAAM,SAAS,cAAc,MAAM,SAAS,SAAS;AAE9D,cAAM,SAAS,UAAM;AAAA,UACnB,OAAO,SAAS,MAAM,QAAQ,WAAW,MAAM,UAAU,QAAQ,IAAI;AAAA,UACrE,CAAC;AAAA,QACH;AACA,cAAM,cAAc,OAAO,qBAAqB,+BAA+B;AAC/E,iBAAS,QAAQ,GAAG,aAAa,eAAe,MAAM,KAAK,GAAG,WAAW,IAAI;AAAA,MAC/E,WAAW,MAAM,SAAS,YAAY;AACpC,cAAM,QAAQ,aAAa,EAAE,OAAO,MAAM,MAAM,CAAC;AACjD,iBAAS,QAAQ,GAAG,aAAa,iBAAiB,QAAQ,MAAM,MAAM,KAAK,CAAC,IAAI;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAED,IAAO,eAAQ;AAAA,EACb;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/mcp/browser/tools/install.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { fork } from 'child_process';\nimport path from 'path';\n\nimport { z } from '../../sdk/bundle';\nimport { defineTool } from './tool';\n\nconst install = defineTool({\n capability: 'core-install',\n schema: {\n name: 'browser_install',\n title: 'Install the browser specified in the config',\n description: 'Install the browser specified in the config. Call this if you get an error about the browser not being installed.',\n inputSchema: z.object({}),\n type: 'action',\n },\n\n handle: async (context, params, response) => {\n const channel = context.config.browser?.launchOptions?.channel ?? context.config.browser?.browserName ?? 'chrome';\n const cliPath = path.join(require.resolve('playwright/package.json'), '../cli.js');\n const child = fork(cliPath, ['install', channel], {\n stdio: 'pipe',\n });\n const output: string[] = [];\n child.stdout?.on('data', data => output.push(data.toString()));\n child.stderr?.on('data', data => output.push(data.toString()));\n await new Promise<void>((resolve, reject) => {\n child.on('close', code => {\n if (code === 0)\n resolve();\n else\n reject(new Error(`Failed to install browser: ${output.join('')}`));\n });\n });\n response.setIncludeTabs();\n },\n});\n\nexport default [\n install,\n];\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,2BAAqB;AACrB,kBAAiB;AAEjB,oBAAkB;AAClB,kBAA2B;AAE3B,MAAM,cAAU,wBAAW;AAAA,EACzB,YAAY;AAAA,EACZ,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO,CAAC,CAAC;AAAA,IACxB,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,QAAQ,aAAa;AAC3C,UAAM,UAAU,QAAQ,OAAO,SAAS,eAAe,WAAW,QAAQ,OAAO,SAAS,eAAe;AACzG,UAAM,UAAU,YAAAA,QAAK,KAAK,gBAAgB,yBAAyB,GAAG,WAAW;AACjF,UAAM,YAAQ,2BAAK,SAAS,CAAC,WAAW,OAAO,GAAG;AAAA,MAChD,OAAO;AAAA,IACT,CAAC;AACD,UAAM,SAAmB,CAAC;AAC1B,UAAM,QAAQ,GAAG,QAAQ,UAAQ,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC;AAC7D,UAAM,QAAQ,GAAG,QAAQ,UAAQ,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC;AAC7D,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,YAAM,GAAG,SAAS,UAAQ;AACxB,YAAI,SAAS;AACX,kBAAQ;AAAA;AAER,iBAAO,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE,CAAC,EAAE,CAAC;AAAA,MACrE,CAAC;AAAA,IACH,CAAC;AACD,aAAS,eAAe;AAAA,EAC1B;AACF,CAAC;AAED,IAAO,kBAAQ;AAAA,EACb;AACF;",
6
- "names": ["path"]
7
- }