Some checks failed
Main Confidence / confidence (push) Failing after 45s
## Summary - introduce surface-aware compressed governance outcomes and reuse the shared truth/explanation seams for operator-first summaries - apply the compressed outcome hierarchy across baseline, evidence, review, review-pack, canonical review/evidence, and artifact-oriented operation-run surfaces - expand spec 214 fixtures and Pest coverage, and fix tenant-panel route assertions by generating explicit tenant-panel URLs in the affected Filament tests ## Validation - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - focused governance compression suite from `specs/214-governance-outcome-compression/quickstart.md` passed (`68` tests, `445` assertions) - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/InventoryItemResourceTest.php tests/Feature/Filament/BackupSetUiEnforcementTest.php tests/Feature/Filament/RestoreRunUiEnforcementTest.php` passed (`18` tests, `81` assertions) Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #253
306 lines
12 KiB
Plaintext
306 lines
12 KiB
Plaintext
"use strict";
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
mod
|
|
));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var response_exports = {};
|
|
__export(response_exports, {
|
|
Response: () => Response,
|
|
parseResponse: () => parseResponse,
|
|
renderTabMarkdown: () => renderTabMarkdown,
|
|
renderTabsMarkdown: () => renderTabsMarkdown,
|
|
requestDebug: () => requestDebug
|
|
});
|
|
module.exports = __toCommonJS(response_exports);
|
|
var import_fs = __toESM(require("fs"));
|
|
var import_path = __toESM(require("path"));
|
|
var import_utilsBundle = require("../../utilsBundle");
|
|
var import_tab = require("./tab");
|
|
var import_screenshot = require("./screenshot");
|
|
const requestDebug = (0, import_utilsBundle.debug)("pw:mcp:request");
|
|
class Response {
|
|
constructor(context, toolName, toolArgs, relativeTo) {
|
|
this._results = [];
|
|
this._errors = [];
|
|
this._code = [];
|
|
this._includeSnapshot = "none";
|
|
this._isClose = false;
|
|
this._imageResults = [];
|
|
this._context = context;
|
|
this.toolName = toolName;
|
|
this.toolArgs = toolArgs;
|
|
this._clientWorkspace = relativeTo ?? context.options.cwd;
|
|
}
|
|
_computRelativeTo(fileName) {
|
|
return import_path.default.relative(this._clientWorkspace, fileName);
|
|
}
|
|
async resolveClientFile(template, title) {
|
|
let fileName;
|
|
if (template.suggestedFilename)
|
|
fileName = await this.resolveClientFilename(template.suggestedFilename);
|
|
else
|
|
fileName = await this._context.outputFile(template, { origin: "llm" });
|
|
const relativeName = this._computRelativeTo(fileName);
|
|
const printableLink = `- [${title}](${relativeName})`;
|
|
return { fileName, relativeName, printableLink };
|
|
}
|
|
async resolveClientFilename(filename) {
|
|
return await this._context.workspaceFile(filename, this._clientWorkspace);
|
|
}
|
|
addTextResult(text) {
|
|
this._results.push(text);
|
|
}
|
|
async addResult(title, data, file) {
|
|
if (file.suggestedFilename || typeof data !== "string") {
|
|
const resolvedFile = await this.resolveClientFile(file, title);
|
|
await this.addFileResult(resolvedFile, data);
|
|
} else {
|
|
this.addTextResult(data);
|
|
}
|
|
}
|
|
async _writeFile(resolvedFile, data) {
|
|
if (typeof data === "string")
|
|
await import_fs.default.promises.writeFile(resolvedFile.fileName, this._redactSecrets(data), "utf-8");
|
|
else if (data)
|
|
await import_fs.default.promises.writeFile(resolvedFile.fileName, data);
|
|
}
|
|
async addFileResult(resolvedFile, data) {
|
|
await this._writeFile(resolvedFile, data);
|
|
this.addTextResult(resolvedFile.printableLink);
|
|
}
|
|
addFileLink(title, fileName) {
|
|
const relativeName = this._computRelativeTo(fileName);
|
|
this.addTextResult(`- [${title}](${relativeName})`);
|
|
}
|
|
async registerImageResult(data, imageType) {
|
|
this._imageResults.push({ data, imageType });
|
|
}
|
|
setClose() {
|
|
this._isClose = true;
|
|
}
|
|
addError(error) {
|
|
this._errors.push(error);
|
|
}
|
|
addCode(code) {
|
|
this._code.push(code);
|
|
}
|
|
setIncludeSnapshot() {
|
|
this._includeSnapshot = this._context.config.snapshot?.mode ?? "full";
|
|
}
|
|
setIncludeFullSnapshot(includeSnapshotFileName, selector, depth) {
|
|
this._includeSnapshot = "explicit";
|
|
this._includeSnapshotFileName = includeSnapshotFileName;
|
|
this._includeSnapshotDepth = depth;
|
|
this._includeSnapshotSelector = selector;
|
|
}
|
|
_redactSecrets(text) {
|
|
for (const [secretName, secretValue] of Object.entries(this._context.config.secrets ?? {})) {
|
|
if (!secretValue)
|
|
continue;
|
|
text = text.replaceAll(secretValue, `<secret>${secretName}</secret>`);
|
|
}
|
|
return text;
|
|
}
|
|
async serialize() {
|
|
const sections = await this._build();
|
|
const text = [];
|
|
for (const section of sections) {
|
|
if (!section.content.length)
|
|
continue;
|
|
text.push(`### ${section.title}`);
|
|
if (section.codeframe)
|
|
text.push(`\`\`\`${section.codeframe}`);
|
|
text.push(...section.content);
|
|
if (section.codeframe)
|
|
text.push("```");
|
|
}
|
|
const content = [
|
|
{
|
|
type: "text",
|
|
text: sanitizeUnicode(this._redactSecrets(text.join("\n")))
|
|
}
|
|
];
|
|
if (this._context.config.imageResponses !== "omit") {
|
|
for (const imageResult of this._imageResults) {
|
|
const scaledData = (0, import_screenshot.scaleImageToFitMessage)(imageResult.data, imageResult.imageType);
|
|
content.push({ type: "image", data: scaledData.toString("base64"), mimeType: imageResult.imageType === "png" ? "image/png" : "image/jpeg" });
|
|
}
|
|
}
|
|
return {
|
|
content,
|
|
...this._isClose ? { isClose: true } : {},
|
|
...sections.some((section) => section.isError) ? { isError: true } : {}
|
|
};
|
|
}
|
|
async _build() {
|
|
const sections = [];
|
|
const addSection = (title, content, codeframe) => {
|
|
const section = { title, content, isError: title === "Error", codeframe };
|
|
sections.push(section);
|
|
return content;
|
|
};
|
|
if (this._errors.length)
|
|
addSection("Error", this._errors);
|
|
if (this._results.length)
|
|
addSection("Result", this._results);
|
|
if (this._context.config.codegen !== "none" && this._code.length)
|
|
addSection("Ran Playwright code", this._code, "js");
|
|
const tabSnapshot = this._context.currentTab() ? await this._context.currentTabOrDie().captureSnapshot(this._includeSnapshotSelector, this._includeSnapshotDepth, this._clientWorkspace) : void 0;
|
|
const tabHeaders = await Promise.all(this._context.tabs().map((tab) => tab.headerSnapshot()));
|
|
if (this._includeSnapshot !== "none" || tabHeaders.some((header) => header.changed)) {
|
|
if (tabHeaders.length !== 1)
|
|
addSection("Open tabs", renderTabsMarkdown(tabHeaders));
|
|
addSection("Page", renderTabMarkdown(tabHeaders.find((h) => h.current) ?? tabHeaders[0]));
|
|
}
|
|
if (this._context.tabs().length === 0)
|
|
this._isClose = true;
|
|
if (tabSnapshot?.modalStates.length)
|
|
addSection("Modal state", (0, import_tab.renderModalStates)(this._context.config, tabSnapshot.modalStates));
|
|
if (tabSnapshot && this._includeSnapshot !== "none") {
|
|
if (this._includeSnapshot !== "explicit" || this._includeSnapshotFileName) {
|
|
const suggestedFilename = this._includeSnapshotFileName === "<auto>" ? void 0 : this._includeSnapshotFileName;
|
|
const resolvedFile = await this.resolveClientFile({ prefix: "page", ext: "yml", suggestedFilename }, "Snapshot");
|
|
await this._writeFile(resolvedFile, tabSnapshot.ariaSnapshot);
|
|
addSection("Snapshot", [resolvedFile.printableLink]);
|
|
} else {
|
|
addSection("Snapshot", [tabSnapshot.ariaSnapshot], "yaml");
|
|
}
|
|
}
|
|
const text = [];
|
|
if (tabSnapshot?.consoleLink)
|
|
text.push(`- New console entries: ${tabSnapshot.consoleLink}`);
|
|
if (tabSnapshot?.events.filter((event) => event.type !== "request").length) {
|
|
for (const event of tabSnapshot.events) {
|
|
if (event.type === "download-start")
|
|
text.push(`- Downloading file ${event.download.download.suggestedFilename()} ...`);
|
|
else if (event.type === "download-finish")
|
|
text.push(`- Downloaded file ${event.download.download.suggestedFilename()} to "${this._computRelativeTo(event.download.outputFile)}"`);
|
|
}
|
|
}
|
|
if (text.length)
|
|
addSection("Events", text);
|
|
const pausedDetails = this._context.debugger().pausedDetails();
|
|
if (pausedDetails) {
|
|
addSection("Paused", [
|
|
`- ${pausedDetails.title} at ${this._computRelativeTo(pausedDetails.location.file)}${pausedDetails.location.line ? ":" + pausedDetails.location.line : ""}`,
|
|
"- Use any tools to explore and interact, resume by calling resume/step-over/pause-at"
|
|
]);
|
|
}
|
|
return sections;
|
|
}
|
|
}
|
|
function renderTabMarkdown(tab) {
|
|
const lines = [`- Page URL: ${tab.url}`];
|
|
if (tab.title)
|
|
lines.push(`- Page Title: ${tab.title}`);
|
|
if (tab.console.errors || tab.console.warnings)
|
|
lines.push(`- Console: ${tab.console.errors} errors, ${tab.console.warnings} warnings`);
|
|
return lines;
|
|
}
|
|
function renderTabsMarkdown(tabs) {
|
|
if (!tabs.length)
|
|
return ["No open tabs. Navigate to a URL to create one."];
|
|
const lines = [];
|
|
for (let i = 0; i < tabs.length; i++) {
|
|
const tab = tabs[i];
|
|
const current = tab.current ? " (current)" : "";
|
|
lines.push(`- ${i}:${current} [${tab.title}](${tab.url})`);
|
|
}
|
|
return lines;
|
|
}
|
|
function sanitizeUnicode(text) {
|
|
return text.toWellFormed?.() ?? text;
|
|
}
|
|
function parseSections(text) {
|
|
const sections = /* @__PURE__ */ new Map();
|
|
const sectionHeaders = text.split(/^### /m).slice(1);
|
|
for (const section of sectionHeaders) {
|
|
const firstNewlineIndex = section.indexOf("\n");
|
|
if (firstNewlineIndex === -1)
|
|
continue;
|
|
const sectionName = section.substring(0, firstNewlineIndex);
|
|
const sectionContent = section.substring(firstNewlineIndex + 1).trim();
|
|
sections.set(sectionName, sectionContent);
|
|
}
|
|
return sections;
|
|
}
|
|
function parseResponse(response, cwd) {
|
|
if (response.content?.[0].type !== "text")
|
|
return void 0;
|
|
const text = response.content[0].text;
|
|
const sections = parseSections(text);
|
|
const error = sections.get("Error");
|
|
const result = sections.get("Result");
|
|
const code = sections.get("Ran Playwright code");
|
|
const tabs = sections.get("Open tabs");
|
|
const page = sections.get("Page");
|
|
const snapshotSection = sections.get("Snapshot");
|
|
const events = sections.get("Events");
|
|
const modalState = sections.get("Modal state");
|
|
const paused = sections.get("Paused");
|
|
const codeNoFrame = code?.replace(/^```js\n/, "").replace(/\n```$/, "");
|
|
const isError = response.isError;
|
|
const attachments = response.content.length > 1 ? response.content.slice(1) : void 0;
|
|
let snapshot;
|
|
let inlineSnapshot;
|
|
if (snapshotSection) {
|
|
const match = snapshotSection.match(/\[Snapshot\]\(([^)]+)\)/);
|
|
if (match) {
|
|
if (cwd) {
|
|
try {
|
|
snapshot = import_fs.default.readFileSync(import_path.default.resolve(cwd, match[1]), "utf-8");
|
|
} catch {
|
|
}
|
|
}
|
|
} else {
|
|
inlineSnapshot = snapshotSection.replace(/^```yaml\n?/, "").replace(/\n?```$/, "");
|
|
}
|
|
}
|
|
return {
|
|
result,
|
|
error,
|
|
code: codeNoFrame,
|
|
tabs,
|
|
page,
|
|
snapshot,
|
|
inlineSnapshot,
|
|
events,
|
|
modalState,
|
|
paused,
|
|
isError,
|
|
attachments,
|
|
text
|
|
};
|
|
}
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
Response,
|
|
parseResponse,
|
|
renderTabMarkdown,
|
|
renderTabsMarkdown,
|
|
requestDebug
|
|
});
|