@midscene/core 1.17.2 → 1.17.3

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 (93) hide show
  1. package/dist/es/agent/utils.mjs +1 -1
  2. package/dist/es/ai-model/model-adapter/resolve.mjs +2 -2
  3. package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
  4. package/dist/es/ai-model/models/ant-ling/adapter.mjs +51 -0
  5. package/dist/es/ai-model/models/ant-ling/adapter.mjs.map +1 -0
  6. package/dist/es/ai-model/models/jev/adapter.mjs +1 -1
  7. package/dist/es/ai-model/models/jev/adapter.mjs.map +1 -1
  8. package/dist/es/ai-model/models/model-fallback.mjs +2 -2
  9. package/dist/es/ai-model/models/model-fallback.mjs.map +1 -1
  10. package/dist/es/ai-model/models/registry.mjs +2 -0
  11. package/dist/es/ai-model/models/registry.mjs.map +1 -1
  12. package/dist/es/dump/execution-recorder.mjs +70 -0
  13. package/dist/es/dump/execution-recorder.mjs.map +1 -0
  14. package/dist/es/dump/html-utils.mjs +51 -1
  15. package/dist/es/dump/html-utils.mjs.map +1 -1
  16. package/dist/es/dump/report-artifact-reader.mjs +85 -0
  17. package/dist/es/dump/report-artifact-reader.mjs.map +1 -0
  18. package/dist/es/dump/report-artifact-store.mjs +164 -0
  19. package/dist/es/dump/report-artifact-store.mjs.map +1 -0
  20. package/dist/es/dump/screenshot-store.mjs +40 -15
  21. package/dist/es/dump/screenshot-store.mjs.map +1 -1
  22. package/dist/es/dump/test-report-images.mjs +120 -0
  23. package/dist/es/dump/test-report-images.mjs.map +1 -0
  24. package/dist/es/report-cli.mjs +8 -7
  25. package/dist/es/report-cli.mjs.map +1 -1
  26. package/dist/es/report-generator.mjs +56 -47
  27. package/dist/es/report-generator.mjs.map +1 -1
  28. package/dist/es/report-html-template.mjs +1 -1
  29. package/dist/es/report.mjs +29 -55
  30. package/dist/es/report.mjs.map +1 -1
  31. package/dist/es/test-run-report.mjs.map +1 -1
  32. package/dist/es/utils.mjs +1 -1
  33. package/dist/lib/agent/utils.js +1 -1
  34. package/dist/lib/ai-model/model-adapter/resolve.js +2 -2
  35. package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
  36. package/dist/lib/ai-model/models/ant-ling/adapter.js +85 -0
  37. package/dist/lib/ai-model/models/ant-ling/adapter.js.map +1 -0
  38. package/dist/lib/ai-model/models/jev/adapter.js +1 -1
  39. package/dist/lib/ai-model/models/jev/adapter.js.map +1 -1
  40. package/dist/lib/ai-model/models/model-fallback.js +2 -2
  41. package/dist/lib/ai-model/models/model-fallback.js.map +1 -1
  42. package/dist/lib/ai-model/models/registry.js +4 -2
  43. package/dist/lib/ai-model/models/registry.js.map +1 -1
  44. package/dist/lib/dump/execution-recorder.js +104 -0
  45. package/dist/lib/dump/execution-recorder.js.map +1 -0
  46. package/dist/lib/dump/html-utils.js +67 -5
  47. package/dist/lib/dump/html-utils.js.map +1 -1
  48. package/dist/lib/dump/report-artifact-reader.js +134 -0
  49. package/dist/lib/dump/report-artifact-reader.js.map +1 -0
  50. package/dist/lib/dump/report-artifact-store.js +204 -0
  51. package/dist/lib/dump/report-artifact-store.js.map +1 -0
  52. package/dist/lib/dump/screenshot-store.js +42 -14
  53. package/dist/lib/dump/screenshot-store.js.map +1 -1
  54. package/dist/lib/dump/test-report-images.js +154 -0
  55. package/dist/lib/dump/test-report-images.js.map +1 -0
  56. package/dist/lib/report-cli.js +8 -7
  57. package/dist/lib/report-cli.js.map +1 -1
  58. package/dist/lib/report-generator.js +54 -45
  59. package/dist/lib/report-generator.js.map +1 -1
  60. package/dist/lib/report-html-template.js +1 -1
  61. package/dist/lib/report.js +54 -56
  62. package/dist/lib/report.js.map +1 -1
  63. package/dist/lib/test-run-report.js.map +1 -1
  64. package/dist/lib/utils.js +1 -1
  65. package/dist/types/ai-model/model-adapter/resolve.d.ts +1 -1
  66. package/dist/types/ai-model/model-adapter/resolve.d.ts.map +1 -1
  67. package/dist/types/ai-model/model-adapter/types.d.ts +4 -2
  68. package/dist/types/ai-model/model-adapter/types.d.ts.map +1 -1
  69. package/dist/types/ai-model/models/ant-ling/adapter.d.ts +23 -0
  70. package/dist/types/ai-model/models/ant-ling/adapter.d.ts.map +1 -0
  71. package/dist/types/ai-model/models/jev/adapter.d.ts +1 -1
  72. package/dist/types/ai-model/models/registry.d.ts +20 -1
  73. package/dist/types/ai-model/models/registry.d.ts.map +1 -1
  74. package/dist/types/dump/execution-recorder.d.ts +23 -0
  75. package/dist/types/dump/execution-recorder.d.ts.map +1 -0
  76. package/dist/types/dump/html-utils.d.ts +9 -0
  77. package/dist/types/dump/html-utils.d.ts.map +1 -1
  78. package/dist/types/dump/report-artifact-reader.d.ts +19 -0
  79. package/dist/types/dump/report-artifact-reader.d.ts.map +1 -0
  80. package/dist/types/dump/report-artifact-store.d.ts +22 -0
  81. package/dist/types/dump/report-artifact-store.d.ts.map +1 -0
  82. package/dist/types/dump/screenshot-store.d.ts +6 -0
  83. package/dist/types/dump/screenshot-store.d.ts.map +1 -1
  84. package/dist/types/dump/test-report-images.d.ts +14 -0
  85. package/dist/types/dump/test-report-images.d.ts.map +1 -0
  86. package/dist/types/report-cli.d.ts.map +1 -1
  87. package/dist/types/report-generator.d.ts +4 -3
  88. package/dist/types/report-generator.d.ts.map +1 -1
  89. package/dist/types/report.d.ts +3 -0
  90. package/dist/types/report.d.ts.map +1 -1
  91. package/dist/types/test-run-report.d.ts +2 -0
  92. package/dist/types/test-run-report.d.ts.map +1 -1
  93. package/package.json +2 -2
@@ -32,15 +32,16 @@ __webpack_require__.d(__webpack_exports__, {
32
32
  isBase64ImageDataUrl: ()=>isBase64ImageDataUrl,
33
33
  normalizeScreenshotRef: ()=>external_image_reference_js_namespaceObject.normalizeScreenshotRef,
34
34
  parseBase64ImageDataUrl: ()=>parseBase64ImageDataUrl,
35
+ reportImageFileName: ()=>reportImageFileName,
35
36
  resolveImageSource: ()=>resolveImageSource,
36
37
  normalizeStoredImageRef: ()=>external_image_reference_js_namespaceObject.normalizeStoredImageRef
37
38
  });
38
39
  const external_node_crypto_namespaceObject = require("node:crypto");
39
40
  const external_node_fs_namespaceObject = require("node:fs");
40
- const promises_namespaceObject = require("node:fs/promises");
41
41
  const external_node_path_namespaceObject = require("node:path");
42
42
  const external_html_utils_js_namespaceObject = require("./html-utils.js");
43
43
  const external_image_reference_js_namespaceObject = require("./image-reference.js");
