ScuttleBot

scuttlebot / tests / e2e / node_modules / playwright / lib / mcp / browser / response.js
Source Blame History 278 lines
f7eb47b… lmata 1 "use strict";
f7eb47b… lmata 2 var __create = Object.create;
f7eb47b… lmata 3 var __defProp = Object.defineProperty;
f7eb47b… lmata 4 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
f7eb47b… lmata 5 var __getOwnPropNames = Object.getOwnPropertyNames;
f7eb47b… lmata 6 var __getProtoOf = Object.getPrototypeOf;
f7eb47b… lmata 7 var __hasOwnProp = Object.prototype.hasOwnProperty;
f7eb47b… lmata 8 var __export = (target, all) => {
f7eb47b… lmata 9 for (var name in all)
f7eb47b… lmata 10 __defProp(target, name, { get: all[name], enumerable: true });
f7eb47b… lmata 11 };
f7eb47b… lmata 12 var __copyProps = (to, from, except, desc) => {
f7eb47b… lmata 13 if (from && typeof from === "object" || typeof from === "function") {
f7eb47b… lmata 14 for (let key of __getOwnPropNames(from))
f7eb47b… lmata 15 if (!__hasOwnProp.call(to, key) && key !== except)
f7eb47b… lmata 16 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
f7eb47b… lmata 17 }
f7eb47b… lmata 18 return to;
f7eb47b… lmata 19 };
f7eb47b… lmata 20 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
f7eb47b… lmata 21 // If the importer is in node compatibility mode or this is not an ESM
f7eb47b… lmata 22 // file that has been converted to a CommonJS file using a Babel-
f7eb47b… lmata 23 // compatible transform (i.e. "__esModule" has not been set), then set
f7eb47b… lmata 24 // "default" to the CommonJS "module.exports" for node compatibility.
f7eb47b… lmata 25 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
f7eb47b… lmata 26 mod
f7eb47b… lmata 27 ));
f7eb47b… lmata 28 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
f7eb47b… lmata 29 var response_exports = {};
f7eb47b… lmata 30 __export(response_exports, {
f7eb47b… lmata 31 Response: () => Response,
f7eb47b… lmata 32 parseResponse: () => parseResponse,
f7eb47b… lmata 33 renderTabMarkdown: () => renderTabMarkdown,
f7eb47b… lmata 34 renderTabsMarkdown: () => renderTabsMarkdown,
f7eb47b… lmata 35 requestDebug: () => requestDebug
f7eb47b… lmata 36 });
f7eb47b… lmata 37 module.exports = __toCommonJS(response_exports);
f7eb47b… lmata 38 var import_fs = __toESM(require("fs"));
f7eb47b… lmata 39 var import_path = __toESM(require("path"));
f7eb47b… lmata 40 var import_utilsBundle = require("playwright-core/lib/utilsBundle");
f7eb47b… lmata 41 var import_tab = require("./tab");
f7eb47b… lmata 42 var import_utils = require("./tools/utils");
f7eb47b… lmata 43 const requestDebug = (0, import_utilsBundle.debug)("pw:mcp:request");
f7eb47b… lmata 44 class Response {
f7eb47b… lmata 45 constructor(ordinal, context, toolName, toolArgs) {
f7eb47b… lmata 46 this._results = [];
f7eb47b… lmata 47 this._errors = [];
f7eb47b… lmata 48 this._code = [];
f7eb47b… lmata 49 this._images = [];
f7eb47b… lmata 50 this._includeSnapshot = "none";
f7eb47b… lmata 51 this._ordinal = ordinal;
f7eb47b… lmata 52 this._context = context;
f7eb47b… lmata 53 this.toolName = toolName;
f7eb47b… lmata 54 this.toolArgs = toolArgs;
f7eb47b… lmata 55 }
f7eb47b… lmata 56 static {
f7eb47b… lmata 57 this._ordinal = 0;
f7eb47b… lmata 58 }
f7eb47b… lmata 59 static create(context, toolName, toolArgs) {
f7eb47b… lmata 60 return new Response(++Response._ordinal, context, toolName, toolArgs);
f7eb47b… lmata 61 }
f7eb47b… lmata 62 addTextResult(result) {
f7eb47b… lmata 63 this._results.push({ text: result });
f7eb47b… lmata 64 }
f7eb47b… lmata 65 async addResult(result) {
f7eb47b… lmata 66 if (result.data && !result.suggestedFilename)
f7eb47b… lmata 67 result.suggestedFilename = (0, import_utils.dateAsFileName)(result.ext ?? "bin");
f7eb47b… lmata 68 if (this._context.config.outputMode === "file") {
f7eb47b… lmata 69 if (!result.suggestedFilename)
f7eb47b… lmata 70 result.suggestedFilename = (0, import_utils.dateAsFileName)(result.ext ?? (result.text ? "txt" : "bin"));
f7eb47b… lmata 71 }
f7eb47b… lmata 72 const entry = { text: result.text, data: result.data, title: result.title };
f7eb47b… lmata 73 if (result.suggestedFilename)
f7eb47b… lmata 74 entry.filename = await this._context.outputFile(result.suggestedFilename, { origin: "llm", title: result.title ?? "Saved result" });
f7eb47b… lmata 75 this._results.push(entry);
f7eb47b… lmata 76 return { fileName: entry.filename };
f7eb47b… lmata 77 }
f7eb47b… lmata 78 addError(error) {
f7eb47b… lmata 79 this._errors.push(error);
f7eb47b… lmata 80 }
f7eb47b… lmata 81 addCode(code) {
f7eb47b… lmata 82 this._code.push(code);
f7eb47b… lmata 83 }
f7eb47b… lmata 84 addImage(image) {
f7eb47b… lmata 85 this._images.push(image);
f7eb47b… lmata 86 }
f7eb47b… lmata 87 setIncludeSnapshot() {
f7eb47b… lmata 88 this._includeSnapshot = this._context.config.snapshot.mode;
f7eb47b… lmata 89 }
f7eb47b… lmata 90 setIncludeFullSnapshot(includeSnapshotFileName) {
f7eb47b… lmata 91 this._includeSnapshot = "full";
f7eb47b… lmata 92 this._includeSnapshotFileName = includeSnapshotFileName;
f7eb47b… lmata 93 }
f7eb47b… lmata 94 async build() {
f7eb47b… lmata 95 const rootPath = this._context.firstRootPath();
f7eb47b… lmata 96 const sections = [];
f7eb47b… lmata 97 const addSection = (title) => {
f7eb47b… lmata 98 const section = { title, content: [] };
f7eb47b… lmata 99 sections.push(section);
f7eb47b… lmata 100 return section.content;
f7eb47b… lmata 101 };
f7eb47b… lmata 102 if (this._errors.length) {
f7eb47b… lmata 103 const text = addSection("Error");
f7eb47b… lmata 104 text.push("### Error");
f7eb47b… lmata 105 text.push(this._errors.join("\n"));
f7eb47b… lmata 106 }
f7eb47b… lmata 107 if (this._results.length) {
f7eb47b… lmata 108 const text = addSection("Result");
f7eb47b… lmata 109 for (const result of this._results) {
f7eb47b… lmata 110 if (result.filename) {
f7eb47b… lmata 111 text.push(`- [${result.title}](${rootPath ? import_path.default.relative(rootPath, result.filename) : result.filename})`);
f7eb47b… lmata 112 if (result.data)
f7eb47b… lmata 113 await import_fs.default.promises.writeFile(result.filename, result.data);
f7eb47b… lmata 114 else if (result.text)
f7eb47b… lmata 115 await import_fs.default.promises.writeFile(result.filename, this._redactText(result.text));
f7eb47b… lmata 116 } else if (result.text) {
f7eb47b… lmata 117 text.push(result.text);
f7eb47b… lmata 118 }
f7eb47b… lmata 119 }
f7eb47b… lmata 120 }
f7eb47b… lmata 121 if (this._context.config.codegen !== "none" && this._code.length) {
f7eb47b… lmata 122 const text = addSection("Ran Playwright code");
f7eb47b… lmata 123 text.push(...this._code);
f7eb47b… lmata 124 }
f7eb47b… lmata 125 const tabSnapshot = this._context.currentTab() ? await this._context.currentTabOrDie().captureSnapshot() : void 0;
f7eb47b… lmata 126 const tabHeaders = await Promise.all(this._context.tabs().map((tab) => tab.headerSnapshot()));
f7eb47b… lmata 127 if (tabHeaders.some((header) => header.changed)) {
f7eb47b… lmata 128 if (tabHeaders.length !== 1) {
f7eb47b… lmata 129 const text2 = addSection("Open tabs");
f7eb47b… lmata 130 text2.push(...renderTabsMarkdown(tabHeaders));
f7eb47b… lmata 131 }
f7eb47b… lmata 132 const text = addSection("Page");
f7eb47b… lmata 133 text.push(...renderTabMarkdown(tabHeaders[0]));
f7eb47b… lmata 134 }
f7eb47b… lmata 135 if (tabSnapshot?.modalStates.length) {
f7eb47b… lmata 136 const text = addSection("Modal state");
f7eb47b… lmata 137 text.push(...(0, import_tab.renderModalStates)(tabSnapshot.modalStates));
f7eb47b… lmata 138 }
f7eb47b… lmata 139 if (tabSnapshot && this._includeSnapshot === "full") {
f7eb47b… lmata 140 let fileName;
f7eb47b… lmata 141 if (this._includeSnapshotFileName)
f7eb47b… lmata 142 fileName = await this._context.outputFile(this._includeSnapshotFileName, { origin: "llm", title: "Saved snapshot" });
f7eb47b… lmata 143 else if (this._context.config.outputMode === "file")
f7eb47b… lmata 144 fileName = await this._context.outputFile(`snapshot-${this._ordinal}.yml`, { origin: "code", title: "Saved snapshot" });
f7eb47b… lmata 145 if (fileName) {
f7eb47b… lmata 146 await import_fs.default.promises.writeFile(fileName, tabSnapshot.ariaSnapshot);
f7eb47b… lmata 147 const text = addSection("Snapshot");
f7eb47b… lmata 148 text.push(`- File: ${rootPath ? import_path.default.relative(rootPath, fileName) : fileName}`);
f7eb47b… lmata 149 } else {
f7eb47b… lmata 150 const text = addSection("Snapshot");
f7eb47b… lmata 151 text.push("```yaml");
f7eb47b… lmata 152 text.push(tabSnapshot.ariaSnapshot);
f7eb47b… lmata 153 text.push("```");
f7eb47b… lmata 154 }
f7eb47b… lmata 155 }
f7eb47b… lmata 156 if (tabSnapshot && this._includeSnapshot === "incremental") {
f7eb47b… lmata 157 const text = addSection("Snapshot");
f7eb47b… lmata 158 text.push("```yaml");
f7eb47b… lmata 159 if (tabSnapshot.ariaSnapshotDiff !== void 0)
f7eb47b… lmata 160 text.push(tabSnapshot.ariaSnapshotDiff);
f7eb47b… lmata 161 else
f7eb47b… lmata 162 text.push(tabSnapshot.ariaSnapshot);
f7eb47b… lmata 163 text.push("```");
f7eb47b… lmata 164 }
f7eb47b… lmata 165 if (tabSnapshot?.events.filter((event) => event.type !== "request").length) {
f7eb47b… lmata 166 const text = addSection("Events");
f7eb47b… lmata 167 for (const event of tabSnapshot.events) {
f7eb47b… lmata 168 if (event.type === "console") {
f7eb47b… lmata 169 if ((0, import_tab.shouldIncludeMessage)(this._context.config.console.level, event.message.type))
f7eb47b… lmata 170 text.push(`- ${trimMiddle(event.message.toString(), 100)}`);
f7eb47b… lmata 171 } else if (event.type === "download-start") {
f7eb47b… lmata 172 text.push(`- Downloading file ${event.download.download.suggestedFilename()} ...`);
f7eb47b… lmata 173 } else if (event.type === "download-finish") {
f7eb47b… lmata 174 text.push(`- Downloaded file ${event.download.download.suggestedFilename()} to "${rootPath ? import_path.default.relative(rootPath, event.download.outputFile) : event.download.outputFile}"`);
f7eb47b… lmata 175 }
f7eb47b… lmata 176 }
f7eb47b… lmata 177 }
f7eb47b… lmata 178 const allText = sections.flatMap((section) => {
f7eb47b… lmata 179 const content2 = [];
f7eb47b… lmata 180 content2.push(`### ${section.title}`);
f7eb47b… lmata 181 content2.push(...section.content);
f7eb47b… lmata 182 content2.push("");
f7eb47b… lmata 183 return content2;
f7eb47b… lmata 184 }).join("\n");
f7eb47b… lmata 185 const content = [
f7eb47b… lmata 186 {
f7eb47b… lmata 187 type: "text",
f7eb47b… lmata 188 text: this._redactText(allText)
f7eb47b… lmata 189 }
f7eb47b… lmata 190 ];
f7eb47b… lmata 191 if (this._context.config.imageResponses !== "omit") {
f7eb47b… lmata 192 for (const image of this._images)
f7eb47b… lmata 193 content.push({ type: "image", data: image.data.toString("base64"), mimeType: image.contentType });
f7eb47b… lmata 194 }
f7eb47b… lmata 195 return {
f7eb47b… lmata 196 content,
f7eb47b… lmata 197 ...this._errors.length > 0 ? { isError: true } : {}
f7eb47b… lmata 198 };
f7eb47b… lmata 199 }
f7eb47b… lmata 200 _redactText(text) {
f7eb47b… lmata 201 for (const [secretName, secretValue] of Object.entries(this._context.config.secrets ?? {}))
f7eb47b… lmata 202 text = text.replaceAll(secretValue, `<secret>${secretName}</secret>`);
f7eb47b… lmata 203 return text;
f7eb47b… lmata 204 }
f7eb47b… lmata 205 }
f7eb47b… lmata 206 function renderTabMarkdown(tab) {
f7eb47b… lmata 207 const lines = [`- Page URL: ${tab.url}`];
f7eb47b… lmata 208 if (tab.title)
f7eb47b… lmata 209 lines.push(`- Page Title: ${tab.title}`);
f7eb47b… lmata 210 return lines;
f7eb47b… lmata 211 }
f7eb47b… lmata 212 function renderTabsMarkdown(tabs) {
f7eb47b… lmata 213 if (!tabs.length)
f7eb47b… lmata 214 return ['No open tabs. Use the "browser_navigate" tool to navigate to a page first.'];
f7eb47b… lmata 215 const lines = [];
f7eb47b… lmata 216 for (let i = 0; i < tabs.length; i++) {
f7eb47b… lmata 217 const tab = tabs[i];
f7eb47b… lmata 218 const current = tab.current ? " (current)" : "";
f7eb47b… lmata 219 lines.push(`- ${i}:${current} [${tab.title}](${tab.url})`);
f7eb47b… lmata 220 }
f7eb47b… lmata 221 return lines;
f7eb47b… lmata 222 }
f7eb47b… lmata 223 function trimMiddle(text, maxLength) {
f7eb47b… lmata 224 if (text.length <= maxLength)
f7eb47b… lmata 225 return text;
f7eb47b… lmata 226 return text.slice(0, Math.floor(maxLength / 2)) + "..." + text.slice(-3 - Math.floor(maxLength / 2));
f7eb47b… lmata 227 }
f7eb47b… lmata 228 function parseSections(text) {
f7eb47b… lmata 229 const sections = /* @__PURE__ */ new Map();
f7eb47b… lmata 230 const sectionHeaders = text.split(/^### /m).slice(1);
f7eb47b… lmata 231 for (const section of sectionHeaders) {
f7eb47b… lmata 232 const firstNewlineIndex = section.indexOf("\n");
f7eb47b… lmata 233 if (firstNewlineIndex === -1)
f7eb47b… lmata 234 continue;
f7eb47b… lmata 235 const sectionName = section.substring(0, firstNewlineIndex);
f7eb47b… lmata 236 const sectionContent = section.substring(firstNewlineIndex + 1).trim();
f7eb47b… lmata 237 sections.set(sectionName, sectionContent);
f7eb47b… lmata 238 }
f7eb47b… lmata 239 return sections;
f7eb47b… lmata 240 }
f7eb47b… lmata 241 function parseResponse(response) {
f7eb47b… lmata 242 if (response.content?.[0].type !== "text")
f7eb47b… lmata 243 return void 0;
f7eb47b… lmata 244 const text = response.content[0].text;
f7eb47b… lmata 245 const sections = parseSections(text);
f7eb47b… lmata 246 const error = sections.get("Error");
f7eb47b… lmata 247 const result = sections.get("Result");
f7eb47b… lmata 248 const code = sections.get("Ran Playwright code");
f7eb47b… lmata 249 const tabs = sections.get("Open tabs");
f7eb47b… lmata 250 const page = sections.get("Page");
f7eb47b… lmata 251 const snapshot = sections.get("Snapshot");
f7eb47b… lmata 252 const events = sections.get("Events");
f7eb47b… lmata 253 const modalState = sections.get("Modal state");
f7eb47b… lmata 254 const codeNoFrame = code?.replace(/^```js\n/, "").replace(/\n```$/, "");
f7eb47b… lmata 255 const isError = response.isError;
f7eb47b… lmata 256 const attachments = response.content.length > 1 ? response.content.slice(1) : void 0;
f7eb47b… lmata 257 return {
f7eb47b… lmata 258 result,
f7eb47b… lmata 259 error,
f7eb47b… lmata 260 code: codeNoFrame,
f7eb47b… lmata 261 tabs,
f7eb47b… lmata 262 page,
f7eb47b… lmata 263 snapshot,
f7eb47b… lmata 264 events,
f7eb47b… lmata 265 modalState,
f7eb47b… lmata 266 isError,
f7eb47b… lmata 267 attachments,
f7eb47b… lmata 268 text
f7eb47b… lmata 269 };
f7eb47b… lmata 270 }
f7eb47b… lmata 271 // Annotate the CommonJS export names for ESM import in node:
f7eb47b… lmata 272 0 && (module.exports = {
f7eb47b… lmata 273 Response,
f7eb47b… lmata 274 parseResponse,
f7eb47b… lmata 275 renderTabMarkdown,
f7eb47b… lmata 276 renderTabsMarkdown,
f7eb47b… lmata 277 requestDebug
f7eb47b… lmata 278 });

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button