rae-playwright-mcp 0.0.1 → 0.0.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.
- package/README.md +63 -21
- package/cli.js +7 -3
- package/index.js +1 -1
- package/lib/common/config.js +282 -0
- package/lib/common/config.js.map +7 -0
- package/lib/common/configLoader.js +345 -0
- package/lib/common/configLoader.js.map +7 -0
- package/lib/common/esmLoaderHost.js +105 -0
- package/lib/common/esmLoaderHost.js.map +7 -0
- package/lib/common/expectBundle.js +44 -0
- package/lib/common/expectBundle.js.map +7 -0
- package/lib/common/expectBundleImpl.js +15781 -0
- package/lib/common/expectBundleImpl.js.map +7 -0
- package/lib/common/fixtures.js +303 -0
- package/lib/common/fixtures.js.map +7 -0
- package/lib/common/globals.js +59 -0
- package/lib/common/globals.js.map +7 -0
- package/lib/common/ipc.js +61 -0
- package/lib/common/ipc.js.map +7 -0
- package/lib/common/poolBuilder.js +86 -0
- package/lib/common/poolBuilder.js.map +7 -0
- package/lib/common/process.js +133 -0
- package/lib/common/process.js.map +7 -0
- package/lib/common/suiteUtils.js +141 -0
- package/lib/common/suiteUtils.js.map +7 -0
- package/lib/common/test.js +323 -0
- package/lib/common/test.js.map +7 -0
- package/lib/common/testLoader.js +102 -0
- package/lib/common/testLoader.js.map +7 -0
- package/lib/common/testType.js +299 -0
- package/lib/common/testType.js.map +7 -0
- package/lib/common/validators.js +69 -0
- package/lib/common/validators.js.map +7 -0
- package/lib/mcp/browser/actions.d.js +17 -0
- package/lib/mcp/browser/actions.d.js.map +7 -0
- package/lib/mcp/browser/browserContextFactory.js +343 -0
- package/lib/mcp/browser/browserContextFactory.js.map +7 -0
- package/lib/mcp/browser/browserServerBackend.js +78 -0
- package/lib/mcp/browser/browserServerBackend.js.map +7 -0
- package/lib/mcp/browser/config.js +421 -0
- package/lib/mcp/browser/config.js.map +7 -0
- package/lib/mcp/browser/context.js +287 -0
- package/lib/mcp/browser/context.js.map +7 -0
- package/lib/mcp/browser/response.js +353 -0
- package/lib/mcp/browser/response.js.map +7 -0
- package/lib/mcp/browser/sessionLog.js +161 -0
- package/lib/mcp/browser/sessionLog.js.map +7 -0
- package/lib/mcp/browser/tab.js +329 -0
- package/lib/mcp/browser/tab.js.map +7 -0
- package/lib/mcp/browser/tools/common.js +64 -0
- package/lib/mcp/browser/tools/common.js.map +7 -0
- package/lib/mcp/browser/tools/console.js +45 -0
- package/lib/mcp/browser/tools/console.js.map +7 -0
- package/lib/mcp/browser/tools/dialogs.js +61 -0
- package/lib/mcp/browser/tools/dialogs.js.map +7 -0
- package/lib/mcp/browser/tools/evaluate.js +60 -0
- package/lib/mcp/browser/tools/evaluate.js.map +7 -0
- package/lib/mcp/browser/tools/files.js +59 -0
- package/lib/mcp/browser/tools/files.js.map +7 -0
- package/lib/mcp/browser/tools/form.js +64 -0
- package/lib/mcp/browser/tools/form.js.map +7 -0
- package/lib/mcp/browser/tools/install.js +70 -0
- package/lib/mcp/browser/tools/install.js.map +7 -0
- package/lib/mcp/browser/tools/keyboard.js +85 -0
- package/lib/mcp/browser/tools/keyboard.js.map +7 -0
- package/lib/mcp/browser/tools/mouse.js +108 -0
- package/lib/mcp/browser/tools/mouse.js.map +7 -0
- package/lib/mcp/browser/tools/navigate.js +63 -0
- package/lib/mcp/browser/tools/navigate.js.map +7 -0
- package/lib/mcp/browser/tools/network.js +61 -0
- package/lib/mcp/browser/tools/network.js.map +7 -0
- package/lib/mcp/browser/tools/pdf.js +49 -0
- package/lib/mcp/browser/tools/pdf.js.map +7 -0
- package/lib/mcp/browser/tools/runCode.js +78 -0
- package/lib/mcp/browser/tools/runCode.js.map +7 -0
- package/lib/mcp/browser/tools/screenshot.js +106 -0
- package/lib/mcp/browser/tools/screenshot.js.map +7 -0
- package/lib/mcp/browser/tools/snapshot.js +192 -0
- package/lib/mcp/browser/tools/snapshot.js.map +7 -0
- package/lib/mcp/browser/tools/tabs.js +68 -0
- package/lib/mcp/browser/tools/tabs.js.map +7 -0
- package/lib/mcp/browser/tools/tool.js +51 -0
- package/lib/mcp/browser/tools/tool.js.map +7 -0
- package/lib/mcp/browser/tools/tracing.js +76 -0
- package/lib/mcp/browser/tools/tracing.js.map +7 -0
- package/lib/mcp/browser/tools/utils.js +95 -0
- package/lib/mcp/browser/tools/utils.js.map +7 -0
- package/lib/mcp/browser/tools/verify.js +144 -0
- package/lib/mcp/browser/tools/verify.js.map +7 -0
- package/lib/mcp/browser/tools/wait.js +64 -0
- package/lib/mcp/browser/tools/wait.js.map +7 -0
- package/lib/mcp/browser/tools.js +83 -0
- package/lib/mcp/browser/tools.js.map +7 -0
- package/lib/mcp/browser/watchdog.js +45 -0
- package/lib/mcp/browser/watchdog.js.map +7 -0
- package/lib/mcp/config.d.js +17 -0
- package/lib/mcp/config.d.js.map +7 -0
- package/lib/mcp/config.d.ts +197 -0
- package/lib/mcp/extension/cdpRelay.js +352 -0
- package/lib/mcp/extension/cdpRelay.js.map +7 -0
- package/lib/mcp/extension/extensionContextFactory.js +77 -0
- package/lib/mcp/extension/extensionContextFactory.js.map +7 -0
- package/lib/mcp/extension/protocol.js +29 -0
- package/lib/mcp/extension/protocol.js.map +7 -0
- package/lib/mcp/index.js +62 -0
- package/lib/mcp/index.js.map +7 -0
- package/lib/mcp/log.js +36 -0
- package/lib/mcp/log.js.map +7 -0
- package/lib/mcp/program.js +94 -0
- package/lib/mcp/program.js.map +7 -0
- package/lib/mcp/sdk/exports.js +29 -0
- package/lib/mcp/sdk/exports.js.map +7 -0
- package/lib/mcp/sdk/http.js +153 -0
- package/lib/mcp/sdk/http.js.map +7 -0
- package/lib/mcp/sdk/inProcessTransport.js +72 -0
- package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
- package/lib/mcp/sdk/server.js +208 -0
- package/lib/mcp/sdk/server.js.map +7 -0
- package/lib/mcp/sdk/tool.js +48 -0
- package/lib/mcp/sdk/tool.js.map +7 -0
- package/lib/mcp/test/browserBackend.js +99 -0
- package/lib/mcp/test/browserBackend.js.map +7 -0
- package/lib/mcp/test/generatorTools.js +123 -0
- package/lib/mcp/test/generatorTools.js.map +7 -0
- package/lib/mcp/test/plannerTools.js +145 -0
- package/lib/mcp/test/plannerTools.js.map +7 -0
- package/lib/mcp/test/seed.js +83 -0
- package/lib/mcp/test/seed.js.map +7 -0
- package/lib/mcp/test/streams.js +45 -0
- package/lib/mcp/test/streams.js.map +7 -0
- package/lib/mcp/test/testBackend.js +100 -0
- package/lib/mcp/test/testBackend.js.map +7 -0
- package/lib/mcp/test/testContext.js +280 -0
- package/lib/mcp/test/testContext.js.map +7 -0
- package/lib/mcp/test/testTool.js +31 -0
- package/lib/mcp/test/testTool.js.map +7 -0
- package/lib/mcp/test/testTools.js +109 -0
- package/lib/mcp/test/testTools.js.map +7 -0
- package/lib/third_party/pirates.js +63 -0
- package/lib/third_party/pirates.js.map +7 -0
- package/lib/third_party/tsconfig-loader.js +104 -0
- package/lib/third_party/tsconfig-loader.js.map +7 -0
- package/lib/transform/babelBundle.js +44 -0
- package/lib/transform/babelBundle.js.map +7 -0
- package/lib/transform/babelBundleImpl.js +68726 -0
- package/lib/transform/babelBundleImpl.js.map +7 -0
- package/lib/transform/babelHighlightUtils.js +64 -0
- package/lib/transform/babelHighlightUtils.js.map +7 -0
- package/lib/transform/compilationCache.js +273 -0
- package/lib/transform/compilationCache.js.map +7 -0
- package/lib/transform/esmLoader.js +104 -0
- package/lib/transform/esmLoader.js.map +7 -0
- package/lib/transform/portTransport.js +68 -0
- package/lib/transform/portTransport.js.map +7 -0
- package/lib/transform/transform.js +297 -0
- package/lib/transform/transform.js.map +7 -0
- package/lib/util.js +404 -0
- package/lib/utilsBundle.js +44 -0
- package/lib/utilsBundleImpl.js +13122 -0
- package/package.json +4 -3
|
@@ -0,0 +1,7 @@
|
|
|
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';\nimport type { ModalState } from './tools/tool';\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 _files: { fileName: string, title: string }[] = [];\n private _context: Context;\n private _includeSnapshot: 'none' | 'full' | 'incremental' = 'none';\n private _includeTabs = false;\n private _includeModalStates: ModalState[] | undefined;\n private _includeMetaOnly: boolean = 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 async addFile(fileName: string, options: { origin: 'code' | 'llm' | 'web', reason: string }) {\n const resolvedFile = await this._context.outputFile(fileName, options);\n this._files.push({ fileName: resolvedFile, title: options.reason });\n return resolvedFile;\n }\n\n setIncludeSnapshot() {\n this._includeSnapshot = this._context.config.snapshot.mode;\n }\n\n setIncludeFullSnapshot() {\n this._includeSnapshot = 'full';\n }\n\n setIncludeTabs() {\n this._includeTabs = true;\n }\n\n setIncludeModalStates(modalStates: ModalState[]) {\n this._includeModalStates = modalStates;\n }\n\n setIncludeMetaOnly() {\n this._includeMetaOnly = true;\n }\n\n async finish() {\n if (this._tabSnapshot)\n return;\n\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();\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());\n }\n\n render(): RenderedResponse{\n const renderedResponse = new RenderedResponse();\n\n if (this._result.length)\n renderedResponse.results.push(...this._result);\n\n // Add code if it exists.\n if (this._code.length)\n renderedResponse.code.push(...this._code);\n\n // List browser tabs.\n if (this._includeSnapshot !== 'none' || this._includeTabs) {\n const tabsMarkdown = renderTabsMarkdown(this._context.tabs(), this._includeTabs);\n if (tabsMarkdown.length)\n renderedResponse.states.tabs = tabsMarkdown.join('\\n');\n }\n\n // Add snapshot if provided.\n if (this._tabSnapshot?.modalStates.length) {\n const modalStatesMarkdown = renderModalStates(this._tabSnapshot.modalStates);\n renderedResponse.states.modal = modalStatesMarkdown.join('\\n');\n } else if (this._tabSnapshot) {\n renderTabSnapshot(this._tabSnapshot, this._includeSnapshot, renderedResponse);\n } else if (this._includeModalStates) {\n const modalStatesMarkdown = renderModalStates(this._includeModalStates);\n renderedResponse.states.modal = modalStatesMarkdown.join('\\n');\n }\n\n if (this._files.length) {\n const lines: string[] = [];\n for (const file of this._files)\n lines.push(`- [${file.title}](${file.fileName})`);\n renderedResponse.updates.push({ category: 'files', content: lines.join('\\n') });\n }\n\n return this._context.config.secrets ? renderedResponse.redact(this._context.config.secrets) : renderedResponse;\n }\n\n serialize(options: { _meta?: Record<string, any> } = {}): { content: (TextContent | ImageContent)[], isError?: boolean, _meta?: Record<string, any> } {\n const renderedResponse = this.render();\n const includeMeta = options._meta && 'dev.lowire/history' in options._meta && 'dev.lowire/state' in options._meta;\n const _meta: any = includeMeta ? renderedResponse.asMeta() : undefined;\n\n const content: (TextContent | ImageContent)[] = [\n {\n type: 'text',\n text: renderedResponse.asText(this._includeMetaOnly ? { categories: ['files'] } : undefined)\n },\n ];\n\n if (this._includeMetaOnly)\n return { _meta, content, isError: this._isError };\n\n // Image attachments.\n if (this._context.config.imageResponses !== 'omit') {\n for (const image of this._images)\n content.push({ type: 'image', data: image.data.toString('base64'), mimeType: image.contentType });\n }\n\n return {\n _meta,\n content,\n isError: this._isError\n };\n }\n}\n\nfunction renderTabSnapshot(tabSnapshot: TabSnapshot, includeSnapshot: 'none' | 'full' | 'incremental', response: RenderedResponse) {\n if (tabSnapshot.consoleMessages.length) {\n const lines: string[] = [];\n for (const message of tabSnapshot.consoleMessages)\n lines.push(`- ${trim(message.toString(), 100)}`);\n response.updates.push({ category: 'console', content: lines.join('\\n') });\n }\n\n if (tabSnapshot.downloads.length) {\n const lines: string[] = [];\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 response.updates.push({ category: 'downloads', content: lines.join('\\n') });\n }\n\n if (includeSnapshot === 'incremental' && tabSnapshot.ariaSnapshotDiff === '') {\n // When incremental snapshot is present, but empty, do not render page state altogether.\n return;\n }\n\n const lines: string[] = [];\n lines.push(`- Page URL: ${tabSnapshot.url}`);\n lines.push(`- Page Title: ${tabSnapshot.title}`);\n\n if (includeSnapshot !== 'none') {\n lines.push(`- Page Snapshot:`);\n lines.push('```yaml');\n if (includeSnapshot === 'incremental' && tabSnapshot.ariaSnapshotDiff !== undefined)\n lines.push(tabSnapshot.ariaSnapshotDiff);\n else\n lines.push(tabSnapshot.ariaSnapshot);\n lines.push('```');\n }\n response.states.page = 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 ['No open tabs. Use the \"browser_navigate\" tool to navigate to a page first.'];\n\n const lines: string[] = [];\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 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\nexport class RenderedResponse {\n readonly states: Partial<Record<'page' | 'tabs' | 'modal', string>> = {};\n readonly updates: { category: 'console' | 'downloads' | 'files', content: string }[] = [];\n readonly results: string[] = [];\n readonly code: string[] = [];\n\n constructor(copy?: { states: Partial<Record<'page' | 'tabs' | 'modal', string>>, updates: { category: 'console' | 'downloads' | 'files', content: string }[], results: string[], code: string[] }) {\n if (copy) {\n this.states = copy.states;\n this.updates = copy.updates;\n this.results = copy.results;\n this.code = copy.code;\n }\n }\n\n asText(filter?: { categories: string[] }): string {\n const text: string[] = [];\n if (this.results.length)\n text.push(`### Result\\n${this.results.join('\\n')}\\n`);\n if (this.code.length)\n text.push(`### Ran Playwright code\\n${this.code.join('\\n')}\\n`);\n\n for (const { category, content } of this.updates) {\n if (filter && !filter.categories.includes(category))\n continue;\n if (!content.trim())\n continue;\n\n switch (category) {\n case 'console':\n text.push(`### New console messages\\n${content}\\n`);\n break;\n case 'downloads':\n text.push(`### Downloads\\n${content}\\n`);\n break;\n case 'files':\n text.push(`### Files\\n${content}\\n`);\n break;\n }\n }\n\n for (const [category, value] of Object.entries(this.states)) {\n if (filter && !filter.categories.includes(category))\n continue;\n if (!value.trim())\n continue;\n\n switch (category) {\n case 'page':\n text.push(`### Page state\\n${value}\\n`);\n break;\n case 'tabs':\n text.push(`### Open tabs\\n${value}\\n`);\n break;\n case 'modal':\n text.push(`### Modal state\\n${value}\\n`);\n break;\n }\n }\n return text.join('\\n');\n }\n\n asMeta() {\n const codeUpdate = this.code.length ? { category: 'code', content: this.code.join('\\n') } : undefined;\n const resultUpdate = this.results.length ? { category: 'result', content: this.results.join('\\n') } : undefined;\n const updates = [resultUpdate, codeUpdate, ...this.updates].filter(Boolean);\n return {\n 'dev.lowire/history': updates,\n 'dev.lowire/state': { ...this.states },\n };\n }\n\n redact(secrets: Record<string, string>): RenderedResponse {\n const redactText = (text: string) => {\n for (const [secretName, secretValue] of Object.entries(secrets))\n text = text.replaceAll(secretValue, `<secret>${secretName}</secret>`);\n return text;\n };\n\n const updates = this.updates.map(update => ({ ...update, content: redactText(update.content) }));\n const results = this.results.map(result => redactText(result));\n const code = this.code.map(code => redactText(code));\n const states = Object.fromEntries(Object.entries(this.states).map(([key, value]) => [key, redactText(value)]));\n return new RenderedResponse({ states, updates, results, code });\n }\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 files = sections.get('Files');\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 files,\n isError,\n attachments,\n _meta: response._meta,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["lines", "code"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var sessionLog_exports = {};
|
|
30
|
+
__export(sessionLog_exports, {
|
|
31
|
+
SessionLog: () => SessionLog
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(sessionLog_exports);
|
|
34
|
+
var import_fs = __toESM(require("fs"));
|
|
35
|
+
var import_path = __toESM(require("path"));
|
|
36
|
+
var import_log = require("../log");
|
|
37
|
+
var import_config = require("./config");
|
|
38
|
+
class SessionLog {
|
|
39
|
+
constructor(sessionFolder) {
|
|
40
|
+
this._ordinal = 0;
|
|
41
|
+
this._pendingEntries = [];
|
|
42
|
+
this._sessionFileQueue = Promise.resolve();
|
|
43
|
+
this._folder = sessionFolder;
|
|
44
|
+
this._file = import_path.default.join(this._folder, "session.md");
|
|
45
|
+
}
|
|
46
|
+
static async create(config, clientInfo) {
|
|
47
|
+
const sessionFolder = await (0, import_config.outputFile)(config, clientInfo, `session-${Date.now()}`, { origin: "code", reason: "Saving session" });
|
|
48
|
+
await import_fs.default.promises.mkdir(sessionFolder, { recursive: true });
|
|
49
|
+
console.error(`Session: ${sessionFolder}`);
|
|
50
|
+
return new SessionLog(sessionFolder);
|
|
51
|
+
}
|
|
52
|
+
logResponse(response) {
|
|
53
|
+
const entry = {
|
|
54
|
+
timestamp: performance.now(),
|
|
55
|
+
toolCall: {
|
|
56
|
+
toolName: response.toolName,
|
|
57
|
+
toolArgs: response.toolArgs,
|
|
58
|
+
result: response.result(),
|
|
59
|
+
isError: response.isError()
|
|
60
|
+
},
|
|
61
|
+
code: response.code(),
|
|
62
|
+
tabSnapshot: response.tabSnapshot()
|
|
63
|
+
};
|
|
64
|
+
this._appendEntry(entry);
|
|
65
|
+
}
|
|
66
|
+
logUserAction(action, tab, code, isUpdate) {
|
|
67
|
+
code = code.trim();
|
|
68
|
+
if (isUpdate) {
|
|
69
|
+
const lastEntry = this._pendingEntries[this._pendingEntries.length - 1];
|
|
70
|
+
if (lastEntry?.userAction?.name === action.name) {
|
|
71
|
+
lastEntry.userAction = action;
|
|
72
|
+
lastEntry.code = code;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (action.name === "navigate") {
|
|
77
|
+
const lastEntry = this._pendingEntries[this._pendingEntries.length - 1];
|
|
78
|
+
if (lastEntry?.tabSnapshot?.url === action.url)
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const entry = {
|
|
82
|
+
timestamp: performance.now(),
|
|
83
|
+
userAction: action,
|
|
84
|
+
code,
|
|
85
|
+
tabSnapshot: {
|
|
86
|
+
url: tab.page.url(),
|
|
87
|
+
title: "",
|
|
88
|
+
ariaSnapshot: action.ariaSnapshot || "",
|
|
89
|
+
modalStates: [],
|
|
90
|
+
consoleMessages: [],
|
|
91
|
+
downloads: []
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
this._appendEntry(entry);
|
|
95
|
+
}
|
|
96
|
+
_appendEntry(entry) {
|
|
97
|
+
this._pendingEntries.push(entry);
|
|
98
|
+
if (this._flushEntriesTimeout)
|
|
99
|
+
clearTimeout(this._flushEntriesTimeout);
|
|
100
|
+
this._flushEntriesTimeout = setTimeout(() => this._flushEntries(), 1e3);
|
|
101
|
+
}
|
|
102
|
+
async _flushEntries() {
|
|
103
|
+
clearTimeout(this._flushEntriesTimeout);
|
|
104
|
+
const entries = this._pendingEntries;
|
|
105
|
+
this._pendingEntries = [];
|
|
106
|
+
const lines = [""];
|
|
107
|
+
for (const entry of entries) {
|
|
108
|
+
const ordinal = (++this._ordinal).toString().padStart(3, "0");
|
|
109
|
+
if (entry.toolCall) {
|
|
110
|
+
lines.push(
|
|
111
|
+
`### Tool call: ${entry.toolCall.toolName}`,
|
|
112
|
+
`- Args`,
|
|
113
|
+
"```json",
|
|
114
|
+
JSON.stringify(entry.toolCall.toolArgs, null, 2),
|
|
115
|
+
"```"
|
|
116
|
+
);
|
|
117
|
+
if (entry.toolCall.result) {
|
|
118
|
+
lines.push(
|
|
119
|
+
entry.toolCall.isError ? `- Error` : `- Result`,
|
|
120
|
+
"```",
|
|
121
|
+
entry.toolCall.result,
|
|
122
|
+
"```"
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (entry.userAction) {
|
|
127
|
+
const actionData = { ...entry.userAction };
|
|
128
|
+
delete actionData.ariaSnapshot;
|
|
129
|
+
delete actionData.selector;
|
|
130
|
+
delete actionData.signals;
|
|
131
|
+
lines.push(
|
|
132
|
+
`### User action: ${entry.userAction.name}`,
|
|
133
|
+
`- Args`,
|
|
134
|
+
"```json",
|
|
135
|
+
JSON.stringify(actionData, null, 2),
|
|
136
|
+
"```"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (entry.code) {
|
|
140
|
+
lines.push(
|
|
141
|
+
`- Code`,
|
|
142
|
+
"```js",
|
|
143
|
+
entry.code,
|
|
144
|
+
"```"
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
if (entry.tabSnapshot) {
|
|
148
|
+
const fileName = `${ordinal}.snapshot.yml`;
|
|
149
|
+
import_fs.default.promises.writeFile(import_path.default.join(this._folder, fileName), entry.tabSnapshot.ariaSnapshot).catch(import_log.logUnhandledError);
|
|
150
|
+
lines.push(`- Snapshot: ${fileName}`);
|
|
151
|
+
}
|
|
152
|
+
lines.push("", "");
|
|
153
|
+
}
|
|
154
|
+
this._sessionFileQueue = this._sessionFileQueue.then(() => import_fs.default.promises.appendFile(this._file, lines.join("\n")));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
158
|
+
0 && (module.exports = {
|
|
159
|
+
SessionLog
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=sessionLog.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var tab_exports = {};
|
|
20
|
+
__export(tab_exports, {
|
|
21
|
+
Tab: () => Tab,
|
|
22
|
+
TabEvents: () => TabEvents,
|
|
23
|
+
renderModalStates: () => renderModalStates
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(tab_exports);
|
|
26
|
+
var import_events = require("events");
|
|
27
|
+
var import_utils = require("playwright-core/lib/utils");
|
|
28
|
+
var import_utils2 = require("./tools/utils");
|
|
29
|
+
var import_log = require("../log");
|
|
30
|
+
var import_dialogs = require("./tools/dialogs");
|
|
31
|
+
var import_files = require("./tools/files");
|
|
32
|
+
var import_transform = require("../../transform/transform");
|
|
33
|
+
const TabEvents = {
|
|
34
|
+
modalState: "modalState"
|
|
35
|
+
};
|
|
36
|
+
class Tab extends import_events.EventEmitter {
|
|
37
|
+
constructor(context, page, onPageClose) {
|
|
38
|
+
super();
|
|
39
|
+
this._lastTitle = "about:blank";
|
|
40
|
+
this._consoleMessages = [];
|
|
41
|
+
this._recentConsoleMessages = [];
|
|
42
|
+
this._requests = /* @__PURE__ */ new Set();
|
|
43
|
+
this._modalStates = [];
|
|
44
|
+
this._downloads = [];
|
|
45
|
+
this._needsFullSnapshot = false;
|
|
46
|
+
this.context = context;
|
|
47
|
+
this.page = page;
|
|
48
|
+
this._onPageClose = onPageClose;
|
|
49
|
+
page.on("console", (event) => this._handleConsoleMessage(messageToConsoleMessage(event)));
|
|
50
|
+
page.on("pageerror", (error) => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));
|
|
51
|
+
page.on("request", (request) => this._requests.add(request));
|
|
52
|
+
page.on("close", () => this._onClose());
|
|
53
|
+
page.on("filechooser", (chooser) => {
|
|
54
|
+
this.setModalState({
|
|
55
|
+
type: "fileChooser",
|
|
56
|
+
description: "File chooser",
|
|
57
|
+
fileChooser: chooser,
|
|
58
|
+
clearedBy: import_files.uploadFile.schema.name
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
page.on("dialog", (dialog) => this._dialogShown(dialog));
|
|
62
|
+
page.on("download", (download) => {
|
|
63
|
+
void this._downloadStarted(download);
|
|
64
|
+
});
|
|
65
|
+
page.setDefaultNavigationTimeout(this.context.config.timeouts.navigation);
|
|
66
|
+
page.setDefaultTimeout(this.context.config.timeouts.action);
|
|
67
|
+
page[tabSymbol] = this;
|
|
68
|
+
this._initializedPromise = this._initialize();
|
|
69
|
+
}
|
|
70
|
+
static forPage(page) {
|
|
71
|
+
return page[tabSymbol];
|
|
72
|
+
}
|
|
73
|
+
static async collectConsoleMessages(page) {
|
|
74
|
+
const result = [];
|
|
75
|
+
const messages = await page.consoleMessages().catch(() => []);
|
|
76
|
+
for (const message of messages)
|
|
77
|
+
result.push(messageToConsoleMessage(message));
|
|
78
|
+
const errors = await page.pageErrors().catch(() => []);
|
|
79
|
+
for (const error of errors)
|
|
80
|
+
result.push(pageErrorToConsoleMessage(error));
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
async _initialize() {
|
|
84
|
+
for (const message of await Tab.collectConsoleMessages(this.page))
|
|
85
|
+
this._handleConsoleMessage(message);
|
|
86
|
+
const requests = await this.page.requests().catch(() => []);
|
|
87
|
+
for (const request of requests)
|
|
88
|
+
this._requests.add(request);
|
|
89
|
+
for (const initPage of this.context.config.browser.initPage || []) {
|
|
90
|
+
try {
|
|
91
|
+
const { default: func } = await (0, import_transform.requireOrImport)(initPage);
|
|
92
|
+
await func({ page: this.page });
|
|
93
|
+
} catch (e) {
|
|
94
|
+
(0, import_log.logUnhandledError)(e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
modalStates() {
|
|
99
|
+
return this._modalStates;
|
|
100
|
+
}
|
|
101
|
+
setModalState(modalState) {
|
|
102
|
+
this._modalStates.push(modalState);
|
|
103
|
+
this.emit(TabEvents.modalState, modalState);
|
|
104
|
+
}
|
|
105
|
+
clearModalState(modalState) {
|
|
106
|
+
this._modalStates = this._modalStates.filter((state) => state !== modalState);
|
|
107
|
+
}
|
|
108
|
+
_dialogShown(dialog) {
|
|
109
|
+
this.setModalState({
|
|
110
|
+
type: "dialog",
|
|
111
|
+
description: `"${dialog.type()}" dialog with message "${dialog.message()}"`,
|
|
112
|
+
dialog,
|
|
113
|
+
clearedBy: import_dialogs.handleDialog.schema.name
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
async _downloadStarted(download) {
|
|
117
|
+
const entry = {
|
|
118
|
+
download,
|
|
119
|
+
finished: false,
|
|
120
|
+
outputFile: await this.context.outputFile(download.suggestedFilename(), { origin: "web", reason: "Saving download" })
|
|
121
|
+
};
|
|
122
|
+
this._downloads.push(entry);
|
|
123
|
+
await download.saveAs(entry.outputFile);
|
|
124
|
+
entry.finished = true;
|
|
125
|
+
}
|
|
126
|
+
_clearCollectedArtifacts() {
|
|
127
|
+
this._consoleMessages.length = 0;
|
|
128
|
+
this._recentConsoleMessages.length = 0;
|
|
129
|
+
this._requests.clear();
|
|
130
|
+
}
|
|
131
|
+
_handleConsoleMessage(message) {
|
|
132
|
+
this._consoleMessages.push(message);
|
|
133
|
+
this._recentConsoleMessages.push(message);
|
|
134
|
+
}
|
|
135
|
+
_onClose() {
|
|
136
|
+
this._clearCollectedArtifacts();
|
|
137
|
+
this._onPageClose(this);
|
|
138
|
+
}
|
|
139
|
+
async updateTitle() {
|
|
140
|
+
await this._raceAgainstModalStates(async () => {
|
|
141
|
+
this._lastTitle = await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.title());
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
lastTitle() {
|
|
145
|
+
return this._lastTitle;
|
|
146
|
+
}
|
|
147
|
+
isCurrentTab() {
|
|
148
|
+
return this === this.context.currentTab();
|
|
149
|
+
}
|
|
150
|
+
async waitForLoadState(state, options) {
|
|
151
|
+
await this._initializedPromise;
|
|
152
|
+
await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => page.waitForLoadState(state, options).catch(import_log.logUnhandledError));
|
|
153
|
+
}
|
|
154
|
+
async navigate(url) {
|
|
155
|
+
await this._initializedPromise;
|
|
156
|
+
this._clearCollectedArtifacts();
|
|
157
|
+
const { promise: downloadEvent, abort: abortDownloadEvent } = (0, import_utils2.eventWaiter)(this.page, "download", 3e3);
|
|
158
|
+
try {
|
|
159
|
+
await this.page.goto(url, { waitUntil: "domcontentloaded" });
|
|
160
|
+
abortDownloadEvent();
|
|
161
|
+
} catch (_e) {
|
|
162
|
+
const e = _e;
|
|
163
|
+
const mightBeDownload = e.message.includes("net::ERR_ABORTED") || e.message.includes("Download is starting");
|
|
164
|
+
if (!mightBeDownload)
|
|
165
|
+
throw e;
|
|
166
|
+
const download = await downloadEvent;
|
|
167
|
+
if (!download)
|
|
168
|
+
throw e;
|
|
169
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
await this.waitForLoadState("load", { timeout: 5e3 });
|
|
173
|
+
}
|
|
174
|
+
async consoleMessages(level) {
|
|
175
|
+
await this._initializedPromise;
|
|
176
|
+
return this._consoleMessages.filter((message) => shouldIncludeMessage(level, message.type));
|
|
177
|
+
}
|
|
178
|
+
async requests() {
|
|
179
|
+
await this._initializedPromise;
|
|
180
|
+
return this._requests;
|
|
181
|
+
}
|
|
182
|
+
async captureSnapshot() {
|
|
183
|
+
await this._initializedPromise;
|
|
184
|
+
let tabSnapshot;
|
|
185
|
+
const modalStates = await this._raceAgainstModalStates(async () => {
|
|
186
|
+
const snapshot = await this.page._snapshotForAI({ track: "response" });
|
|
187
|
+
tabSnapshot = {
|
|
188
|
+
url: this.page.url(),
|
|
189
|
+
title: await this.page.title(),
|
|
190
|
+
ariaSnapshot: snapshot.full,
|
|
191
|
+
ariaSnapshotDiff: this._needsFullSnapshot ? void 0 : snapshot.incremental,
|
|
192
|
+
modalStates: [],
|
|
193
|
+
consoleMessages: [],
|
|
194
|
+
downloads: this._downloads
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
if (tabSnapshot) {
|
|
198
|
+
tabSnapshot.consoleMessages = this._recentConsoleMessages.filter((message) => shouldIncludeMessage(this.context.config.console.level, message.type));
|
|
199
|
+
this._recentConsoleMessages = [];
|
|
200
|
+
}
|
|
201
|
+
this._needsFullSnapshot = !tabSnapshot;
|
|
202
|
+
return tabSnapshot ?? {
|
|
203
|
+
url: this.page.url(),
|
|
204
|
+
title: "",
|
|
205
|
+
ariaSnapshot: "",
|
|
206
|
+
modalStates,
|
|
207
|
+
consoleMessages: [],
|
|
208
|
+
downloads: []
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
_javaScriptBlocked() {
|
|
212
|
+
return this._modalStates.some((state) => state.type === "dialog");
|
|
213
|
+
}
|
|
214
|
+
async _raceAgainstModalStates(action) {
|
|
215
|
+
if (this.modalStates().length)
|
|
216
|
+
return this.modalStates();
|
|
217
|
+
const promise = new import_utils.ManualPromise();
|
|
218
|
+
const listener = (modalState) => promise.resolve([modalState]);
|
|
219
|
+
this.once(TabEvents.modalState, listener);
|
|
220
|
+
return await Promise.race([
|
|
221
|
+
action().then(() => {
|
|
222
|
+
this.off(TabEvents.modalState, listener);
|
|
223
|
+
return [];
|
|
224
|
+
}),
|
|
225
|
+
promise
|
|
226
|
+
]);
|
|
227
|
+
}
|
|
228
|
+
async waitForCompletion(callback) {
|
|
229
|
+
await this._initializedPromise;
|
|
230
|
+
await this._raceAgainstModalStates(() => (0, import_utils2.waitForCompletion)(this, callback));
|
|
231
|
+
}
|
|
232
|
+
async refLocator(params) {
|
|
233
|
+
await this._initializedPromise;
|
|
234
|
+
return (await this.refLocators([params]))[0];
|
|
235
|
+
}
|
|
236
|
+
async refLocators(params) {
|
|
237
|
+
await this._initializedPromise;
|
|
238
|
+
return Promise.all(params.map(async (param) => {
|
|
239
|
+
try {
|
|
240
|
+
const locator = this.page.locator(`aria-ref=${param.ref}`).describe(param.element);
|
|
241
|
+
const { resolvedSelector } = await locator._resolveSelector();
|
|
242
|
+
return { locator, resolved: (0, import_utils.asLocator)("javascript", resolvedSelector) };
|
|
243
|
+
} catch (e) {
|
|
244
|
+
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
|
245
|
+
}
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
async waitForTimeout(time) {
|
|
249
|
+
if (this._javaScriptBlocked()) {
|
|
250
|
+
await new Promise((f) => setTimeout(f, time));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
await (0, import_utils2.callOnPageNoTrace)(this.page, (page) => {
|
|
254
|
+
return page.evaluate(() => new Promise((f) => setTimeout(f, 1e3))).catch(() => {
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function messageToConsoleMessage(message) {
|
|
260
|
+
return {
|
|
261
|
+
type: message.type(),
|
|
262
|
+
text: message.text(),
|
|
263
|
+
toString: () => `[${message.type().toUpperCase()}] ${message.text()} @ ${message.location().url}:${message.location().lineNumber}`
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function pageErrorToConsoleMessage(errorOrValue) {
|
|
267
|
+
if (errorOrValue instanceof Error) {
|
|
268
|
+
return {
|
|
269
|
+
type: "error",
|
|
270
|
+
text: errorOrValue.message,
|
|
271
|
+
toString: () => errorOrValue.stack || errorOrValue.message
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
type: "error",
|
|
276
|
+
text: String(errorOrValue),
|
|
277
|
+
toString: () => String(errorOrValue)
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function renderModalStates(modalStates) {
|
|
281
|
+
const result = [];
|
|
282
|
+
if (modalStates.length === 0)
|
|
283
|
+
result.push("- There is no modal state present");
|
|
284
|
+
for (const state of modalStates)
|
|
285
|
+
result.push(`- [${state.description}]: can be handled by the "${state.clearedBy}" tool`);
|
|
286
|
+
return result;
|
|
287
|
+
}
|
|
288
|
+
const consoleMessageLevels = ["error", "warning", "info", "debug"];
|
|
289
|
+
function shouldIncludeMessage(thresholdLevel, type) {
|
|
290
|
+
const messageLevel = consoleLevelForMessageType(type);
|
|
291
|
+
return consoleMessageLevels.indexOf(messageLevel) <= consoleMessageLevels.indexOf(thresholdLevel);
|
|
292
|
+
}
|
|
293
|
+
function consoleLevelForMessageType(type) {
|
|
294
|
+
switch (type) {
|
|
295
|
+
case "assert":
|
|
296
|
+
case "error":
|
|
297
|
+
return "error";
|
|
298
|
+
case "warning":
|
|
299
|
+
return "warning";
|
|
300
|
+
case "count":
|
|
301
|
+
case "dir":
|
|
302
|
+
case "dirxml":
|
|
303
|
+
case "info":
|
|
304
|
+
case "log":
|
|
305
|
+
case "table":
|
|
306
|
+
case "time":
|
|
307
|
+
case "timeEnd":
|
|
308
|
+
return "info";
|
|
309
|
+
case "clear":
|
|
310
|
+
case "debug":
|
|
311
|
+
case "endGroup":
|
|
312
|
+
case "profile":
|
|
313
|
+
case "profileEnd":
|
|
314
|
+
case "startGroup":
|
|
315
|
+
case "startGroupCollapsed":
|
|
316
|
+
case "trace":
|
|
317
|
+
return "debug";
|
|
318
|
+
default:
|
|
319
|
+
return "info";
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const tabSymbol = Symbol("tabSymbol");
|
|
323
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
324
|
+
0 && (module.exports = {
|
|
325
|
+
Tab,
|
|
326
|
+
TabEvents,
|
|
327
|
+
renderModalStates
|
|
328
|
+
});
|
|
329
|
+
//# sourceMappingURL=tab.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
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, eventWaiter } from './tools/utils';\nimport { logUnhandledError } from '../log';\nimport { ModalState } from './tools/tool';\nimport { handleDialog } from './tools/dialogs';\nimport { uploadFile } from './tools/files';\nimport { requireOrImport } from '../../transform/transform';\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 ariaSnapshotDiff?: 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 // TODO: split into Tab and TabHeader\n private _initializedPromise: Promise<void>;\n private _needsFullSnapshot = false;\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 for (const initPage of this.context.config.browser.initPage || []) {\n try {\n const { default: func } = await requireOrImport(initPage);\n await func({ page: this.page });\n } catch (e) {\n logUnhandledError(e);\n }\n }\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 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 this._initializedPromise;\n await callOnPageNoTrace(this.page, page => page.waitForLoadState(state, options).catch(logUnhandledError));\n }\n\n async navigate(url: string) {\n await this._initializedPromise;\n this._clearCollectedArtifacts();\n\n const { promise: downloadEvent, abort: abortDownloadEvent } = eventWaiter<playwright.Download>(this.page, 'download', 3000);\n try {\n await this.page.goto(url, { waitUntil: 'domcontentloaded' });\n abortDownloadEvent();\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 downloadEvent;\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(level: ConsoleMessageLevel): Promise<ConsoleMessage[]> {\n await this._initializedPromise;\n return this._consoleMessages.filter(message => shouldIncludeMessage(level, message.type));\n }\n\n async requests(): Promise<Set<playwright.Request>> {\n await this._initializedPromise;\n return this._requests;\n }\n\n async captureSnapshot(): Promise<TabSnapshot> {\n await this._initializedPromise;\n let tabSnapshot: TabSnapshot | undefined;\n const modalStates = await this._raceAgainstModalStates(async () => {\n const snapshot = await this.page._snapshotForAI({ track: 'response' });\n tabSnapshot = {\n url: this.page.url(),\n title: await this.page.title(),\n ariaSnapshot: snapshot.full,\n ariaSnapshotDiff: this._needsFullSnapshot ? undefined : snapshot.incremental,\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.filter(message => shouldIncludeMessage(this.context.config.console.level, message.type));\n this._recentConsoleMessages = [];\n }\n // If we failed to capture a snapshot this time, make sure we do a full one next time,\n // to avoid reporting deltas against un-reported snapshot.\n this._needsFullSnapshot = !tabSnapshot;\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._initializedPromise;\n await this._raceAgainstModalStates(() => waitForCompletion(this, callback));\n }\n\n async refLocator(params: { element: string, ref: string }): Promise<{ locator: Locator, resolved: string }> {\n await this._initializedPromise;\n return (await this.refLocators([params]))[0];\n }\n\n async refLocators(params: { element: string, ref: string }[]): Promise<{ locator: Locator, resolved: string }[]> {\n await this._initializedPromise;\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))).catch(() => {});\n });\n }\n}\n\nexport type ConsoleMessage = {\n type: ReturnType<playwright.ConsoleMessage['type']>;\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(modalStates: ModalState[]): string[] {\n const result: string[] = [];\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\ntype ConsoleMessageType = ReturnType<playwright.ConsoleMessage['type']>;\ntype ConsoleMessageLevel = 'error' | 'warning' | 'info' | 'debug';\nconst consoleMessageLevels: ConsoleMessageLevel[] = ['error', 'warning', 'info', 'debug'];\n\nfunction shouldIncludeMessage(thresholdLevel: ConsoleMessageLevel, type: ConsoleMessageType): boolean {\n const messageLevel = consoleLevelForMessageType(type);\n return consoleMessageLevels.indexOf(messageLevel) <= consoleMessageLevels.indexOf(thresholdLevel);\n}\n\nfunction consoleLevelForMessageType(type: ConsoleMessageType): ConsoleMessageLevel {\n switch (type) {\n case 'assert':\n case 'error':\n return 'error';\n case 'warning':\n return 'warning';\n case 'count':\n case 'dir':\n case 'dirxml':\n case 'info':\n case 'log':\n case 'table':\n case 'time':\n case 'timeEnd':\n return 'info';\n case 'clear':\n case 'debug':\n case 'endGroup':\n case 'profile':\n case 'profileEnd':\n case 'startGroup':\n case 'startGroupCollapsed':\n case 'trace':\n return 'debug';\n default:\n return 'info';\n }\n}\n\nconst tabSymbol = Symbol('tabSymbol');\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_utils"]
|
|
7
|
+
}
|