@midscene/web 0.15.0 → 0.15.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 (50) hide show
  1. package/dist/es/agent.js +8 -11
  2. package/dist/es/agent.js.map +1 -1
  3. package/dist/es/bridge-mode-browser.js +3 -3
  4. package/dist/es/bridge-mode.js +14 -15
  5. package/dist/es/bridge-mode.js.map +1 -1
  6. package/dist/es/chrome-extension.js +9 -12
  7. package/dist/es/chrome-extension.js.map +1 -1
  8. package/dist/es/index.js +8 -11
  9. package/dist/es/index.js.map +1 -1
  10. package/dist/es/midscene-playground.js +8 -11
  11. package/dist/es/midscene-playground.js.map +1 -1
  12. package/dist/es/midscene-server.js +1 -1
  13. package/dist/es/midscene-server.js.map +1 -1
  14. package/dist/es/playground.js +8 -11
  15. package/dist/es/playground.js.map +1 -1
  16. package/dist/es/playwright-report.js +2 -2
  17. package/dist/es/playwright-report.js.map +1 -1
  18. package/dist/es/playwright.js +8 -11
  19. package/dist/es/playwright.js.map +1 -1
  20. package/dist/es/puppeteer-agent-launcher.js +8 -11
  21. package/dist/es/puppeteer-agent-launcher.js.map +1 -1
  22. package/dist/es/puppeteer.js +8 -11
  23. package/dist/es/puppeteer.js.map +1 -1
  24. package/dist/es/utils.js +2 -2
  25. package/dist/es/utils.js.map +1 -1
  26. package/dist/lib/agent.js +7 -10
  27. package/dist/lib/agent.js.map +1 -1
  28. package/dist/lib/bridge-mode-browser.js +3 -3
  29. package/dist/lib/bridge-mode.js +15 -16
  30. package/dist/lib/bridge-mode.js.map +1 -1
  31. package/dist/lib/chrome-extension.js +8 -11
  32. package/dist/lib/chrome-extension.js.map +1 -1
  33. package/dist/lib/index.js +7 -10
  34. package/dist/lib/index.js.map +1 -1
  35. package/dist/lib/midscene-playground.js +7 -10
  36. package/dist/lib/midscene-playground.js.map +1 -1
  37. package/dist/lib/midscene-server.js.map +1 -1
  38. package/dist/lib/playground.js +7 -10
  39. package/dist/lib/playground.js.map +1 -1
  40. package/dist/lib/playwright-report.js +1 -1
  41. package/dist/lib/playwright-report.js.map +1 -1
  42. package/dist/lib/playwright.js +7 -10
  43. package/dist/lib/playwright.js.map +1 -1
  44. package/dist/lib/puppeteer-agent-launcher.js +7 -10
  45. package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
  46. package/dist/lib/puppeteer.js +7 -10
  47. package/dist/lib/puppeteer.js.map +1 -1
  48. package/dist/lib/utils.js +1 -1
  49. package/dist/lib/utils.js.map +1 -1
  50. package/package.json +3 -3
@@ -9,7 +9,7 @@ import { uploadTestInfoToServer } from "@midscene/core/utils";
9
9
  import { NodeType } from "@midscene/shared/constants";
10
10
  import { traverseTree, treeToList } from "@midscene/shared/extractor";
11
11
  import { compositeElementInfoImg, resizeImgBase64 } from "@midscene/shared/img";
12
- import { assert, uuid } from "@midscene/shared/utils";
12
+ import { assert, logMsg, uuid } from "@midscene/shared/utils";
13
13
  import dayjs from "dayjs";
14
14
  function reportFileName(tag = "web") {
15
15
  const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);
@@ -17,7 +17,7 @@ function reportFileName(tag = "web") {
17
17
  return `${reportTagName || tag}-${dateTimeInFileName}`;
18
18
  }
19
19
  function printReportMsg(filepath) {
20
- console.log("Midscene - report file updated:", filepath);
20
+ logMsg(`Midscene - report file updated: ${filepath}`);
21
21
  }
