@aiscene/core 9.0.0 → 9.0.1

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 (136) hide show
  1. package/dist/es/agent/tasks.mjs +5 -1
  2. package/dist/es/agent/tasks.mjs.map +1 -1
  3. package/dist/es/agent/utils.mjs +1 -1
  4. package/dist/es/index.mjs +2 -2
  5. package/dist/es/index.mjs.map +1 -1
  6. package/dist/es/report-generator.mjs.map +1 -1
  7. package/dist/es/types.mjs +20 -1
  8. package/dist/es/types.mjs.map +1 -1
  9. package/dist/es/utils.mjs +2 -2
  10. package/dist/lib/agent/agent.js +1 -1
  11. package/dist/lib/agent/agent.js.map +1 -1
  12. package/dist/lib/agent/execution-session.js +1 -1
  13. package/dist/lib/agent/execution-session.js.map +1 -1
  14. package/dist/lib/agent/index.js +1 -1
  15. package/dist/lib/agent/index.js.map +1 -1
  16. package/dist/lib/agent/task-builder.js +1 -1
  17. package/dist/lib/agent/task-builder.js.map +1 -1
  18. package/dist/lib/agent/task-cache.js +1 -1
  19. package/dist/lib/agent/task-cache.js.map +1 -1
  20. package/dist/lib/agent/tasks.js +5 -1
  21. package/dist/lib/agent/tasks.js.map +1 -1
  22. package/dist/lib/agent/ui-utils.js +1 -1
  23. package/dist/lib/agent/ui-utils.js.map +1 -1
  24. package/dist/lib/agent/usage-intent.js +1 -1
  25. package/dist/lib/agent/usage-intent.js.map +1 -1
  26. package/dist/lib/agent/utils.js +2 -2
  27. package/dist/lib/agent/utils.js.map +1 -1
  28. package/dist/lib/ai-model/auto-glm/actions.js +1 -1
  29. package/dist/lib/ai-model/auto-glm/actions.js.map +1 -1
  30. package/dist/lib/ai-model/auto-glm/index.js +1 -1
  31. package/dist/lib/ai-model/auto-glm/index.js.map +1 -1
  32. package/dist/lib/ai-model/auto-glm/parser.js +1 -1
  33. package/dist/lib/ai-model/auto-glm/parser.js.map +1 -1
  34. package/dist/lib/ai-model/auto-glm/planning.js +1 -1
  35. package/dist/lib/ai-model/auto-glm/planning.js.map +1 -1
  36. package/dist/lib/ai-model/auto-glm/prompt.js +1 -1
  37. package/dist/lib/ai-model/auto-glm/prompt.js.map +1 -1
  38. package/dist/lib/ai-model/auto-glm/util.js +1 -1
  39. package/dist/lib/ai-model/auto-glm/util.js.map +1 -1
  40. package/dist/lib/ai-model/connectivity.js +1 -1
  41. package/dist/lib/ai-model/connectivity.js.map +1 -1
  42. package/dist/lib/ai-model/conversation-history.js +1 -1
  43. package/dist/lib/ai-model/conversation-history.js.map +1 -1
  44. package/dist/lib/ai-model/index.js +1 -1
  45. package/dist/lib/ai-model/index.js.map +1 -1
  46. package/dist/lib/ai-model/inspect.js +1 -1
  47. package/dist/lib/ai-model/inspect.js.map +1 -1
  48. package/dist/lib/ai-model/llm-planning.js +1 -1
  49. package/dist/lib/ai-model/llm-planning.js.map +1 -1
  50. package/dist/lib/ai-model/prompt/common.js +1 -1
  51. package/dist/lib/ai-model/prompt/common.js.map +1 -1
  52. package/dist/lib/ai-model/prompt/describe.js +1 -1
  53. package/dist/lib/ai-model/prompt/describe.js.map +1 -1
  54. package/dist/lib/ai-model/prompt/extraction.js +1 -1
  55. package/dist/lib/ai-model/prompt/extraction.js.map +1 -1
  56. package/dist/lib/ai-model/prompt/llm-locator.js +1 -1
  57. package/dist/lib/ai-model/prompt/llm-locator.js.map +1 -1
  58. package/dist/lib/ai-model/prompt/llm-planning.js +1 -1
  59. package/dist/lib/ai-model/prompt/llm-planning.js.map +1 -1
  60. package/dist/lib/ai-model/prompt/llm-section-locator.js +1 -1
  61. package/dist/lib/ai-model/prompt/llm-section-locator.js.map +1 -1
  62. package/dist/lib/ai-model/prompt/order-sensitive-judge.js +1 -1
  63. package/dist/lib/ai-model/prompt/order-sensitive-judge.js.map +1 -1
  64. package/dist/lib/ai-model/prompt/playwright-generator.js +1 -1
  65. package/dist/lib/ai-model/prompt/playwright-generator.js.map +1 -1
  66. package/dist/lib/ai-model/prompt/ui-tars-planning.js +1 -1
  67. package/dist/lib/ai-model/prompt/ui-tars-planning.js.map +1 -1
  68. package/dist/lib/ai-model/prompt/util.js +1 -1
  69. package/dist/lib/ai-model/prompt/util.js.map +1 -1
  70. package/dist/lib/ai-model/prompt/yaml-generator.js +1 -1
  71. package/dist/lib/ai-model/prompt/yaml-generator.js.map +1 -1
  72. package/dist/lib/ai-model/service-caller/codex-app-server.js +1 -1
  73. package/dist/lib/ai-model/service-caller/codex-app-server.js.map +1 -1
  74. package/dist/lib/ai-model/service-caller/image-detail.js +1 -1
  75. package/dist/lib/ai-model/service-caller/image-detail.js.map +1 -1
  76. package/dist/lib/ai-model/service-caller/index.js +1 -1
  77. package/dist/lib/ai-model/service-caller/index.js.map +1 -1
  78. package/dist/lib/ai-model/service-caller/request-timeout.js +1 -1
  79. package/dist/lib/ai-model/service-caller/request-timeout.js.map +1 -1
  80. package/dist/lib/ai-model/ui-tars-planning.js +1 -1
  81. package/dist/lib/ai-model/ui-tars-planning.js.map +1 -1
  82. package/dist/lib/common.js +1 -1
  83. package/dist/lib/common.js.map +1 -1
  84. package/dist/lib/device/device-options.js +1 -1
  85. package/dist/lib/device/device-options.js.map +1 -1
  86. package/dist/lib/device/index.js +1 -1
  87. package/dist/lib/device/index.js.map +1 -1
  88. package/dist/lib/dump/html-utils.js +1 -1
  89. package/dist/lib/dump/html-utils.js.map +1 -1
  90. package/dist/lib/dump/index.js +1 -1
  91. package/dist/lib/dump/index.js.map +1 -1
  92. package/dist/lib/dump/screenshot-restoration.js +1 -1
  93. package/dist/lib/dump/screenshot-restoration.js.map +1 -1
  94. package/dist/lib/dump/screenshot-store.js +1 -1
  95. package/dist/lib/dump/screenshot-store.js.map +1 -1
  96. package/dist/lib/index.js +8 -2
  97. package/dist/lib/index.js.map +1 -1
  98. package/dist/lib/report-cli.js +1 -1
  99. package/dist/lib/report-cli.js.map +1 -1
  100. package/dist/lib/report-generator.js +1 -1
  101. package/dist/lib/report-generator.js.map +1 -1
  102. package/dist/lib/report-markdown.js +1 -1
  103. package/dist/lib/report-markdown.js.map +1 -1
  104. package/dist/lib/report.js +1 -1
  105. package/dist/lib/report.js.map +1 -1
  106. package/dist/lib/screenshot-item.js +1 -1
  107. package/dist/lib/screenshot-item.js.map +1 -1
  108. package/dist/lib/service/index.js +1 -1
  109. package/dist/lib/service/index.js.map +1 -1
  110. package/dist/lib/service/utils.js +1 -1
  111. package/dist/lib/service/utils.js.map +1 -1
  112. package/dist/lib/skill/index.js +1 -1
  113. package/dist/lib/skill/index.js.map +1 -1
  114. package/dist/lib/task-runner.js +1 -1
  115. package/dist/lib/task-runner.js.map +1 -1
  116. package/dist/lib/task-timing.js +1 -1
  117. package/dist/lib/task-timing.js.map +1 -1
  118. package/dist/lib/tree.js +1 -1
  119. package/dist/lib/tree.js.map +1 -1
  120. package/dist/lib/types.js +36 -9
  121. package/dist/lib/types.js.map +1 -1
  122. package/dist/lib/utils.js +3 -3
  123. package/dist/lib/utils.js.map +1 -1
  124. package/dist/lib/yaml/builder.js +1 -1
  125. package/dist/lib/yaml/builder.js.map +1 -1
  126. package/dist/lib/yaml/index.js +1 -1
  127. package/dist/lib/yaml/index.js.map +1 -1
  128. package/dist/lib/yaml/player.js +1 -1
  129. package/dist/lib/yaml/player.js.map +1 -1
  130. package/dist/lib/yaml/utils.js +1 -1
  131. package/dist/lib/yaml/utils.js.map +1 -1
  132. package/dist/lib/yaml.js +1 -1
  133. package/dist/lib/yaml.js.map +1 -1
  134. package/dist/types/index.d.ts +1 -1
  135. package/dist/types/types.d.ts +35 -0
  136. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"report-markdown.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report-markdown.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 { basename } from 'node:path';\nimport { extractInsightParam, paramStr, typeStr } from '@/agent/ui-utils';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n ExecutionDump,\n ExecutionRecorderItem,\n ExecutionTask,\n IExecutionDump,\n IReportActionDump,\n ReportActionDump,\n} from '@/types';\nimport { normalizeScreenshotRef } from './dump/screenshot-store';\n\nexport interface MarkdownAttachment {\n id: string;\n suggestedFileName: string;\n mimeType?: string;\n filePath: string;\n executionIndex: number;\n taskIndex: number;\n /** Populated when screenshot data is available in memory (e.g. browser context). */\n base64Data?: string;\n}\n\nexport interface ExecutionMarkdownOptions {\n screenshotBaseDir?: string;\n}\n\nexport interface ExecutionMarkdownResult {\n markdown: string;\n attachments: MarkdownAttachment[];\n}\n\nexport interface ReportMarkdownResult {\n markdown: string;\n attachments: MarkdownAttachment[];\n}\n\nfunction toExecutionDump(\n execution: ExecutionDump | IExecutionDump,\n): IExecutionDump {\n if (!execution || typeof execution !== 'object') {\n throw new Error('executionToMarkdown: execution is required');\n }\n\n if (!Array.isArray(execution.tasks)) {\n throw new Error('executionToMarkdown: execution.tasks must be an array');\n }\n\n if (!execution.name) {\n throw new Error('executionToMarkdown: execution.name is required');\n }\n\n return execution;\n}\n\nfunction toReportDump(\n report: ReportActionDump | IReportActionDump,\n): IReportActionDump {\n if (!report || typeof report !== 'object') {\n throw new Error('reportToMarkdown: report is required');\n }\n\n if (!Array.isArray(report.executions)) {\n throw new Error('reportToMarkdown: report.executions must be an array');\n }\n\n return report;\n}\n\nfunction formatTime(ts?: number): string {\n if (typeof ts !== 'number' || Number.isNaN(ts)) {\n return 'N/A';\n }\n return new Date(ts).toISOString();\n}\n\nfunction resolveTaskTiming(task: ExecutionTask): {\n start?: number;\n end?: number;\n cost?: number;\n} {\n const timing = task.timing;\n if (!timing) {\n return {};\n }\n\n const start = timing.start ?? timing.callAiStart ?? timing.callActionStart;\n const end =\n timing.end ??\n timing.callAiEnd ??\n timing.callActionEnd ??\n timing.captureAfterCallingSnapshotEnd;\n const cost =\n timing.cost ??\n (typeof start === 'number' && typeof end === 'number'\n ? end - start\n : undefined);\n\n return { start, end, cost };\n}\n\nfunction safeTaskParam(task: ExecutionTask): string {\n const readable = paramStr(task);\n if (readable) {\n return readable;\n }\n\n if (task.type === 'Insight') {\n return extractInsightParam((task as any).param).content;\n }\n\n return '';\n}\n\nfunction formatSize(\n size?: { width?: number; height?: number } | null,\n): string | undefined {\n if (\n !size ||\n typeof size.width !== 'number' ||\n typeof size.height !== 'number' ||\n Number.isNaN(size.width) ||\n Number.isNaN(size.height)\n ) {\n return undefined;\n }\n\n return `${size.width} x ${size.height}`;\n}\n\nfunction extractLocateCenter(\n task: ExecutionTask,\n): [number, number] | undefined {\n const outputCenter = (task.output as { element?: { center?: unknown } })\n ?.element?.center;\n if (\n Array.isArray(outputCenter) &&\n outputCenter.length >= 2 &&\n typeof outputCenter[0] === 'number' &&\n typeof outputCenter[1] === 'number'\n ) {\n return [outputCenter[0], outputCenter[1]];\n }\n\n const paramLocateCenter = (task.param as { locate?: { center?: unknown } })\n ?.locate?.center;\n if (\n Array.isArray(paramLocateCenter) &&\n paramLocateCenter.length >= 2 &&\n typeof paramLocateCenter[0] === 'number' &&\n typeof paramLocateCenter[1] === 'number'\n ) {\n return [paramLocateCenter[0], paramLocateCenter[1]];\n }\n\n const paramCenter = (task.param as { center?: unknown })?.center;\n if (\n Array.isArray(paramCenter) &&\n paramCenter.length >= 2 &&\n typeof paramCenter[0] === 'number' &&\n typeof paramCenter[1] === 'number'\n ) {\n return [paramCenter[0], paramCenter[1]];\n }\n\n return undefined;\n}\n\nfunction tryExtractBase64(screenshot: unknown): string | undefined {\n if (!screenshot || typeof screenshot !== 'object') return undefined;\n const s = screenshot as Record<string, unknown>;\n if (typeof s.base64 === 'string' && s.base64.length > 0) {\n return s.base64;\n }\n return undefined;\n}\n\nfunction screenshotAttachment(\n screenshot: unknown,\n screenshotBaseDir: string,\n executionIndex: number,\n taskIndex: number,\n): { markdown: string; attachment: MarkdownAttachment } {\n if (screenshot instanceof ScreenshotItem) {\n const ext = screenshot.extension;\n const suggestedFileName = `execution-${executionIndex + 1}-task-${taskIndex + 1}-${screenshot.id}.${ext}`;\n const filePath = `${screenshotBaseDir}/${suggestedFileName}`;\n return {\n markdown: `\\n![task-${taskIndex + 1}](${filePath})`,\n attachment: {\n id: screenshot.id,\n suggestedFileName,\n filePath,\n mimeType: `image/${ext === 'jpeg' ? 'jpeg' : 'png'}`,\n executionIndex,\n taskIndex,\n base64Data: tryExtractBase64(screenshot),\n },\n };\n }\n\n const ref = normalizeScreenshotRef(screenshot);\n if (ref) {\n const ext = ref.mimeType === 'image/jpeg' ? 'jpeg' : 'png';\n const suggestedFileName = `execution-${executionIndex + 1}-task-${taskIndex + 1}-${ref.id}.${ext}`;\n const filePath = ref.path || `${screenshotBaseDir}/${suggestedFileName}`;\n return {\n markdown: `\\n![task-${taskIndex + 1}](${filePath})`,\n attachment: {\n id: ref.id,\n suggestedFileName,\n filePath,\n mimeType: ref.mimeType,\n executionIndex,\n taskIndex,\n base64Data: tryExtractBase64(screenshot),\n },\n };\n }\n\n const base64 = tryExtractBase64(screenshot);\n if (base64) {\n const ext = base64.startsWith('data:image/jpeg') ? 'jpeg' : 'png';\n const id = `restored-${executionIndex + 1}-${taskIndex + 1}`;\n const suggestedFileName = `execution-${executionIndex + 1}-task-${taskIndex + 1}-${id}.${ext}`;\n const filePath = `${screenshotBaseDir}/${suggestedFileName}`;\n return {\n markdown: `\\n![task-${taskIndex + 1}](${filePath})`,\n attachment: {\n id,\n suggestedFileName,\n filePath,\n mimeType: `image/${ext}`,\n executionIndex,\n taskIndex,\n base64Data: base64,\n },\n };\n }\n\n throw new Error(\n `executionToMarkdown: missing screenshot for execution #${executionIndex + 1} task #${taskIndex + 1}`,\n );\n}\n\nfunction recorderMarkdownSection(\n recorder: ExecutionRecorderItem[] | undefined,\n screenshotBaseDir: string,\n executionIndex: number,\n taskIndex: number,\n): { lines: string[]; attachments: MarkdownAttachment[] } {\n if (!recorder?.length) {\n return { lines: [], attachments: [] };\n }\n\n const lines: string[] = ['', '### Recorder'];\n const attachments: MarkdownAttachment[] = [];\n\n recorder.forEach((item, recorderIndex) => {\n lines.push(\n `- #${recorderIndex + 1} type=${item.type}, ts=${formatTime(item.ts)}, timing=${item.timing || 'N/A'}`,\n );\n\n if (!item.screenshot) {\n return;\n }\n\n const imageResult = screenshotAttachment(\n item.screenshot,\n screenshotBaseDir,\n executionIndex,\n taskIndex,\n );\n\n lines.push(imageResult.markdown);\n attachments.push(imageResult.attachment);\n });\n\n return { lines, attachments };\n}\n\nfunction renderExecution(\n executionRaw: ExecutionDump | IExecutionDump,\n executionIndex: number,\n options?: ExecutionMarkdownOptions,\n): ExecutionMarkdownResult {\n const execution = toExecutionDump(executionRaw);\n const screenshotBaseDir = options?.screenshotBaseDir ?? './screenshots';\n\n const lines: string[] = [];\n const attachments: MarkdownAttachment[] = [];\n\n lines.push(`# ${execution.name}`);\n if (execution.description) {\n lines.push('', execution.description);\n }\n\n lines.push('', `- Execution start: ${formatTime(execution.logTime)}`);\n lines.push(`- Task count: ${execution.tasks.length}`);\n\n execution.tasks.forEach((task, taskIndex) => {\n const title = typeStr(task);\n const detail = safeTaskParam(task);\n const time = resolveTaskTiming(task);\n\n lines.push(\n '',\n `## ${taskIndex + 1}. ${title}${detail ? ` - ${detail}` : ''}`,\n );\n lines.push(`- Status: ${task.status || 'unknown'}`);\n lines.push(`- Start: ${formatTime(time.start)}`);\n lines.push(`- End: ${formatTime(time.end)}`);\n lines.push(\n `- Cost(ms): ${typeof time.cost === 'number' ? time.cost : 'N/A'}`,\n );\n lines.push(\n `- Screen size: ${formatSize(task.uiContext?.shotSize) || 'N/A'}`,\n );\n\n if (task.subType === 'Locate') {\n const locateCenter = extractLocateCenter(task);\n if (locateCenter) {\n lines.push(`- Locate center: (${locateCenter[0]}, ${locateCenter[1]})`);\n }\n }\n\n if (task.errorMessage) {\n lines.push(`- Error: ${task.errorMessage}`);\n }\n\n if (task.uiContext?.screenshot) {\n const imageResult = screenshotAttachment(\n task.uiContext.screenshot,\n screenshotBaseDir,\n executionIndex,\n taskIndex,\n );\n\n lines.push(imageResult.markdown);\n attachments.push(imageResult.attachment);\n }\n\n const recorderSection = recorderMarkdownSection(\n task.recorder,\n screenshotBaseDir,\n executionIndex,\n taskIndex,\n );\n if (recorderSection.lines.length) {\n lines.push(...recorderSection.lines);\n attachments.push(...recorderSection.attachments);\n }\n });\n\n return {\n markdown: lines.join('\\n'),\n attachments,\n };\n}\n\nfunction reportFileName(\n execution: IExecutionDump,\n executionIndex: number,\n): string {\n const safeName =\n execution.name\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/[^a-zA-Z0-9-_]/g, '') || `execution-${executionIndex + 1}`;\n return `${executionIndex + 1}-${basename(safeName)}.md`;\n}\n\nexport function executionToMarkdown(\n execution: ExecutionDump | IExecutionDump,\n options?: ExecutionMarkdownOptions,\n): ExecutionMarkdownResult {\n return renderExecution(execution, 0, options);\n}\n\nexport function reportToMarkdown(\n report: ReportActionDump | IReportActionDump,\n): ReportMarkdownResult {\n const reportDump = toReportDump(report);\n\n const executionResults = reportDump.executions.map((execution, index) => {\n const rendered = renderExecution(execution, index);\n return {\n executionIndex: index,\n executionName: execution.name,\n markdown: rendered.markdown,\n attachments: rendered.attachments,\n suggestedFileName: reportFileName(execution, index),\n };\n });\n\n const attachments = executionResults.flatMap((item) => item.attachments);\n\n const header = [\n `# ${reportDump.groupName}`,\n reportDump.groupDescription ? `\\n${reportDump.groupDescription}` : '',\n `\\n- SDK Version: ${reportDump.sdkVersion}`,\n `- Execution count: ${reportDump.executions.length}`,\n '\\n## Suggested execution markdown files',\n ...executionResults.map(\n (item) => `- ${item.suggestedFileName} (${item.executionName})`,\n ),\n ]\n .filter(Boolean)\n .join('\\n');\n\n return {\n markdown: `${header}\\n\\n${executionResults.map((item) => item.markdown).join('\\n\\n---\\n\\n')}`,\n attachments,\n };\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","toExecutionDump","execution","Error","Array","toReportDump","report","formatTime","ts","Number","Date","resolveTaskTiming","task","timing","start","end","cost","undefined","safeTaskParam","readable","paramStr","extractInsightParam","formatSize","size","extractLocateCenter","outputCenter","paramLocateCenter","paramCenter","tryExtractBase64","screenshot","s","screenshotAttachment","screenshotBaseDir","executionIndex","taskIndex","ScreenshotItem","ext","suggestedFileName","filePath","ref","normalizeScreenshotRef","base64","id","recorderMarkdownSection","recorder","lines","attachments","item","recorderIndex","imageResult","renderExecution","executionRaw","options","title","typeStr","detail","time","locateCenter","recorderSection","reportFileName","safeName","basename","executionToMarkdown","reportToMarkdown","reportDump","executionResults","index","rendered","header","Boolean"],"mappings":"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"}