44
+ const external_report_artifact_store_js_namespaceObject = require("./report-artifact-store.js");
44
45
  function _define_property(obj, key, value) {
45
46
  if (key in obj) Object.defineProperty(obj, key, {
46
47
  value: value,
@@ -65,6 +66,10 @@ function parseBase64ImageDataUrl(imageUrl) {
65
66
  function isBase64ImageDataUrl(value) {
66
67
  return base64ImageDataUrlPattern.test(value);
67
68
  }
69
+ function reportImageFileName(extension, bytes) {
70
+ const hash = (0, external_node_crypto_namespaceObject.createHash)('sha256').update(extension).update('\0').update(bytes).digest('hex');
71
+ return `${hash}.${extension}`;
72
+ }
68
73
  function resolveImageSource(refInput, options) {
69
74
  const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(refInput);
70
75
  const id = ref?.id ?? options.fallbackId;
@@ -115,6 +120,11 @@ class ReportImageStore {
115
120
  enableFileCopies() {
116
121
  this.alsoWriteFileCopy = true;
117
122
  }
123
+ getFilePath(id) {
124
+ const file = this.fileLocations.get(id);
125
+ if (!file) throw new Error(`ReportImageStore: image ${id} has no persisted file`);
126
+ return file.relativePath;
127
+ }
118
128
  async persist(screenshot) {
119
129
  await this.ensureExistingInlineImageIdsLoaded();
120
130
  const shouldWriteFileCopy = 'directory' === this.mode || this.alsoWriteFileCopy;
@@ -183,11 +193,7 @@ class ReportImageStore {
183
193
  await this.existingInlineImageIdsPromise;
184
194
  }
185
195
  async persistToSharedFileIfNeeded(screenshot, options) {
186
- const fileName = `${screenshot.id}.${screenshot.extension}`;
187
- const { relativePath, absolutePath } = this.writtenFileIds.has(screenshot.id) ? {
188
- relativePath: `./screenshots/${fileName}`,
189
- absolutePath: (0, external_node_path_namespaceObject.join)(this.screenshotsDir, fileName)
190
- } : await this.writeImageFileIfNeeded({
196
+ const { relativePath, absolutePath } = this.fileLocations.get(screenshot.id) ?? await this.writeImageFileIfNeeded({
191
197
  id: screenshot.id,
192
198
  extension: screenshot.extension,
193
199
  rawBase64: screenshot.rawBase64
@@ -201,17 +207,33 @@ class ReportImageStore {
201
207
  if (!(0, external_node_fs_namespaceObject.existsSync)(screenshotsDir)) (0, external_node_fs_namespaceObject.mkdirSync)(screenshotsDir, {
202
208
  recursive: true
203
209
  });
204
- const fileName = `${image.id}.${image.extension}`;
210
+ const known = this.fileLocations.get(image.id);
211
+ if (known) return known;
212
+ const bytes = Buffer.from(image.rawBase64, 'base64');
213
+ const fileName = reportImageFileName(image.extension, bytes);
205
214
  const relativePath = `./screenshots/${fileName}`;
206
215
  const absolutePath = (0, external_node_path_namespaceObject.join)(screenshotsDir, fileName);
207
- if (!this.writtenFileIds.has(image.id)) {
208
- await (0, promises_namespaceObject.writeFile)(absolutePath, Buffer.from(image.rawBase64, 'base64'));
209
- this.writtenFileIds.add(image.id);
216
+ let publication = this.pendingFiles.get(fileName);
217
+ if (!publication) {
218
+ publication = (async ()=>{
219
+ if (!this.writtenFileIds.has(fileName)) {
220
+ await (0, external_report_artifact_store_js_namespaceObject.writeReportArtifactFile)(absolutePath, bytes);
221
+ this.writtenFileIds.add(fileName);
222
+ }
223
+ return {
224
+ relativePath,
225
+ absolutePath
226
+ };
227
+ })();
228
+ this.pendingFiles.set(fileName, publication);
229
+ }
230
+ try {
231
+ const location = await publication;
232
+ this.fileLocations.set(image.id, location);
233
+ return location;
234
+ } finally{
235
+ this.pendingFiles.delete(fileName);
210
236
  }
211
- return {
212
- relativePath,
213
- absolutePath
214
- };
215
237
  }
216
238
  loadDataUri(refInput) {
217
239
  const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(refInput);
@@ -236,6 +258,8 @@ class ReportImageStore {
236
258
  });
237
259
  this.writtenInlineIds.clear();
238
260
  this.writtenFileIds.clear();
261
+ this.fileLocations.clear();
262
+ this.pendingFiles.clear();
239
263
  this.existingInlineImageIdsPromise = void 0;
240
264
  }
241
265
  constructor(options){
@@ -246,6 +270,8 @@ class ReportImageStore {
246
270
  _define_property(this, "alsoWriteFileCopy", void 0);
247
271
  _define_property(this, "writtenInlineIds", new Set());
248
272
  _define_property(this, "writtenFileIds", new Set());
273
+ _define_property(this, "fileLocations", new Map());
274
+ _define_property(this, "pendingFiles", new Map());
249
275
  _define_property(this, "shouldReuseExistingInlineReport", void 0);
250
276
  _define_property(this, "existingInlineImageIdsPromise", void 0);
251
277
  this.mode = options.mode;
@@ -264,6 +290,7 @@ exports.normalizeImageUrlRef = __webpack_exports__.normalizeImageUrlRef;
264
290
  exports.normalizeScreenshotRef = __webpack_exports__.normalizeScreenshotRef;
265
291
  exports.normalizeStoredImageRef = __webpack_exports__.normalizeStoredImageRef;
266
292
  exports.parseBase64ImageDataUrl = __webpack_exports__.parseBase64ImageDataUrl;
293
+ exports.reportImageFileName = __webpack_exports__.reportImageFileName;
267
294
  exports.resolveImageSource = __webpack_exports__.resolveImageSource;
268
295
  exports.resolveScreenshotSource = __webpack_exports__.resolveScreenshotSource;
269
296
  for(var __rspack_i in __webpack_exports__)if (-1 === [
@@ -275,6 +302,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
275
302
  "normalizeScreenshotRef",
276
303
  "normalizeStoredImageRef",
277
304
  "parseBase64ImageDataUrl",
305
+ "reportImageFileName",
278
306
  "resolveImageSource",
279
307
  "resolveScreenshotSource"
280
308
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
@@ -1 +1 @@
1
- {"version":3,"file":"dump/screenshot-store.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/screenshot-store.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';\nimport { writeFile as writeFileAsync } from 'node:fs/promises';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport type { ScreenshotItem } from '../screenshot-item';\nimport { collectImageScriptIds, extractImageByIdSync } from './html-utils';\nimport {\n type ImageUrlRef,\n type ScreenshotRef,\n type StoredImageRef,\n imageFileExtensionForMimeType,\n imageRefFileExtension,\n normalizeImageUrlRef,\n normalizeScreenshotRef,\n normalizeStoredImageRef,\n} from './image-reference';\n\nexport type {\n ImageUrlRef,\n ScreenshotRef,\n StoredImageRef,\n} from './image-reference';\nexport {\n imageRefFileExtension,\n normalizeImageUrlRef,\n normalizeScreenshotRef,\n normalizeStoredImageRef,\n} from './image-reference';\n\nconst base64ImageDataUrlPattern =\n /^data:(image\\/[a-z0-9.+-]+)(?:;[^,]*)?;base64,([a-z0-9+/=\\s]+)$/i;\ntype ResolvedImageSource =\n | {\n type: 'data-uri';\n id: string;\n mimeType: StoredImageRef['mimeType'];\n dataUri: string;\n }\n | {\n type: 'file';\n id: string;\n mimeType: StoredImageRef['mimeType'];\n filePath: string;\n };\n\n/** Parse and normalize a base64 image data URL for report persistence. */\nexport function parseBase64ImageDataUrl(imageUrl: string): {\n mimeType: `image/${string}`;\n extension: string;\n rawBase64: string;\n} {\n const match = imageUrl.match(base64ImageDataUrlPattern);\n if (!match) {\n throw new Error(\n 'ReportImageStore: reference image must be a valid base64 image data URL',\n );\n }\n const mimeType = match[1].toLowerCase() as `image/${string}`;\n return {\n mimeType,\n extension: imageFileExtensionForMimeType(mimeType),\n rawBase64: match[2].replace(/\\s/g, ''),\n };\n}\n\nexport function isBase64ImageDataUrl(value: string): boolean {\n return base64ImageDataUrlPattern.test(value);\n}\n\nexport function resolveImageSource(\n refInput: unknown,\n options: {\n reportPath: string;\n imageDirectory?: string;\n fallbackId?: string;\n fallbackMimeType?: ScreenshotRef['mimeType'];\n },\n): ResolvedImageSource {\n const ref = normalizeStoredImageRef(refInput);\n const id = ref?.id ?? options.fallbackId;\n const mimeType = ref?.mimeType ?? options.fallbackMimeType;\n\n if (!id || !mimeType) {\n throw new Error(\n 'ReportImageStore: image id and mimeType are required to resolve an image',\n );\n }\n\n const resolveReportRelativePath = (filePath: string): string =>\n isAbsolute(filePath)\n ? filePath\n : join(dirname(options.reportPath), filePath);\n\n if (ref?.storage === 'file') {\n if (!ref.path) {\n throw new Error(\n `ReportImageStore: image ref \"${ref.id}\" missing file path`,\n );\n }\n\n const explicitFilePath = resolveReportRelativePath(ref.path);\n if (existsSync(explicitFilePath)) {\n return {\n type: 'file',\n id,\n mimeType,\n filePath: explicitFilePath,\n };\n }\n }\n\n const inlineDataUri = extractImageByIdSync(options.reportPath, id);\n if (inlineDataUri) {\n return {\n type: 'data-uri',\n id,\n mimeType,\n dataUri: inlineDataUri,\n };\n }\n\n const extension = ref\n ? imageRefFileExtension(ref)\n : imageFileExtensionForMimeType(options.fallbackMimeType!);\n if (options.imageDirectory) {\n const companionImagePath = join(\n options.imageDirectory,\n `${id}.${extension}`,\n );\n if (existsSync(companionImagePath)) {\n return {\n type: 'file',\n id,\n mimeType,\n filePath: companionImagePath,\n };\n }\n }\n const siblingImagePath = join(\n dirname(options.reportPath),\n 'screenshots',\n `${id}.${extension}`,\n );\n if (existsSync(siblingImagePath)) {\n return {\n type: 'file',\n id,\n mimeType,\n filePath: siblingImagePath,\n };\n }\n\n throw new Error(\n `ReportImageStore: cannot resolve image \"${id}\" from ${options.reportPath}`,\n );\n}\n\nexport function resolveScreenshotSource(\n refInput: unknown,\n options: {\n reportPath: string;\n imageDirectory?: string;\n fallbackId?: string;\n fallbackMimeType?: ScreenshotRef['mimeType'];\n },\n): ResolvedImageSource {\n const ref = normalizeScreenshotRef(refInput);\n return resolveImageSource(ref, options);\n}\n\n/** Persists and restores every image asset referenced by a report. */\nexport class ReportImageStore {\n private readonly mode: 'inline' | 'directory';\n private readonly reportPath: string;\n private readonly screenshotsDir?: string;\n private readonly writeInlineImage?: (\n id: string,\n base64: string,\n ) => void | Promise<void>;\n private alsoWriteFileCopy: boolean;\n private readonly writtenInlineIds = new Set<string>();\n private readonly writtenFileIds = new Set<string>();\n private readonly shouldReuseExistingInlineReport: boolean;\n private existingInlineImageIdsPromise?: Promise<void>;\n\n constructor(options: {\n mode: 'inline' | 'directory';\n reportPath: string;\n screenshotsDir?: string;\n writeInlineImage?: (id: string, base64: string) => void | Promise<void>;\n alsoWriteFileCopy?: boolean;\n /** @deprecated Use alsoWriteFileCopy instead. */\n ensureFileCopy?: boolean;\n /** Reuse inline image assets already present in reportPath. */\n reuseExistingReport?: boolean;\n }) {\n this.mode = options.mode;\n this.reportPath = options.reportPath;\n this.screenshotsDir = options.screenshotsDir;\n this.writeInlineImage = options.writeInlineImage;\n this.alsoWriteFileCopy =\n options.alsoWriteFileCopy ?? options.ensureFileCopy ?? false;\n this.shouldReuseExistingInlineReport = Boolean(\n options.reuseExistingReport && this.mode === 'inline',\n );\n }\n\n enableFileCopies(): void {\n this.alsoWriteFileCopy = true;\n }\n\n async persist(screenshot: ScreenshotItem): Promise<ScreenshotRef> {\n await this.ensureExistingInlineImageIdsLoaded();\n const shouldWriteFileCopy =\n this.mode === 'directory' || this.alsoWriteFileCopy;\n const fileRef = shouldWriteFileCopy\n ? await this.persistToSharedFileIfNeeded(screenshot, {\n markAsPersisted: this.mode === 'directory',\n })\n : null;\n\n if (this.mode === 'inline') {\n if (!this.writeInlineImage) {\n throw new Error(\n 'ReportImageStore: writeInlineImage is required in inline mode',\n );\n }\n if (!this.writtenInlineIds.has(screenshot.id)) {\n await this.writeInlineImage(screenshot.id, screenshot.base64);\n this.writtenInlineIds.add(screenshot.id);\n }\n return screenshot.markPersistedInline(this.reportPath);\n }\n\n if (!fileRef) {\n throw new Error(\n 'ReportImageStore: file persistence is required in directory mode',\n );\n }\n return fileRef;\n }\n\n /** Persist a base64 multimodal prompt image and return its content-addressed ref. */\n async persistReferenceImage(imageUrl: string): Promise<ImageUrlRef> {\n await this.ensureExistingInlineImageIdsLoaded();\n const { mimeType, extension, rawBase64 } =\n parseBase64ImageDataUrl(imageUrl);\n const id = `reference-${createHash('sha256')\n .update(mimeType)\n .update('\\0')\n .update(Buffer.from(rawBase64, 'base64'))\n .digest('hex')}`;\n const shouldWriteFileCopy =\n this.mode === 'directory' || this.alsoWriteFileCopy;\n const fileLocation = shouldWriteFileCopy\n ? await this.writeImageFileIfNeeded({ id, extension, rawBase64 })\n : null;\n\n let ref: ImageUrlRef;\n if (this.mode === 'inline') {\n if (!this.writeInlineImage) {\n throw new Error(\n 'ReportImageStore: writeInlineImage is required in inline mode',\n );\n }\n if (!this.writtenInlineIds.has(id)) {\n await this.writeInlineImage(id, imageUrl);\n this.writtenInlineIds.add(id);\n }\n ref = {\n type: 'midscene_image_url_ref',\n id,\n mimeType,\n storage: 'inline',\n };\n } else {\n if (!fileLocation) {\n throw new Error(\n 'ReportImageStore: file persistence is required in directory mode',\n );\n }\n ref = {\n type: 'midscene_image_url_ref',\n id,\n mimeType,\n storage: 'file',\n path: fileLocation.relativePath,\n };\n }\n return ref;\n }\n\n private async ensureExistingInlineImageIdsLoaded(): Promise<void> {\n if (!this.shouldReuseExistingInlineReport) return;\n if (!this.existingInlineImageIdsPromise) {\n this.existingInlineImageIdsPromise = (async () => {\n try {\n const imageIds = await collectImageScriptIds(this.reportPath);\n for (const imageId of imageIds) this.writtenInlineIds.add(imageId);\n } catch (error) {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === 'ENOENT'\n ) {\n return;\n }\n throw new Error(\n `ReportImageStore: failed to index existing inline images from ${this.reportPath}`,\n { cause: error },\n );\n }\n })();\n }\n await this.existingInlineImageIdsPromise;\n }\n\n private async persistToSharedFileIfNeeded(\n screenshot: ScreenshotItem,\n options: {\n markAsPersisted: boolean;\n },\n ): Promise<ScreenshotRef> {\n const fileName = `${screenshot.id}.${screenshot.extension}`;\n const { relativePath, absolutePath } = this.writtenFileIds.has(\n screenshot.id,\n )\n ? {\n relativePath: `./screenshots/${fileName}`,\n absolutePath: join(this.screenshotsDir!, fileName),\n }\n : await this.writeImageFileIfNeeded({\n id: screenshot.id,\n extension: screenshot.extension,\n rawBase64: screenshot.rawBase64,\n });\n\n if (options.markAsPersisted) {\n return screenshot.markPersistedToPath(relativePath, absolutePath);\n }\n\n return screenshot.registerPersistedFileCopy(relativePath, absolutePath);\n }\n\n private async writeImageFileIfNeeded(image: {\n id: string;\n extension: string;\n rawBase64: string;\n }): Promise<{ relativePath: string; absolutePath: string }> {\n const screenshotsDir = this.screenshotsDir;\n if (!screenshotsDir) {\n throw new Error(\n 'ReportImageStore: screenshotsDir is required when file persistence is enabled',\n );\n }\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n\n const fileName = `${image.id}.${image.extension}`;\n const relativePath = `./screenshots/${fileName}`;\n const absolutePath = join(screenshotsDir, fileName);\n if (!this.writtenFileIds.has(image.id)) {\n await writeFileAsync(\n absolutePath,\n Buffer.from(image.rawBase64, 'base64'),\n );\n this.writtenFileIds.add(image.id);\n }\n return { relativePath, absolutePath };\n }\n\n /** Resolve any stored report image reference to a data URI. */\n loadDataUri(refInput: unknown): string {\n const ref = normalizeStoredImageRef(refInput);\n if (!ref) {\n throw new Error('ReportImageStore: invalid image reference');\n }\n\n const resolved = resolveImageSource(ref, {\n reportPath: this.reportPath,\n imageDirectory: this.screenshotsDir,\n });\n\n if (resolved.type === 'data-uri') {\n return resolved.dataUri;\n }\n\n const data = readFileSync(resolved.filePath);\n return `data:${resolved.mimeType};base64,${data.toString('base64')}`;\n }\n\n /** @deprecated Use loadDataUri. */\n loadBase64(refInput: unknown): string {\n const screenshotRef = normalizeScreenshotRef(refInput);\n if (!screenshotRef) {\n throw new Error('ReportImageStore: invalid screenshot reference');\n }\n return this.loadDataUri(screenshotRef);\n }\n\n cleanup(): void {\n if (\n this.mode === 'directory' &&\n this.screenshotsDir &&\n existsSync(this.screenshotsDir)\n ) {\n rmSync(this.screenshotsDir, { recursive: true, force: true });\n }\n this.writtenInlineIds.clear();\n this.writtenFileIds.clear();\n this.existingInlineImageIdsPromise = undefined;\n }\n}\n\n/** @deprecated Use ReportImageStore. */\nexport { ReportImageStore as ScreenshotStore };\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","base64ImageDataUrlPattern","parseBase64ImageDataUrl","imageUrl","match","Error","mimeType","imageFileExtensionForMimeType","isBase64ImageDataUrl","value","resolveImageSource","refInput","options","ref","normalizeStoredImageRef","id","resolveReportRelativePath","filePath","isAbsolute","join","dirname","explicitFilePath","existsSync","inlineDataUri","extractImageByIdSync","extension","imageRefFileExtension","companionImagePath","siblingImagePath","resolveScreenshotSource","normalizeScreenshotRef","ReportImageStore","screenshot","shouldWriteFileCopy","fileRef","rawBase64","createHash","Buffer","fileLocation","imageIds","collectImageScriptIds","imageId","error","fileName","relativePath","absolutePath","image","screenshotsDir","mkdirSync","writeFileAsync","resolved","data","readFileSync","screenshotRef","rmSync","undefined","Set","Boolean"],"mappings":"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"}
1
+ {"version":3,"file":"dump/screenshot-store.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/screenshot-store.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport type { ScreenshotItem } from '../screenshot-item';\nimport { collectImageScriptIds, extractImageByIdSync } from './html-utils';\nimport {\n type ImageUrlRef,\n type ScreenshotRef,\n type StoredImageRef,\n imageFileExtensionForMimeType,\n imageRefFileExtension,\n normalizeImageUrlRef,\n normalizeScreenshotRef,\n normalizeStoredImageRef,\n} from './image-reference';\nimport { writeReportArtifactFile } from './report-artifact-store';\n\nexport type {\n ImageUrlRef,\n ScreenshotRef,\n StoredImageRef,\n} from './image-reference';\nexport {\n imageRefFileExtension,\n normalizeImageUrlRef,\n normalizeScreenshotRef,\n normalizeStoredImageRef,\n} from './image-reference';\n\nconst base64ImageDataUrlPattern =\n /^data:(image\\/[a-z0-9.+-]+)(?:;[^,]*)?;base64,([a-z0-9+/=\\s]+)$/i;\ntype ResolvedImageSource =\n | {\n type: 'data-uri';\n id: string;\n mimeType: StoredImageRef['mimeType'];\n dataUri: string;\n }\n | {\n type: 'file';\n id: string;\n mimeType: StoredImageRef['mimeType'];\n filePath: string;\n };\n\n/** Parse and normalize a base64 image data URL for report persistence. */\nexport function parseBase64ImageDataUrl(imageUrl: string): {\n mimeType: `image/${string}`;\n extension: string;\n rawBase64: string;\n} {\n const match = imageUrl.match(base64ImageDataUrlPattern);\n if (!match) {\n throw new Error(\n 'ReportImageStore: reference image must be a valid base64 image data URL',\n );\n }\n const mimeType = match[1].toLowerCase() as `image/${string}`;\n return {\n mimeType,\n extension: imageFileExtensionForMimeType(mimeType),\n rawBase64: match[2].replace(/\\s/g, ''),\n };\n}\n\nexport function isBase64ImageDataUrl(value: string): boolean {\n return base64ImageDataUrlPattern.test(value);\n}\n\n/** Stable asset names allow different observations to share the same bytes. */\nexport function reportImageFileName(\n extension: string,\n bytes: Uint8Array,\n): string {\n const hash = createHash('sha256')\n .update(extension)\n .update('\\0')\n .update(bytes)\n .digest('hex');\n return `${hash}.${extension}`;\n}\n\nexport function resolveImageSource(\n refInput: unknown,\n options: {\n reportPath: string;\n imageDirectory?: string;\n fallbackId?: string;\n fallbackMimeType?: ScreenshotRef['mimeType'];\n },\n): ResolvedImageSource {\n const ref = normalizeStoredImageRef(refInput);\n const id = ref?.id ?? options.fallbackId;\n const mimeType = ref?.mimeType ?? options.fallbackMimeType;\n\n if (!id || !mimeType) {\n throw new Error(\n 'ReportImageStore: image id and mimeType are required to resolve an image',\n );\n }\n\n const resolveReportRelativePath = (filePath: string): string =>\n isAbsolute(filePath)\n ? filePath\n : join(dirname(options.reportPath), filePath);\n\n if (ref?.storage === 'file') {\n if (!ref.path) {\n throw new Error(\n `ReportImageStore: image ref \"${ref.id}\" missing file path`,\n );\n }\n\n const explicitFilePath = resolveReportRelativePath(ref.path);\n if (existsSync(explicitFilePath)) {\n return {\n type: 'file',\n id,\n mimeType,\n filePath: explicitFilePath,\n };\n }\n }\n\n const inlineDataUri = extractImageByIdSync(options.reportPath, id);\n if (inlineDataUri) {\n return {\n type: 'data-uri',\n id,\n mimeType,\n dataUri: inlineDataUri,\n };\n }\n\n const extension = ref\n ? imageRefFileExtension(ref)\n : imageFileExtensionForMimeType(options.fallbackMimeType!);\n if (options.imageDirectory) {\n const companionImagePath = join(\n options.imageDirectory,\n `${id}.${extension}`,\n );\n if (existsSync(companionImagePath)) {\n return {\n type: 'file',\n id,\n mimeType,\n filePath: companionImagePath,\n };\n }\n }\n const siblingImagePath = join(\n dirname(options.reportPath),\n 'screenshots',\n `${id}.${extension}`,\n );\n if (existsSync(siblingImagePath)) {\n return {\n type: 'file',\n id,\n mimeType,\n filePath: siblingImagePath,\n };\n }\n\n throw new Error(\n `ReportImageStore: cannot resolve image \"${id}\" from ${options.reportPath}`,\n );\n}\n\nexport function resolveScreenshotSource(\n refInput: unknown,\n options: {\n reportPath: string;\n imageDirectory?: string;\n fallbackId?: string;\n fallbackMimeType?: ScreenshotRef['mimeType'];\n },\n): ResolvedImageSource {\n const ref = normalizeScreenshotRef(refInput);\n return resolveImageSource(ref, options);\n}\n\n/** Persists and restores every image asset referenced by a report. */\nexport class ReportImageStore {\n private readonly mode: 'inline' | 'directory';\n private readonly reportPath: string;\n private readonly screenshotsDir?: string;\n private readonly writeInlineImage?: (\n id: string,\n base64: string,\n ) => void | Promise<void>;\n private alsoWriteFileCopy: boolean;\n private readonly writtenInlineIds = new Set<string>();\n private readonly writtenFileIds = new Set<string>();\n private readonly fileLocations = new Map<\n string,\n { relativePath: string; absolutePath: string }\n >();\n private readonly pendingFiles = new Map<\n string,\n Promise<{ relativePath: string; absolutePath: string }>\n >();\n private readonly shouldReuseExistingInlineReport: boolean;\n private existingInlineImageIdsPromise?: Promise<void>;\n\n constructor(options: {\n mode: 'inline' | 'directory';\n reportPath: string;\n screenshotsDir?: string;\n writeInlineImage?: (id: string, base64: string) => void | Promise<void>;\n alsoWriteFileCopy?: boolean;\n /** @deprecated Use alsoWriteFileCopy instead. */\n ensureFileCopy?: boolean;\n /** Reuse inline image assets already present in reportPath. */\n reuseExistingReport?: boolean;\n }) {\n this.mode = options.mode;\n this.reportPath = options.reportPath;\n this.screenshotsDir = options.screenshotsDir;\n this.writeInlineImage = options.writeInlineImage;\n this.alsoWriteFileCopy =\n options.alsoWriteFileCopy ?? options.ensureFileCopy ?? false;\n this.shouldReuseExistingInlineReport = Boolean(\n options.reuseExistingReport && this.mode === 'inline',\n );\n }\n\n enableFileCopies(): void {\n this.alsoWriteFileCopy = true;\n }\n\n /** Resolve an observation/reference ID to its content-addressed asset. */\n getFilePath(id: string): string {\n const file = this.fileLocations.get(id);\n if (!file)\n throw new Error(`ReportImageStore: image ${id} has no persisted file`);\n return file.relativePath;\n }\n\n async persist(screenshot: ScreenshotItem): Promise<ScreenshotRef> {\n await this.ensureExistingInlineImageIdsLoaded();\n const shouldWriteFileCopy =\n this.mode === 'directory' || this.alsoWriteFileCopy;\n const fileRef = shouldWriteFileCopy\n ? await this.persistToSharedFileIfNeeded(screenshot, {\n markAsPersisted: this.mode === 'directory',\n })\n : null;\n\n if (this.mode === 'inline') {\n if (!this.writeInlineImage) {\n throw new Error(\n 'ReportImageStore: writeInlineImage is required in inline mode',\n );\n }\n if (!this.writtenInlineIds.has(screenshot.id)) {\n await this.writeInlineImage(screenshot.id, screenshot.base64);\n this.writtenInlineIds.add(screenshot.id);\n }\n return screenshot.markPersistedInline(this.reportPath);\n }\n\n if (!fileRef) {\n throw new Error(\n 'ReportImageStore: file persistence is required in directory mode',\n );\n }\n return fileRef;\n }\n\n /** Persist a base64 multimodal prompt image and return its content-addressed ref. */\n async persistReferenceImage(imageUrl: string): Promise<ImageUrlRef> {\n await this.ensureExistingInlineImageIdsLoaded();\n const { mimeType, extension, rawBase64 } =\n parseBase64ImageDataUrl(imageUrl);\n const id = `reference-${createHash('sha256')\n .update(mimeType)\n .update('\\0')\n .update(Buffer.from(rawBase64, 'base64'))\n .digest('hex')}`;\n const shouldWriteFileCopy =\n this.mode === 'directory' || this.alsoWriteFileCopy;\n const fileLocation = shouldWriteFileCopy\n ? await this.writeImageFileIfNeeded({ id, extension, rawBase64 })\n : null;\n\n let ref: ImageUrlRef;\n if (this.mode === 'inline') {\n if (!this.writeInlineImage) {\n throw new Error(\n 'ReportImageStore: writeInlineImage is required in inline mode',\n );\n }\n if (!this.writtenInlineIds.has(id)) {\n await this.writeInlineImage(id, imageUrl);\n this.writtenInlineIds.add(id);\n }\n ref = {\n type: 'midscene_image_url_ref',\n id,\n mimeType,\n storage: 'inline',\n };\n } else {\n if (!fileLocation) {\n throw new Error(\n 'ReportImageStore: file persistence is required in directory mode',\n );\n }\n ref = {\n type: 'midscene_image_url_ref',\n id,\n mimeType,\n storage: 'file',\n path: fileLocation.relativePath,\n };\n }\n return ref;\n }\n\n private async ensureExistingInlineImageIdsLoaded(): Promise<void> {\n if (!this.shouldReuseExistingInlineReport) return;\n if (!this.existingInlineImageIdsPromise) {\n this.existingInlineImageIdsPromise = (async () => {\n try {\n const imageIds = await collectImageScriptIds(this.reportPath);\n for (const imageId of imageIds) this.writtenInlineIds.add(imageId);\n } catch (error) {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === 'ENOENT'\n ) {\n return;\n }\n throw new Error(\n `ReportImageStore: failed to index existing inline images from ${this.reportPath}`,\n { cause: error },\n );\n }\n })();\n }\n await this.existingInlineImageIdsPromise;\n }\n\n private async persistToSharedFileIfNeeded(\n screenshot: ScreenshotItem,\n options: {\n markAsPersisted: boolean;\n },\n ): Promise<ScreenshotRef> {\n const { relativePath, absolutePath } =\n this.fileLocations.get(screenshot.id) ??\n (await this.writeImageFileIfNeeded({\n id: screenshot.id,\n extension: screenshot.extension,\n rawBase64: screenshot.rawBase64,\n }));\n\n if (options.markAsPersisted) {\n return screenshot.markPersistedToPath(relativePath, absolutePath);\n }\n\n return screenshot.registerPersistedFileCopy(relativePath, absolutePath);\n }\n\n private async writeImageFileIfNeeded(image: {\n id: string;\n extension: string;\n rawBase64: string;\n }): Promise<{ relativePath: string; absolutePath: string }> {\n const screenshotsDir = this.screenshotsDir;\n if (!screenshotsDir) {\n throw new Error(\n 'ReportImageStore: screenshotsDir is required when file persistence is enabled',\n );\n }\n if (!existsSync(screenshotsDir)) {\n mkdirSync(screenshotsDir, { recursive: true });\n }\n\n const known = this.fileLocations.get(image.id);\n if (known) return known;\n const bytes = Buffer.from(image.rawBase64, 'base64');\n const fileName = reportImageFileName(image.extension, bytes);\n const relativePath = `./screenshots/${fileName}`;\n const absolutePath = join(screenshotsDir, fileName);\n let publication = this.pendingFiles.get(fileName);\n if (!publication) {\n publication = (async () => {\n if (!this.writtenFileIds.has(fileName)) {\n await writeReportArtifactFile(absolutePath, bytes);\n this.writtenFileIds.add(fileName);\n }\n return { relativePath, absolutePath };\n })();\n this.pendingFiles.set(fileName, publication);\n }\n try {\n const location = await publication;\n this.fileLocations.set(image.id, location);\n return location;\n } finally {\n this.pendingFiles.delete(fileName);\n }\n }\n\n /** Resolve any stored report image reference to a data URI. */\n loadDataUri(refInput: unknown): string {\n const ref = normalizeStoredImageRef(refInput);\n if (!ref) {\n throw new Error('ReportImageStore: invalid image reference');\n }\n\n const resolved = resolveImageSource(ref, {\n reportPath: this.reportPath,\n imageDirectory: this.screenshotsDir,\n });\n\n if (resolved.type === 'data-uri') {\n return resolved.dataUri;\n }\n\n const data = readFileSync(resolved.filePath);\n return `data:${resolved.mimeType};base64,${data.toString('base64')}`;\n }\n\n /** @deprecated Use loadDataUri. */\n loadBase64(refInput: unknown): string {\n const screenshotRef = normalizeScreenshotRef(refInput);\n if (!screenshotRef) {\n throw new Error('ReportImageStore: invalid screenshot reference');\n }\n return this.loadDataUri(screenshotRef);\n }\n\n cleanup(): void {\n if (\n this.mode === 'directory' &&\n this.screenshotsDir &&\n existsSync(this.screenshotsDir)\n ) {\n rmSync(this.screenshotsDir, { recursive: true, force: true });\n }\n this.writtenInlineIds.clear();\n this.writtenFileIds.clear();\n this.fileLocations.clear();\n this.pendingFiles.clear();\n this.existingInlineImageIdsPromise = undefined;\n }\n}\n\n/** @deprecated Use ReportImageStore. */\nexport { ReportImageStore as ScreenshotStore };\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","base64ImageDataUrlPattern","parseBase64ImageDataUrl","imageUrl","match","Error","mimeType","imageFileExtensionForMimeType","isBase64ImageDataUrl","value","reportImageFileName","extension","bytes","hash","createHash","resolveImageSource","refInput","options","ref","normalizeStoredImageRef","id","resolveReportRelativePath","filePath","isAbsolute","join","dirname","explicitFilePath","existsSync","inlineDataUri","extractImageByIdSync","imageRefFileExtension","companionImagePath","siblingImagePath","resolveScreenshotSource","normalizeScreenshotRef","ReportImageStore","file","screenshot","shouldWriteFileCopy","fileRef","rawBase64","Buffer","fileLocation","imageIds","collectImageScriptIds","imageId","error","relativePath","absolutePath","image","screenshotsDir","mkdirSync","known","fileName","publication","writeReportArtifactFile","location","resolved","data","readFileSync","screenshotRef","rmSync","undefined","Set","Map","Boolean"],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ TestReportImages: ()=>TestReportImages
28
+ });
29
+ const external_node_fs_namespaceObject = require("node:fs");
30
+ const promises_namespaceObject = require("node:fs/promises");
31
+ const external_node_path_namespaceObject = require("node:path");
32
+ const external_html_utils_js_namespaceObject = require("./html-utils.js");
33
+ const external_image_reference_js_namespaceObject = require("./image-reference.js");
34
+ const external_screenshot_store_js_namespaceObject = require("./screenshot-store.js");
35
+ function _define_property(obj, key, value) {
36
+ if (key in obj) Object.defineProperty(obj, key, {
37
+ value: value,
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true
41
+ });
42
+ else obj[key] = value;
43
+ return obj;
44
+ }
45
+ class TestReportImages {
46
+ reference(ref, dataUri) {
47
+ const known = this.locations.get(ref.id);
48
+ if (known) return {
49
+ ...ref,
50
+ ...known
51
+ };
52
+ const location = this.external ? {
53
+ storage: 'file',
54
+ path: `./screenshots/${(0, external_screenshot_store_js_namespaceObject.reportImageFileName)((0, external_image_reference_js_namespaceObject.imageRefFileExtension)(ref), Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(dataUri).rawBase64, 'base64'))}`
55
+ } : {
56
+ storage: 'inline',
57
+ path: void 0
58
+ };
59
+ this.locations.set(ref.id, location);
60
+ return {
61
+ ...ref,
62
+ ...location
63
+ };
64
+ }
65
+ rewrite(serialized) {
66
+ return JSON.stringify(JSON.parse(serialized), (_key, value)=>{
67
+ const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(value);
68
+ return ref ? {
69
+ ...ref,
70
+ ...this.locations.get(ref.id)
71
+ } : value;
72
+ });
73
+ }
74
+ collect(serialized) {
75
+ const refs = new Map();
76
+ JSON.parse(serialized, (_key, value)=>{
77
+ const ref = (0, external_image_reference_js_namespaceObject.normalizeStoredImageRef)(value);
78
+ if (ref && !this.locations.has(ref.id)) refs.set(ref.id, ref);
79
+ return value;
80
+ });
81
+ return [
82
+ ...refs.values()
83
+ ];
84
+ }
85
+ rewriteSync(serialized, sourcePath) {
86
+ let inlineImages;
87
+ for (const ref of this.collect(serialized)){
88
+ let data;
89
+ if ('file' === ref.storage) data = `data:${ref.mimeType};base64,${(0, external_node_fs_namespaceObject.readFileSync)((0, external_node_path_namespaceObject.resolve)((0, external_node_path_namespaceObject.dirname)(sourcePath), ref.path)).toString('base64')}`;
90
+ else {
91
+ inlineImages ??= (0, external_html_utils_js_namespaceObject.parseImageScripts)((0, external_node_fs_namespaceObject.readFileSync)(sourcePath, 'utf8'));
92
+ data = inlineImages[ref.id];
93
+ if (!data) throw new Error(`Missing report image ${ref.id} in ${sourcePath}`);
94
+ }
95
+ const target = this.reference(ref, data);
96
+ if ('file' === target.storage) {
97
+ if (!this.files.has(target.path)) {
98
+ const file = (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.reportPath), target.path);
99
+ (0, external_node_fs_namespaceObject.mkdirSync)((0, external_node_path_namespaceObject.dirname)(file), {
100
+ recursive: true
101
+ });
102
+ (0, external_node_fs_namespaceObject.writeFileSync)(file, Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(data).rawBase64, 'base64'));
103
+ this.files.add(target.path);
104
+ }
105
+ } else (0, external_node_fs_namespaceObject.appendFileSync)(this.reportPath, `${(0, external_html_utils_js_namespaceObject.generateImageScriptTag)(ref.id, data)}\n`);
106
+ }
107
+ return this.rewrite(serialized);
108
+ }
109
+ async rewriteAsync(serialized, sourcePath) {
110
+ let inlineImages;
111
+ for (const ref of this.collect(serialized)){
112
+ let data;
113
+ if ('file' === ref.storage) {
114
+ const bytes = await promises_namespaceObject.readFile((0, external_node_path_namespaceObject.resolve)((0, external_node_path_namespaceObject.dirname)(sourcePath), ref.path));
115
+ data = `data:${ref.mimeType};base64,${bytes.toString('base64')}`;
116
+ } else {
117
+ inlineImages ??= (0, external_html_utils_js_namespaceObject.parseImageScripts)(await promises_namespaceObject.readFile(sourcePath, 'utf8'));
118
+ data = inlineImages[ref.id];
119
+ if (!data) throw new Error(`Missing report image ${ref.id} in ${sourcePath}`);
120
+ }
121
+ const target = this.reference(ref, data);
122
+ if ('file' === target.storage) {
123
+ if (!this.files.has(target.path)) {
124
+ const file = (0, external_node_path_namespaceObject.join)((0, external_node_path_namespaceObject.dirname)(this.reportPath), target.path);
125
+ await promises_namespaceObject.mkdir((0, external_node_path_namespaceObject.dirname)(file), {
126
+ recursive: true
127
+ });
128
+ await promises_namespaceObject.writeFile(file, Buffer.from((0, external_screenshot_store_js_namespaceObject.parseBase64ImageDataUrl)(data).rawBase64, 'base64'));
129
+ this.files.add(target.path);
130
+ }
131
+ } else await promises_namespaceObject.appendFile(this.reportPath, `${(0, external_html_utils_js_namespaceObject.generateImageScriptTag)(ref.id, data)}\n`);
132
+ }
133
+ return this.rewrite(serialized);
134
+ }
135
+ constructor(reportPath, external){
136
+ _define_property(this, "reportPath", void 0);
137
+ _define_property(this, "external", void 0);
138
+ _define_property(this, "locations", void 0);
139
+ _define_property(this, "files", void 0);
140
+ this.reportPath = reportPath;
141
+ this.external = external;
142
+ this.locations = new Map();
143
+ this.files = new Set();
144
+ }
145
+ }
146
+ exports.TestReportImages = __webpack_exports__.TestReportImages;
147
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
148
+ "TestReportImages"
149
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
150
+ Object.defineProperty(exports, '__esModule', {
151
+ value: true
152
+ });
153
+
154
+ //# sourceMappingURL=test-report-images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump/test-report-images.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/test-report-images.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import {\n appendFileSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from 'node:fs';\nimport * as fs from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport { generateImageScriptTag, parseImageScripts } from './html-utils';\nimport {\n type StoredImageRef,\n imageRefFileExtension,\n normalizeStoredImageRef,\n} from './image-reference';\nimport {\n parseBase64ImageDataUrl,\n reportImageFileName,\n} from './screenshot-store';\n\n/** Final delivery format is independent of how Agents stored their source records. */\nexport class TestReportImages {\n private readonly locations = new Map<\n string,\n Pick<StoredImageRef, 'storage' | 'path'>\n >();\n private readonly files = new Set<string>();\n\n constructor(\n private readonly reportPath: string,\n private readonly external: boolean,\n ) {}\n\n private reference(ref: StoredImageRef, dataUri: string): StoredImageRef {\n const known = this.locations.get(ref.id);\n if (known) return { ...ref, ...known };\n const location: Pick<StoredImageRef, 'storage' | 'path'> = this.external\n ? {\n storage: 'file',\n path: `./screenshots/${reportImageFileName(imageRefFileExtension(ref), Buffer.from(parseBase64ImageDataUrl(dataUri).rawBase64, 'base64'))}`,\n }\n : { storage: 'inline', path: undefined };\n this.locations.set(ref.id, location);\n return { ...ref, ...location };\n }\n\n private rewrite(serialized: string): string {\n return JSON.stringify(JSON.parse(serialized), (_key, value) => {\n const ref = normalizeStoredImageRef(value);\n return ref ? { ...ref, ...this.locations.get(ref.id) } : value;\n });\n }\n\n private collect(serialized: string): StoredImageRef[] {\n const refs = new Map<string, StoredImageRef>();\n JSON.parse(serialized, (_key, value) => {\n const ref = normalizeStoredImageRef(value);\n if (ref && !this.locations.has(ref.id)) refs.set(ref.id, ref);\n return value;\n });\n return [...refs.values()];\n }\n\n rewriteSync(serialized: string, sourcePath: string): string {\n let inlineImages: Record<string, string> | undefined;\n for (const ref of this.collect(serialized)) {\n let data: string;\n if (ref.storage === 'file')\n data = `data:${ref.mimeType};base64,${readFileSync(resolve(dirname(sourcePath), ref.path!)).toString('base64')}`;\n else {\n inlineImages ??= parseImageScripts(readFileSync(sourcePath, 'utf8'));\n data = inlineImages[ref.id];\n if (!data)\n throw new Error(`Missing report image ${ref.id} in ${sourcePath}`);\n }\n const target = this.reference(ref, data);\n if (target.storage === 'file') {\n if (!this.files.has(target.path!)) {\n const file = join(dirname(this.reportPath), target.path!);\n mkdirSync(dirname(file), { recursive: true });\n writeFileSync(\n file,\n Buffer.from(parseBase64ImageDataUrl(data).rawBase64, 'base64'),\n );\n this.files.add(target.path!);\n }\n } else\n appendFileSync(\n this.reportPath,\n `${generateImageScriptTag(ref.id, data)}\\n`,\n );\n }\n return this.rewrite(serialized);\n }\n\n async rewriteAsync(serialized: string, sourcePath: string): Promise<string> {\n let inlineImages: Record<string, string> | undefined;\n for (const ref of this.collect(serialized)) {\n let data: string;\n if (ref.storage === 'file') {\n const bytes = await fs.readFile(\n resolve(dirname(sourcePath), ref.path!),\n );\n data = `data:${ref.mimeType};base64,${bytes.toString('base64')}`;\n } else {\n inlineImages ??= parseImageScripts(\n await fs.readFile(sourcePath, 'utf8'),\n );\n data = inlineImages[ref.id];\n if (!data)\n throw new Error(`Missing report image ${ref.id} in ${sourcePath}`);\n }\n const target = this.reference(ref, data);\n if (target.storage === 'file') {\n if (!this.files.has(target.path!)) {\n const file = join(dirname(this.reportPath), target.path!);\n await fs.mkdir(dirname(file), { recursive: true });\n await fs.writeFile(\n file,\n Buffer.from(parseBase64ImageDataUrl(data).rawBase64, 'base64'),\n );\n this.files.add(target.path!);\n }\n } else\n await fs.appendFile(\n this.reportPath,\n `${generateImageScriptTag(ref.id, data)}\\n`,\n );\n }\n return this.rewrite(serialized);\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","TestReportImages","ref","dataUri","known","location","reportImageFileName","imageRefFileExtension","Buffer","parseBase64ImageDataUrl","undefined","serialized","JSON","_key","value","normalizeStoredImageRef","refs","Map","sourcePath","inlineImages","data","readFileSync","resolve","dirname","parseImageScripts","Error","target","file","join","mkdirSync","writeFileSync","appendFileSync","generateImageScriptTag","bytes","fs","reportPath","external","Set"],"mappings":"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"}
@@ -32,7 +32,7 @@ __webpack_require__.d(__webpack_exports__, {
32
32
  const external_node_fs_namespaceObject = require("node:fs");
33
33
  const external_node_path_namespaceObject = require("node:path");
34
34
  const external_zod_namespaceObject = require("zod");
35
- const html_utils_js_namespaceObject = require("./dump/html-utils.js");
35
+ const report_artifact_reader_js_namespaceObject = require("./dump/report-artifact-reader.js");
36
36
  const screenshot_store_js_namespaceObject = require("./dump/screenshot-store.js");
37
37
  const task_status_js_namespaceObject = require("./dump/task-status.js");
38
38
  const external_report_js_namespaceObject = require("./report.js");
@@ -131,21 +131,22 @@ const FAILING_TEST_STATUSES = new Set([
131
131
  ]);
132
132
  function readSourceTestStatus(htmlPath) {
133
133
  const recorded = [];
134
- for (const { openTag } of (0, html_utils_js_namespaceObject.extractAllDumpScriptsSync)(htmlPath)){
134
+ (0, report_artifact_reader_js_namespaceObject.streamReportDumpScripts)(htmlPath, ({ openTag })=>{
135
135
  const match = openTag.match(/playwright_test_status="([^"]*)"/);
136
- if (!match) continue;
136
+ if (!match) return false;
137
137
  const status = decodeURIComponent(match[1]);
138
138
  if (TEST_STATUS_VALUES.has(status)) recorded.push(status);
139
- }
139
+ return false;
140
+ });
140
141
  if (0 === recorded.length) return;
141
142
  return recorded.find((s)=>FAILING_TEST_STATUSES.has(s)) ?? recorded[0];
142
143
  }
143
144
  function deriveReportAttributesFromHtml(htmlPath, index) {
144
145
  const fallbackId = `${external_node_path_namespaceObject.basename(external_node_path_namespaceObject.dirname(htmlPath)) || external_node_path_namespaceObject.basename(htmlPath, external_node_path_namespaceObject.extname(htmlPath))}-${index + 1}`;
145
- const runnerDump = (0, html_utils_js_namespaceObject.extractTestRunReportDumpSync)(htmlPath);
146
+ const runnerDump = (0, report_artifact_reader_js_namespaceObject.readReportRunnerDump)(htmlPath);
147
+ const recordedStatus = readSourceTestStatus(htmlPath);
146
148
  try {
147
149
  const { baseDump, executions } = (0, external_report_js_namespaceObject.collectDedupedExecutions)(htmlPath);
148
- const recordedStatus = readSourceTestStatus(htmlPath);
149
150
  const testStatus = recordedStatus && FAILING_TEST_STATUSES.has(recordedStatus) ? recordedStatus : runnerDump?.status === 'failed' ? 'failed' : recordedStatus ?? (runnerDump ? 'passed' : (0, task_status_js_namespaceObject.deriveCaseStatus)(executions));
150
151
  return {
151
152
  testId: fallbackId,
@@ -162,7 +163,7 @@ function deriveReportAttributesFromHtml(htmlPath, index) {
162
163
  testTitle: fallbackId,
163
164
  testDescription: '',
164
165
  testDuration: 0,
165
- testStatus: runnerDump?.status === 'failed' ? 'failed' : 'passed'
166
+ testStatus: recordedStatus && FAILING_TEST_STATUSES.has(recordedStatus) ? recordedStatus : runnerDump?.status === 'failed' ? 'failed' : recordedStatus ?? 'passed'
166
167
  };
167
168
  }
168
169
  }
@@ -1 +1 @@
1
- {"version":3,"file":"report-cli.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report-cli.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import {\n copyFileSync,\n existsSync,\n mkdirSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport * as path from 'node:path';\nimport { z } from 'zod';\nimport {\n extractAllDumpScriptsSync,\n extractTestRunReportDumpSync,\n} from './dump/html-utils';\nimport { resolveScreenshotSource } from './dump/screenshot-store';\nimport { deriveCaseStatus } from './dump/task-status';\nimport {\n ReportMergingTool,\n collectDedupedExecutions,\n splitReportHtmlByExecution,\n} from './report';\nimport { reportToMarkdown } from './report-markdown';\nimport type { MarkdownAttachment } from './report-markdown';\nimport { collectReportSummary } from './report-stats';\nimport type { ReportFileAttributes, TestStatus } from './types';\nimport { ReportActionDump } from './types';\n\ntype ReportCliToolResult = {\n isError: boolean;\n content: Array<{\n type: 'text';\n text: string;\n }>;\n};\n\ntype ReportCliSchema = Record<string, z.ZodTypeAny>;\n\nexport interface ReportCliCommandDefinition {\n name: string;\n description: string;\n schema: ReportCliSchema;\n handler: (args: Record<string, unknown>) => Promise<ReportCliToolResult>;\n}\n\nexport interface ReportCliCommandEntry {\n name: string;\n def: ReportCliCommandDefinition;\n}\n\nexport type ConsumeReportFileAction = 'split' | 'to-markdown' | 'merge-html';\n\nexport interface ConsumeReportFileOptions {\n htmlPath: string;\n outputDir: string;\n}\n\nexport type SplitReportFileOptions = ConsumeReportFileOptions;\nexport type ReportFileToMarkdownOptions = ConsumeReportFileOptions;\n\nexport interface MergeReportFilesOptions {\n htmlPaths: string[];\n outputDir?: string;\n outputName?: string;\n overwrite?: boolean;\n}\n\nexport interface MergeReportFilesResult {\n mergedReportPath: string;\n}\n\nfunction writeAttachmentFromReport(\n attachment: MarkdownAttachment,\n opts: {\n htmlPath: string;\n screenshotsDir: string;\n writtenFiles: Set<string>;\n },\n): void {\n const { suggestedFileName, id, mimeType } = attachment;\n if (opts.writtenFiles.has(suggestedFileName)) return;\n\n const absolutePath = path.join(opts.screenshotsDir, suggestedFileName);\n\n const resolved = resolveScreenshotSource(attachment.sourceRef ?? null, {\n reportPath: opts.htmlPath,\n fallbackId: id,\n fallbackMimeType: (mimeType || 'image/png') as 'image/png' | 'image/jpeg',\n });\n\n if (resolved.type === 'data-uri') {\n const rawBase64 = resolved.dataUri.replace(\n /^data:image\\/[a-zA-Z+]+;base64,/,\n '',\n );\n writeFileSync(absolutePath, Buffer.from(rawBase64, 'base64'));\n opts.writtenFiles.add(suggestedFileName);\n return;\n }\n\n if (!existsSync(resolved.filePath)) {\n throw new Error(\n `Cannot resolve screenshot \"${id}\" for markdown attachment from ${opts.htmlPath}`,\n );\n }\n\n copyFileSync(resolved.filePath, absolutePath);\n opts.writtenFiles.add(suggestedFileName);\n}\n\nasync function markdownFromReport(\n htmlPath: string,\n outputDir: string,\n): Promise<{ markdownFiles: string[]; screenshotFiles: string[] }> {\n const screenshotsDir = path.join(outputDir, 'screenshots');\n\n mkdirSync(outputDir, { recursive: true });\n mkdirSync(screenshotsDir, { recursive: true });\n\n const { baseDump, executions } = collectDedupedExecutions(htmlPath);\n\n const mergedReport = new ReportActionDump({\n sdkVersion: baseDump.sdkVersion,\n groupName: baseDump.groupName,\n groupDescription: baseDump.groupDescription,\n modelBriefs: baseDump.modelBriefs,\n deviceType: baseDump.deviceType,\n executions,\n });\n\n const result = reportToMarkdown(mergedReport);\n\n const markdownFiles: string[] = [];\n const writtenScreenshots = new Set<string>();\n\n const mdPath = path.join(outputDir, 'report.md');\n writeFileSync(mdPath, result.markdown, 'utf-8');\n markdownFiles.push(mdPath);\n\n for (const attachment of result.attachments) {\n writeAttachmentFromReport(attachment, {\n htmlPath,\n screenshotsDir,\n writtenFiles: writtenScreenshots,\n });\n }\n\n return {\n markdownFiles,\n screenshotFiles: Array.from(writtenScreenshots)\n .sort()\n .map((f) => path.join(screenshotsDir, f)),\n };\n}\n\nfunction resolveReportHtmlPath(htmlPath: string): string {\n const normalizedPath = path.resolve(htmlPath);\n\n if (!existsSync(normalizedPath)) {\n throw new Error(`report-tool: --htmlPath does not exist: ${htmlPath}`);\n }\n\n const stats = statSync(normalizedPath);\n if (!stats.isDirectory()) {\n return normalizedPath;\n }\n\n const indexHtmlPath = path.join(normalizedPath, 'index.html');\n if (!existsSync(indexHtmlPath)) {\n throw new Error(\n `report-tool: \"${htmlPath}\" is not an HTML report file, and no index.html was found under this directory.`,\n );\n }\n\n return indexHtmlPath;\n}\n\nexport function splitReportFile(options: SplitReportFileOptions): {\n executionJsonFiles: string[];\n screenshotFiles: string[];\n} {\n const { htmlPath, outputDir } = options;\n if (!htmlPath) {\n throw new Error('splitReportFile: htmlPath is required');\n }\n\n if (!outputDir) {\n throw new Error('splitReportFile: outputDir is required');\n }\n\n const resolvedHtmlPath = resolveReportHtmlPath(htmlPath);\n return splitReportHtmlByExecution({\n htmlPath: resolvedHtmlPath,\n outputDir,\n });\n}\n\nexport async function reportFileToMarkdown(\n options: ReportFileToMarkdownOptions,\n): Promise<{ markdownFiles: string[]; screenshotFiles: string[] }> {\n const { htmlPath, outputDir } = options;\n if (!htmlPath) {\n throw new Error('reportFileToMarkdown: htmlPath is required');\n }\n\n if (!outputDir) {\n throw new Error('reportFileToMarkdown: outputDir is required');\n }\n\n const resolvedHtmlPath = resolveReportHtmlPath(htmlPath);\n return markdownFromReport(resolvedHtmlPath, outputDir);\n}\n\nconst TEST_STATUS_VALUES: ReadonlySet<TestStatus> = new Set<TestStatus>([\n 'passed',\n 'failed',\n 'timedOut',\n 'skipped',\n 'interrupted',\n]);\n\nconst FAILING_TEST_STATUSES: ReadonlySet<TestStatus> = new Set<TestStatus>([\n 'failed',\n 'timedOut',\n 'interrupted',\n]);\n\n/**\n * Reuse a `playwright_test_status` already recorded on the source report's dump\n * scripts (e.g. a Playwright-generated report carries the precise\n * timedOut/skipped/interrupted status). Returns undefined when the source has\n * no such attribute, so the caller can fall back to deriving from the dump.\n *\n * A single source report may bundle several executions (e.g. an already-merged\n * report), so surface a failing status if any execution failed — mirroring\n * `deriveCaseStatus`'s any-failure-wins semantics rather than taking the first\n * script's status and masking later failures.\n */\nfunction readSourceTestStatus(htmlPath: string): TestStatus | undefined {\n const recorded: TestStatus[] = [];\n for (const { openTag } of extractAllDumpScriptsSync(htmlPath)) {\n const match = openTag.match(/playwright_test_status=\"([^\"]*)\"/);\n if (!match) continue;\n const status = decodeURIComponent(match[1]) as TestStatus;\n if (TEST_STATUS_VALUES.has(status)) {\n recorded.push(status);\n }\n }\n if (recorded.length === 0) return undefined;\n return recorded.find((s) => FAILING_TEST_STATUSES.has(s)) ?? recorded[0];\n}\n\nfunction deriveReportAttributesFromHtml(\n htmlPath: string,\n index: number,\n): ReportFileAttributes {\n const fallbackId = `${path.basename(path.dirname(htmlPath)) || path.basename(htmlPath, path.extname(htmlPath))}-${index + 1}`;\n const runnerDump = extractTestRunReportDumpSync(htmlPath);\n try {\n const { baseDump, executions } = collectDedupedExecutions(htmlPath);\n // Prefer a status the source report already recorded (keeps Playwright's\n // precise timedOut/skipped/interrupted); otherwise infer it from the dump\n // so a failing case is not silently merged in as passed.\n const recordedStatus = readSourceTestStatus(htmlPath);\n const testStatus =\n recordedStatus && FAILING_TEST_STATUSES.has(recordedStatus)\n ? recordedStatus\n : runnerDump?.status === 'failed'\n ? 'failed'\n : (recordedStatus ??\n (runnerDump ? 'passed' : deriveCaseStatus(executions)));\n return {\n testId: fallbackId,\n testTitle: baseDump.groupName || fallbackId,\n testDescription: baseDump.groupDescription ?? '',\n testDuration:\n runnerDump?.durationMs ??\n collectReportSummary({ executions }).timing.wallTimeMs ??\n 0,\n testStatus,\n };\n } catch {\n return {\n testId: fallbackId,\n testTitle: fallbackId,\n testDescription: '',\n testDuration: 0,\n testStatus: runnerDump?.status === 'failed' ? 'failed' : 'passed',\n };\n }\n}\n\nexport function mergeReportFiles(\n options: MergeReportFilesOptions,\n): MergeReportFilesResult {\n const { htmlPaths, outputDir, outputName, overwrite = false } = options;\n if (!htmlPaths || htmlPaths.length === 0) {\n throw new Error('mergeReportFiles: htmlPaths is required');\n }\n\n const resolvedPaths = htmlPaths.map((p) => resolveReportHtmlPath(p));\n\n const tool = new ReportMergingTool();\n resolvedPaths.forEach((htmlPath, index) => {\n tool.append({\n reportFilePath: htmlPath,\n reportAttributes: deriveReportAttributesFromHtml(htmlPath, index),\n });\n });\n\n const mergedReportPath = tool.mergeReports(outputName ?? 'AUTO', {\n overwrite,\n outputDir,\n });\n\n if (!mergedReportPath) {\n throw new Error('mergeReportFiles: failed to produce a merged report');\n }\n\n return { mergedReportPath };\n}\n\nfunction normalizeHtmlReportArg(raw: unknown): string[] | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (Array.isArray(raw)) {\n return raw.filter(\n (p): p is string => typeof p === 'string' && p.length > 0,\n );\n }\n if (typeof raw === 'string') {\n const trimmed = raw.trim();\n return trimmed ? [trimmed] : [];\n }\n return undefined;\n}\n\nconst reportCommandDefinition: ReportCliCommandDefinition = {\n name: 'report-tool',\n description:\n 'Transform Midscene report artifacts, including splitting executions, converting to markdown, and merging multiple reports.',\n schema: {\n action: z\n .enum(['split', 'to-markdown', 'merge-html'])\n .optional()\n .describe(\n 'Report action to run. Supports: split, to-markdown, merge-html. Defaults to split.',\n ),\n htmlPath: z\n .string()\n .optional()\n .describe(\n 'Input report HTML path (e.g. ./report/index.html). Used by split and to-markdown.',\n ),\n htmlReport: z\n .union([z.string(), z.array(z.string())])\n .optional()\n .describe(\n 'Input report HTML path for the merge action. Repeat the flag to merge multiple reports (e.g. --htmlReport ./a/index.html --htmlReport ./b.html).',\n ),\n outputDir: z\n .string()\n .optional()\n .describe(\n 'Output directory for generated report artifacts. For merge, defaults to the Midscene report directory.',\n ),\n outputName: z\n .string()\n .optional()\n .describe(\n 'Output report file/directory name (without .html) for the merge action. Defaults to an auto-generated name.',\n ),\n overwrite: z\n .union([z.boolean(), z.string()])\n .optional()\n .describe(\n 'Overwrite the existing merged report file if present (merge action only).',\n ),\n },\n handler: async (args) => {\n const {\n action = 'split',\n htmlPath,\n htmlReport,\n outputDir,\n outputName,\n overwrite,\n } = args as {\n action?: string;\n htmlPath?: string;\n htmlReport?: unknown;\n outputDir?: string;\n outputName?: string;\n overwrite?: unknown;\n };\n if (\n action !== 'split' &&\n action !== 'to-markdown' &&\n action !== 'merge-html'\n ) {\n throw new Error(\n `report-tool: unsupported --action value \"${action}\". Currently supported: split, to-markdown, merge-html`,\n );\n }\n\n if (action === 'merge-html') {\n const paths = normalizeHtmlReportArg(htmlReport);\n if (!paths || paths.length === 0) {\n throw new Error(\n 'report-tool: --htmlReport is required for action \"merge-html\". Repeat --htmlReport for each report (e.g. --htmlReport ./a/index.html --htmlReport ./b.html).',\n );\n }\n\n const overwriteFlag =\n overwrite === true || overwrite === 'true' || overwrite === '1';\n\n const result = mergeReportFiles({\n htmlPaths: paths,\n outputDir,\n outputName,\n overwrite: overwriteFlag,\n });\n\n return {\n isError: false,\n content: [\n {\n type: 'text',\n text: `Merged ${paths.length} report(s) into ${result.mergedReportPath}`,\n },\n ],\n };\n }\n\n if (!htmlPath) {\n throw new Error('report-tool: --htmlPath is required');\n }\n\n if (!outputDir) {\n throw new Error('report-tool: --outputDir is required');\n }\n\n if (action === 'to-markdown') {\n const result = await reportFileToMarkdown({\n htmlPath,\n outputDir,\n });\n return {\n isError: false,\n content: [\n {\n type: 'text',\n text: `Markdown export completed. Generated ${result.markdownFiles.length} markdown file(s) and ${result.screenshotFiles.length} screenshot(s). Output path: ${outputDir}`,\n },\n ],\n };\n }\n\n const result = splitReportFile({\n htmlPath,\n outputDir,\n });\n\n return {\n isError: false,\n content: [\n {\n type: 'text',\n text: `Report split completed. Generated ${result.executionJsonFiles.length} execution JSON files and ${result.screenshotFiles.length} screenshots. Output path: ${outputDir}`,\n },\n ],\n };\n },\n};\n\nexport function createReportCliCommands(): ReportCliCommandEntry[] {\n return [\n {\n name: 'report-tool',\n def: reportCommandDefinition,\n },\n ];\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","writeAttachmentFromReport","attachment","opts","suggestedFileName","id","mimeType","absolutePath","path","resolved","resolveScreenshotSource","rawBase64","writeFileSync","Buffer","existsSync","Error","copyFileSync","markdownFromReport","htmlPath","outputDir","screenshotsDir","mkdirSync","baseDump","executions","collectDedupedExecutions","mergedReport","ReportActionDump","result","reportToMarkdown","markdownFiles","writtenScreenshots","Set","mdPath","Array","f","resolveReportHtmlPath","normalizedPath","stats","statSync","indexHtmlPath","splitReportFile","options","resolvedHtmlPath","splitReportHtmlByExecution","reportFileToMarkdown","TEST_STATUS_VALUES","FAILING_TEST_STATUSES","readSourceTestStatus","recorded","openTag","extractAllDumpScriptsSync","match","status","decodeURIComponent","s","deriveReportAttributesFromHtml","index","fallbackId","runnerDump","extractTestRunReportDumpSync","recordedStatus","testStatus","deriveCaseStatus","collectReportSummary","mergeReportFiles","htmlPaths","outputName","overwrite","resolvedPaths","p","tool","ReportMergingTool","mergedReportPath","normalizeHtmlReportArg","raw","trimmed","reportCommandDefinition","z","args","action","htmlReport","paths","overwriteFlag","createReportCliCommands"],"mappings":"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"}
1
+ {"version":3,"file":"report-cli.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report-cli.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import {\n copyFileSync,\n existsSync,\n mkdirSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport * as path from 'node:path';\nimport { z } from 'zod';\nimport {\n readReportRunnerDump,\n streamReportDumpScripts,\n} from './dump/report-artifact-reader';\nimport { resolveScreenshotSource } from './dump/screenshot-store';\nimport { deriveCaseStatus } from './dump/task-status';\nimport {\n ReportMergingTool,\n collectDedupedExecutions,\n splitReportHtmlByExecution,\n} from './report';\nimport { reportToMarkdown } from './report-markdown';\nimport type { MarkdownAttachment } from './report-markdown';\nimport { collectReportSummary } from './report-stats';\nimport type { ReportFileAttributes, TestStatus } from './types';\nimport { ReportActionDump } from './types';\n\ntype ReportCliToolResult = {\n isError: boolean;\n content: Array<{\n type: 'text';\n text: string;\n }>;\n};\n\ntype ReportCliSchema = Record<string, z.ZodTypeAny>;\n\nexport interface ReportCliCommandDefinition {\n name: string;\n description: string;\n schema: ReportCliSchema;\n handler: (args: Record<string, unknown>) => Promise<ReportCliToolResult>;\n}\n\nexport interface ReportCliCommandEntry {\n name: string;\n def: ReportCliCommandDefinition;\n}\n\nexport type ConsumeReportFileAction = 'split' | 'to-markdown' | 'merge-html';\n\nexport interface ConsumeReportFileOptions {\n htmlPath: string;\n outputDir: string;\n}\n\nexport type SplitReportFileOptions = ConsumeReportFileOptions;\nexport type ReportFileToMarkdownOptions = ConsumeReportFileOptions;\n\nexport interface MergeReportFilesOptions {\n htmlPaths: string[];\n outputDir?: string;\n outputName?: string;\n overwrite?: boolean;\n}\n\nexport interface MergeReportFilesResult {\n mergedReportPath: string;\n}\n\nfunction writeAttachmentFromReport(\n attachment: MarkdownAttachment,\n opts: {\n htmlPath: string;\n screenshotsDir: string;\n writtenFiles: Set<string>;\n },\n): void {\n const { suggestedFileName, id, mimeType } = attachment;\n if (opts.writtenFiles.has(suggestedFileName)) return;\n\n const absolutePath = path.join(opts.screenshotsDir, suggestedFileName);\n\n const resolved = resolveScreenshotSource(attachment.sourceRef ?? null, {\n reportPath: opts.htmlPath,\n fallbackId: id,\n fallbackMimeType: (mimeType || 'image/png') as 'image/png' | 'image/jpeg',\n });\n\n if (resolved.type === 'data-uri') {\n const rawBase64 = resolved.dataUri.replace(\n /^data:image\\/[a-zA-Z+]+;base64,/,\n '',\n );\n writeFileSync(absolutePath, Buffer.from(rawBase64, 'base64'));\n opts.writtenFiles.add(suggestedFileName);\n return;\n }\n\n if (!existsSync(resolved.filePath)) {\n throw new Error(\n `Cannot resolve screenshot \"${id}\" for markdown attachment from ${opts.htmlPath}`,\n );\n }\n\n copyFileSync(resolved.filePath, absolutePath);\n opts.writtenFiles.add(suggestedFileName);\n}\n\nasync function markdownFromReport(\n htmlPath: string,\n outputDir: string,\n): Promise<{ markdownFiles: string[]; screenshotFiles: string[] }> {\n const screenshotsDir = path.join(outputDir, 'screenshots');\n\n mkdirSync(outputDir, { recursive: true });\n mkdirSync(screenshotsDir, { recursive: true });\n\n const { baseDump, executions } = collectDedupedExecutions(htmlPath);\n\n const mergedReport = new ReportActionDump({\n sdkVersion: baseDump.sdkVersion,\n groupName: baseDump.groupName,\n groupDescription: baseDump.groupDescription,\n modelBriefs: baseDump.modelBriefs,\n deviceType: baseDump.deviceType,\n executions,\n });\n\n const result = reportToMarkdown(mergedReport);\n\n const markdownFiles: string[] = [];\n const writtenScreenshots = new Set<string>();\n\n const mdPath = path.join(outputDir, 'report.md');\n writeFileSync(mdPath, result.markdown, 'utf-8');\n markdownFiles.push(mdPath);\n\n for (const attachment of result.attachments) {\n writeAttachmentFromReport(attachment, {\n htmlPath,\n screenshotsDir,\n writtenFiles: writtenScreenshots,\n });\n }\n\n return {\n markdownFiles,\n screenshotFiles: Array.from(writtenScreenshots)\n .sort()\n .map((f) => path.join(screenshotsDir, f)),\n };\n}\n\nfunction resolveReportHtmlPath(htmlPath: string): string {\n const normalizedPath = path.resolve(htmlPath);\n\n if (!existsSync(normalizedPath)) {\n throw new Error(`report-tool: --htmlPath does not exist: ${htmlPath}`);\n }\n\n const stats = statSync(normalizedPath);\n if (!stats.isDirectory()) {\n return normalizedPath;\n }\n\n const indexHtmlPath = path.join(normalizedPath, 'index.html');\n if (!existsSync(indexHtmlPath)) {\n throw new Error(\n `report-tool: \"${htmlPath}\" is not an HTML report file, and no index.html was found under this directory.`,\n );\n }\n\n return indexHtmlPath;\n}\n\nexport function splitReportFile(options: SplitReportFileOptions): {\n executionJsonFiles: string[];\n screenshotFiles: string[];\n} {\n const { htmlPath, outputDir } = options;\n if (!htmlPath) {\n throw new Error('splitReportFile: htmlPath is required');\n }\n\n if (!outputDir) {\n throw new Error('splitReportFile: outputDir is required');\n }\n\n const resolvedHtmlPath = resolveReportHtmlPath(htmlPath);\n return splitReportHtmlByExecution({\n htmlPath: resolvedHtmlPath,\n outputDir,\n });\n}\n\nexport async function reportFileToMarkdown(\n options: ReportFileToMarkdownOptions,\n): Promise<{ markdownFiles: string[]; screenshotFiles: string[] }> {\n const { htmlPath, outputDir } = options;\n if (!htmlPath) {\n throw new Error('reportFileToMarkdown: htmlPath is required');\n }\n\n if (!outputDir) {\n throw new Error('reportFileToMarkdown: outputDir is required');\n }\n\n const resolvedHtmlPath = resolveReportHtmlPath(htmlPath);\n return markdownFromReport(resolvedHtmlPath, outputDir);\n}\n\nconst TEST_STATUS_VALUES: ReadonlySet<TestStatus> = new Set<TestStatus>([\n 'passed',\n 'failed',\n 'timedOut',\n 'skipped',\n 'interrupted',\n]);\n\nconst FAILING_TEST_STATUSES: ReadonlySet<TestStatus> = new Set<TestStatus>([\n 'failed',\n 'timedOut',\n 'interrupted',\n]);\n\n/**\n * Reuse a `playwright_test_status` already recorded on the source report's dump\n * scripts (e.g. a Playwright-generated report carries the precise\n * timedOut/skipped/interrupted status). Returns undefined when the source has\n * no such attribute, so the caller can fall back to deriving from the dump.\n *\n * A single source report may bundle several executions (e.g. an already-merged\n * report), so surface a failing status if any execution failed — mirroring\n * `deriveCaseStatus`'s any-failure-wins semantics rather than taking the first\n * script's status and masking later failures.\n */\nfunction readSourceTestStatus(htmlPath: string): TestStatus | undefined {\n const recorded: TestStatus[] = [];\n streamReportDumpScripts(htmlPath, ({ openTag }) => {\n const match = openTag.match(/playwright_test_status=\"([^\"]*)\"/);\n if (!match) return false;\n const status = decodeURIComponent(match[1]) as TestStatus;\n if (TEST_STATUS_VALUES.has(status)) {\n recorded.push(status);\n }\n return false;\n });\n if (recorded.length === 0) return undefined;\n return recorded.find((s) => FAILING_TEST_STATUSES.has(s)) ?? recorded[0];\n}\n\nfunction deriveReportAttributesFromHtml(\n htmlPath: string,\n index: number,\n): ReportFileAttributes {\n const fallbackId = `${path.basename(path.dirname(htmlPath)) || path.basename(htmlPath, path.extname(htmlPath))}-${index + 1}`;\n const runnerDump = readReportRunnerDump(htmlPath);\n const recordedStatus = readSourceTestStatus(htmlPath);\n try {\n const { baseDump, executions } = collectDedupedExecutions(htmlPath);\n // Prefer a status the source report already recorded (keeps Playwright's\n // precise timedOut/skipped/interrupted); otherwise infer it from the dump\n // so a failing case is not silently merged in as passed.\n const testStatus =\n recordedStatus && FAILING_TEST_STATUSES.has(recordedStatus)\n ? recordedStatus\n : runnerDump?.status === 'failed'\n ? 'failed'\n : (recordedStatus ??\n (runnerDump ? 'passed' : deriveCaseStatus(executions)));\n return {\n testId: fallbackId,\n testTitle: baseDump.groupName || fallbackId,\n testDescription: baseDump.groupDescription ?? '',\n testDuration:\n runnerDump?.durationMs ??\n collectReportSummary({ executions }).timing.wallTimeMs ??\n 0,\n testStatus,\n };\n } catch {\n return {\n testId: fallbackId,\n testTitle: fallbackId,\n testDescription: '',\n testDuration: 0,\n testStatus:\n recordedStatus && FAILING_TEST_STATUSES.has(recordedStatus)\n ? recordedStatus\n : runnerDump?.status === 'failed'\n ? 'failed'\n : (recordedStatus ?? 'passed'),\n };\n }\n}\n\nexport function mergeReportFiles(\n options: MergeReportFilesOptions,\n): MergeReportFilesResult {\n const { htmlPaths, outputDir, outputName, overwrite = false } = options;\n if (!htmlPaths || htmlPaths.length === 0) {\n throw new Error('mergeReportFiles: htmlPaths is required');\n }\n\n const resolvedPaths = htmlPaths.map((p) => resolveReportHtmlPath(p));\n\n const tool = new ReportMergingTool();\n resolvedPaths.forEach((htmlPath, index) => {\n tool.append({\n reportFilePath: htmlPath,\n reportAttributes: deriveReportAttributesFromHtml(htmlPath, index),\n });\n });\n\n const mergedReportPath = tool.mergeReports(outputName ?? 'AUTO', {\n overwrite,\n outputDir,\n });\n\n if (!mergedReportPath) {\n throw new Error('mergeReportFiles: failed to produce a merged report');\n }\n\n return { mergedReportPath };\n}\n\nfunction normalizeHtmlReportArg(raw: unknown): string[] | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (Array.isArray(raw)) {\n return raw.filter(\n (p): p is string => typeof p === 'string' && p.length > 0,\n );\n }\n if (typeof raw === 'string') {\n const trimmed = raw.trim();\n return trimmed ? [trimmed] : [];\n }\n return undefined;\n}\n\nconst reportCommandDefinition: ReportCliCommandDefinition = {\n name: 'report-tool',\n description:\n 'Transform Midscene report artifacts, including splitting executions, converting to markdown, and merging multiple reports.',\n schema: {\n action: z\n .enum(['split', 'to-markdown', 'merge-html'])\n .optional()\n .describe(\n 'Report action to run. Supports: split, to-markdown, merge-html. Defaults to split.',\n ),\n htmlPath: z\n .string()\n .optional()\n .describe(\n 'Input report HTML path (e.g. ./report/index.html). Used by split and to-markdown.',\n ),\n htmlReport: z\n .union([z.string(), z.array(z.string())])\n .optional()\n .describe(\n 'Input report HTML path for the merge action. Repeat the flag to merge multiple reports (e.g. --htmlReport ./a/index.html --htmlReport ./b.html).',\n ),\n outputDir: z\n .string()\n .optional()\n .describe(\n 'Output directory for generated report artifacts. For merge, defaults to the Midscene report directory.',\n ),\n outputName: z\n .string()\n .optional()\n .describe(\n 'Output report file/directory name (without .html) for the merge action. Defaults to an auto-generated name.',\n ),\n overwrite: z\n .union([z.boolean(), z.string()])\n .optional()\n .describe(\n 'Overwrite the existing merged report file if present (merge action only).',\n ),\n },\n handler: async (args) => {\n const {\n action = 'split',\n htmlPath,\n htmlReport,\n outputDir,\n outputName,\n overwrite,\n } = args as {\n action?: string;\n htmlPath?: string;\n htmlReport?: unknown;\n outputDir?: string;\n outputName?: string;\n overwrite?: unknown;\n };\n if (\n action !== 'split' &&\n action !== 'to-markdown' &&\n action !== 'merge-html'\n ) {\n throw new Error(\n `report-tool: unsupported --action value \"${action}\". Currently supported: split, to-markdown, merge-html`,\n );\n }\n\n if (action === 'merge-html') {\n const paths = normalizeHtmlReportArg(htmlReport);\n if (!paths || paths.length === 0) {\n throw new Error(\n 'report-tool: --htmlReport is required for action \"merge-html\". Repeat --htmlReport for each report (e.g. --htmlReport ./a/index.html --htmlReport ./b.html).',\n );\n }\n\n const overwriteFlag =\n overwrite === true || overwrite === 'true' || overwrite === '1';\n\n const result = mergeReportFiles({\n htmlPaths: paths,\n outputDir,\n outputName,\n overwrite: overwriteFlag,\n });\n\n return {\n isError: false,\n content: [\n {\n type: 'text',\n text: `Merged ${paths.length} report(s) into ${result.mergedReportPath}`,\n },\n ],\n };\n }\n\n if (!htmlPath) {\n throw new Error('report-tool: --htmlPath is required');\n }\n\n if (!outputDir) {\n throw new Error('report-tool: --outputDir is required');\n }\n\n if (action === 'to-markdown') {\n const result = await reportFileToMarkdown({\n htmlPath,\n outputDir,\n });\n return {\n isError: false,\n content: [\n {\n type: 'text',\n text: `Markdown export completed. Generated ${result.markdownFiles.length} markdown file(s) and ${result.screenshotFiles.length} screenshot(s). Output path: ${outputDir}`,\n },\n ],\n };\n }\n\n const result = splitReportFile({\n htmlPath,\n outputDir,\n });\n\n return {\n isError: false,\n content: [\n {\n type: 'text',\n text: `Report split completed. Generated ${result.executionJsonFiles.length} execution JSON files and ${result.screenshotFiles.length} screenshots. Output path: ${outputDir}`,\n },\n ],\n };\n },\n};\n\nexport function createReportCliCommands(): ReportCliCommandEntry[] {\n return [\n {\n name: 'report-tool',\n def: reportCommandDefinition,\n },\n ];\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","writeAttachmentFromReport","attachment","opts","suggestedFileName","id","mimeType","absolutePath","path","resolved","resolveScreenshotSource","rawBase64","writeFileSync","Buffer","existsSync","Error","copyFileSync","markdownFromReport","htmlPath","outputDir","screenshotsDir","mkdirSync","baseDump","executions","collectDedupedExecutions","mergedReport","ReportActionDump","result","reportToMarkdown","markdownFiles","writtenScreenshots","Set","mdPath","Array","f","resolveReportHtmlPath","normalizedPath","stats","statSync","indexHtmlPath","splitReportFile","options","resolvedHtmlPath","splitReportHtmlByExecution","reportFileToMarkdown","TEST_STATUS_VALUES","FAILING_TEST_STATUSES","readSourceTestStatus","recorded","streamReportDumpScripts","openTag","match","status","decodeURIComponent","s","deriveReportAttributesFromHtml","index","fallbackId","runnerDump","readReportRunnerDump","recordedStatus","testStatus","deriveCaseStatus","collectReportSummary","mergeReportFiles","htmlPaths","outputName","overwrite","resolvedPaths","p","tool","ReportMergingTool","mergedReportPath","normalizeHtmlReportArg","raw","trimmed","reportCommandDefinition","z","args","action","htmlReport","paths","overwriteFlag","createReportCliCommands"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;;;;AC+DA,SAASI,0BACPC,UAA8B,EAC9BC,IAIC;IAED,MAAM,EAAEC,iBAAiB,EAAEC,EAAE,EAAEC,QAAQ,EAAE,GAAGJ;IAC5C,IAAIC,KAAK,YAAY,CAAC,GAAG,CAACC,oBAAoB;IAE9C,MAAMG,eAAeC,mCAAAA,IAAS,CAACL,KAAK,cAAc,EAAEC;IAEpD,MAAMK,WAAWC,AAAAA,IAAAA,oCAAAA,uBAAAA,AAAAA,EAAwBR,WAAW,SAAS,IAAI,MAAM;QACrE,YAAYC,KAAK,QAAQ;QACzB,YAAYE;QACZ,kBAAmBC,YAAY;IACjC;IAEA,IAAIG,AAAkB,eAAlBA,SAAS,IAAI,EAAiB;QAChC,MAAME,YAAYF,SAAS,OAAO,CAAC,OAAO,CACxC,mCACA;QAEFG,IAAAA,iCAAAA,aAAAA,AAAAA,EAAcL,cAAcM,OAAO,IAAI,CAACF,WAAW;QACnDR,KAAK,YAAY,CAAC,GAAG,CAACC;QACtB;IACF;IAEA,IAAI,CAACU,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAWL,SAAS,QAAQ,GAC/B,MAAM,IAAIM,MACR,CAAC,2BAA2B,EAAEV,GAAG,+BAA+B,EAAEF,KAAK,QAAQ,EAAE;IAIrFa,IAAAA,iCAAAA,YAAAA,AAAAA,EAAaP,SAAS,QAAQ,EAAEF;IAChCJ,KAAK,YAAY,CAAC,GAAG,CAACC;AACxB;AAEA,eAAea,mBACbC,QAAgB,EAChBC,SAAiB;IAEjB,MAAMC,iBAAiBZ,mCAAAA,IAAS,CAACW,WAAW;IAE5CE,IAAAA,iCAAAA,SAAAA,AAAAA,EAAUF,WAAW;QAAE,WAAW;IAAK;IACvCE,IAAAA,iCAAAA,SAAAA,AAAAA,EAAUD,gBAAgB;QAAE,WAAW;IAAK;IAE5C,MAAM,EAAEE,QAAQ,EAAEC,UAAU,EAAE,GAAGC,AAAAA,IAAAA,mCAAAA,wBAAAA,AAAAA,EAAyBN;IAE1D,MAAMO,eAAe,IAAIC,kCAAAA,gBAAgBA,CAAC;QACxC,YAAYJ,SAAS,UAAU;QAC/B,WAAWA,SAAS,SAAS;QAC7B,kBAAkBA,SAAS,gBAAgB;QAC3C,aAAaA,SAAS,WAAW;QACjC,YAAYA,SAAS,UAAU;QAC/BC;IACF;IAEA,MAAMI,SAASC,AAAAA,IAAAA,4CAAAA,gBAAAA,AAAAA,EAAiBH;IAEhC,MAAMI,gBAA0B,EAAE;IAClC,MAAMC,qBAAqB,IAAIC;IAE/B,MAAMC,SAASxB,mCAAAA,IAAS,CAACW,WAAW;IACpCP,IAAAA,iCAAAA,aAAAA,AAAAA,EAAcoB,QAAQL,OAAO,QAAQ,EAAE;IACvCE,cAAc,IAAI,CAACG;IAEnB,KAAK,MAAM9B,cAAcyB,OAAO,WAAW,CACzC1B,0BAA0BC,YAAY;QACpCgB;QACAE;QACA,cAAcU;IAChB;IAGF,OAAO;QACLD;QACA,iBAAiBI,MAAM,IAAI,CAACH,oBACzB,IAAI,GACJ,GAAG,CAAC,CAACI,IAAM1B,mCAAAA,IAAS,CAACY,gBAAgBc;IAC1C;AACF;AAEA,SAASC,sBAAsBjB,QAAgB;IAC7C,MAAMkB,iBAAiB5B,mCAAAA,OAAY,CAACU;IAEpC,IAAI,CAACJ,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAWsB,iBACd,MAAM,IAAIrB,MAAM,CAAC,wCAAwC,EAAEG,UAAU;IAGvE,MAAMmB,QAAQC,AAAAA,IAAAA,iCAAAA,QAAAA,AAAAA,EAASF;IACvB,IAAI,CAACC,MAAM,WAAW,IACpB,OAAOD;IAGT,MAAMG,gBAAgB/B,mCAAAA,IAAS,CAAC4B,gBAAgB;IAChD,IAAI,CAACtB,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAWyB,gBACd,MAAM,IAAIxB,MACR,CAAC,cAAc,EAAEG,SAAS,+EAA+E,CAAC;IAI9G,OAAOqB;AACT;AAEO,SAASC,gBAAgBC,OAA+B;IAI7D,MAAM,EAAEvB,QAAQ,EAAEC,SAAS,EAAE,GAAGsB;IAChC,IAAI,CAACvB,UACH,MAAM,IAAIH,MAAM;IAGlB,IAAI,CAACI,WACH,MAAM,IAAIJ,MAAM;IAGlB,MAAM2B,mBAAmBP,sBAAsBjB;IAC/C,OAAOyB,AAAAA,IAAAA,mCAAAA,0BAAAA,AAAAA,EAA2B;QAChC,UAAUD;QACVvB;IACF;AACF;AAEO,eAAeyB,qBACpBH,OAAoC;IAEpC,MAAM,EAAEvB,QAAQ,EAAEC,SAAS,EAAE,GAAGsB;IAChC,IAAI,CAACvB,UACH,MAAM,IAAIH,MAAM;IAGlB,IAAI,CAACI,WACH,MAAM,IAAIJ,MAAM;IAGlB,MAAM2B,mBAAmBP,sBAAsBjB;IAC/C,OAAOD,mBAAmByB,kBAAkBvB;AAC9C;AAEA,MAAM0B,qBAA8C,IAAId,IAAgB;IACtE;IACA;IACA;IACA;IACA;CACD;AAED,MAAMe,wBAAiD,IAAIf,IAAgB;IACzE;IACA;IACA;CACD;AAaD,SAASgB,qBAAqB7B,QAAgB;IAC5C,MAAM8B,WAAyB,EAAE;IACjCC,IAAAA,0CAAAA,uBAAAA,AAAAA,EAAwB/B,UAAU,CAAC,EAAEgC,OAAO,EAAE;QAC5C,MAAMC,QAAQD,QAAQ,KAAK,CAAC;QAC5B,IAAI,CAACC,OAAO,OAAO;QACnB,MAAMC,SAASC,mBAAmBF,KAAK,CAAC,EAAE;QAC1C,IAAIN,mBAAmB,GAAG,CAACO,SACzBJ,SAAS,IAAI,CAACI;QAEhB,OAAO;IACT;IACA,IAAIJ,AAAoB,MAApBA,SAAS,MAAM,EAAQ;IAC3B,OAAOA,SAAS,IAAI,CAAC,CAACM,IAAMR,sBAAsB,GAAG,CAACQ,OAAON,QAAQ,CAAC,EAAE;AAC1E;AAEA,SAASO,+BACPrC,QAAgB,EAChBsC,KAAa;IAEb,MAAMC,aAAa,GAAGjD,mCAAAA,QAAa,CAACA,mCAAAA,OAAY,CAACU,cAAcV,mCAAAA,QAAa,CAACU,UAAUV,mCAAAA,OAAY,CAACU,WAAW,CAAC,EAAEsC,QAAQ,GAAG;IAC7H,MAAME,aAAaC,AAAAA,IAAAA,0CAAAA,oBAAAA,AAAAA,EAAqBzC;IACxC,MAAM0C,iBAAiBb,qBAAqB7B;IAC5C,IAAI;QACF,MAAM,EAAEI,QAAQ,EAAEC,UAAU,EAAE,GAAGC,AAAAA,IAAAA,mCAAAA,wBAAAA,AAAAA,EAAyBN;QAI1D,MAAM2C,aACJD,kBAAkBd,sBAAsB,GAAG,CAACc,kBACxCA,iBACAF,YAAY,WAAW,WACrB,WACCE,kBACAF,CAAAA,aAAa,WAAWI,AAAAA,IAAAA,+BAAAA,gBAAAA,AAAAA,EAAiBvC,WAAU;QAC5D,OAAO;YACL,QAAQkC;YACR,WAAWnC,SAAS,SAAS,IAAImC;YACjC,iBAAiBnC,SAAS,gBAAgB,IAAI;YAC9C,cACEoC,YAAY,cACZK,AAAAA,IAAAA,yCAAAA,oBAAAA,AAAAA,EAAqB;gBAAExC;YAAW,GAAG,MAAM,CAAC,UAAU,IACtD;YACFsC;QACF;IACF,EAAE,OAAM;QACN,OAAO;YACL,QAAQJ;YACR,WAAWA;YACX,iBAAiB;YACjB,cAAc;YACd,YACEG,kBAAkBd,sBAAsB,GAAG,CAACc,kBACxCA,iBACAF,YAAY,WAAW,WACrB,WACCE,kBAAkB;QAC7B;IACF;AACF;AAEO,SAASI,iBACdvB,OAAgC;IAEhC,MAAM,EAAEwB,SAAS,EAAE9C,SAAS,EAAE+C,UAAU,EAAEC,YAAY,KAAK,EAAE,GAAG1B;IAChE,IAAI,CAACwB,aAAaA,AAAqB,MAArBA,UAAU,MAAM,EAChC,MAAM,IAAIlD,MAAM;IAGlB,MAAMqD,gBAAgBH,UAAU,GAAG,CAAC,CAACI,IAAMlC,sBAAsBkC;IAEjE,MAAMC,OAAO,IAAIC,mCAAAA,iBAAiBA;IAClCH,cAAc,OAAO,CAAC,CAAClD,UAAUsC;QAC/Bc,KAAK,MAAM,CAAC;YACV,gBAAgBpD;YAChB,kBAAkBqC,+BAA+BrC,UAAUsC;QAC7D;IACF;IAEA,MAAMgB,mBAAmBF,KAAK,YAAY,CAACJ,cAAc,QAAQ;QAC/DC;QACAhD;IACF;IAEA,IAAI,CAACqD,kBACH,MAAM,IAAIzD,MAAM;IAGlB,OAAO;QAAEyD;IAAiB;AAC5B;AAEA,SAASC,uBAAuBC,GAAY;IAC1C,IAAIA,QAAAA,KAAmC;IACvC,IAAIzC,MAAM,OAAO,CAACyC,MAChB,OAAOA,IAAI,MAAM,CACf,CAACL,IAAmB,AAAa,YAAb,OAAOA,KAAkBA,EAAE,MAAM,GAAG;IAG5D,IAAI,AAAe,YAAf,OAAOK,KAAkB;QAC3B,MAAMC,UAAUD,IAAI,IAAI;QACxB,OAAOC,UAAU;YAACA;SAAQ,GAAG,EAAE;IACjC;AAEF;AAEA,MAAMC,0BAAsD;IAC1D,MAAM;IACN,aACE;IACF,QAAQ;QACN,QAAQC,6BAAAA,CAAAA,CAAAA,OACD,CAAC;YAAC;YAAS;YAAe;SAAa,EAC3C,QAAQ,GACR,QAAQ,CACP;QAEJ,UAAUA,6BAAAA,CAAAA,CAAAA,MACD,GACN,QAAQ,GACR,QAAQ,CACP;QAEJ,YAAYA,6BAAAA,CAAAA,CAAAA,KACJ,CAAC;YAACA,6BAAAA,CAAAA,CAAAA,MAAQ;YAAIA,6BAAAA,CAAAA,CAAAA,KAAO,CAACA,6BAAAA,CAAAA,CAAAA,MAAQ;SAAI,EACvC,QAAQ,GACR,QAAQ,CACP;QAEJ,WAAWA,6BAAAA,CAAAA,CAAAA,MACF,GACN,QAAQ,GACR,QAAQ,CACP;QAEJ,YAAYA,6BAAAA,CAAAA,CAAAA,MACH,GACN,QAAQ,GACR,QAAQ,CACP;QAEJ,WAAWA,6BAAAA,CAAAA,CAAAA,KACH,CAAC;YAACA,6BAAAA,CAAAA,CAAAA,OAAS;YAAIA,6BAAAA,CAAAA,CAAAA,MAAQ;SAAG,EAC/B,QAAQ,GACR,QAAQ,CACP;IAEN;IACA,SAAS,OAAOC;QACd,MAAM,EACJC,SAAS,OAAO,EAChB7D,QAAQ,EACR8D,UAAU,EACV7D,SAAS,EACT+C,UAAU,EACVC,SAAS,EACV,GAAGW;QAQJ,IACEC,AAAW,YAAXA,UACAA,AAAW,kBAAXA,UACAA,AAAW,iBAAXA,QAEA,MAAM,IAAIhE,MACR,CAAC,yCAAyC,EAAEgE,OAAO,sDAAsD,CAAC;QAI9G,IAAIA,AAAW,iBAAXA,QAAyB;YAC3B,MAAME,QAAQR,uBAAuBO;YACrC,IAAI,CAACC,SAASA,AAAiB,MAAjBA,MAAM,MAAM,EACxB,MAAM,IAAIlE,MACR;YAIJ,MAAMmE,gBACJf,AAAc,SAAdA,aAAsBA,AAAc,WAAdA,aAAwBA,AAAc,QAAdA;YAEhD,MAAMxC,SAASqC,iBAAiB;gBAC9B,WAAWiB;gBACX9D;gBACA+C;gBACA,WAAWgB;YACb;YAEA,OAAO;gBACL,SAAS;gBACT,SAAS;oBACP;wBACE,MAAM;wBACN,MAAM,CAAC,OAAO,EAAED,MAAM,MAAM,CAAC,gBAAgB,EAAEtD,OAAO,gBAAgB,EAAE;oBAC1E;iBACD;YACH;QACF;QAEA,IAAI,CAACT,UACH,MAAM,IAAIH,MAAM;QAGlB,IAAI,CAACI,WACH,MAAM,IAAIJ,MAAM;QAGlB,IAAIgE,AAAW,kBAAXA,QAA0B;YAC5B,MAAMpD,SAAS,MAAMiB,qBAAqB;gBACxC1B;gBACAC;YACF;YACA,OAAO;gBACL,SAAS;gBACT,SAAS;oBACP;wBACE,MAAM;wBACN,MAAM,CAAC,qCAAqC,EAAEQ,OAAO,aAAa,CAAC,MAAM,CAAC,sBAAsB,EAAEA,OAAO,eAAe,CAAC,MAAM,CAAC,6BAA6B,EAAER,WAAW;oBAC5K;iBACD;YACH;QACF;QAEA,MAAMQ,SAASa,gBAAgB;YAC7BtB;YACAC;QACF;QAEA,OAAO;YACL,SAAS;YACT,SAAS;gBACP;oBACE,MAAM;oBACN,MAAM,CAAC,kCAAkC,EAAEQ,OAAO,kBAAkB,CAAC,MAAM,CAAC,0BAA0B,EAAEA,OAAO,eAAe,CAAC,MAAM,CAAC,2BAA2B,EAAER,WAAW;gBAChL;aACD;QACH;IACF;AACF;AAEO,SAASgE;IACd,OAAO;QACL;YACE,MAAM;YACN,KAAKP;QACP;KACD;AACH"}