22
22
 
23
23
  // src/playwright/reporter/index.ts
@@ -1 +1 @@
1
- {"version":3,"mappings":";AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,8BAA8B;AACvC,SAAS,gBAAgB;AAEzB,SAAS,cAAc,kBAAkB;AACzC,SAAS,yBAAyB,uBAAuB;AACzD,SAAS,QAAQ,YAAY;AAC7B,OAAO,WAAW;AAyFX,SAAS,eAAe,MAAM,OAAO;AAC1C,QAAM,gBAAgB,YAAY,wBAAwB;AAC1D,QAAM,qBAAqB,MAAM,EAAE,OAAO,yBAAyB;AACnE,SAAO,GAAG,iBAAiB,GAAG,IAAI,kBAAkB;AACtD;AAEO,SAAS,eAAe,UAAkB;AAE/C,UAAQ,IAAI,mCAAmC,QAAQ;AAGzD;;;ACpHA,SAAS,uBAAuB;AAUhC,SAAS,UAAU,SAAgB;AACjC,MAAI,QAAQ,IAAI,UAAU,QAAQ;AAChC,YAAQ,IAAI,wBAAwB,GAAG,OAAO;AAAA,EAChD;AACF;AAEA,IAAM,eAAgD,CAAC;AACvD,IAAI;AACJ,SAAS,eAAe;AACtB,QAAM,aAAa,gBAAgB,UAAU,YAAY;AACzD,gBAAc,eAAe,UAAU;AACzC;AAEA,IAAM,mBAAN,MAA2C;AAAA,EACzC,MAAM,QAAQ,QAAoB,OAAc;AAC9C,QAAI,CAAC,UAAU;AACb,iBAAW,eAAe,mBAAmB;AAAA,IAC/C;AAAA,EAGF;AAAA,EAEA,YAAY,MAAgB,SAAqB;AAAA,EAEjD;AAAA,EAEA,UAAU,MAAgB,QAAoB;AAC5C,UAAM,iBAAiB,KAAK,YAAY,KAAK,CAAC,eAAe;AAC3D,aAAO,WAAW,SAAS;AAAA,IAC7B,CAAC;AACD,QAAI,CAAC,gBAAgB;AAAa;AAClC,iBAAa,KAAK;AAAA,MAChB,YAAY,eAAe;AAAA,MAC3B,YAAY;AAAA,QACV,oBAAoB,KAAK;AAAA,QACzB,uBAAuB,KAAK;AAAA,QAC5B,wBAAwB,OAAO;AAAA,QAC/B,0BAA0B,OAAO;AAAA,MACnC;AAAA,IACF,CAAC;AAED,SAAK,cAAc,KAAK,YAAY;AAAA,MAClC,CAAC,eAAe,WAAW,SAAS;AAAA,IACtC;AAEA,iBAAa;AAAA,EACf;AAAA,EAEA,MAAM,QAAoB;AACxB,iBAAa;AAEb,WAAO,qBAAqB,OAAO,MAAM,EAAE;AAAA,EAC7C;AACF;AAEA,IAAO,mBAAQ","names":[],"ignoreList":[],"sources":["../../src/common/utils.ts","../../src/playwright/reporter/index.ts"],"sourcesContent":["import type { StaticPage } from '@/playground';\nimport type {\n ElementTreeNode,\n PlaywrightParserOpt,\n UIContext,\n} from '@midscene/core';\nimport {\n MIDSCENE_REPORT_TAG_NAME,\n MIDSCENE_USE_VLM_UI_TARS,\n getAIConfig,\n getAIConfigInBoolean,\n} from '@midscene/core/env';\nimport { uploadTestInfoToServer } from '@midscene/core/utils';\nimport { NodeType } from '@midscene/shared/constants';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { traverseTree, treeToList } from '@midscene/shared/extractor';\nimport { compositeElementInfoImg, resizeImgBase64 } from '@midscene/shared/img';\nimport { assert, uuid } from '@midscene/shared/utils';\nimport dayjs from 'dayjs';\nimport { WebElementInfo } from '../web-element';\nimport type { WebPage } from './page';\nexport type WebUIContext = UIContext<WebElementInfo> & {\n url: string;\n};\n\nexport async function parseContextFromWebPage(\n page: WebPage,\n _opt?: PlaywrightParserOpt,\n): Promise<WebUIContext> {\n assert(page, 'page is required');\n if ((page as StaticPage)._forceUsePageContext) {\n return await (page as any)._forceUsePageContext();\n }\n const url = await page.url();\n uploadTestInfoToServer({ testUrl: url });\n\n let screenshotBase64: string;\n let tree: ElementTreeNode<ElementInfo>;\n\n await Promise.all([\n page.screenshotBase64().then((base64) => {\n screenshotBase64 = base64;\n }),\n page.getElementsNodeTree().then(async (treeRoot) => {\n tree = treeRoot;\n }),\n ]);\n\n const webTree = traverseTree(tree!, (elementInfo) => {\n const { rect, id, content, attributes, locator, indexId } = elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\n });\n });\n\n const elementsInfo = treeToList(webTree);\n\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const elementsPositionInfoWithoutText = elementsInfo!.filter(\n (elementInfo) => {\n if (elementInfo.attributes.nodeType === NodeType.TEXT) {\n return false;\n }\n return true;\n },\n );\n\n const size = await page.size();\n\n if (size.dpr && size.dpr > 1) {\n // console.time('resizeImgBase64');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n // console.timeEnd('resizeImgBase64');\n }\n\n let screenshotBase64WithElementMarker = screenshotBase64;\n if (!getAIConfigInBoolean(MIDSCENE_USE_VLM_UI_TARS)) {\n if (_opt?.ignoreMarker) {\n screenshotBase64WithElementMarker = screenshotBase64;\n } else {\n screenshotBase64WithElementMarker = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n elementsPositionInfo: elementsPositionInfoWithoutText,\n size,\n });\n }\n }\n\n return {\n content: elementsInfo!,\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\n screenshotBase64WithElementMarker: screenshotBase64WithElementMarker,\n url,\n };\n}\n\nexport function reportFileName(tag = 'web') {\n const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss-SSS');\n return `${reportTagName || tag}-${dateTimeInFileName}`;\n}\n\nexport function printReportMsg(filepath: string) {\n //mcp need use obj format to console msg: https://github.com/modelcontextprotocol/typescript-sdk/issues/244\n console.log('Midscene - report file updated:', filepath);\n // For MCP\n // console.log(`{\"midscene-report-file-updated\": \"${filepath}\"}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED =\n 'NOT_IMPLEMENTED_AS_DESIGNED';\n","import { printReportMsg, reportFileName } from '@/common/utils';\nimport type { ReportDumpWithAttributes } from '@midscene/core';\nimport { writeDumpReport } from '@midscene/core/utils';\nimport type {\n FullConfig,\n FullResult,\n Reporter,\n Suite,\n TestCase,\n TestResult,\n} from '@playwright/test/reporter';\n\nfunction logger(...message: any[]) {\n if (process.env.DEBUG === 'true') {\n console.log('Midscene e2e report:', ...message);\n }\n}\n\nconst testDataList: Array<ReportDumpWithAttributes> = [];\nlet filename: string;\nfunction updateReport() {\n const reportPath = writeDumpReport(filename, testDataList);\n reportPath && printReportMsg(reportPath);\n}\n\nclass MidsceneReporter implements Reporter {\n async onBegin(config: FullConfig, suite: Suite) {\n if (!filename) {\n filename = reportFileName('playwright-merged');\n }\n // const suites = suite.allTests();\n // logger(`Starting the run with ${suites.length} tests`);\n }\n\n onTestBegin(test: TestCase, _result: TestResult) {\n // logger(`Starting test ${test.title}`);\n }\n\n onTestEnd(test: TestCase, result: TestResult) {\n const dumpAnnotation = test.annotations.find((annotation) => {\n return annotation.type === 'MIDSCENE_DUMP_ANNOTATION';\n });\n if (!dumpAnnotation?.description) return;\n testDataList.push({\n dumpString: dumpAnnotation.description,\n attributes: {\n playwright_test_id: test.id,\n playwright_test_title: test.title,\n playwright_test_status: result.status,\n playwright_test_duration: result.duration,\n },\n });\n\n test.annotations = test.annotations.filter(\n (annotation) => annotation.type !== 'MIDSCENE_DUMP_ANNOTATION',\n );\n\n updateReport();\n }\n\n onEnd(result: FullResult) {\n updateReport();\n\n logger(`Finished the run: ${result.status}`);\n }\n}\n\nexport default MidsceneReporter;\n"]}
1
+ {"version":3,"mappings":";AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,8BAA8B;AACvC,SAAS,gBAAgB;AAEzB,SAAS,cAAc,kBAAkB;AACzC,SAAS,yBAAyB,uBAAuB;AACzD,SAAS,QAAQ,QAAQ,YAAY;AACrC,OAAO,WAAW;AAyFX,SAAS,eAAe,MAAM,OAAO;AAC1C,QAAM,gBAAgB,YAAY,wBAAwB;AAC1D,QAAM,qBAAqB,MAAM,EAAE,OAAO,yBAAyB;AACnE,SAAO,GAAG,iBAAiB,GAAG,IAAI,kBAAkB;AACtD;AAEO,SAAS,eAAe,UAAkB;AAC/C,SAAO,mCAAmC,QAAQ,EAAE;AACtD;;;ACjHA,SAAS,uBAAuB;AAUhC,SAAS,UAAU,SAAgB;AACjC,MAAI,QAAQ,IAAI,UAAU,QAAQ;AAChC,YAAQ,IAAI,wBAAwB,GAAG,OAAO;AAAA,EAChD;AACF;AAEA,IAAM,eAAgD,CAAC;AACvD,IAAI;AACJ,SAAS,eAAe;AACtB,QAAM,aAAa,gBAAgB,UAAU,YAAY;AACzD,gBAAc,eAAe,UAAU;AACzC;AAEA,IAAM,mBAAN,MAA2C;AAAA,EACzC,MAAM,QAAQ,QAAoB,OAAc;AAC9C,QAAI,CAAC,UAAU;AACb,iBAAW,eAAe,mBAAmB;AAAA,IAC/C;AAAA,EAGF;AAAA,EAEA,YAAY,MAAgB,SAAqB;AAAA,EAEjD;AAAA,EAEA,UAAU,MAAgB,QAAoB;AAC5C,UAAM,iBAAiB,KAAK,YAAY,KAAK,CAAC,eAAe;AAC3D,aAAO,WAAW,SAAS;AAAA,IAC7B,CAAC;AACD,QAAI,CAAC,gBAAgB;AAAa;AAClC,iBAAa,KAAK;AAAA,MAChB,YAAY,eAAe;AAAA,MAC3B,YAAY;AAAA,QACV,oBAAoB,KAAK;AAAA,QACzB,uBAAuB,KAAK;AAAA,QAC5B,wBAAwB,OAAO;AAAA,QAC/B,0BAA0B,OAAO;AAAA,MACnC;AAAA,IACF,CAAC;AAED,SAAK,cAAc,KAAK,YAAY;AAAA,MAClC,CAAC,eAAe,WAAW,SAAS;AAAA,IACtC;AAEA,iBAAa;AAAA,EACf;AAAA,EAEA,MAAM,QAAoB;AACxB,iBAAa;AAEb,WAAO,qBAAqB,OAAO,MAAM,EAAE;AAAA,EAC7C;AACF;AAEA,IAAO,mBAAQ","names":[],"ignoreList":[],"sources":["../../src/common/utils.ts","../../src/playwright/reporter/index.ts"],"sourcesContent":["import type { StaticPage } from '@/playground';\nimport type {\n ElementTreeNode,\n PlaywrightParserOpt,\n UIContext,\n} from '@midscene/core';\nimport {\n MIDSCENE_REPORT_TAG_NAME,\n MIDSCENE_USE_VLM_UI_TARS,\n getAIConfig,\n getAIConfigInBoolean,\n} from '@midscene/core/env';\nimport { uploadTestInfoToServer } from '@midscene/core/utils';\nimport { NodeType } from '@midscene/shared/constants';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { traverseTree, treeToList } from '@midscene/shared/extractor';\nimport { compositeElementInfoImg, resizeImgBase64 } from '@midscene/shared/img';\nimport { assert, logMsg, uuid } from '@midscene/shared/utils';\nimport dayjs from 'dayjs';\nimport { WebElementInfo } from '../web-element';\nimport type { WebPage } from './page';\nexport type WebUIContext = UIContext<WebElementInfo> & {\n url: string;\n};\n\nexport async function parseContextFromWebPage(\n page: WebPage,\n _opt?: PlaywrightParserOpt,\n): Promise<WebUIContext> {\n assert(page, 'page is required');\n if ((page as StaticPage)._forceUsePageContext) {\n return await (page as any)._forceUsePageContext();\n }\n const url = await page.url();\n uploadTestInfoToServer({ testUrl: url });\n\n let screenshotBase64: string;\n let tree: ElementTreeNode<ElementInfo>;\n\n await Promise.all([\n page.screenshotBase64().then((base64) => {\n screenshotBase64 = base64;\n }),\n page.getElementsNodeTree().then(async (treeRoot) => {\n tree = treeRoot;\n }),\n ]);\n\n const webTree = traverseTree(tree!, (elementInfo) => {\n const { rect, id, content, attributes, locator, indexId } = elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\n });\n });\n\n const elementsInfo = treeToList(webTree);\n\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const elementsPositionInfoWithoutText = elementsInfo!.filter(\n (elementInfo) => {\n if (elementInfo.attributes.nodeType === NodeType.TEXT) {\n return false;\n }\n return true;\n },\n );\n\n const size = await page.size();\n\n if (size.dpr && size.dpr > 1) {\n // console.time('resizeImgBase64');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n // console.timeEnd('resizeImgBase64');\n }\n\n let screenshotBase64WithElementMarker = screenshotBase64;\n if (!getAIConfigInBoolean(MIDSCENE_USE_VLM_UI_TARS)) {\n if (_opt?.ignoreMarker) {\n screenshotBase64WithElementMarker = screenshotBase64;\n } else {\n screenshotBase64WithElementMarker = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n elementsPositionInfo: elementsPositionInfoWithoutText,\n size,\n });\n }\n }\n\n return {\n content: elementsInfo!,\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\n screenshotBase64WithElementMarker: screenshotBase64WithElementMarker,\n url,\n };\n}\n\nexport function reportFileName(tag = 'web') {\n const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss-SSS');\n return `${reportTagName || tag}-${dateTimeInFileName}`;\n}\n\nexport function printReportMsg(filepath: string) {\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED =\n 'NOT_IMPLEMENTED_AS_DESIGNED';\n","import { printReportMsg, reportFileName } from '@/common/utils';\nimport type { ReportDumpWithAttributes } from '@midscene/core';\nimport { writeDumpReport } from '@midscene/core/utils';\nimport type {\n FullConfig,\n FullResult,\n Reporter,\n Suite,\n TestCase,\n TestResult,\n} from '@playwright/test/reporter';\n\nfunction logger(...message: any[]) {\n if (process.env.DEBUG === 'true') {\n console.log('Midscene e2e report:', ...message);\n }\n}\n\nconst testDataList: Array<ReportDumpWithAttributes> = [];\nlet filename: string;\nfunction updateReport() {\n const reportPath = writeDumpReport(filename, testDataList);\n reportPath && printReportMsg(reportPath);\n}\n\nclass MidsceneReporter implements Reporter {\n async onBegin(config: FullConfig, suite: Suite) {\n if (!filename) {\n filename = reportFileName('playwright-merged');\n }\n // const suites = suite.allTests();\n // logger(`Starting the run with ${suites.length} tests`);\n }\n\n onTestBegin(test: TestCase, _result: TestResult) {\n // logger(`Starting test ${test.title}`);\n }\n\n onTestEnd(test: TestCase, result: TestResult) {\n const dumpAnnotation = test.annotations.find((annotation) => {\n return annotation.type === 'MIDSCENE_DUMP_ANNOTATION';\n });\n if (!dumpAnnotation?.description) return;\n testDataList.push({\n dumpString: dumpAnnotation.description,\n attributes: {\n playwright_test_id: test.id,\n playwright_test_title: test.title,\n playwright_test_status: result.status,\n playwright_test_duration: result.duration,\n },\n });\n\n test.annotations = test.annotations.filter(\n (annotation) => annotation.type !== 'MIDSCENE_DUMP_ANNOTATION',\n );\n\n updateReport();\n }\n\n onEnd(result: FullResult) {\n updateReport();\n\n logger(`Finished the run: ${result.status}`);\n }\n}\n\nexport default MidsceneReporter;\n"]}
@@ -656,6 +656,10 @@ var PageTaskExecutor = class {
656
656
  const dumpCollector = (dump) => {
657
657
  insightDump = dump;
658
658
  usage = dump?.taskInfo?.usage;
659
+ task.log = {
660
+ dump: insightDump
661
+ };
662
+ task.usage = usage;
659
663
  };
660
664
  this.insight.onceDumpUpdatedFn = dumpCollector;
661
665
  const shotTime = Date.now();
@@ -666,6 +670,7 @@ var PageTaskExecutor = class {
666
670
  screenshot: pageContext.screenshotBase64,
667
671
  timing: "before locate"
668
672
  };
673
+ task.recorder = [recordItem];
669
674
  const cachePrompt = param.prompt;
670
675
  const locateCache = cacheGroup?.matchCache(
671
676
  pageContext,
@@ -709,9 +714,6 @@ var PageTaskExecutor = class {
709
714
  });
710
715
  }