1
+ {"version":3,"file":"report-markdown.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report-markdown.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 { basename } from 'node:path';\nimport { extractInsightParam, paramStr, typeStr } from '@/agent/ui-utils';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n ExecutionDump,\n ExecutionRecorderItem,\n ExecutionTask,\n IExecutionDump,\n IReportActionDump,\n ReportActionDump,\n} from '@/types';\nimport { normalizeScreenshotRef } from './dump/screenshot-store';\n\nexport interface MarkdownAttachment {\n id: string;\n suggestedFileName: string;\n mimeType?: string;\n filePath: string;\n executionIndex: number;\n taskIndex: number;\n /** Populated when screenshot data is available in memory (e.g. browser context). */\n base64Data?: string;\n}\n\nexport interface ExecutionMarkdownOptions {\n screenshotBaseDir?: string;\n}\n\nexport interface ExecutionMarkdownResult {\n markdown: string;\n attachments: MarkdownAttachment[];\n}\n\nexport interface ReportMarkdownResult {\n markdown: string;\n attachments: MarkdownAttachment[];\n}\n\nfunction toExecutionDump(\n execution: ExecutionDump | IExecutionDump,\n): IExecutionDump {\n if (!execution || typeof execution !== 'object') {\n throw new Error('executionToMarkdown: execution is required');\n }\n\n if (!Array.isArray(execution.tasks)) {\n throw new Error('executionToMarkdown: execution.tasks must be an array');\n }\n\n if (!execution.name) {\n throw new Error('executionToMarkdown: execution.name is required');\n }\n\n return execution;\n}\n\nfunction toReportDump(\n report: ReportActionDump | IReportActionDump,\n): IReportActionDump {\n if (!report || typeof report !== 'object') {\n throw new Error('reportToMarkdown: report is required');\n }\n\n if (!Array.isArray(report.executions)) {\n throw new Error('reportToMarkdown: report.executions must be an array');\n }\n\n return report;\n}\n\nfunction formatTime(ts?: number): string {\n if (typeof ts !== 'number' || Number.isNaN(ts)) {\n return 'N/A';\n }\n return new Date(ts).toISOString();\n}\n\nfunction resolveTaskTiming(task: ExecutionTask): {\n start?: number;\n end?: number;\n cost?: number;\n} {\n const timing = task.timing;\n if (!timing) {\n return {};\n }\n\n const start = timing.start ?? timing.callAiStart ?? timing.callActionStart;\n const end =\n timing.end ??\n timing.callAiEnd ??\n timing.callActionEnd ??\n timing.captureAfterCallingSnapshotEnd;\n const cost =\n timing.cost ??\n (typeof start === 'number' && typeof end === 'number'\n ? end - start\n : undefined);\n\n return { start, end, cost };\n}\n\nfunction safeTaskParam(task: ExecutionTask): string {\n const readable = paramStr(task);\n if (readable) {\n return readable;\n }\n\n if (task.type === 'Insight') {\n return extractInsightParam((task as any).param).content;\n }\n\n return '';\n}\n\nfunction formatSize(\n size?: { width?: number; height?: number } | null,\n): string | undefined {\n if (\n !size ||\n typeof size.width !== 'number' ||\n typeof size.height !== 'number' ||\n Number.isNaN(size.width) ||\n Number.isNaN(size.height)\n ) {\n return undefined;\n }\n\n return `${size.width} x ${size.height}`;\n}\n\nfunction extractLocateCenter(\n task: ExecutionTask,\n): [number, number] | undefined {\n const outputCenter = (task.output as { element?: { center?: unknown } })\n ?.element?.center;\n if (\n Array.isArray(outputCenter) &&\n outputCenter.length >= 2 &&\n typeof outputCenter[0] === 'number' &&\n typeof outputCenter[1] === 'number'\n ) {\n return [outputCenter[0], outputCenter[1]];\n }\n\n const paramLocateCenter = (task.param as { locate?: { center?: unknown } })\n ?.locate?.center;\n if (\n Array.isArray(paramLocateCenter) &&\n paramLocateCenter.length >= 2 &&\n typeof paramLocateCenter[0] === 'number' &&\n typeof paramLocateCenter[1] === 'number'\n ) {\n return [paramLocateCenter[0], paramLocateCenter[1]];\n }\n\n const paramCenter = (task.param as { center?: unknown })?.center;\n if (\n Array.isArray(paramCenter) &&\n paramCenter.length >= 2 &&\n typeof paramCenter[0] === 'number' &&\n typeof paramCenter[1] === 'number'\n ) {\n return [paramCenter[0], paramCenter[1]];\n }\n\n return undefined;\n}\n\nfunction tryExtractBase64(screenshot: unknown): string | undefined {\n if (!screenshot || typeof screenshot !== 'object') return undefined;\n const s = screenshot as Record<string, unknown>;\n if (typeof s.base64 === 'string' && s.base64.length > 0) {\n return s.base64;\n }\n return undefined;\n}\n\nfunction screenshotAttachment(\n screenshot: unknown,\n screenshotBaseDir: string,\n executionIndex: number,\n taskIndex: number,\n): { markdown: string; attachment: MarkdownAttachment } {\n if (screenshot instanceof ScreenshotItem) {\n const ext = screenshot.extension;\n const suggestedFileName = `execution-${executionIndex + 1}-task-${taskIndex + 1}-${screenshot.id}.${ext}`;\n const filePath = `${screenshotBaseDir}/${suggestedFileName}`;\n return {\n markdown: `\\n![task-${taskIndex + 1}](${filePath})`,\n attachment: {\n id: screenshot.id,\n suggestedFileName,\n filePath,\n mimeType: `image/${ext === 'jpeg' ? 'jpeg' : 'png'}`,\n executionIndex,\n taskIndex,\n base64Data: tryExtractBase64(screenshot),\n },\n };\n }\n\n const ref = normalizeScreenshotRef(screenshot);\n if (ref) {\n const ext = ref.mimeType === 'image/jpeg' ? 'jpeg' : 'png';\n const suggestedFileName = `execution-${executionIndex + 1}-task-${taskIndex + 1}-${ref.id}.${ext}`;\n const filePath = ref.path || `${screenshotBaseDir}/${suggestedFileName}`;\n return {\n markdown: `\\n![task-${taskIndex + 1}](${filePath})`,\n attachment: {\n id: ref.id,\n suggestedFileName,\n filePath,\n mimeType: ref.mimeType,\n executionIndex,\n taskIndex,\n base64Data: tryExtractBase64(screenshot),\n },\n };\n }\n\n const base64 = tryExtractBase64(screenshot);\n if (base64) {\n const ext = base64.startsWith('data:image/jpeg') ? 'jpeg' : 'png';\n const id = `restored-${executionIndex + 1}-${taskIndex + 1}`;\n const suggestedFileName = `execution-${executionIndex + 1}-task-${taskIndex + 1}-${id}.${ext}`;\n const filePath = `${screenshotBaseDir}/${suggestedFileName}`;\n return {\n markdown: `\\n![task-${taskIndex + 1}](${filePath})`,\n attachment: {\n id,\n suggestedFileName,\n filePath,\n mimeType: `image/${ext}`,\n executionIndex,\n taskIndex,\n base64Data: base64,\n },\n };\n }\n\n throw new Error(\n `executionToMarkdown: missing screenshot for execution #${executionIndex + 1} task #${taskIndex + 1}`,\n );\n}\n\nfunction recorderMarkdownSection(\n recorder: ExecutionRecorderItem[] | undefined,\n screenshotBaseDir: string,\n executionIndex: number,\n taskIndex: number,\n): { lines: string[]; attachments: MarkdownAttachment[] } {\n if (!recorder?.length) {\n return { lines: [], attachments: [] };\n }\n\n const lines: string[] = ['', '### Recorder'];\n const attachments: MarkdownAttachment[] = [];\n\n recorder.forEach((item, recorderIndex) => {\n lines.push(\n `- #${recorderIndex + 1} type=${item.type}, ts=${formatTime(item.ts)}, timing=${item.timing || 'N/A'}`,\n );\n\n if (!item.screenshot) {\n return;\n }\n\n const imageResult = screenshotAttachment(\n item.screenshot,\n screenshotBaseDir,\n executionIndex,\n taskIndex,\n );\n\n lines.push(imageResult.markdown);\n attachments.push(imageResult.attachment);\n });\n\n return { lines, attachments };\n}\n\nfunction renderExecution(\n executionRaw: ExecutionDump | IExecutionDump,\n executionIndex: number,\n options?: ExecutionMarkdownOptions,\n): ExecutionMarkdownResult {\n const execution = toExecutionDump(executionRaw);\n const screenshotBaseDir = options?.screenshotBaseDir ?? './screenshots';\n\n const lines: string[] = [];\n const attachments: MarkdownAttachment[] = [];\n\n lines.push(`# ${execution.name}`);\n if (execution.description) {\n lines.push('', execution.description);\n }\n\n lines.push('', `- Execution start: ${formatTime(execution.logTime)}`);\n lines.push(`- Task count: ${execution.tasks.length}`);\n\n execution.tasks.forEach((task, taskIndex) => {\n const title = typeStr(task);\n const detail = safeTaskParam(task);\n const time = resolveTaskTiming(task);\n\n lines.push(\n '',\n `## ${taskIndex + 1}. ${title}${detail ? ` - ${detail}` : ''}`,\n );\n lines.push(`- Status: ${task.status || 'unknown'}`);\n lines.push(`- Start: ${formatTime(time.start)}`);\n lines.push(`- End: ${formatTime(time.end)}`);\n lines.push(\n `- Cost(ms): ${typeof time.cost === 'number' ? time.cost : 'N/A'}`,\n );\n lines.push(\n `- Screen size: ${formatSize(task.uiContext?.shotSize) || 'N/A'}`,\n );\n\n if (task.subType === 'Locate') {\n const locateCenter = extractLocateCenter(task);\n if (locateCenter) {\n lines.push(`- Locate center: (${locateCenter[0]}, ${locateCenter[1]})`);\n }\n }\n\n if (task.errorMessage) {\n lines.push(`- Error: ${task.errorMessage}`);\n }\n\n if (task.uiContext?.screenshot) {\n const imageResult = screenshotAttachment(\n task.uiContext.screenshot,\n screenshotBaseDir,\n executionIndex,\n taskIndex,\n );\n\n lines.push(imageResult.markdown);\n attachments.push(imageResult.attachment);\n }\n\n const recorderSection = recorderMarkdownSection(\n task.recorder,\n screenshotBaseDir,\n executionIndex,\n taskIndex,\n );\n if (recorderSection.lines.length) {\n lines.push(...recorderSection.lines);\n attachments.push(...recorderSection.attachments);\n }\n });\n\n return {\n markdown: lines.join('\\n'),\n attachments,\n };\n}\n\nfunction reportFileName(\n execution: IExecutionDump,\n executionIndex: number,\n): string {\n const safeName =\n execution.name\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/[^a-zA-Z0-9-_]/g, '') || `execution-${executionIndex + 1}`;\n return `${executionIndex + 1}-${basename(safeName)}.md`;\n}\n\nexport function executionToMarkdown(\n execution: ExecutionDump | IExecutionDump,\n options?: ExecutionMarkdownOptions,\n): ExecutionMarkdownResult {\n return renderExecution(execution, 0, options);\n}\n\nexport function reportToMarkdown(\n report: ReportActionDump | IReportActionDump,\n): ReportMarkdownResult {\n const reportDump = toReportDump(report);\n\n const executionResults = reportDump.executions.map((execution, index) => {\n const rendered = renderExecution(execution, index);\n return {\n executionIndex: index,\n executionName: execution.name,\n markdown: rendered.markdown,\n attachments: rendered.attachments,\n suggestedFileName: reportFileName(execution, index),\n };\n });\n\n const attachments = executionResults.flatMap((item) => item.attachments);\n\n const header = [\n `# ${reportDump.groupName}`,\n reportDump.groupDescription ? `\\n${reportDump.groupDescription}` : '',\n `\\n- SDK Version: ${reportDump.sdkVersion}`,\n `- Execution count: ${reportDump.executions.length}`,\n '\\n## Suggested execution markdown files',\n ...executionResults.map(\n (item) => `- ${item.suggestedFileName} (${item.executionName})`,\n ),\n ]\n .filter(Boolean)\n .join('\\n');\n\n return {\n markdown: `${header}\\n\\n${executionResults.map((item) => item.markdown).join('\\n\\n---\\n\\n')}`,\n attachments,\n };\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","toExecutionDump","execution","Error","Array","toReportDump","report","formatTime","ts","Number","Date","resolveTaskTiming","task","timing","start","end","cost","undefined","safeTaskParam","readable","paramStr","extractInsightParam","formatSize","size","extractLocateCenter","outputCenter","paramLocateCenter","paramCenter","tryExtractBase64","screenshot","s","screenshotAttachment","screenshotBaseDir","executionIndex","taskIndex","ScreenshotItem","ext","suggestedFileName","filePath","ref","normalizeScreenshotRef","base64","id","recorderMarkdownSection","recorder","lines","attachments","item","recorderIndex","imageResult","renderExecution","executionRaw","options","title","typeStr","detail","time","locateCenter","recorderSection","reportFileName","safeName","basename","executionToMarkdown","reportToMarkdown","reportDump","executionResults","index","rendered","header","Boolean"],"mappings":"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"}
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report.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 copyFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport * as path from 'node:path';\nimport { getMidsceneRunSubDir } from '@aiscene/shared/common';\nimport { antiEscapeScriptTag, logMsg } from '@aiscene/shared/utils';\nimport { getReportFileName } from './agent';\nimport {\n extractAllDumpScriptsSync,\n extractLastDumpScriptSync,\n getBaseUrlFixScript,\n streamDumpScriptsSync,\n streamImageScriptsToFile,\n} from './dump/html-utils';\nimport {\n normalizeScreenshotRef,\n resolveScreenshotSource,\n} from './dump/screenshot-store';\nimport {\n type ExecutionDump,\n type IExecutionDump,\n ReportActionDump,\n} from './types';\nimport type { ReportFileWithAttributes } from './types';\nimport { getReportTpl, getVersion, reportHTMLContent } from './utils';\n\n/**\n * Check if a report is in directory mode (html-and-external-assets).\n * Directory mode reports: {name}/index.html + {name}/screenshots/\n */\nexport function isDirectoryModeReport(reportFilePath: string): boolean {\n const reportDir = path.dirname(reportFilePath);\n return (\n path.basename(reportFilePath) === 'index.html' &&\n existsSync(path.join(reportDir, 'screenshots'))\n );\n}\n\n/**\n * Deduplicate executions by stable id, keeping only the last occurrence.\n * Old-format executions without id are always preserved.\n */\nexport function dedupeExecutionsKeepLatest<T extends Pick<ExecutionDump, 'id'>>(\n executions: T[],\n): T[] {\n let noIdCounter = 0;\n const deduped = new Map<string, T>();\n for (const exec of executions) {\n const key = exec.id || `__no_id_${noIdCounter++}`;\n deduped.set(key, exec);\n }\n return Array.from(deduped.values());\n}\n/**\n * Peek at the first `sdkVersion` field embedded in a midscene_web_dump\n * script tag inside the given report file. Returns undefined if no\n * recognizable tag or sdkVersion is present.\n */\nfunction peekReportSdkVersion(reportFilePath: string): string | undefined {\n try {\n const dump = extractLastDumpScriptSync(reportFilePath);\n if (!dump) return undefined;\n const match = dump.match(/\"sdkVersion\"\\s*:\\s*\"([^\"]+)\"/);\n return match?.[1];\n } catch {\n return undefined;\n }\n}\n\nconst warnedMismatchedVersions = new Set<string>();\n\nexport class ReportMergingTool {\n private reportInfos: ReportFileWithAttributes[] = [];\n\n private createEmptyDumpString(groupName: string, groupDescription?: string) {\n return new ReportActionDump({\n sdkVersion: '',\n groupName,\n groupDescription,\n modelBriefs: [],\n executions: [],\n }).serialize();\n }\n\n public append(reportInfo: ReportFileWithAttributes) {\n if (reportInfo.reportFilePath) {\n const sourceVersion = peekReportSdkVersion(reportInfo.reportFilePath);\n const currentVersion = getVersion();\n if (\n sourceVersion &&\n currentVersion &&\n sourceVersion !== currentVersion &&\n !warnedMismatchedVersions.has(sourceVersion)\n ) {\n warnedMismatchedVersions.add(sourceVersion);\n logMsg(\n `[@aiscene/core] ReportMergingTool version mismatch: source report was written by @aiscene/core@${sourceVersion} but the merger is @aiscene/core@${currentVersion}. This commonly means @aiscene/core and the device package (e.g. @aiscene/android) resolve to different versions in node_modules. Merged output may silently drop intermediate steps. Align the versions and reinstall (rm -rf node_modules package-lock.json && npm install).`,\n );\n }\n }\n this.reportInfos.push(reportInfo);\n }\n public clear() {\n this.reportInfos = [];\n }\n\n /**\n * Merge multiple dump script contents (from the same source report)\n * into a single serialized ReportActionDump string.\n * If there's only one dump, return it as-is. If multiple, merge\n * all executions into the first dump's group structure.\n */\n private mergeDumpScripts(contents: string[]): string {\n const unescaped = contents\n .map((c) => antiEscapeScriptTag(c))\n .filter((c) => c.length > 0);\n if (unescaped.length === 0) return '';\n if (unescaped.length === 1) return unescaped[0];\n\n // Parse all dumps and collect executions, deduplicating by id (keep last).\n // Only executions with a stable id are deduped; old-format entries without\n // id are always kept (they may be distinct despite sharing the same name).\n const base = ReportActionDump.fromSerializedString(unescaped[0]);\n const allExecutions = [...base.executions];\n for (let i = 1; i < unescaped.length; i++) {\n const other = ReportActionDump.fromSerializedString(unescaped[i]);\n allExecutions.push(...other.executions);\n }\n base.executions = dedupeExecutionsKeepLatest(allExecutions);\n return base.serialize();\n }\n\n public mergeReports(\n reportFileName: 'AUTO' | string = 'AUTO',\n opts?: {\n rmOriginalReports?: boolean;\n overwrite?: boolean;\n },\n ): string | null {\n const { rmOriginalReports = false, overwrite = false } = opts ?? {};\n\n if (this.reportInfos.length === 0) {\n logMsg('No reports to merge');\n return null;\n }\n\n const targetDir = getMidsceneRunSubDir('report');\n\n // Check if any source report is directory mode\n const hasDirectoryModeReport = this.reportInfos.some((info) => {\n const reportFilePath = info.reportFilePath;\n return Boolean(reportFilePath && isDirectoryModeReport(reportFilePath));\n });\n\n const resolvedName =\n reportFileName === 'AUTO'\n ? getReportFileName('merged-report')\n : reportFileName;\n\n // Directory mode: output as {name}/index.html to keep relative paths working\n // Inline mode: output as {name}.html (single file)\n const outputFilePath = hasDirectoryModeReport\n ? path.resolve(targetDir, resolvedName, 'index.html')\n : path.resolve(targetDir, `${resolvedName}.html`);\n\n if (reportFileName !== 'AUTO' && existsSync(outputFilePath)) {\n if (!overwrite) {\n throw new Error(\n `Report file already exists: ${outputFilePath}\\nSet overwrite to true to overwrite this file.`,\n );\n }\n if (hasDirectoryModeReport) {\n rmSync(path.dirname(outputFilePath), { recursive: true, force: true });\n } else {\n unlinkSync(outputFilePath);\n }\n }\n\n if (hasDirectoryModeReport) {\n mkdirSync(path.dirname(outputFilePath), { recursive: true });\n }\n\n logMsg(\n `Start merging ${this.reportInfos.length} reports...\\nCreating template file...`,\n );\n\n try {\n // Write template without closing </html> tag so we can append\n // dump scripts before it. The closing tag is added at the end.\n const htmlEndTag = '</html>';\n const tpl = getReportTpl();\n const htmlEndIdx = tpl.lastIndexOf(htmlEndTag);\n const tplWithoutClose =\n htmlEndIdx !== -1 ? tpl.slice(0, htmlEndIdx) : tpl;\n appendFileSync(outputFilePath, tplWithoutClose);\n\n // For directory-mode output, inject base URL fix script\n if (hasDirectoryModeReport) {\n appendFileSync(outputFilePath, getBaseUrlFixScript());\n }\n\n // Process all reports one by one\n for (let i = 0; i < this.reportInfos.length; i++) {\n const reportInfo = this.reportInfos[i];\n logMsg(`Processing report ${i + 1}/${this.reportInfos.length}`);\n\n const { reportAttributes } = reportInfo;\n let dumpString = this.createEmptyDumpString(\n reportAttributes.testTitle,\n reportAttributes.testDescription,\n );\n let mergedGroupId = `merged-group-${i}`;\n\n if (reportInfo.reportFilePath) {\n if (isDirectoryModeReport(reportInfo.reportFilePath)) {\n // Directory mode: copy external screenshot files\n const reportDir = path.dirname(reportInfo.reportFilePath);\n const screenshotsDir = path.join(reportDir, 'screenshots');\n const mergedScreenshotsDir = path.join(\n path.dirname(outputFilePath),\n 'screenshots',\n );\n mkdirSync(mergedScreenshotsDir, { recursive: true });\n for (const file of readdirSync(screenshotsDir)) {\n const src = path.join(screenshotsDir, file);\n const dest = path.join(mergedScreenshotsDir, file);\n copyFileSync(src, dest);\n }\n } else {\n // Inline mode: stream image scripts to output file\n streamImageScriptsToFile(reportInfo.reportFilePath, outputFilePath);\n }\n\n // Extract all dump scripts from the source report.\n // After the per-execution append refactor, a single source report\n // may contain multiple <script type=\"midscene_web_dump\"> tags\n // (one per execution). We merge them into a single ReportActionDump.\n // Filter by data-group-id to exclude false matches from the template's\n // bundled JS code, which also references the midscene_web_dump type string.\n const allDumps = extractAllDumpScriptsSync(\n reportInfo.reportFilePath,\n ).filter((d) => d.openTag.includes('data-group-id'));\n const groupIdMatch = allDumps[0]?.openTag.match(\n /data-group-id=\"([^\"]+)\"/,\n );\n if (groupIdMatch) {\n mergedGroupId = decodeURIComponent(groupIdMatch[1]);\n }\n const extractedDumpString =\n allDumps.length > 0\n ? this.mergeDumpScripts(allDumps.map((d) => d.content))\n : extractLastDumpScriptSync(reportInfo.reportFilePath);\n if (extractedDumpString) {\n dumpString = extractedDumpString;\n }\n }\n\n const reportHtmlStr = `${reportHTMLContent(\n {\n dumpString,\n attributes: {\n 'data-group-id': mergedGroupId,\n playwright_test_duration: reportAttributes.testDuration,\n playwright_test_status: reportAttributes.testStatus,\n playwright_test_title: reportAttributes.testTitle,\n playwright_test_id: reportAttributes.testId,\n playwright_test_description: reportAttributes.testDescription,\n is_merged: true,\n },\n },\n undefined,\n undefined,\n false,\n )}\\n`;\n\n appendFileSync(outputFilePath, reportHtmlStr);\n }\n\n // Close the HTML document\n appendFileSync(outputFilePath, `${htmlEndTag}\\n`);\n\n logMsg(`Successfully merged new report: ${outputFilePath}`);\n\n // Remove original reports if needed\n if (rmOriginalReports) {\n for (const info of this.reportInfos) {\n if (!info.reportFilePath) continue;\n try {\n if (isDirectoryModeReport(info.reportFilePath)) {\n // Directory mode: remove the entire report directory\n const reportDir = path.dirname(info.reportFilePath);\n rmSync(reportDir, { recursive: true, force: true });\n } else {\n unlinkSync(info.reportFilePath);\n }\n } catch (error) {\n logMsg(`Error deleting report ${info.reportFilePath}: ${error}`);\n }\n }\n logMsg(`Removed ${this.reportInfos.length} original reports`);\n }\n return outputFilePath;\n } catch (error) {\n logMsg(`Error in mergeReports: ${error}`);\n throw error;\n }\n }\n}\n\nexport interface SplitReportHtmlOptions {\n htmlPath: string;\n outputDir: string;\n}\n\nexport interface SplitReportHtmlResult {\n executionJsonFiles: string[];\n screenshotFiles: string[];\n}\n\nexport interface CollectedReportExecutions {\n baseDump: ReportActionDump;\n executions: IExecutionDump[];\n}\n\n/**\n * Collect executions from a report HTML, deduplicating by stable id while\n * keeping only the latest occurrence. Old-format executions without id are\n * always preserved.\n */\nexport function collectDedupedExecutions(\n htmlPath: string,\n): CollectedReportExecutions {\n let baseDump: ReportActionDump | null = null;\n let executionSerial = 0;\n const latestSerialByExecutionId = new Map<string, number>();\n\n streamDumpScriptsSync(htmlPath, (dumpScript) => {\n if (!dumpScript.openTag.includes('data-group-id')) {\n return false;\n }\n const groupedDump = ReportActionDump.fromSerializedString(\n antiEscapeScriptTag(dumpScript.content),\n );\n for (const execution of groupedDump.executions) {\n executionSerial += 1;\n if (execution.id) {\n latestSerialByExecutionId.set(execution.id, executionSerial);\n }\n }\n return false;\n });\n\n const executions: IExecutionDump[] = [];\n executionSerial = 0;\n streamDumpScriptsSync(htmlPath, (dumpScript) => {\n if (!dumpScript.openTag.includes('data-group-id')) {\n return false;\n }\n\n const groupedDump = ReportActionDump.fromSerializedString(\n antiEscapeScriptTag(dumpScript.content),\n );\n if (!baseDump) {\n baseDump = groupedDump;\n }\n\n for (const execution of groupedDump.executions) {\n executionSerial += 1;\n if (\n execution.id &&\n latestSerialByExecutionId.get(execution.id) !== executionSerial\n ) {\n continue;\n }\n executions.push(execution);\n }\n\n return false;\n });\n\n if (!baseDump) {\n throw new Error(`No report dump scripts found in ${htmlPath}`);\n }\n\n return {\n baseDump,\n executions,\n };\n}\n\nfunction extensionByMimeType(mimeType: string): 'png' | 'jpeg' {\n if (mimeType === 'image/png') return 'png';\n if (mimeType === 'image/jpeg') return 'jpeg';\n throw new Error(`Unsupported screenshot mime type: ${mimeType}`);\n}\n\nfunction externalizeScreenshotsInExecution(\n execution: IExecutionDump,\n opts: {\n htmlPath: string;\n screenshotsDir: string;\n writtenFiles: Set<string>;\n },\n): void {\n const visit = (node: unknown): void => {\n if (Array.isArray(node)) {\n for (const item of node) {\n visit(item);\n }\n return;\n }\n\n if (typeof node !== 'object' || node === null) return;\n\n const ref = normalizeScreenshotRef(node);\n if (ref) {\n const ext = extensionByMimeType(ref.mimeType);\n const fileName = `${ref.id}.${ext}`;\n const relativePath = `./screenshots/${fileName}`;\n const absolutePath = path.join(opts.screenshotsDir, fileName);\n\n if (!opts.writtenFiles.has(fileName)) {\n const resolved = resolveScreenshotSource(ref, {\n reportPath: opts.htmlPath,\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 } else {\n copyFileSync(resolved.filePath, absolutePath);\n }\n opts.writtenFiles.add(fileName);\n }\n\n ref.storage = 'file';\n ref.path = relativePath;\n return;\n }\n\n for (const value of Object.values(node)) {\n visit(value);\n }\n };\n\n visit(execution);\n}\n\n/**\n * Reverse parse a Midscene report HTML into per-execution JSON files and\n * externalized screenshots.\n */\nexport function splitReportHtmlByExecution(\n options: SplitReportHtmlOptions,\n): SplitReportHtmlResult {\n const { htmlPath, outputDir } = options;\n const screenshotsDir = path.join(outputDir, 'screenshots');\n\n mkdirSync(outputDir, { recursive: true });\n mkdirSync(screenshotsDir, { recursive: true });\n\n const executionJsonFiles: string[] = [];\n const writtenScreenshotFiles = new Set<string>();\n const { baseDump, executions } = collectDedupedExecutions(htmlPath);\n\n let fileIndex = 0;\n for (const execution of executions) {\n fileIndex += 1;\n externalizeScreenshotsInExecution(execution, {\n htmlPath,\n screenshotsDir,\n writtenFiles: writtenScreenshotFiles,\n });\n const singleExecutionDump = new ReportActionDump({\n sdkVersion: baseDump.sdkVersion,\n groupName: baseDump.groupName,\n groupDescription: baseDump.groupDescription,\n modelBriefs: baseDump.modelBriefs,\n deviceType: baseDump.deviceType,\n executions: [execution],\n });\n\n const jsonFilePath = path.join(outputDir, `${fileIndex}.execution.json`);\n writeFileSync(jsonFilePath, singleExecutionDump.serialize(2), 'utf-8');\n executionJsonFiles.push(jsonFilePath);\n }\n\n return {\n executionJsonFiles,\n screenshotFiles: Array.from(writtenScreenshotFiles)\n .sort()\n .map((fileName) => path.join(screenshotsDir, fileName)),\n };\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","isDirectoryModeReport","reportFilePath","reportDir","path","existsSync","dedupeExecutionsKeepLatest","executions","noIdCounter","deduped","Map","exec","Array","peekReportSdkVersion","dump","extractLastDumpScriptSync","match","warnedMismatchedVersions","Set","ReportMergingTool","groupName","groupDescription","ReportActionDump","reportInfo","sourceVersion","currentVersion","getVersion","logMsg","contents","unescaped","c","antiEscapeScriptTag","base","allExecutions","i","other","reportFileName","opts","rmOriginalReports","overwrite","targetDir","getMidsceneRunSubDir","hasDirectoryModeReport","info","Boolean","resolvedName","getReportFileName","outputFilePath","Error","rmSync","unlinkSync","mkdirSync","htmlEndTag","tpl","getReportTpl","htmlEndIdx","tplWithoutClose","appendFileSync","getBaseUrlFixScript","reportAttributes","dumpString","mergedGroupId","screenshotsDir","mergedScreenshotsDir","file","readdirSync","src","dest","copyFileSync","streamImageScriptsToFile","allDumps","extractAllDumpScriptsSync","d","groupIdMatch","decodeURIComponent","extractedDumpString","reportHtmlStr","reportHTMLContent","undefined","error","collectDedupedExecutions","htmlPath","baseDump","executionSerial","latestSerialByExecutionId","streamDumpScriptsSync","dumpScript","groupedDump","execution","extensionByMimeType","mimeType","externalizeScreenshotsInExecution","visit","node","item","ref","normalizeScreenshotRef","ext","fileName","relativePath","absolutePath","resolved","resolveScreenshotSource","rawBase64","writeFileSync","Buffer","value","splitReportHtmlByExecution","options","outputDir","executionJsonFiles","writtenScreenshotFiles","fileIndex","singleExecutionDump","jsonFilePath"],"mappings":"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"}
1
+ {"version":3,"file":"report.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/report.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 copyFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n rmSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport * as path from 'node:path';\nimport { getMidsceneRunSubDir } from '@aiscene/shared/common';\nimport { antiEscapeScriptTag, logMsg } from '@aiscene/shared/utils';\nimport { getReportFileName } from './agent';\nimport {\n extractAllDumpScriptsSync,\n extractLastDumpScriptSync,\n getBaseUrlFixScript,\n streamDumpScriptsSync,\n streamImageScriptsToFile,\n} from './dump/html-utils';\nimport {\n normalizeScreenshotRef,\n resolveScreenshotSource,\n} from './dump/screenshot-store';\nimport {\n type ExecutionDump,\n type IExecutionDump,\n ReportActionDump,\n} from './types';\nimport type { ReportFileWithAttributes } from './types';\nimport { getReportTpl, getVersion, reportHTMLContent } from './utils';\n\n/**\n * Check if a report is in directory mode (html-and-external-assets).\n * Directory mode reports: {name}/index.html + {name}/screenshots/\n */\nexport function isDirectoryModeReport(reportFilePath: string): boolean {\n const reportDir = path.dirname(reportFilePath);\n return (\n path.basename(reportFilePath) === 'index.html' &&\n existsSync(path.join(reportDir, 'screenshots'))\n );\n}\n\n/**\n * Deduplicate executions by stable id, keeping only the last occurrence.\n * Old-format executions without id are always preserved.\n */\nexport function dedupeExecutionsKeepLatest<T extends Pick<ExecutionDump, 'id'>>(\n executions: T[],\n): T[] {\n let noIdCounter = 0;\n const deduped = new Map<string, T>();\n for (const exec of executions) {\n const key = exec.id || `__no_id_${noIdCounter++}`;\n deduped.set(key, exec);\n }\n return Array.from(deduped.values());\n}\n/**\n * Peek at the first `sdkVersion` field embedded in a midscene_web_dump\n * script tag inside the given report file. Returns undefined if no\n * recognizable tag or sdkVersion is present.\n */\nfunction peekReportSdkVersion(reportFilePath: string): string | undefined {\n try {\n const dump = extractLastDumpScriptSync(reportFilePath);\n if (!dump) return undefined;\n const match = dump.match(/\"sdkVersion\"\\s*:\\s*\"([^\"]+)\"/);\n return match?.[1];\n } catch {\n return undefined;\n }\n}\n\nconst warnedMismatchedVersions = new Set<string>();\n\nexport class ReportMergingTool {\n private reportInfos: ReportFileWithAttributes[] = [];\n\n private createEmptyDumpString(groupName: string, groupDescription?: string) {\n return new ReportActionDump({\n sdkVersion: '',\n groupName,\n groupDescription,\n modelBriefs: [],\n executions: [],\n }).serialize();\n }\n\n public append(reportInfo: ReportFileWithAttributes) {\n if (reportInfo.reportFilePath) {\n const sourceVersion = peekReportSdkVersion(reportInfo.reportFilePath);\n const currentVersion = getVersion();\n if (\n sourceVersion &&\n currentVersion &&\n sourceVersion !== currentVersion &&\n !warnedMismatchedVersions.has(sourceVersion)\n ) {\n warnedMismatchedVersions.add(sourceVersion);\n logMsg(\n `[@aiscene/core] ReportMergingTool version mismatch: source report was written by @aiscene/core@${sourceVersion} but the merger is @aiscene/core@${currentVersion}. This commonly means @aiscene/core and the device package (e.g. @aiscene/android) resolve to different versions in node_modules. Merged output may silently drop intermediate steps. Align the versions and reinstall (rm -rf node_modules package-lock.json && npm install).`,\n );\n }\n }\n this.reportInfos.push(reportInfo);\n }\n public clear() {\n this.reportInfos = [];\n }\n\n /**\n * Merge multiple dump script contents (from the same source report)\n * into a single serialized ReportActionDump string.\n * If there's only one dump, return it as-is. If multiple, merge\n * all executions into the first dump's group structure.\n */\n private mergeDumpScripts(contents: string[]): string {\n const unescaped = contents\n .map((c) => antiEscapeScriptTag(c))\n .filter((c) => c.length > 0);\n if (unescaped.length === 0) return '';\n if (unescaped.length === 1) return unescaped[0];\n\n // Parse all dumps and collect executions, deduplicating by id (keep last).\n // Only executions with a stable id are deduped; old-format entries without\n // id are always kept (they may be distinct despite sharing the same name).\n const base = ReportActionDump.fromSerializedString(unescaped[0]);\n const allExecutions = [...base.executions];\n for (let i = 1; i < unescaped.length; i++) {\n const other = ReportActionDump.fromSerializedString(unescaped[i]);\n allExecutions.push(...other.executions);\n }\n base.executions = dedupeExecutionsKeepLatest(allExecutions);\n return base.serialize();\n }\n\n public mergeReports(\n reportFileName: 'AUTO' | string = 'AUTO',\n opts?: {\n rmOriginalReports?: boolean;\n overwrite?: boolean;\n },\n ): string | null {\n const { rmOriginalReports = false, overwrite = false } = opts ?? {};\n\n if (this.reportInfos.length === 0) {\n logMsg('No reports to merge');\n return null;\n }\n\n const targetDir = getMidsceneRunSubDir('report');\n\n // Check if any source report is directory mode\n const hasDirectoryModeReport = this.reportInfos.some((info) => {\n const reportFilePath = info.reportFilePath;\n return Boolean(reportFilePath && isDirectoryModeReport(reportFilePath));\n });\n\n const resolvedName =\n reportFileName === 'AUTO'\n ? getReportFileName('merged-report')\n : reportFileName;\n\n // Directory mode: output as {name}/index.html to keep relative paths working\n // Inline mode: output as {name}.html (single file)\n const outputFilePath = hasDirectoryModeReport\n ? path.resolve(targetDir, resolvedName, 'index.html')\n : path.resolve(targetDir, `${resolvedName}.html`);\n\n if (reportFileName !== 'AUTO' && existsSync(outputFilePath)) {\n if (!overwrite) {\n throw new Error(\n `Report file already exists: ${outputFilePath}\\nSet overwrite to true to overwrite this file.`,\n );\n }\n if (hasDirectoryModeReport) {\n rmSync(path.dirname(outputFilePath), { recursive: true, force: true });\n } else {\n unlinkSync(outputFilePath);\n }\n }\n\n if (hasDirectoryModeReport) {\n mkdirSync(path.dirname(outputFilePath), { recursive: true });\n }\n\n logMsg(\n `Start merging ${this.reportInfos.length} reports...\\nCreating template file...`,\n );\n\n try {\n // Write template without closing </html> tag so we can append\n // dump scripts before it. The closing tag is added at the end.\n const htmlEndTag = '</html>';\n const tpl = getReportTpl();\n const htmlEndIdx = tpl.lastIndexOf(htmlEndTag);\n const tplWithoutClose =\n htmlEndIdx !== -1 ? tpl.slice(0, htmlEndIdx) : tpl;\n appendFileSync(outputFilePath, tplWithoutClose);\n\n // For directory-mode output, inject base URL fix script\n if (hasDirectoryModeReport) {\n appendFileSync(outputFilePath, getBaseUrlFixScript());\n }\n\n // Process all reports one by one\n for (let i = 0; i < this.reportInfos.length; i++) {\n const reportInfo = this.reportInfos[i];\n logMsg(`Processing report ${i + 1}/${this.reportInfos.length}`);\n\n const { reportAttributes } = reportInfo;\n let dumpString = this.createEmptyDumpString(\n reportAttributes.testTitle,\n reportAttributes.testDescription,\n );\n let mergedGroupId = `merged-group-${i}`;\n\n if (reportInfo.reportFilePath) {\n if (isDirectoryModeReport(reportInfo.reportFilePath)) {\n // Directory mode: copy external screenshot files\n const reportDir = path.dirname(reportInfo.reportFilePath);\n const screenshotsDir = path.join(reportDir, 'screenshots');\n const mergedScreenshotsDir = path.join(\n path.dirname(outputFilePath),\n 'screenshots',\n );\n mkdirSync(mergedScreenshotsDir, { recursive: true });\n for (const file of readdirSync(screenshotsDir)) {\n const src = path.join(screenshotsDir, file);\n const dest = path.join(mergedScreenshotsDir, file);\n copyFileSync(src, dest);\n }\n } else {\n // Inline mode: stream image scripts to output file\n streamImageScriptsToFile(reportInfo.reportFilePath, outputFilePath);\n }\n\n // Extract all dump scripts from the source report.\n // After the per-execution append refactor, a single source report\n // may contain multiple <script type=\"midscene_web_dump\"> tags\n // (one per execution). We merge them into a single ReportActionDump.\n // Filter by data-group-id to exclude false matches from the template's\n // bundled JS code, which also references the midscene_web_dump type string.\n const allDumps = extractAllDumpScriptsSync(\n reportInfo.reportFilePath,\n ).filter((d) => d.openTag.includes('data-group-id'));\n const groupIdMatch = allDumps[0]?.openTag.match(\n /data-group-id=\"([^\"]+)\"/,\n );\n if (groupIdMatch) {\n mergedGroupId = decodeURIComponent(groupIdMatch[1]);\n }\n const extractedDumpString =\n allDumps.length > 0\n ? this.mergeDumpScripts(allDumps.map((d) => d.content))\n : extractLastDumpScriptSync(reportInfo.reportFilePath);\n if (extractedDumpString) {\n dumpString = extractedDumpString;\n }\n }\n\n const reportHtmlStr = `${reportHTMLContent(\n {\n dumpString,\n attributes: {\n 'data-group-id': mergedGroupId,\n playwright_test_duration: reportAttributes.testDuration,\n playwright_test_status: reportAttributes.testStatus,\n playwright_test_title: reportAttributes.testTitle,\n playwright_test_id: reportAttributes.testId,\n playwright_test_description: reportAttributes.testDescription,\n is_merged: true,\n },\n },\n undefined,\n undefined,\n false,\n )}\\n`;\n\n appendFileSync(outputFilePath, reportHtmlStr);\n }\n\n // Close the HTML document\n appendFileSync(outputFilePath, `${htmlEndTag}\\n`);\n\n logMsg(`Successfully merged new report: ${outputFilePath}`);\n\n // Remove original reports if needed\n if (rmOriginalReports) {\n for (const info of this.reportInfos) {\n if (!info.reportFilePath) continue;\n try {\n if (isDirectoryModeReport(info.reportFilePath)) {\n // Directory mode: remove the entire report directory\n const reportDir = path.dirname(info.reportFilePath);\n rmSync(reportDir, { recursive: true, force: true });\n } else {\n unlinkSync(info.reportFilePath);\n }\n } catch (error) {\n logMsg(`Error deleting report ${info.reportFilePath}: ${error}`);\n }\n }\n logMsg(`Removed ${this.reportInfos.length} original reports`);\n }\n return outputFilePath;\n } catch (error) {\n logMsg(`Error in mergeReports: ${error}`);\n throw error;\n }\n }\n}\n\nexport interface SplitReportHtmlOptions {\n htmlPath: string;\n outputDir: string;\n}\n\nexport interface SplitReportHtmlResult {\n executionJsonFiles: string[];\n screenshotFiles: string[];\n}\n\nexport interface CollectedReportExecutions {\n baseDump: ReportActionDump;\n executions: IExecutionDump[];\n}\n\n/**\n * Collect executions from a report HTML, deduplicating by stable id while\n * keeping only the latest occurrence. Old-format executions without id are\n * always preserved.\n */\nexport function collectDedupedExecutions(\n htmlPath: string,\n): CollectedReportExecutions {\n let baseDump: ReportActionDump | null = null;\n let executionSerial = 0;\n const latestSerialByExecutionId = new Map<string, number>();\n\n streamDumpScriptsSync(htmlPath, (dumpScript) => {\n if (!dumpScript.openTag.includes('data-group-id')) {\n return false;\n }\n const groupedDump = ReportActionDump.fromSerializedString(\n antiEscapeScriptTag(dumpScript.content),\n );\n for (const execution of groupedDump.executions) {\n executionSerial += 1;\n if (execution.id) {\n latestSerialByExecutionId.set(execution.id, executionSerial);\n }\n }\n return false;\n });\n\n const executions: IExecutionDump[] = [];\n executionSerial = 0;\n streamDumpScriptsSync(htmlPath, (dumpScript) => {\n if (!dumpScript.openTag.includes('data-group-id')) {\n return false;\n }\n\n const groupedDump = ReportActionDump.fromSerializedString(\n antiEscapeScriptTag(dumpScript.content),\n );\n if (!baseDump) {\n baseDump = groupedDump;\n }\n\n for (const execution of groupedDump.executions) {\n executionSerial += 1;\n if (\n execution.id &&\n latestSerialByExecutionId.get(execution.id) !== executionSerial\n ) {\n continue;\n }\n executions.push(execution);\n }\n\n return false;\n });\n\n if (!baseDump) {\n throw new Error(`No report dump scripts found in ${htmlPath}`);\n }\n\n return {\n baseDump,\n executions,\n };\n}\n\nfunction extensionByMimeType(mimeType: string): 'png' | 'jpeg' {\n if (mimeType === 'image/png') return 'png';\n if (mimeType === 'image/jpeg') return 'jpeg';\n throw new Error(`Unsupported screenshot mime type: ${mimeType}`);\n}\n\nfunction externalizeScreenshotsInExecution(\n execution: IExecutionDump,\n opts: {\n htmlPath: string;\n screenshotsDir: string;\n writtenFiles: Set<string>;\n },\n): void {\n const visit = (node: unknown): void => {\n if (Array.isArray(node)) {\n for (const item of node) {\n visit(item);\n }\n return;\n }\n\n if (typeof node !== 'object' || node === null) return;\n\n const ref = normalizeScreenshotRef(node);\n if (ref) {\n const ext = extensionByMimeType(ref.mimeType);\n const fileName = `${ref.id}.${ext}`;\n const relativePath = `./screenshots/${fileName}`;\n const absolutePath = path.join(opts.screenshotsDir, fileName);\n\n if (!opts.writtenFiles.has(fileName)) {\n const resolved = resolveScreenshotSource(ref, {\n reportPath: opts.htmlPath,\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 } else {\n copyFileSync(resolved.filePath, absolutePath);\n }\n opts.writtenFiles.add(fileName);\n }\n\n ref.storage = 'file';\n ref.path = relativePath;\n return;\n }\n\n for (const value of Object.values(node)) {\n visit(value);\n }\n };\n\n visit(execution);\n}\n\n/**\n * Reverse parse a Midscene report HTML into per-execution JSON files and\n * externalized screenshots.\n */\nexport function splitReportHtmlByExecution(\n options: SplitReportHtmlOptions,\n): SplitReportHtmlResult {\n const { htmlPath, outputDir } = options;\n const screenshotsDir = path.join(outputDir, 'screenshots');\n\n mkdirSync(outputDir, { recursive: true });\n mkdirSync(screenshotsDir, { recursive: true });\n\n const executionJsonFiles: string[] = [];\n const writtenScreenshotFiles = new Set<string>();\n const { baseDump, executions } = collectDedupedExecutions(htmlPath);\n\n let fileIndex = 0;\n for (const execution of executions) {\n fileIndex += 1;\n externalizeScreenshotsInExecution(execution, {\n htmlPath,\n screenshotsDir,\n writtenFiles: writtenScreenshotFiles,\n });\n const singleExecutionDump = new ReportActionDump({\n sdkVersion: baseDump.sdkVersion,\n groupName: baseDump.groupName,\n groupDescription: baseDump.groupDescription,\n modelBriefs: baseDump.modelBriefs,\n deviceType: baseDump.deviceType,\n executions: [execution],\n });\n\n const jsonFilePath = path.join(outputDir, `${fileIndex}.execution.json`);\n writeFileSync(jsonFilePath, singleExecutionDump.serialize(2), 'utf-8');\n executionJsonFiles.push(jsonFilePath);\n }\n\n return {\n executionJsonFiles,\n screenshotFiles: Array.from(writtenScreenshotFiles)\n .sort()\n .map((fileName) => path.join(screenshotsDir, fileName)),\n };\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","isDirectoryModeReport","reportFilePath","reportDir","path","existsSync","dedupeExecutionsKeepLatest","executions","noIdCounter","deduped","Map","exec","Array","peekReportSdkVersion","dump","extractLastDumpScriptSync","match","warnedMismatchedVersions","Set","ReportMergingTool","groupName","groupDescription","ReportActionDump","reportInfo","sourceVersion","currentVersion","getVersion","logMsg","contents","unescaped","c","antiEscapeScriptTag","base","allExecutions","i","other","reportFileName","opts","rmOriginalReports","overwrite","targetDir","getMidsceneRunSubDir","hasDirectoryModeReport","info","Boolean","resolvedName","getReportFileName","outputFilePath","Error","rmSync","unlinkSync","mkdirSync","htmlEndTag","tpl","getReportTpl","htmlEndIdx","tplWithoutClose","appendFileSync","getBaseUrlFixScript","reportAttributes","dumpString","mergedGroupId","screenshotsDir","mergedScreenshotsDir","file","readdirSync","src","dest","copyFileSync","streamImageScriptsToFile","allDumps","extractAllDumpScriptsSync","d","groupIdMatch","decodeURIComponent","extractedDumpString","reportHtmlStr","reportHTMLContent","undefined","error","collectDedupedExecutions","htmlPath","baseDump","executionSerial","latestSerialByExecutionId","streamDumpScriptsSync","dumpScript","groupedDump","execution","extensionByMimeType","mimeType","externalizeScreenshotsInExecution","visit","node","item","ref","normalizeScreenshotRef","ext","fileName","relativePath","absolutePath","resolved","resolveScreenshotSource","rawBase64","writeFileSync","Buffer","value","splitReportHtmlByExecution","options","outputDir","executionJsonFiles","writtenScreenshotFiles","fileIndex","singleExecutionDump","jsonFilePath"],"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+BO,SAASI,sBAAsBC,cAAsB;IAC1D,MAAMC,YAAYC,mCAAAA,OAAY,CAACF;IAC/B,OACEE,AAAkC,iBAAlCA,mCAAAA,QAAa,CAACF,mBACdG,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAWD,mCAAAA,IAAS,CAACD,WAAW;AAEpC;AAMO,SAASG,2BACdC,UAAe;IAEf,IAAIC,cAAc;IAClB,MAAMC,UAAU,IAAIC;IACpB,KAAK,MAAMC,QAAQJ,WAAY;QAC7B,MAAMX,MAAMe,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAEH,eAAe;QACjDC,QAAQ,GAAG,CAACb,KAAKe;IACnB;IACA,OAAOC,MAAM,IAAI,CAACH,QAAQ,MAAM;AAClC;AAMA,SAASI,qBAAqBX,cAAsB;IAClD,IAAI;QACF,MAAMY,OAAOC,AAAAA,IAAAA,8BAAAA,yBAAAA,AAAAA,EAA0Bb;QACvC,IAAI,CAACY,MAAM;QACX,MAAME,QAAQF,KAAK,KAAK,CAAC;QACzB,OAAOE,OAAO,CAAC,EAAE;IACnB,EAAE,OAAM;QACN;IACF;AACF;AAEA,MAAMC,2BAA2B,IAAIC;AAE9B,MAAMC;IAGH,sBAAsBC,SAAiB,EAAEC,gBAAyB,EAAE;QAC1E,OAAO,IAAIC,kCAAAA,gBAAgBA,CAAC;YAC1B,YAAY;YACZF;YACAC;YACA,aAAa,EAAE;YACf,YAAY,EAAE;QAChB,GAAG,SAAS;IACd;IAEO,OAAOE,UAAoC,EAAE;QAClD,IAAIA,WAAW,cAAc,EAAE;YAC7B,MAAMC,gBAAgBX,qBAAqBU,WAAW,cAAc;YACpE,MAAME,iBAAiBC,AAAAA,IAAAA,kCAAAA,UAAAA,AAAAA;YACvB,IACEF,iBACAC,kBACAD,kBAAkBC,kBAClB,CAACR,yBAAyB,GAAG,CAACO,gBAC9B;gBACAP,yBAAyB,GAAG,CAACO;gBAC7BG,IAAAA,sBAAAA,MAAAA,AAAAA,EACE,CAAC,+FAA+F,EAAEH,cAAc,iCAAiC,EAAEC,eAAe,8QAA8Q,CAAC;YAErb;QACF;QACA,IAAI,CAAC,WAAW,CAAC,IAAI,CAACF;IACxB;IACO,QAAQ;QACb,IAAI,CAAC,WAAW,GAAG,EAAE;IACvB;IAQQ,iBAAiBK,QAAkB,EAAU;QACnD,MAAMC,YAAYD,SACf,GAAG,CAAC,CAACE,IAAMC,AAAAA,IAAAA,sBAAAA,mBAAAA,AAAAA,EAAoBD,IAC/B,MAAM,CAAC,CAACA,IAAMA,EAAE,MAAM,GAAG;QAC5B,IAAID,AAAqB,MAArBA,UAAU,MAAM,EAAQ,OAAO;QACnC,IAAIA,AAAqB,MAArBA,UAAU,MAAM,EAAQ,OAAOA,SAAS,CAAC,EAAE;QAK/C,MAAMG,OAAOV,kCAAAA,gBAAAA,CAAAA,oBAAqC,CAACO,SAAS,CAAC,EAAE;QAC/D,MAAMI,gBAAgB;eAAID,KAAK,UAAU;SAAC;QAC1C,IAAK,IAAIE,IAAI,GAAGA,IAAIL,UAAU,MAAM,EAAEK,IAAK;YACzC,MAAMC,QAAQb,kCAAAA,gBAAAA,CAAAA,oBAAqC,CAACO,SAAS,CAACK,EAAE;YAChED,cAAc,IAAI,IAAIE,MAAM,UAAU;QACxC;QACAH,KAAK,UAAU,GAAG1B,2BAA2B2B;QAC7C,OAAOD,KAAK,SAAS;IACvB;IAEO,aACLI,iBAAkC,MAAM,EACxCC,IAGC,EACc;QACf,MAAM,EAAEC,oBAAoB,KAAK,EAAEC,YAAY,KAAK,EAAE,GAAGF,QAAQ,CAAC;QAElE,IAAI,AAA4B,MAA5B,IAAI,CAAC,WAAW,CAAC,MAAM,EAAQ;YACjCV,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO;YACP,OAAO;QACT;QAEA,MAAMa,YAAYC,AAAAA,IAAAA,uBAAAA,oBAAAA,AAAAA,EAAqB;QAGvC,MAAMC,yBAAyB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAACC;YACpD,MAAMzC,iBAAiByC,KAAK,cAAc;YAC1C,OAAOC,QAAQ1C,kBAAkBD,sBAAsBC;QACzD;QAEA,MAAM2C,eACJT,AAAmB,WAAnBA,iBACIU,AAAAA,IAAAA,yBAAAA,iBAAAA,AAAAA,EAAkB,mBAClBV;QAIN,MAAMW,iBAAiBL,yBACnBtC,mCAAAA,OAAY,CAACoC,WAAWK,cAAc,gBACtCzC,mCAAAA,OAAY,CAACoC,WAAW,GAAGK,aAAa,KAAK,CAAC;QAElD,IAAIT,AAAmB,WAAnBA,kBAA6B/B,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAW0C,iBAAiB;YAC3D,IAAI,CAACR,WACH,MAAM,IAAIS,MACR,CAAC,4BAA4B,EAAED,eAAe,+CAA+C,CAAC;YAGlG,IAAIL,wBACFO,AAAAA,IAAAA,iCAAAA,MAAAA,AAAAA,EAAO7C,mCAAAA,OAAY,CAAC2C,iBAAiB;gBAAE,WAAW;gBAAM,OAAO;YAAK;iBAEpEG,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAWH;QAEf;QAEA,IAAIL,wBACFS,AAAAA,IAAAA,iCAAAA,SAAAA,AAAAA,EAAU/C,mCAAAA,OAAY,CAAC2C,iBAAiB;YAAE,WAAW;QAAK;QAG5DpB,IAAAA,sBAAAA,MAAAA,AAAAA,EACE,CAAC,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,sCAAsC,CAAC;QAGlF,IAAI;YAGF,MAAMyB,aAAa;YACnB,MAAMC,MAAMC,AAAAA,IAAAA,kCAAAA,YAAAA,AAAAA;YACZ,MAAMC,aAAaF,IAAI,WAAW,CAACD;YACnC,MAAMI,kBACJD,AAAe,OAAfA,aAAoBF,IAAI,KAAK,CAAC,GAAGE,cAAcF;YACjDI,IAAAA,iCAAAA,cAAAA,AAAAA,EAAeV,gBAAgBS;YAG/B,IAAId,wBACFe,AAAAA,IAAAA,iCAAAA,cAAAA,AAAAA,EAAeV,gBAAgBW,AAAAA,IAAAA,8BAAAA,mBAAAA,AAAAA;YAIjC,IAAK,IAAIxB,IAAI,GAAGA,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAEA,IAAK;gBAChD,MAAMX,aAAa,IAAI,CAAC,WAAW,CAACW,EAAE;gBACtCP,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAAC,kBAAkB,EAAEO,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE;gBAE9D,MAAM,EAAEyB,gBAAgB,EAAE,GAAGpC;gBAC7B,IAAIqC,aAAa,IAAI,CAAC,qBAAqB,CACzCD,iBAAiB,SAAS,EAC1BA,iBAAiB,eAAe;gBAElC,IAAIE,gBAAgB,CAAC,aAAa,EAAE3B,GAAG;gBAEvC,IAAIX,WAAW,cAAc,EAAE;oBAC7B,IAAItB,sBAAsBsB,WAAW,cAAc,GAAG;wBAEpD,MAAMpB,YAAYC,mCAAAA,OAAY,CAACmB,WAAW,cAAc;wBACxD,MAAMuC,iBAAiB1D,mCAAAA,IAAS,CAACD,WAAW;wBAC5C,MAAM4D,uBAAuB3D,mCAAAA,IAAS,CACpCA,mCAAAA,OAAY,CAAC2C,iBACb;wBAEFI,IAAAA,iCAAAA,SAAAA,AAAAA,EAAUY,sBAAsB;4BAAE,WAAW;wBAAK;wBAClD,KAAK,MAAMC,QAAQC,AAAAA,IAAAA,iCAAAA,WAAAA,AAAAA,EAAYH,gBAAiB;4BAC9C,MAAMI,MAAM9D,mCAAAA,IAAS,CAAC0D,gBAAgBE;4BACtC,MAAMG,OAAO/D,mCAAAA,IAAS,CAAC2D,sBAAsBC;4BAC7CI,IAAAA,iCAAAA,YAAAA,AAAAA,EAAaF,KAAKC;wBACpB;oBACF,OAEEE,AAAAA,IAAAA,8BAAAA,wBAAAA,AAAAA,EAAyB9C,WAAW,cAAc,EAAEwB;oBAStD,MAAMuB,WAAWC,AAAAA,IAAAA,8BAAAA,yBAAAA,AAAAA,EACfhD,WAAW,cAAc,EACzB,MAAM,CAAC,CAACiD,IAAMA,EAAE,OAAO,CAAC,QAAQ,CAAC;oBACnC,MAAMC,eAAeH,QAAQ,CAAC,EAAE,EAAE,QAAQ,MACxC;oBAEF,IAAIG,cACFZ,gBAAgBa,mBAAmBD,YAAY,CAAC,EAAE;oBAEpD,MAAME,sBACJL,SAAS,MAAM,GAAG,IACd,IAAI,CAAC,gBAAgB,CAACA,SAAS,GAAG,CAAC,CAACE,IAAMA,EAAE,OAAO,KACnDzD,AAAAA,IAAAA,8BAAAA,yBAAAA,AAAAA,EAA0BQ,WAAW,cAAc;oBACzD,IAAIoD,qBACFf,aAAae;gBAEjB;gBAEA,MAAMC,gBAAgB,GAAGC,AAAAA,IAAAA,kCAAAA,iBAAAA,AAAAA,EACvB;oBACEjB;oBACA,YAAY;wBACV,iBAAiBC;wBACjB,0BAA0BF,iBAAiB,YAAY;wBACvD,wBAAwBA,iBAAiB,UAAU;wBACnD,uBAAuBA,iBAAiB,SAAS;wBACjD,oBAAoBA,iBAAiB,MAAM;wBAC3C,6BAA6BA,iBAAiB,eAAe;wBAC7D,WAAW;oBACb;gBACF,GACAmB,QACAA,QACA,OACA,EAAE,CAAC;gBAELrB,IAAAA,iCAAAA,cAAAA,AAAAA,EAAeV,gBAAgB6B;YACjC;YAGAnB,IAAAA,iCAAAA,cAAAA,AAAAA,EAAeV,gBAAgB,GAAGK,WAAW,EAAE,CAAC;YAEhDzB,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAAC,gCAAgC,EAAEoB,gBAAgB;YAG1D,IAAIT,mBAAmB;gBACrB,KAAK,MAAMK,QAAQ,IAAI,CAAC,WAAW,CACjC,IAAKA,KAAK,cAAc,EACxB,IAAI;oBACF,IAAI1C,sBAAsB0C,KAAK,cAAc,GAAG;wBAE9C,MAAMxC,YAAYC,mCAAAA,OAAY,CAACuC,KAAK,cAAc;wBAClDM,IAAAA,iCAAAA,MAAAA,AAAAA,EAAO9C,WAAW;4BAAE,WAAW;4BAAM,OAAO;wBAAK;oBACnD,OACE+C,AAAAA,IAAAA,iCAAAA,UAAAA,AAAAA,EAAWP,KAAK,cAAc;gBAElC,EAAE,OAAOoC,OAAO;oBACdpD,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAAC,sBAAsB,EAAEgB,KAAK,cAAc,CAAC,EAAE,EAAEoC,OAAO;gBACjE;gBAEFpD,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC9D;YACA,OAAOoB;QACT,EAAE,OAAOgC,OAAO;YACdpD,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAAC,uBAAuB,EAAEoD,OAAO;YACxC,MAAMA;QACR;IACF;;QA1OA,uBAAQ,eAA0C,EAAE;;AA2OtD;AAsBO,SAASC,yBACdC,QAAgB;IAEhB,IAAIC,WAAoC;IACxC,IAAIC,kBAAkB;IACtB,MAAMC,4BAA4B,IAAI1E;IAEtC2E,IAAAA,8BAAAA,qBAAAA,AAAAA,EAAsBJ,UAAU,CAACK;QAC/B,IAAI,CAACA,WAAW,OAAO,CAAC,QAAQ,CAAC,kBAC/B,OAAO;QAET,MAAMC,cAAcjE,kCAAAA,gBAAAA,CAAAA,oBAAqC,CACvDS,AAAAA,IAAAA,sBAAAA,mBAAAA,AAAAA,EAAoBuD,WAAW,OAAO;QAExC,KAAK,MAAME,aAAaD,YAAY,UAAU,CAAE;YAC9CJ,mBAAmB;YACnB,IAAIK,UAAU,EAAE,EACdJ,0BAA0B,GAAG,CAACI,UAAU,EAAE,EAAEL;QAEhD;QACA,OAAO;IACT;IAEA,MAAM5E,aAA+B,EAAE;IACvC4E,kBAAkB;IAClBE,IAAAA,8BAAAA,qBAAAA,AAAAA,EAAsBJ,UAAU,CAACK;QAC/B,IAAI,CAACA,WAAW,OAAO,CAAC,QAAQ,CAAC,kBAC/B,OAAO;QAGT,MAAMC,cAAcjE,kCAAAA,gBAAAA,CAAAA,oBAAqC,CACvDS,AAAAA,IAAAA,sBAAAA,mBAAAA,AAAAA,EAAoBuD,WAAW,OAAO;QAExC,IAAI,CAACJ,UACHA,WAAWK;QAGb,KAAK,MAAMC,aAAaD,YAAY,UAAU,CAAE;YAC9CJ,mBAAmB;YACnB,IACEK,CAAAA,UAAU,EAAE,IACZJ,0BAA0B,GAAG,CAACI,UAAU,EAAE,MAAML,iBAIlD5E,WAAW,IAAI,CAACiF;QAClB;QAEA,OAAO;IACT;IAEA,IAAI,CAACN,UACH,MAAM,IAAIlC,MAAM,CAAC,gCAAgC,EAAEiC,UAAU;IAG/D,OAAO;QACLC;QACA3E;IACF;AACF;AAEA,SAASkF,oBAAoBC,QAAgB;IAC3C,IAAIA,AAAa,gBAAbA,UAA0B,OAAO;IACrC,IAAIA,AAAa,iBAAbA,UAA2B,OAAO;IACtC,MAAM,IAAI1C,MAAM,CAAC,kCAAkC,EAAE0C,UAAU;AACjE;AAEA,SAASC,kCACPH,SAAyB,EACzBnD,IAIC;IAED,MAAMuD,QAAQ,CAACC;QACb,IAAIjF,MAAM,OAAO,CAACiF,OAAO;YACvB,KAAK,MAAMC,QAAQD,KACjBD,MAAME;YAER;QACF;QAEA,IAAI,AAAgB,YAAhB,OAAOD,QAAqBA,AAAS,SAATA,MAAe;QAE/C,MAAME,MAAMC,AAAAA,IAAAA,oCAAAA,sBAAAA,AAAAA,EAAuBH;QACnC,IAAIE,KAAK;YACP,MAAME,MAAMR,oBAAoBM,IAAI,QAAQ;YAC5C,MAAMG,WAAW,GAAGH,IAAI,EAAE,CAAC,CAAC,EAAEE,KAAK;YACnC,MAAME,eAAe,CAAC,cAAc,EAAED,UAAU;YAChD,MAAME,eAAehG,mCAAAA,IAAS,CAACiC,KAAK,cAAc,EAAE6D;YAEpD,IAAI,CAAC7D,KAAK,YAAY,CAAC,GAAG,CAAC6D,WAAW;gBACpC,MAAMG,WAAWC,AAAAA,IAAAA,oCAAAA,uBAAAA,AAAAA,EAAwBP,KAAK;oBAC5C,YAAY1D,KAAK,QAAQ;gBAC3B;gBACA,IAAIgE,AAAkB,eAAlBA,SAAS,IAAI,EAAiB;oBAChC,MAAME,YAAYF,SAAS,OAAO,CAAC,OAAO,CACxC,mCACA;oBAEFG,IAAAA,iCAAAA,aAAAA,AAAAA,EAAcJ,cAAcK,OAAO,IAAI,CAACF,WAAW;gBACrD,OACEnC,AAAAA,IAAAA,iCAAAA,YAAAA,AAAAA,EAAaiC,SAAS,QAAQ,EAAED;gBAElC/D,KAAK,YAAY,CAAC,GAAG,CAAC6D;YACxB;YAEAH,IAAI,OAAO,GAAG;YACdA,IAAI,IAAI,GAAGI;YACX;QACF;QAEA,KAAK,MAAMO,SAAS7G,OAAO,MAAM,CAACgG,MAChCD,MAAMc;IAEV;IAEAd,MAAMJ;AACR;AAMO,SAASmB,2BACdC,OAA+B;IAE/B,MAAM,EAAE3B,QAAQ,EAAE4B,SAAS,EAAE,GAAGD;IAChC,MAAM9C,iBAAiB1D,mCAAAA,IAAS,CAACyG,WAAW;IAE5C1D,IAAAA,iCAAAA,SAAAA,AAAAA,EAAU0D,WAAW;QAAE,WAAW;IAAK;IACvC1D,IAAAA,iCAAAA,SAAAA,AAAAA,EAAUW,gBAAgB;QAAE,WAAW;IAAK;IAE5C,MAAMgD,qBAA+B,EAAE;IACvC,MAAMC,yBAAyB,IAAI7F;IACnC,MAAM,EAAEgE,QAAQ,EAAE3E,UAAU,EAAE,GAAGyE,yBAAyBC;IAE1D,IAAI+B,YAAY;IAChB,KAAK,MAAMxB,aAAajF,WAAY;QAClCyG,aAAa;QACbrB,kCAAkCH,WAAW;YAC3CP;YACAnB;YACA,cAAciD;QAChB;QACA,MAAME,sBAAsB,IAAI3F,kCAAAA,gBAAgBA,CAAC;YAC/C,YAAY4D,SAAS,UAAU;YAC/B,WAAWA,SAAS,SAAS;YAC7B,kBAAkBA,SAAS,gBAAgB;YAC3C,aAAaA,SAAS,WAAW;YACjC,YAAYA,SAAS,UAAU;YAC/B,YAAY;gBAACM;aAAU;QACzB;QAEA,MAAM0B,eAAe9G,mCAAAA,IAAS,CAACyG,WAAW,GAAGG,UAAU,eAAe,CAAC;QACvER,IAAAA,iCAAAA,aAAAA,AAAAA,EAAcU,cAAcD,oBAAoB,SAAS,CAAC,IAAI;QAC9DH,mBAAmB,IAAI,CAACI;IAC1B;IAEA,OAAO;QACLJ;QACA,iBAAiBlG,MAAM,IAAI,CAACmG,wBACzB,IAAI,GACJ,GAAG,CAAC,CAACb,WAAa9F,mCAAAA,IAAS,CAAC0D,gBAAgBoC;IACjD;AACF"}
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot-item.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/screenshot-item.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 { readFileSync } from 'node:fs';\nimport { uuid } from '@aiscene/shared/utils';\nimport { extractImageByIdSync } from './dump/html-utils';\nimport {\n type ScreenshotRef,\n normalizeScreenshotRef,\n} from './dump/screenshot-store';\n\n/**\n * Serialization format for ScreenshotItem\n * - { $screenshot: \"id\" } - inline mode, references imageMap in HTML\n * - { base64: \"path\" } - directory mode, references external file path\n */\nexport type ScreenshotSerializeFormat = ScreenshotRef;\n\n/**\n * Detect image format from base64 data URI prefix.\n */\nfunction detectFormat(base64: string): 'png' | 'jpeg' {\n if (base64.startsWith('data:image/jpeg')) return 'jpeg';\n if (base64.startsWith('data:image/jpg')) return 'jpeg';\n return 'png';\n}\n\n/**\n * ScreenshotItem encapsulates screenshot data.\n *\n * Supports lazy loading after memory release:\n * - inline mode: reads from HTML file using streaming (extractImageByIdSync)\n * - directory mode: reads from file on disk\n *\n * After persistence, memory is released but the screenshot can be recovered\n * on-demand from disk, making it safe to release memory at any time.\n */\nexport class ScreenshotItem {\n private _id: string;\n private _base64: string | null;\n private _format: 'png' | 'jpeg';\n private _capturedAt: number;\n private _serializedRef: ScreenshotRef | null = null;\n private _persistedPath: string | null = null;\n private _persistedHtmlPath: string | null = null;\n\n private constructor(id: string, base64: string, capturedAt: number) {\n this._id = id;\n this._base64 = base64;\n this._format = detectFormat(base64);\n this._capturedAt = capturedAt;\n }\n\n /** Create a new ScreenshotItem from base64 data */\n static create(base64: string, capturedAt: number): ScreenshotItem {\n return new ScreenshotItem(uuid(), base64, capturedAt);\n }\n\n get id(): string {\n return this._id;\n }\n\n /** Get the image format (png or jpeg) */\n get format(): 'png' | 'jpeg' {\n return this._format;\n }\n\n /** Get the file extension for this screenshot */\n get extension(): string {\n return this._format === 'jpeg' ? 'jpeg' : 'png';\n }\n\n /** Get screenshot capture timestamp in milliseconds */\n get capturedAt(): number {\n return this._capturedAt;\n }\n\n get base64(): string {\n // If data is in memory, return it directly\n if (this._base64 !== null) {\n return this._base64;\n }\n\n const loadFromFile = (): string => {\n if (this._persistedPath === null) {\n throw new Error(`Screenshot ${this._id}: file recovery path missing`);\n }\n const buffer = readFileSync(this._persistedPath);\n return `data:image/${this._format};base64,${buffer.toString('base64')}`;\n };\n\n const loadFromInline = (): string => {\n if (this._persistedHtmlPath === null) {\n throw new Error(`Screenshot ${this._id}: HTML recovery path missing`);\n }\n const data = extractImageByIdSync(this._persistedHtmlPath, this._id);\n if (data) {\n return data;\n }\n throw new Error(\n `Screenshot ${this._id}: cannot recover from HTML (id not found in ${this._persistedHtmlPath})`,\n );\n };\n\n // Recover from the primary serialized mode first.\n if (this._serializedRef?.storage === 'file') {\n return loadFromFile();\n }\n\n if (this._serializedRef?.storage === 'inline') {\n return loadFromInline();\n }\n\n // Fall back to whichever recovery path is available.\n if (this._persistedPath !== null) {\n return loadFromFile();\n }\n\n if (this._persistedHtmlPath !== null) {\n return loadFromInline();\n }\n\n throw new Error(\n `Screenshot ${this._id}: base64 data released without recovery path`,\n );\n }\n\n /** Check if base64 data is still available in memory (not yet released) */\n hasBase64(): boolean {\n return this._base64 !== null;\n }\n\n /**\n * Mark as persisted to HTML (inline mode).\n * Releases base64 memory, but keeps HTML path for lazy loading recovery.\n * @param htmlPath - absolute path to the HTML file containing the image\n */\n markPersistedInline(htmlPath: string): ScreenshotRef {\n const ref = this.createRef('inline');\n this._serializedRef = ref;\n this._persistedHtmlPath = htmlPath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Register a file-backed recovery path without changing the serialized mode.\n * Used when inline persistence also needs a shared file copy next to dumps.\n */\n registerPersistedFileCopy(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.createRef('file', relativePath);\n this._persistedPath = absolutePath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Mark as persisted to file (directory mode).\n * Releases base64 memory, but keeps file path for lazy loading recovery.\n * @param relativePath - relative path for serialization (e.g., \"./screenshots/id.jpeg\")\n * @param absolutePath - absolute path for lazy loading recovery\n */\n markPersistedToPath(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.registerPersistedFileCopy(relativePath, absolutePath);\n this._serializedRef = ref;\n return ref;\n }\n\n /** Serialize for JSON - format depends on persistence state */\n toSerializable(): ScreenshotSerializeFormat {\n return (\n this._serializedRef ?? {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage: 'inline',\n }\n );\n }\n\n /** Check if a value is a serialized ScreenshotItem reference (inline or directory mode) */\n static isSerialized(value: unknown): value is ScreenshotSerializeFormat {\n return normalizeScreenshotRef(value) !== null;\n }\n\n private createRef(\n storage: 'inline' | 'file',\n relativePath?: string,\n ): ScreenshotRef {\n const baseRef: Omit<ScreenshotRef, 'path'> = {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage,\n };\n if (storage === 'file') {\n return {\n ...baseRef,\n storage,\n path: relativePath!,\n };\n }\n return baseRef;\n }\n\n /**\n * Get base64 data without the data URI prefix.\n * Useful for writing raw binary data to files.\n */\n get rawBase64(): string {\n return this.base64.replace(/^data:image\\/(png|jpeg|jpg);base64,/, '');\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","detectFormat","base64","ScreenshotItem","capturedAt","uuid","loadFromFile","Error","buffer","readFileSync","loadFromInline","data","extractImageByIdSync","htmlPath","ref","relativePath","absolutePath","value","normalizeScreenshotRef","storage","baseRef","id"],"mappings":"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"}
1
+ {"version":3,"file":"screenshot-item.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/screenshot-item.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 { readFileSync } from 'node:fs';\nimport { uuid } from '@aiscene/shared/utils';\nimport { extractImageByIdSync } from './dump/html-utils';\nimport {\n type ScreenshotRef,\n normalizeScreenshotRef,\n} from './dump/screenshot-store';\n\n/**\n * Serialization format for ScreenshotItem\n * - { $screenshot: \"id\" } - inline mode, references imageMap in HTML\n * - { base64: \"path\" } - directory mode, references external file path\n */\nexport type ScreenshotSerializeFormat = ScreenshotRef;\n\n/**\n * Detect image format from base64 data URI prefix.\n */\nfunction detectFormat(base64: string): 'png' | 'jpeg' {\n if (base64.startsWith('data:image/jpeg')) return 'jpeg';\n if (base64.startsWith('data:image/jpg')) return 'jpeg';\n return 'png';\n}\n\n/**\n * ScreenshotItem encapsulates screenshot data.\n *\n * Supports lazy loading after memory release:\n * - inline mode: reads from HTML file using streaming (extractImageByIdSync)\n * - directory mode: reads from file on disk\n *\n * After persistence, memory is released but the screenshot can be recovered\n * on-demand from disk, making it safe to release memory at any time.\n */\nexport class ScreenshotItem {\n private _id: string;\n private _base64: string | null;\n private _format: 'png' | 'jpeg';\n private _capturedAt: number;\n private _serializedRef: ScreenshotRef | null = null;\n private _persistedPath: string | null = null;\n private _persistedHtmlPath: string | null = null;\n\n private constructor(id: string, base64: string, capturedAt: number) {\n this._id = id;\n this._base64 = base64;\n this._format = detectFormat(base64);\n this._capturedAt = capturedAt;\n }\n\n /** Create a new ScreenshotItem from base64 data */\n static create(base64: string, capturedAt: number): ScreenshotItem {\n return new ScreenshotItem(uuid(), base64, capturedAt);\n }\n\n get id(): string {\n return this._id;\n }\n\n /** Get the image format (png or jpeg) */\n get format(): 'png' | 'jpeg' {\n return this._format;\n }\n\n /** Get the file extension for this screenshot */\n get extension(): string {\n return this._format === 'jpeg' ? 'jpeg' : 'png';\n }\n\n /** Get screenshot capture timestamp in milliseconds */\n get capturedAt(): number {\n return this._capturedAt;\n }\n\n get base64(): string {\n // If data is in memory, return it directly\n if (this._base64 !== null) {\n return this._base64;\n }\n\n const loadFromFile = (): string => {\n if (this._persistedPath === null) {\n throw new Error(`Screenshot ${this._id}: file recovery path missing`);\n }\n const buffer = readFileSync(this._persistedPath);\n return `data:image/${this._format};base64,${buffer.toString('base64')}`;\n };\n\n const loadFromInline = (): string => {\n if (this._persistedHtmlPath === null) {\n throw new Error(`Screenshot ${this._id}: HTML recovery path missing`);\n }\n const data = extractImageByIdSync(this._persistedHtmlPath, this._id);\n if (data) {\n return data;\n }\n throw new Error(\n `Screenshot ${this._id}: cannot recover from HTML (id not found in ${this._persistedHtmlPath})`,\n );\n };\n\n // Recover from the primary serialized mode first.\n if (this._serializedRef?.storage === 'file') {\n return loadFromFile();\n }\n\n if (this._serializedRef?.storage === 'inline') {\n return loadFromInline();\n }\n\n // Fall back to whichever recovery path is available.\n if (this._persistedPath !== null) {\n return loadFromFile();\n }\n\n if (this._persistedHtmlPath !== null) {\n return loadFromInline();\n }\n\n throw new Error(\n `Screenshot ${this._id}: base64 data released without recovery path`,\n );\n }\n\n /** Check if base64 data is still available in memory (not yet released) */\n hasBase64(): boolean {\n return this._base64 !== null;\n }\n\n /**\n * Mark as persisted to HTML (inline mode).\n * Releases base64 memory, but keeps HTML path for lazy loading recovery.\n * @param htmlPath - absolute path to the HTML file containing the image\n */\n markPersistedInline(htmlPath: string): ScreenshotRef {\n const ref = this.createRef('inline');\n this._serializedRef = ref;\n this._persistedHtmlPath = htmlPath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Register a file-backed recovery path without changing the serialized mode.\n * Used when inline persistence also needs a shared file copy next to dumps.\n */\n registerPersistedFileCopy(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.createRef('file', relativePath);\n this._persistedPath = absolutePath;\n this._base64 = null;\n return ref;\n }\n\n /**\n * Mark as persisted to file (directory mode).\n * Releases base64 memory, but keeps file path for lazy loading recovery.\n * @param relativePath - relative path for serialization (e.g., \"./screenshots/id.jpeg\")\n * @param absolutePath - absolute path for lazy loading recovery\n */\n markPersistedToPath(\n relativePath: string,\n absolutePath: string,\n ): ScreenshotRef {\n const ref = this.registerPersistedFileCopy(relativePath, absolutePath);\n this._serializedRef = ref;\n return ref;\n }\n\n /** Serialize for JSON - format depends on persistence state */\n toSerializable(): ScreenshotSerializeFormat {\n return (\n this._serializedRef ?? {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage: 'inline',\n }\n );\n }\n\n /** Check if a value is a serialized ScreenshotItem reference (inline or directory mode) */\n static isSerialized(value: unknown): value is ScreenshotSerializeFormat {\n return normalizeScreenshotRef(value) !== null;\n }\n\n private createRef(\n storage: 'inline' | 'file',\n relativePath?: string,\n ): ScreenshotRef {\n const baseRef: Omit<ScreenshotRef, 'path'> = {\n type: 'midscene_screenshot_ref',\n id: this._id,\n capturedAt: this._capturedAt,\n mimeType: this._format === 'jpeg' ? 'image/jpeg' : 'image/png',\n storage,\n };\n if (storage === 'file') {\n return {\n ...baseRef,\n storage,\n path: relativePath!,\n };\n }\n return baseRef;\n }\n\n /**\n * Get base64 data without the data URI prefix.\n * Useful for writing raw binary data to files.\n */\n get rawBase64(): string {\n return this.base64.replace(/^data:image\\/(png|jpeg|jpg);base64,/, '');\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","detectFormat","base64","ScreenshotItem","capturedAt","uuid","loadFromFile","Error","buffer","readFileSync","loadFromInline","data","extractImageByIdSync","htmlPath","ref","relativePath","absolutePath","value","normalizeScreenshotRef","storage","baseRef","id"],"mappings":"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"}
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {
@@ -1 +1 @@
1
- {"version":3,"file":"service/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/service/index.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 { isAutoGLM, isUITars } from '@/ai-model/auto-glm/util';\nimport {\n AIResponseParseError,\n AiExtractElementInfo,\n AiLocateElement,\n callAIWithObjectResponse,\n} from '@/ai-model/index';\nimport { AiLocateSection, buildSearchAreaConfig } from '@/ai-model/inspect';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport { type AIArgs, expandSearchArea } from '@/common';\nimport type {\n AIDescribeElementResponse,\n AIUsageInfo,\n DetailedLocateParam,\n LocateResultElement,\n LocateResultWithDump,\n PartialServiceDumpFromSDK,\n PlanningLocateParam,\n Rect,\n ServiceExtractOption,\n ServiceExtractParam,\n ServiceExtractResult,\n ServiceTaskInfo,\n UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport type { IModelConfig } from '@aiscene/shared/env';\nimport { compositeElementInfoImg, cropByRect } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { assert } from '@aiscene/shared/utils';\nimport type { TMultimodalPrompt } from '../common';\nimport { createServiceDump } from './utils';\n\nexport interface LocateOpts {\n context?: UIContext;\n planLocatedElement?: LocateResultElement;\n}\n\nexport type AnyValue<T> = {\n [K in keyof T]: unknown extends T[K] ? any : T[K];\n};\n\ninterface ServiceOptions {\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n}\n\nconst debug = getDebug('ai:service');\nexport default class Service {\n contextRetrieverFn: () => Promise<UIContext> | UIContext;\n\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n\n constructor(\n context: UIContext | (() => Promise<UIContext> | UIContext),\n opt?: ServiceOptions,\n ) {\n assert(context, 'context is required for Service');\n if (typeof context === 'function') {\n this.contextRetrieverFn = context;\n } else {\n this.contextRetrieverFn = () => Promise.resolve(context);\n }\n\n if (typeof opt?.taskInfo !== 'undefined') {\n this.taskInfo = opt.taskInfo;\n }\n }\n\n async locate(\n query: PlanningLocateParam,\n opt: LocateOpts,\n modelConfig: IModelConfig,\n abortSignal?: AbortSignal,\n ): Promise<LocateResultWithDump> {\n const queryPrompt = typeof query === 'string' ? query : query.prompt;\n assert(queryPrompt, 'query is required for locate');\n\n assert(typeof query === 'object', 'query should be an object for locate');\n\n const hasPlanLocatedElement = !!opt?.planLocatedElement?.rect;\n\n let searchAreaPrompt;\n if (query.deepLocate && !hasPlanLocatedElement) {\n searchAreaPrompt = query.prompt;\n }\n\n const { modelFamily } = modelConfig;\n\n if (searchAreaPrompt && !modelFamily) {\n console.warn(\n 'The \"deepLocate\" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config',\n );\n searchAreaPrompt = undefined;\n }\n\n if (searchAreaPrompt && isAutoGLM(modelFamily)) {\n console.warn('The \"deepLocate\" feature is not supported with AutoGLM.');\n searchAreaPrompt = undefined;\n }\n\n const context = opt?.context || (await this.contextRetrieverFn());\n\n let searchArea: Rect | undefined = undefined;\n let searchAreaRawResponse: string | undefined = undefined;\n let searchAreaUsage: AIUsageInfo | undefined = undefined;\n let searchAreaResponse:\n | Awaited<ReturnType<typeof AiLocateSection>>\n | undefined = undefined;\n if (query.deepLocate && hasPlanLocatedElement) {\n const searchAreaConfig = await buildSearchAreaConfig({\n context,\n baseRect: opt.planLocatedElement!.rect,\n modelFamily,\n });\n searchArea = searchAreaConfig.rect;\n\n searchAreaRawResponse = JSON.stringify({\n source: 'plan-located-element',\n rect: opt.planLocatedElement!.rect,\n });\n searchAreaResponse = {\n rect: searchArea,\n imageBase64: searchAreaConfig.imageBase64,\n scale: searchAreaConfig.scale,\n rawResponse: searchAreaRawResponse,\n };\n } else if (searchAreaPrompt) {\n searchAreaResponse = await AiLocateSection({\n context,\n sectionDescription: searchAreaPrompt,\n modelConfig,\n abortSignal,\n });\n assert(\n searchAreaResponse.rect,\n `cannot find search area for \"${searchAreaPrompt}\"${\n searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\n }`,\n );\n searchAreaRawResponse = searchAreaResponse.rawResponse;\n searchAreaUsage = searchAreaResponse.usage;\n searchArea = searchAreaResponse.rect;\n }\n\n const startTime = Date.now();\n const { parseResult, rect, rawResponse, usage, reasoning_content } =\n await AiLocateElement({\n context,\n targetElementDescription: queryPrompt,\n searchConfig: searchAreaResponse,\n modelConfig,\n abortSignal,\n });\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: JSON.stringify(rawResponse),\n formatResponse: JSON.stringify(parseResult),\n usage,\n searchArea,\n searchAreaRawResponse,\n searchAreaUsage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `failed to locate element: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'locate',\n userQuery: {\n element: queryPrompt,\n },\n matchedElement: [],\n matchedRect: rect,\n data: null,\n taskInfo,\n deepLocate: !!searchArea,\n error: errorLog,\n };\n\n const elements = parseResult.elements || [];\n\n const dump = createServiceDump({\n ...dumpData,\n matchedElement: elements,\n });\n\n if (errorLog) {\n throw new ServiceError(errorLog, dump);\n }\n\n if (elements.length > 1) {\n throw new ServiceError(\n `locate: multiple elements found, length = ${elements.length}`,\n dump,\n );\n }\n\n if (elements.length === 1) {\n return {\n element: {\n center: elements[0]!.center,\n rect: elements[0]!.rect,\n description: elements[0]!.description,\n },\n rect,\n dump,\n };\n }\n\n return {\n element: null,\n rect,\n dump,\n };\n }\n\n async extract<T>(\n dataDemand: ServiceExtractParam,\n modelConfig: IModelConfig,\n opt?: ServiceExtractOption,\n pageDescription?: string,\n multimodalPrompt?: TMultimodalPrompt,\n context?: UIContext,\n ): Promise<ServiceExtractResult<T>> {\n assert(context, 'context is required for extract');\n assert(\n typeof dataDemand === 'object' || typeof dataDemand === 'string',\n `dataDemand should be object or string, but get ${typeof dataDemand}`,\n );\n\n const startTime = Date.now();\n\n let parseResult: Awaited<\n ReturnType<typeof AiExtractElementInfo<T>>\n >['parseResult'];\n let rawResponse: string;\n let usage: Awaited<ReturnType<typeof AiExtractElementInfo<T>>>['usage'];\n let reasoning_content: string | undefined;\n\n try {\n const result = await AiExtractElementInfo<T>({\n context,\n dataQuery: dataDemand,\n multimodalPrompt,\n extractOption: opt,\n modelConfig,\n pageDescription,\n });\n parseResult = result.parseResult;\n rawResponse = result.rawResponse;\n usage = result.usage;\n reasoning_content = result.reasoning_content;\n } catch (error) {\n if (error instanceof AIResponseParseError) {\n // Create dump with usage and rawResponse from the error\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: error.rawResponse,\n usage: error.usage,\n };\n const dump = createServiceDump({\n type: 'extract',\n userQuery: { dataDemand },\n matchedElement: [],\n data: null,\n taskInfo,\n error: error.message,\n });\n throw new ServiceError(error.message, dump);\n }\n throw error;\n }\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse,\n formatResponse: JSON.stringify(parseResult),\n usage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `AI response error: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'extract',\n userQuery: {\n dataDemand,\n },\n matchedElement: [],\n data: null,\n taskInfo,\n error: errorLog,\n };\n\n const { data, thought } = parseResult || {};\n\n const dump = createServiceDump({\n ...dumpData,\n data,\n });\n\n if (errorLog && !data) {\n throw new ServiceError(errorLog, dump);\n }\n\n return {\n data,\n thought,\n usage,\n reasoning_content,\n dump,\n };\n }\n\n async describe(\n target: Rect | [number, number],\n modelConfig: IModelConfig,\n opt?: {\n deepLocate?: boolean;\n },\n ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n assert(target, 'target is required for service.describe');\n const context = await this.contextRetrieverFn();\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for service.describe');\n // The result of the \"describe\" function will be used for positioning, so essentially it is a form of grounding.\n const { modelFamily } = modelConfig;\n const systemPrompt = elementDescriberInstruction();\n\n // Convert [x,y] center point to Rect if needed\n const defaultRectSize = 30;\n const targetRect: Rect = Array.isArray(target)\n ? {\n left: Math.floor(target[0] - defaultRectSize / 2),\n top: Math.floor(target[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n }\n : target;\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [\n {\n rect: targetRect,\n },\n ],\n borderThickness: 3,\n });\n\n if (opt?.deepLocate) {\n const searchArea = expandSearchArea(targetRect, shotSize);\n // Always crop in describe mode. Unlike locate's deepLocate (where\n // cropping too small loses context for finding elements), describe's\n // deepLocate intentionally zooms in so the model produces a more\n // precise description from a focused view. expandSearchArea already\n // guarantees a minimum 400x400 area with surrounding context.\n debug('describe: cropping to searchArea', searchArea);\n const croppedResult = await cropByRect(\n imagePayload,\n searchArea,\n modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n }\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n ],\n },\n ];\n\n const res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n msgs,\n modelConfig,\n );\n\n const { content } = res;\n assert(!content.error, `describe failed: ${content.error}`);\n assert(content.description, 'failed to describe the element');\n return content;\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","debug","getDebug","Service","query","opt","modelConfig","abortSignal","queryPrompt","assert","hasPlanLocatedElement","searchAreaPrompt","modelFamily","console","undefined","isAutoGLM","context","searchArea","searchAreaRawResponse","searchAreaUsage","searchAreaResponse","searchAreaConfig","buildSearchAreaConfig","JSON","AiLocateSection","startTime","Date","parseResult","rect","rawResponse","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","errorLog","dumpData","elements","dump","createServiceDump","ServiceError","dataDemand","pageDescription","multimodalPrompt","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","msgs","res","callAIWithObjectResponse","content","Promise"],"mappings":"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"}
1
+ {"version":3,"file":"service/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/service/index.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 { isAutoGLM, isUITars } from '@/ai-model/auto-glm/util';\nimport {\n AIResponseParseError,\n AiExtractElementInfo,\n AiLocateElement,\n callAIWithObjectResponse,\n} from '@/ai-model/index';\nimport { AiLocateSection, buildSearchAreaConfig } from '@/ai-model/inspect';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport { type AIArgs, expandSearchArea } from '@/common';\nimport type {\n AIDescribeElementResponse,\n AIUsageInfo,\n DetailedLocateParam,\n LocateResultElement,\n LocateResultWithDump,\n PartialServiceDumpFromSDK,\n PlanningLocateParam,\n Rect,\n ServiceExtractOption,\n ServiceExtractParam,\n ServiceExtractResult,\n ServiceTaskInfo,\n UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport type { IModelConfig } from '@aiscene/shared/env';\nimport { compositeElementInfoImg, cropByRect } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { assert } from '@aiscene/shared/utils';\nimport type { TMultimodalPrompt } from '../common';\nimport { createServiceDump } from './utils';\n\nexport interface LocateOpts {\n context?: UIContext;\n planLocatedElement?: LocateResultElement;\n}\n\nexport type AnyValue<T> = {\n [K in keyof T]: unknown extends T[K] ? any : T[K];\n};\n\ninterface ServiceOptions {\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n}\n\nconst debug = getDebug('ai:service');\nexport default class Service {\n contextRetrieverFn: () => Promise<UIContext> | UIContext;\n\n taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n\n constructor(\n context: UIContext | (() => Promise<UIContext> | UIContext),\n opt?: ServiceOptions,\n ) {\n assert(context, 'context is required for Service');\n if (typeof context === 'function') {\n this.contextRetrieverFn = context;\n } else {\n this.contextRetrieverFn = () => Promise.resolve(context);\n }\n\n if (typeof opt?.taskInfo !== 'undefined') {\n this.taskInfo = opt.taskInfo;\n }\n }\n\n async locate(\n query: PlanningLocateParam,\n opt: LocateOpts,\n modelConfig: IModelConfig,\n abortSignal?: AbortSignal,\n ): Promise<LocateResultWithDump> {\n const queryPrompt = typeof query === 'string' ? query : query.prompt;\n assert(queryPrompt, 'query is required for locate');\n\n assert(typeof query === 'object', 'query should be an object for locate');\n\n const hasPlanLocatedElement = !!opt?.planLocatedElement?.rect;\n\n let searchAreaPrompt;\n if (query.deepLocate && !hasPlanLocatedElement) {\n searchAreaPrompt = query.prompt;\n }\n\n const { modelFamily } = modelConfig;\n\n if (searchAreaPrompt && !modelFamily) {\n console.warn(\n 'The \"deepLocate\" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config',\n );\n searchAreaPrompt = undefined;\n }\n\n if (searchAreaPrompt && isAutoGLM(modelFamily)) {\n console.warn('The \"deepLocate\" feature is not supported with AutoGLM.');\n searchAreaPrompt = undefined;\n }\n\n const context = opt?.context || (await this.contextRetrieverFn());\n\n let searchArea: Rect | undefined = undefined;\n let searchAreaRawResponse: string | undefined = undefined;\n let searchAreaUsage: AIUsageInfo | undefined = undefined;\n let searchAreaResponse:\n | Awaited<ReturnType<typeof AiLocateSection>>\n | undefined = undefined;\n if (query.deepLocate && hasPlanLocatedElement) {\n const searchAreaConfig = await buildSearchAreaConfig({\n context,\n baseRect: opt.planLocatedElement!.rect,\n modelFamily,\n });\n searchArea = searchAreaConfig.rect;\n\n searchAreaRawResponse = JSON.stringify({\n source: 'plan-located-element',\n rect: opt.planLocatedElement!.rect,\n });\n searchAreaResponse = {\n rect: searchArea,\n imageBase64: searchAreaConfig.imageBase64,\n scale: searchAreaConfig.scale,\n rawResponse: searchAreaRawResponse,\n };\n } else if (searchAreaPrompt) {\n searchAreaResponse = await AiLocateSection({\n context,\n sectionDescription: searchAreaPrompt,\n modelConfig,\n abortSignal,\n });\n assert(\n searchAreaResponse.rect,\n `cannot find search area for \"${searchAreaPrompt}\"${\n searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\n }`,\n );\n searchAreaRawResponse = searchAreaResponse.rawResponse;\n searchAreaUsage = searchAreaResponse.usage;\n searchArea = searchAreaResponse.rect;\n }\n\n const startTime = Date.now();\n const { parseResult, rect, rawResponse, usage, reasoning_content } =\n await AiLocateElement({\n context,\n targetElementDescription: queryPrompt,\n searchConfig: searchAreaResponse,\n modelConfig,\n abortSignal,\n });\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: JSON.stringify(rawResponse),\n formatResponse: JSON.stringify(parseResult),\n usage,\n searchArea,\n searchAreaRawResponse,\n searchAreaUsage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `failed to locate element: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'locate',\n userQuery: {\n element: queryPrompt,\n },\n matchedElement: [],\n matchedRect: rect,\n data: null,\n taskInfo,\n deepLocate: !!searchArea,\n error: errorLog,\n };\n\n const elements = parseResult.elements || [];\n\n const dump = createServiceDump({\n ...dumpData,\n matchedElement: elements,\n });\n\n if (errorLog) {\n throw new ServiceError(errorLog, dump);\n }\n\n if (elements.length > 1) {\n throw new ServiceError(\n `locate: multiple elements found, length = ${elements.length}`,\n dump,\n );\n }\n\n if (elements.length === 1) {\n return {\n element: {\n center: elements[0]!.center,\n rect: elements[0]!.rect,\n description: elements[0]!.description,\n },\n rect,\n dump,\n };\n }\n\n return {\n element: null,\n rect,\n dump,\n };\n }\n\n async extract<T>(\n dataDemand: ServiceExtractParam,\n modelConfig: IModelConfig,\n opt?: ServiceExtractOption,\n pageDescription?: string,\n multimodalPrompt?: TMultimodalPrompt,\n context?: UIContext,\n ): Promise<ServiceExtractResult<T>> {\n assert(context, 'context is required for extract');\n assert(\n typeof dataDemand === 'object' || typeof dataDemand === 'string',\n `dataDemand should be object or string, but get ${typeof dataDemand}`,\n );\n\n const startTime = Date.now();\n\n let parseResult: Awaited<\n ReturnType<typeof AiExtractElementInfo<T>>\n >['parseResult'];\n let rawResponse: string;\n let usage: Awaited<ReturnType<typeof AiExtractElementInfo<T>>>['usage'];\n let reasoning_content: string | undefined;\n\n try {\n const result = await AiExtractElementInfo<T>({\n context,\n dataQuery: dataDemand,\n multimodalPrompt,\n extractOption: opt,\n modelConfig,\n pageDescription,\n });\n parseResult = result.parseResult;\n rawResponse = result.rawResponse;\n usage = result.usage;\n reasoning_content = result.reasoning_content;\n } catch (error) {\n if (error instanceof AIResponseParseError) {\n // Create dump with usage and rawResponse from the error\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse: error.rawResponse,\n usage: error.usage,\n };\n const dump = createServiceDump({\n type: 'extract',\n userQuery: { dataDemand },\n matchedElement: [],\n data: null,\n taskInfo,\n error: error.message,\n });\n throw new ServiceError(error.message, dump);\n }\n throw error;\n }\n\n const timeCost = Date.now() - startTime;\n const taskInfo: ServiceTaskInfo = {\n ...(this.taskInfo ? this.taskInfo : {}),\n durationMs: timeCost,\n rawResponse,\n formatResponse: JSON.stringify(parseResult),\n usage,\n reasoning_content,\n };\n\n let errorLog: string | undefined;\n if (parseResult.errors?.length) {\n errorLog = `AI response error: \\n${parseResult.errors.join('\\n')}`;\n }\n\n const dumpData: PartialServiceDumpFromSDK = {\n type: 'extract',\n userQuery: {\n dataDemand,\n },\n matchedElement: [],\n data: null,\n taskInfo,\n error: errorLog,\n };\n\n const { data, thought } = parseResult || {};\n\n const dump = createServiceDump({\n ...dumpData,\n data,\n });\n\n if (errorLog && !data) {\n throw new ServiceError(errorLog, dump);\n }\n\n return {\n data,\n thought,\n usage,\n reasoning_content,\n dump,\n };\n }\n\n async describe(\n target: Rect | [number, number],\n modelConfig: IModelConfig,\n opt?: {\n deepLocate?: boolean;\n },\n ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n assert(target, 'target is required for service.describe');\n const context = await this.contextRetrieverFn();\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for service.describe');\n // The result of the \"describe\" function will be used for positioning, so essentially it is a form of grounding.\n const { modelFamily } = modelConfig;\n const systemPrompt = elementDescriberInstruction();\n\n // Convert [x,y] center point to Rect if needed\n const defaultRectSize = 30;\n const targetRect: Rect = Array.isArray(target)\n ? {\n left: Math.floor(target[0] - defaultRectSize / 2),\n top: Math.floor(target[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n }\n : target;\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [\n {\n rect: targetRect,\n },\n ],\n borderThickness: 3,\n });\n\n if (opt?.deepLocate) {\n const searchArea = expandSearchArea(targetRect, shotSize);\n // Always crop in describe mode. Unlike locate's deepLocate (where\n // cropping too small loses context for finding elements), describe's\n // deepLocate intentionally zooms in so the model produces a more\n // precise description from a focused view. expandSearchArea already\n // guarantees a minimum 400x400 area with surrounding context.\n debug('describe: cropping to searchArea', searchArea);\n const croppedResult = await cropByRect(\n imagePayload,\n searchArea,\n modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n }\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n ],\n },\n ];\n\n const res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n msgs,\n modelConfig,\n );\n\n const { content } = res;\n assert(!content.error, `describe failed: ${content.error}`);\n assert(content.description, 'failed to describe the element');\n return content;\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","debug","getDebug","Service","query","opt","modelConfig","abortSignal","queryPrompt","assert","hasPlanLocatedElement","searchAreaPrompt","modelFamily","console","undefined","isAutoGLM","context","searchArea","searchAreaRawResponse","searchAreaUsage","searchAreaResponse","searchAreaConfig","buildSearchAreaConfig","JSON","AiLocateSection","startTime","Date","parseResult","rect","rawResponse","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","errorLog","dumpData","elements","dump","createServiceDump","ServiceError","dataDemand","pageDescription","multimodalPrompt","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","msgs","res","callAIWithObjectResponse","content","Promise"],"mappings":"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"}
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {
@@ -1 +1 @@
1
- {"version":3,"file":"service/utils.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/service/utils.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 type { DumpMeta, PartialServiceDumpFromSDK, ServiceDump } from '@/types';\nimport { uuid } from '@aiscene/shared/utils';\n\nexport function createServiceDump(\n data: PartialServiceDumpFromSDK,\n): ServiceDump {\n const baseData: DumpMeta = {\n logTime: Date.now(),\n };\n const finalData: ServiceDump = {\n logId: uuid(),\n ...baseData,\n ...data,\n };\n\n return finalData;\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","createServiceDump","data","baseData","Date","finalData","uuid"],"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,MAAlB,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;;;;;;;;ACHO,SAASI,kBACdC,IAA+B;IAE/B,MAAMC,WAAqB;QACzB,SAASC,KAAK,GAAG;IACnB;IACA,MAAMC,YAAyB;QAC7B,OAAOC,AAAAA,IAAAA,sBAAAA,IAAAA,AAAAA;QACP,GAAGH,QAAQ;QACX,GAAGD,IAAI;IACT;IAEA,OAAOG;AACT"}
1
+ {"version":3,"file":"service/utils.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/service/utils.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 type { DumpMeta, PartialServiceDumpFromSDK, ServiceDump } from '@/types';\nimport { uuid } from '@aiscene/shared/utils';\n\nexport function createServiceDump(\n data: PartialServiceDumpFromSDK,\n): ServiceDump {\n const baseData: DumpMeta = {\n logTime: Date.now(),\n };\n const finalData: ServiceDump = {\n logId: uuid(),\n ...baseData,\n ...data,\n };\n\n return finalData;\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","createServiceDump","data","baseData","Date","finalData","uuid"],"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;;;;;;;;ACHO,SAASI,kBACdC,IAA+B;IAE/B,MAAMC,WAAqB;QACzB,SAASC,KAAK,GAAG;IACnB;IACA,MAAMC,YAAyB;QAC7B,OAAOC,AAAAA,IAAAA,sBAAAA,IAAAA,AAAAA;QACP,GAAGH,QAAQ;QACX,GAAGD,IAAI;IACT;IAEA,OAAOG;AACT"}
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {
@@ -1 +1 @@
1
- {"version":3,"file":"skill/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/skill/index.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 { reportCLIError, runToolsCLI } from '@aiscene/shared/cli';\nimport { BaseMidsceneTools } from '@aiscene/shared/mcp/base-tools';\nimport type { BaseAgent, BaseDevice } from '@aiscene/shared/mcp/types';\nimport { Agent } from '../agent/agent';\nimport type { AbstractInterface } from '../device';\n\ntype DeviceClass = new (...args: any[]) => AbstractInterface;\n\n/**\n * Skill tools manager that lazily creates Agent from a Device class.\n * Used by runSkillCLI for CLI / Agent Skills scenarios where no agent exists at startup.\n */\nclass SkillMidsceneTools extends BaseMidsceneTools<BaseAgent> {\n constructor(private DeviceClass: DeviceClass) {\n super();\n }\n\n protected createTemporaryDevice(): BaseDevice {\n return new this.DeviceClass() as unknown as BaseDevice;\n }\n\n protected async ensureAgent(): Promise<BaseAgent> {\n if (!this.agent) {\n const device = new this.DeviceClass();\n this.agent = new Agent(device) as unknown as BaseAgent;\n }\n return this.agent;\n }\n}\n\nexport interface SkillCLIOptions {\n scriptName: string;\n DeviceClass: DeviceClass;\n}\n\n/**\n * Launch a Skill CLI for a custom interface Device class.\n * This enables AI coding assistants (Claude Code, Cline, etc.) to control\n * your custom interface through CLI commands.\n *\n * @example\n * ```typescript\n * #!/usr/bin/env node\n * import { runSkillCLI } from '@aiscene/core/skill';\n * import { SampleDevice } from './sample-device';\n *\n * runSkillCLI({\n * DeviceClass: SampleDevice,\n * scriptName: 'my-device',\n * });\n * ```\n */\nexport function runSkillCLI(options: SkillCLIOptions): Promise<void> {\n const tools = new SkillMidsceneTools(options.DeviceClass);\n return runToolsCLI(tools, options.scriptName).catch((e) => {\n process.exit(reportCLIError(e));\n });\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","SkillMidsceneTools","BaseMidsceneTools","device","Agent","DeviceClass","runSkillCLI","options","tools","runToolsCLI","e","process","reportCLIError"],"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,MAAlB,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;;;;;;;;;;;;;;;;;;;;ACMA,MAAMI,2BAA2BC,2BAAAA,iBAAiBA;IAKtC,wBAAoC;QAC5C,OAAO,IAAI,IAAI,CAAC,WAAW;IAC7B;IAEA,MAAgB,cAAkC;QAChD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;YACf,MAAMC,SAAS,IAAI,IAAI,CAAC,WAAW;YACnC,IAAI,CAAC,KAAK,GAAG,IAAIC,yBAAAA,KAAKA,CAACD;QACzB;QACA,OAAO,IAAI,CAAC,KAAK;IACnB;IAdA,YAAoBE,WAAwB,CAAE;QAC5C,KAAK,wDADaA,WAAW,GAAXA;IAEpB;AAaF;AAwBO,SAASC,YAAYC,OAAwB;IAClD,MAAMC,QAAQ,IAAIP,mBAAmBM,QAAQ,WAAW;IACxD,OAAOE,AAAAA,IAAAA,oBAAAA,WAAAA,AAAAA,EAAYD,OAAOD,QAAQ,UAAU,EAAE,KAAK,CAAC,CAACG;QACnDC,QAAQ,IAAI,CAACC,AAAAA,IAAAA,oBAAAA,cAAAA,AAAAA,EAAeF;IAC9B;AACF"}
1
+ {"version":3,"file":"skill/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/skill/index.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 { reportCLIError, runToolsCLI } from '@aiscene/shared/cli';\nimport { BaseMidsceneTools } from '@aiscene/shared/mcp/base-tools';\nimport type { BaseAgent, BaseDevice } from '@aiscene/shared/mcp/types';\nimport { Agent } from '../agent/agent';\nimport type { AbstractInterface } from '../device';\n\ntype DeviceClass = new (...args: any[]) => AbstractInterface;\n\n/**\n * Skill tools manager that lazily creates Agent from a Device class.\n * Used by runSkillCLI for CLI / Agent Skills scenarios where no agent exists at startup.\n */\nclass SkillMidsceneTools extends BaseMidsceneTools<BaseAgent> {\n constructor(private DeviceClass: DeviceClass) {\n super();\n }\n\n protected createTemporaryDevice(): BaseDevice {\n return new this.DeviceClass() as unknown as BaseDevice;\n }\n\n protected async ensureAgent(): Promise<BaseAgent> {\n if (!this.agent) {\n const device = new this.DeviceClass();\n this.agent = new Agent(device) as unknown as BaseAgent;\n }\n return this.agent;\n }\n}\n\nexport interface SkillCLIOptions {\n scriptName: string;\n DeviceClass: DeviceClass;\n}\n\n/**\n * Launch a Skill CLI for a custom interface Device class.\n * This enables AI coding assistants (Claude Code, Cline, etc.) to control\n * your custom interface through CLI commands.\n *\n * @example\n * ```typescript\n * #!/usr/bin/env node\n * import { runSkillCLI } from '@aiscene/core/skill';\n * import { SampleDevice } from './sample-device';\n *\n * runSkillCLI({\n * DeviceClass: SampleDevice,\n * scriptName: 'my-device',\n * });\n * ```\n */\nexport function runSkillCLI(options: SkillCLIOptions): Promise<void> {\n const tools = new SkillMidsceneTools(options.DeviceClass);\n return runToolsCLI(tools, options.scriptName).catch((e) => {\n process.exit(reportCLIError(e));\n });\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","SkillMidsceneTools","BaseMidsceneTools","device","Agent","DeviceClass","runSkillCLI","options","tools","runToolsCLI","e","process","reportCLIError"],"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;;;;;;;;;;;;;;;;;;;;ACMA,MAAMI,2BAA2BC,2BAAAA,iBAAiBA;IAKtC,wBAAoC;QAC5C,OAAO,IAAI,IAAI,CAAC,WAAW;IAC7B;IAEA,MAAgB,cAAkC;QAChD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;YACf,MAAMC,SAAS,IAAI,IAAI,CAAC,WAAW;YACnC,IAAI,CAAC,KAAK,GAAG,IAAIC,yBAAAA,KAAKA,CAACD;QACzB;QACA,OAAO,IAAI,CAAC,KAAK;IACnB;IAdA,YAAoBE,WAAwB,CAAE;QAC5C,KAAK,wDADaA,WAAW,GAAXA;IAEpB;AAaF;AAwBO,SAASC,YAAYC,OAAwB;IAClD,MAAMC,QAAQ,IAAIP,mBAAmBM,QAAQ,WAAW;IACxD,OAAOE,AAAAA,IAAAA,oBAAAA,WAAAA,AAAAA,EAAYD,OAAOD,QAAQ,UAAU,EAAE,KAAK,CAAC,CAACG;QACnDC,QAAQ,IAAI,CAACC,AAAAA,IAAAA,oBAAAA,cAAAA,AAAAA,EAAeF;IAC9B;AACF"}
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
13
13
  })();
14
14
  (()=>{
15
15
  __webpack_require__.r = (exports1)=>{
16
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
17
  value: 'Module'
18
18
  });
19
19
  Object.defineProperty(exports1, '__esModule', {