711
716
  if (!element) {
712
- task.log = {
713
- dump: insightDump
714
- };
715
717
  throw new Error(`Element not found: ${param.prompt}`);
716
718
  }
717
719
  return {
@@ -719,15 +721,10 @@ var PageTaskExecutor = class {
719
721
  element
720
722
  },
721
723
  pageContext,
722
- log: {
723
- dump: insightDump
724
- },
725
724
  cache: {
726
725
  hit: cacheHitFlag
727
726
  },
728
- recorder: [recordItem],
729
- aiCost,
730
- usage
727
+ aiCost
731
728
  };
732
729
  }
733
730
  };
@@ -1547,7 +1544,7 @@ import { uploadTestInfoToServer } from "@midscene/core/utils";
1547
1544
  import { NodeType } from "@midscene/shared/constants";
1548
1545
  import { traverseTree, treeToList } from "@midscene/shared/extractor";
1549
1546
  import { compositeElementInfoImg, resizeImgBase64 } from "@midscene/shared/img";
1550
- import { assert as assert5, uuid } from "@midscene/shared/utils";
1547
+ import { assert as assert5, logMsg, uuid } from "@midscene/shared/utils";
1551
1548
  import dayjs from "dayjs";
1552
1549
 
1553
1550
  // src/web-element.ts
@@ -1647,7 +1644,7 @@ function reportFileName(tag = "web") {
1647
1644
  return `${reportTagName || tag}-${dateTimeInFileName}`;
1648
1645
  }
1649
1646
  function printReportMsg(filepath) {
1650
- console.log("Midscene - report file updated:", filepath);
1647
+ logMsg(`Midscene - report file updated: ${filepath}`);
1651
1648
  }
1652
1649
 
1653
1650
  // src/common/agent.ts