misoai-web 1.6.0 → 1.6.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.
- package/dist/es/agent.js +105 -50
- package/dist/es/agent.js.map +1 -1
- package/dist/es/bridge-mode-browser.js +3 -3
- package/dist/es/bridge-mode-browser.js.map +1 -1
- package/dist/es/bridge-mode.js +107 -52
- package/dist/es/bridge-mode.js.map +1 -1
- package/dist/es/chrome-extension.js +106 -51
- package/dist/es/chrome-extension.js.map +1 -1
- package/dist/es/index.js +106 -51
- package/dist/es/index.js.map +1 -1
- package/dist/es/midscene-playground.js +108 -53
- package/dist/es/midscene-playground.js.map +1 -1
- package/dist/es/midscene-server.js +4 -4
- package/dist/es/midscene-server.js.map +1 -1
- package/dist/es/playground.js +105 -50
- package/dist/es/playground.js.map +1 -1
- package/dist/es/playwright-report.js +1 -1
- package/dist/es/playwright-report.js.map +1 -1
- package/dist/es/playwright.js +106 -51
- package/dist/es/playwright.js.map +1 -1
- package/dist/es/puppeteer-agent-launcher.js +105 -50
- package/dist/es/puppeteer-agent-launcher.js.map +1 -1
- package/dist/es/puppeteer.js +105 -50
- package/dist/es/puppeteer.js.map +1 -1
- package/dist/es/utils.js +1 -1
- package/dist/es/utils.js.map +1 -1
- package/dist/es/yaml.js +1 -1
- package/dist/es/yaml.js.map +1 -1
- package/dist/lib/agent.js +105 -50
- package/dist/lib/agent.js.map +1 -1
- package/dist/lib/bridge-mode-browser.js +3 -3
- package/dist/lib/bridge-mode-browser.js.map +1 -1
- package/dist/lib/bridge-mode.js +107 -52
- package/dist/lib/bridge-mode.js.map +1 -1
- package/dist/lib/chrome-extension.js +106 -51
- package/dist/lib/chrome-extension.js.map +1 -1
- package/dist/lib/index.js +106 -51
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/midscene-playground.js +108 -53
- package/dist/lib/midscene-playground.js.map +1 -1
- package/dist/lib/midscene-server.js +4 -4
- package/dist/lib/midscene-server.js.map +1 -1
- package/dist/lib/playground.js +105 -50
- package/dist/lib/playground.js.map +1 -1
- package/dist/lib/playwright-report.js +1 -1
- package/dist/lib/playwright-report.js.map +1 -1
- package/dist/lib/playwright.js +106 -51
- package/dist/lib/playwright.js.map +1 -1
- package/dist/lib/puppeteer-agent-launcher.js +105 -50
- package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
- package/dist/lib/puppeteer.js +105 -50
- package/dist/lib/puppeteer.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/yaml.js +1 -1
- package/dist/lib/yaml.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/playwright.d.ts +1 -1
- package/package.json +18 -54
@@ -35,13 +35,13 @@ __export(reporter_exports, {
|
|
35
35
|
module.exports = __toCommonJS(reporter_exports);
|
36
36
|
|
37
37
|
// src/common/utils.ts
|
38
|
+
var import_dayjs = __toESM(require("dayjs"));
|
38
39
|
var import_ai_model = require("misoai-core/ai-model");
|
39
40
|
var import_utils = require("misoai-core/utils");
|
40
41
|
var import_env = require("misoai-shared/env");
|
41
42
|
var import_extractor = require("misoai-shared/extractor");
|
42
43
|
var import_img = require("misoai-shared/img");
|
43
44
|
var import_utils2 = require("misoai-shared/utils");
|
44
|
-
var import_dayjs = __toESM(require("dayjs"));
|
45
45
|
function reportFileName(tag = "web") {
|
46
46
|
const reportTagName = (0, import_env.getAIConfig)(import_env.MIDSCENE_REPORT_TAG_NAME);
|
47
47
|
const dateTimeInFileName = (0, import_dayjs.default)().format("YYYY-MM-DD_HH-mm-ss");
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"mappings":"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","names":["import_utils","dayjs"],"ignoreList":[],"sources":["../../src/playwright/reporter/index.ts","../../src/common/utils.ts"],"sourcesContent":["import {\n printReportMsg,\n replaceIllegalPathCharsAndSpace,\n reportFileName,\n} from '@/common/utils';\nimport type { ReportDumpWithAttributes } from 'misoai-core';\nimport { writeDumpReport } from 'misoai-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 mergedFilename: string;\nconst testTitleToFilename: Map<string, string> = new Map();\n\nfunction getStableFilename(testTitle: string): string {\n if (!testTitleToFilename.has(testTitle)) {\n // use reportFileName to generate the base filename\n // only replace the illegal characters in the file system: /, \\, :, *, ?, \", <, >, |\n const baseTag = `playwright-${replaceIllegalPathCharsAndSpace(testTitle)}`;\n const generatedFilename = reportFileName(baseTag);\n testTitleToFilename.set(testTitle, generatedFilename);\n }\n return testTitleToFilename.get(testTitle)!;\n}\n\nfunction updateReport(mode: 'merged' | 'separate', testId?: string) {\n if (mode === 'separate') {\n // in separate mode, find the data for the corresponding testID and generate a separate report\n const testData = testDataList.find(\n (data) => data.attributes?.playwright_test_id === testId,\n );\n\n if (testData) {\n // use the stable filename\n const stableFilename = getStableFilename(\n testData.attributes?.playwright_test_title,\n );\n\n const reportPath = writeDumpReport(stableFilename, [testData]);\n reportPath && printReportMsg(reportPath);\n }\n } else if (mode === 'merged') {\n // in merged mode, write all test data into one file\n if (!mergedFilename) {\n mergedFilename = reportFileName('playwright-merged');\n }\n\n const reportPath = writeDumpReport(mergedFilename, testDataList);\n reportPath && printReportMsg(reportPath);\n } else {\n throw new Error(\n `Unknown reporter type in playwright config: ${mode}, only support 'merged' or 'separate'`,\n );\n }\n}\n\nfunction getMode(reporterType: string) {\n if (!reporterType) {\n return 'merged';\n }\n\n if (reporterType !== 'merged' && reporterType !== 'separate') {\n throw new Error(\n `Unknown reporter type in playwright config: ${reporterType}, only support 'merged' or 'separate'`,\n );\n }\n\n return reporterType;\n}\n\nclass MidsceneReporter implements Reporter {\n mode?: 'merged' | 'separate';\n\n async onBegin(config: FullConfig, suite: Suite) {\n const reporterType = config.reporter?.[1]?.[1]?.type;\n\n this.mode = getMode(reporterType);\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 const retry = result.retry ? `(retry #${result.retry})` : '';\n const testId = `${test.id}${retry}`;\n const testData: ReportDumpWithAttributes = {\n dumpString: dumpAnnotation.description,\n attributes: {\n playwright_test_id: testId,\n playwright_test_title: `${test.title}${retry}`,\n playwright_test_status: result.status,\n playwright_test_duration: result.duration,\n },\n };\n\n testDataList.push(testData);\n\n updateReport(this.mode!, testId);\n\n test.annotations = test.annotations.filter(\n (annotation) => annotation.type !== 'MIDSCENE_DUMP_ANNOTATION',\n );\n }\n\n onEnd(result: FullResult) {\n updateReport(this.mode!);\n\n logger(`Finished the run: ${result.status}`);\n }\n}\n\nexport default MidsceneReporter;\n","import type { StaticPage } from '@/playground';\nimport type {\n BaseElement,\n ElementTreeNode,\n PlanningLocateParam,\n PlaywrightParserOpt,\n UIContext,\n} from 'misoai-core';\nimport { elementByPositionWithElementInfo } from 'misoai-core/ai-model';\nimport { uploadTestInfoToServer } from 'misoai-core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from 'misoai-shared/env';\nimport type { ElementInfo } from 'misoai-shared/extractor';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n traverseTree,\n treeToList,\n} from 'misoai-shared/extractor';\nimport { resizeImgBase64 } from 'misoai-shared/img';\nimport type { DebugFunction } from 'misoai-shared/logger';\nimport { assert, logMsg, uuid } from 'misoai-shared/utils';\nimport dayjs from 'dayjs';\nimport type { Page as PlaywrightPage } from 'playwright';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport { WebElementInfo } from '../web-element';\nimport type { WebPage } from './page';\n\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, isVisible } =\n elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\n isVisible,\n });\n });\n\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const elementsInfo = treeToList(webTree);\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 return {\n content: elementsInfo!,\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\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');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\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\nexport function replaceIllegalPathCharsAndSpace(str: string) {\n // Only replace characters that are illegal in filenames, but preserve path separators\n return str.replace(/[:*?\"<>| ]/g, '-');\n}\n\nexport function forceClosePopup(\n page: PuppeteerPage | PlaywrightPage,\n debug: DebugFunction,\n) {\n page.on('popup', async (popup) => {\n if (!popup) {\n console.warn('got a popup event, but the popup is not ready yet, skip');\n return;\n }\n const url = await (popup as PuppeteerPage).url();\n console.log(`Popup opened: ${url}`);\n if (!(popup as PuppeteerPage).isClosed()) {\n try {\n await (popup as PuppeteerPage).close(); // Close the newly opened TAB\n } catch (error) {\n debug(`failed to close popup ${url}, error: ${error}`);\n }\n } else {\n debug(`popup is already closed, skip close ${url}`);\n }\n\n if (!page.isClosed()) {\n try {\n await page.goto(url);\n } catch (error) {\n debug(`failed to goto ${url}, error: ${error}`);\n }\n } else {\n debug(`page is already closed, skip goto ${url}`);\n }\n });\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n"]}
|
1
|
+
{"version":3,"mappings":"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","names":["import_utils","dayjs"],"ignoreList":[],"sources":["../../src/playwright/reporter/index.ts","../../src/common/utils.ts"],"sourcesContent":["import {\n printReportMsg,\n replaceIllegalPathCharsAndSpace,\n reportFileName,\n} from '@/common/utils';\nimport type {\n FullConfig,\n FullResult,\n Reporter,\n Suite,\n TestCase,\n TestResult,\n} from '@playwright/test/reporter';\nimport type { ReportDumpWithAttributes } from 'misoai-core';\nimport { writeDumpReport } from 'misoai-core/utils';\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 mergedFilename: string;\nconst testTitleToFilename: Map<string, string> = new Map();\n\nfunction getStableFilename(testTitle: string): string {\n if (!testTitleToFilename.has(testTitle)) {\n // use reportFileName to generate the base filename\n // only replace the illegal characters in the file system: /, \\, :, *, ?, \", <, >, |\n const baseTag = `playwright-${replaceIllegalPathCharsAndSpace(testTitle)}`;\n const generatedFilename = reportFileName(baseTag);\n testTitleToFilename.set(testTitle, generatedFilename);\n }\n return testTitleToFilename.get(testTitle)!;\n}\n\nfunction updateReport(mode: 'merged' | 'separate', testId?: string) {\n if (mode === 'separate') {\n // in separate mode, find the data for the corresponding testID and generate a separate report\n const testData = testDataList.find(\n (data) => data.attributes?.playwright_test_id === testId,\n );\n\n if (testData) {\n // use the stable filename\n const stableFilename = getStableFilename(\n testData.attributes?.playwright_test_title,\n );\n\n const reportPath = writeDumpReport(stableFilename, [testData]);\n reportPath && printReportMsg(reportPath);\n }\n } else if (mode === 'merged') {\n // in merged mode, write all test data into one file\n if (!mergedFilename) {\n mergedFilename = reportFileName('playwright-merged');\n }\n\n const reportPath = writeDumpReport(mergedFilename, testDataList);\n reportPath && printReportMsg(reportPath);\n } else {\n throw new Error(\n `Unknown reporter type in playwright config: ${mode}, only support 'merged' or 'separate'`,\n );\n }\n}\n\nfunction getMode(reporterType: string) {\n if (!reporterType) {\n return 'merged';\n }\n\n if (reporterType !== 'merged' && reporterType !== 'separate') {\n throw new Error(\n `Unknown reporter type in playwright config: ${reporterType}, only support 'merged' or 'separate'`,\n );\n }\n\n return reporterType;\n}\n\nclass MidsceneReporter implements Reporter {\n mode?: 'merged' | 'separate';\n\n async onBegin(config: FullConfig, suite: Suite) {\n const reporterType = config.reporter?.[1]?.[1]?.type;\n\n this.mode = getMode(reporterType);\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 const retry = result.retry ? `(retry #${result.retry})` : '';\n const testId = `${test.id}${retry}`;\n const testData: ReportDumpWithAttributes = {\n dumpString: dumpAnnotation.description,\n attributes: {\n playwright_test_id: testId,\n playwright_test_title: `${test.title}${retry}`,\n playwright_test_status: result.status,\n playwright_test_duration: result.duration,\n },\n };\n\n testDataList.push(testData);\n\n updateReport(this.mode!, testId);\n\n test.annotations = test.annotations.filter(\n (annotation) => annotation.type !== 'MIDSCENE_DUMP_ANNOTATION',\n );\n }\n\n onEnd(result: FullResult) {\n updateReport(this.mode!);\n\n logger(`Finished the run: ${result.status}`);\n }\n}\n\nexport default MidsceneReporter;\n","import type { StaticPage } from '@/playground';\nimport dayjs from 'dayjs';\nimport type {\n BaseElement,\n ElementTreeNode,\n PlanningLocateParam,\n PlaywrightParserOpt,\n UIContext,\n} from 'misoai-core';\nimport { elementByPositionWithElementInfo } from 'misoai-core/ai-model';\nimport { uploadTestInfoToServer } from 'misoai-core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from 'misoai-shared/env';\nimport type { ElementInfo } from 'misoai-shared/extractor';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n traverseTree,\n treeToList,\n} from 'misoai-shared/extractor';\nimport { resizeImgBase64 } from 'misoai-shared/img';\nimport type { DebugFunction } from 'misoai-shared/logger';\nimport { assert, logMsg, uuid } from 'misoai-shared/utils';\nimport type { Page as PlaywrightPage } from 'playwright';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport { WebElementInfo } from '../web-element';\nimport type { WebPage } from './page';\n\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, isVisible } =\n elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\n isVisible,\n });\n });\n\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const elementsInfo = treeToList(webTree);\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 return {\n content: elementsInfo!,\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\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');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\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\nexport function replaceIllegalPathCharsAndSpace(str: string) {\n // Only replace characters that are illegal in filenames, but preserve path separators\n return str.replace(/[:*?\"<>| ]/g, '-');\n}\n\nexport function forceClosePopup(\n page: PuppeteerPage | PlaywrightPage,\n debug: DebugFunction,\n) {\n page.on('popup', async (popup) => {\n if (!popup) {\n console.warn('got a popup event, but the popup is not ready yet, skip');\n return;\n }\n const url = await (popup as PuppeteerPage).url();\n console.log(`Popup opened: ${url}`);\n if (!(popup as PuppeteerPage).isClosed()) {\n try {\n await (popup as PuppeteerPage).close(); // Close the newly opened TAB\n } catch (error) {\n debug(`failed to close popup ${url}, error: ${error}`);\n }\n } else {\n debug(`popup is already closed, skip close ${url}`);\n }\n\n if (!page.isClosed()) {\n try {\n await page.goto(url);\n } catch (error) {\n debug(`failed to goto ${url}, error: ${error}`);\n }\n } else {\n debug(`page is already closed, skip goto ${url}`);\n }\n });\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n"]}
|
package/dist/lib/playwright.js
CHANGED
@@ -345,8 +345,8 @@ var ScriptPlayer = class {
|
|
345
345
|
var import_js_yaml = __toESM(require("js-yaml"));
|
346
346
|
|
347
347
|
// src/yaml/utils.ts
|
348
|
-
var import_utils2 = require("misoai-shared/utils");
|
349
348
|
var import_js_yaml2 = __toESM(require("js-yaml"));
|
349
|
+
var import_utils2 = require("misoai-shared/utils");
|
350
350
|
function interpolateEnvVars(content) {
|
351
351
|
return content.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
|
352
352
|
const value = process.env[envVar.trim()];
|
@@ -492,13 +492,13 @@ function paramStr(task) {
|
|
492
492
|
}
|
493
493
|
|
494
494
|
// src/common/utils.ts
|
495
|
+
var import_dayjs = __toESM(require("dayjs"));
|
495
496
|
var import_ai_model = require("misoai-core/ai-model");
|
496
497
|
var import_utils3 = require("misoai-core/utils");
|
497
498
|
var import_env = require("misoai-shared/env");
|
498
499
|
var import_extractor = require("misoai-shared/extractor");
|
499
500
|
var import_img = require("misoai-shared/img");
|
500
501
|
var import_utils4 = require("misoai-shared/utils");
|
501
|
-
var import_dayjs = __toESM(require("dayjs"));
|
502
502
|
|
503
503
|
// src/web-element.ts
|
504
504
|
var WebElementInfo = class {
|
@@ -667,8 +667,12 @@ var WorkflowMemory = class {
|
|
667
667
|
const workflow = this.workflows.get(workflowId) || this.createEmptyWorkflowData(workflowId);
|
668
668
|
workflow.memory = [...memory];
|
669
669
|
workflow.metadata.totalSteps = workflow.steps.length;
|
670
|
-
workflow.metadata.completedSteps = workflow.steps.filter(
|
671
|
-
|
670
|
+
workflow.metadata.completedSteps = workflow.steps.filter(
|
671
|
+
(s) => s.status === "completed"
|
672
|
+
).length;
|
673
|
+
workflow.metadata.failedSteps = workflow.steps.filter(
|
674
|
+
(s) => s.status === "failed"
|
675
|
+
).length;
|
672
676
|
this.workflows.set(workflowId, workflow);
|
673
677
|
this.enforceRetentionPolicy();
|
674
678
|
}
|
@@ -679,7 +683,9 @@ var WorkflowMemory = class {
|
|
679
683
|
const workflow = this.workflows.get(workflowId) || this.createEmptyWorkflowData(workflowId);
|
680
684
|
workflow.context = { ...workflow.context, ...context };
|
681
685
|
if (context.currentStep) {
|
682
|
-
const existingStep = workflow.steps.find(
|
686
|
+
const existingStep = workflow.steps.find(
|
687
|
+
(s) => s.stepName === context.currentStep
|
688
|
+
);
|
683
689
|
if (!existingStep) {
|
684
690
|
workflow.steps.push({
|
685
691
|
stepId: `step_${workflow.steps.length + 1}`,
|
@@ -724,7 +730,9 @@ var WorkflowMemory = class {
|
|
724
730
|
enforceRetentionPolicy() {
|
725
731
|
const maxWorkflows = 10;
|
726
732
|
if (this.workflows.size > maxWorkflows) {
|
727
|
-
const sortedWorkflows = Array.from(this.workflows.entries()).sort(
|
733
|
+
const sortedWorkflows = Array.from(this.workflows.entries()).sort(
|
734
|
+
([, a], [, b]) => (b.metadata.endTime || b.metadata.startTime) - (a.metadata.endTime || a.metadata.startTime)
|
735
|
+
);
|
728
736
|
const toDelete = sortedWorkflows.slice(maxWorkflows);
|
729
737
|
toDelete.forEach(([workflowId]) => this.workflows.delete(workflowId));
|
730
738
|
}
|
@@ -1463,7 +1471,9 @@ var PageTaskExecutor = class {
|
|
1463
1471
|
*/
|
1464
1472
|
getPersistentExecutor() {
|
1465
1473
|
if (!this.persistentExecutor || this.persistentExecutor.status === "error") {
|
1466
|
-
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1474
|
+
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1475
|
+
this.sessionContext.workflowId
|
1476
|
+
);
|
1467
1477
|
this.persistentExecutor = new import_misoai_core.Executor("Persistent Task Executor", {
|
1468
1478
|
onTaskStart: this.onTaskStartCallback,
|
1469
1479
|
initialMemory: previousMemory
|
@@ -1492,7 +1502,9 @@ var PageTaskExecutor = class {
|
|
1492
1502
|
if (this.persistentExecutor) {
|
1493
1503
|
this.persistentExecutor.clearMemory();
|
1494
1504
|
}
|
1495
|
-
this.workflowMemory.clearWorkflow(
|
1505
|
+
this.workflowMemory.clearWorkflow(
|
1506
|
+
this.sessionContext.workflowId || "default"
|
1507
|
+
);
|
1496
1508
|
}
|
1497
1509
|
/**
|
1498
1510
|
* Mevcut hafızayı döndürür
|
@@ -1504,7 +1516,9 @@ var PageTaskExecutor = class {
|
|
1504
1516
|
* İş akışı hafızasını döndürür
|
1505
1517
|
*/
|
1506
1518
|
getWorkflowMemory() {
|
1507
|
-
return this.workflowMemory.getWorkflowData(
|
1519
|
+
return this.workflowMemory.getWorkflowData(
|
1520
|
+
this.sessionContext.workflowId || "default"
|
1521
|
+
);
|
1508
1522
|
}
|
1509
1523
|
/**
|
1510
1524
|
* Hafıza istatistiklerini döndürür
|
@@ -1512,7 +1526,13 @@ var PageTaskExecutor = class {
|
|
1512
1526
|
getMemoryStats() {
|
1513
1527
|
return this.persistentExecutor?.getMemoryStats() || {
|
1514
1528
|
totalItems: 0,
|
1515
|
-
analytics: {
|
1529
|
+
analytics: {
|
1530
|
+
totalTasks: 0,
|
1531
|
+
memoryHits: 0,
|
1532
|
+
memoryMisses: 0,
|
1533
|
+
averageMemorySize: 0,
|
1534
|
+
memoryEffectiveness: 0
|
1535
|
+
},
|
1516
1536
|
config: this.memoryConfig
|
1517
1537
|
};
|
1518
1538
|
}
|
@@ -1548,11 +1568,14 @@ var PageTaskExecutor = class {
|
|
1548
1568
|
let taskExecutor;
|
1549
1569
|
if (useMemory) {
|
1550
1570
|
taskExecutor = this.getPersistentExecutor();
|
1551
|
-
this.workflowMemory.updateWorkflowContext(
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1571
|
+
this.workflowMemory.updateWorkflowContext(
|
1572
|
+
{
|
1573
|
+
currentStep: title,
|
1574
|
+
pageInfo: this.sessionContext.pageInfo,
|
1575
|
+
timestamp: Date.now()
|
1576
|
+
},
|
1577
|
+
this.sessionContext.workflowId || "default"
|
1578
|
+
);
|
1556
1579
|
} else {
|
1557
1580
|
taskExecutor = new import_misoai_core.Executor(title, {
|
1558
1581
|
onTaskStart: this.onTaskStartCallback
|
@@ -1918,14 +1941,19 @@ var PageTaskExecutor = class {
|
|
1918
1941
|
*/
|
1919
1942
|
addToMemory(memoryItem) {
|
1920
1943
|
if (!this.persistentExecutor || this.persistentExecutor.status === "error") {
|
1921
|
-
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1944
|
+
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1945
|
+
this.sessionContext.workflowId
|
1946
|
+
);
|
1922
1947
|
this.persistentExecutor = new import_misoai_core.Executor("Persistent Task Executor", {
|
1923
1948
|
onTaskStart: this.onTaskStartCallback,
|
1924
1949
|
initialMemory: previousMemory
|
1925
1950
|
});
|
1926
1951
|
}
|
1927
1952
|
this.persistentExecutor.memoryStore?.add(memoryItem);
|
1928
|
-
this.persistentExecutor.memoryAnalytics?.recordMemoryOperation(
|
1953
|
+
this.persistentExecutor.memoryAnalytics?.recordMemoryOperation(
|
1954
|
+
"add",
|
1955
|
+
memoryItem
|
1956
|
+
);
|
1929
1957
|
}
|
1930
1958
|
};
|
1931
1959
|
|
@@ -2014,14 +2042,14 @@ function buildPlans(type, locateParam, param) {
|
|
2014
2042
|
var import_node_assert = __toESM(require("assert"));
|
2015
2043
|
var import_node_fs2 = require("fs");
|
2016
2044
|
var import_node_path2 = require("path");
|
2045
|
+
var import_js_yaml3 = __toESM(require("js-yaml"));
|
2017
2046
|
var import_common2 = require("misoai-shared/common");
|
2018
2047
|
var import_logger3 = require("misoai-shared/logger");
|
2019
2048
|
var import_utils9 = require("misoai-shared/utils");
|
2020
|
-
var import_js_yaml3 = __toESM(require("js-yaml"));
|
2021
2049
|
var import_semver = __toESM(require("semver"));
|
2022
2050
|
|
2023
2051
|
// package.json
|
2024
|
-
var version = "1.6.
|
2052
|
+
var version = "1.6.1";
|
2025
2053
|
|
2026
2054
|
// src/common/task-cache.ts
|
2027
2055
|
var debug3 = (0, import_logger3.getDebug)("cache");
|
@@ -2316,22 +2344,28 @@ var PageAgent = class {
|
|
2316
2344
|
const allThoughts = executor.tasks.filter((task) => task.thought).map((task) => task.thought);
|
2317
2345
|
const allLocates = executor.tasks.filter((task) => task.locate).map((task) => task.locate);
|
2318
2346
|
const allPlans = executor.tasks.filter((task) => task.param?.plans).map((task) => task.param?.plans);
|
2319
|
-
const planningTasks = executor.tasks.filter(
|
2320
|
-
|
2347
|
+
const planningTasks = executor.tasks.filter(
|
2348
|
+
(task) => task.type === "Planning"
|
2349
|
+
);
|
2350
|
+
const insightTasks = executor.tasks.filter(
|
2351
|
+
(task) => task.type === "Insight"
|
2352
|
+
);
|
2321
2353
|
const actionTasks = executor.tasks.filter((task) => task.type === "Action");
|
2322
2354
|
const planning = planningTasks.length > 0 ? {
|
2323
2355
|
type: "Planning",
|
2324
|
-
description:
|
2356
|
+
description: "Planning for task execution",
|
2325
2357
|
steps: planningTasks.map((task) => task.thought || "Planning step")
|
2326
2358
|
} : void 0;
|
2327
2359
|
const insight = insightTasks.length > 0 ? {
|
2328
2360
|
type: "Insight",
|
2329
|
-
description:
|
2330
|
-
elements: insightTasks.map(
|
2361
|
+
description: "Insight for task execution",
|
2362
|
+
elements: insightTasks.map(
|
2363
|
+
(task) => task.thought || "Insight element"
|
2364
|
+
)
|
2331
2365
|
} : void 0;
|
2332
2366
|
const action = actionTasks.length > 0 ? {
|
2333
2367
|
type: "Action",
|
2334
|
-
description:
|
2368
|
+
description: "Action for task execution",
|
2335
2369
|
result: lastTask?.output
|
2336
2370
|
} : void 0;
|
2337
2371
|
const actionDetails = executor.tasks.map((task) => ({
|
@@ -2665,7 +2699,10 @@ ${memoryContext}` : void 0;
|
|
2665
2699
|
}
|
2666
2700
|
const memoryContext = this.getMemoryAsContext();
|
2667
2701
|
const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
|
2668
|
-
const { output, executor } = await this.taskExecutor.assert(
|
2702
|
+
const { output, executor } = await this.taskExecutor.assert(
|
2703
|
+
assertionWithContext,
|
2704
|
+
memoryContext
|
2705
|
+
);
|
2669
2706
|
const metadata = this.afterTaskRunning(executor, true);
|
2670
2707
|
if (output && opt?.keepRawResponse) {
|
2671
2708
|
return {
|
@@ -2704,7 +2741,10 @@ A complex CAPTCHA typically has one or more of these characteristics:
|
|
2704
2741
|
Return only "complex" or "simple" based on your analysis.
|
2705
2742
|
`;
|
2706
2743
|
const complexityMsgs = [
|
2707
|
-
{
|
2744
|
+
{
|
2745
|
+
role: "system",
|
2746
|
+
content: "You are an AI assistant that analyzes screenshots to determine CAPTCHA complexity."
|
2747
|
+
},
|
2708
2748
|
{
|
2709
2749
|
role: "user",
|
2710
2750
|
content: [
|
@@ -2728,7 +2768,12 @@ Return only "complex" or "simple" based on your analysis.
|
|
2728
2768
|
);
|
2729
2769
|
const responseText = typeof complexityResult.content === "string" ? complexityResult.content.toLowerCase() : JSON.stringify(complexityResult.content).toLowerCase();
|
2730
2770
|
shouldUseDeepThink = responseText.includes("complex");
|
2731
|
-
debug4(
|
2771
|
+
debug4(
|
2772
|
+
"CAPTCHA complexity analysis:",
|
2773
|
+
responseText,
|
2774
|
+
"Using deep think:",
|
2775
|
+
shouldUseDeepThink
|
2776
|
+
);
|
2732
2777
|
} catch (error) {
|
2733
2778
|
debug4("Failed to analyze CAPTCHA complexity:", error);
|
2734
2779
|
}
|
@@ -2745,7 +2790,9 @@ Return only "complex" or "simple" based on your analysis.
|
|
2745
2790
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
2746
2791
|
} else if (action.type === "input" && action.value) {
|
2747
2792
|
if (action.target) {
|
2748
|
-
await this.aiInput(action.value, action.target, {
|
2793
|
+
await this.aiInput(action.value, action.target, {
|
2794
|
+
deepThink: shouldUseDeepThink
|
2795
|
+
});
|
2749
2796
|
}
|
2750
2797
|
} else if (action.type === "verify" && action.target) {
|
2751
2798
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
@@ -2757,7 +2804,9 @@ Return only "complex" or "simple" based on your analysis.
|
|
2757
2804
|
if (action.coordinates) {
|
2758
2805
|
const x = action.coordinates[0];
|
2759
2806
|
const y = action.coordinates[1];
|
2760
|
-
await this.aiTap(`element at coordinates (${x}, ${y})`, {
|
2807
|
+
await this.aiTap(`element at coordinates (${x}, ${y})`, {
|
2808
|
+
deepThink: shouldUseDeepThink
|
2809
|
+
});
|
2761
2810
|
} else if (action.target) {
|
2762
2811
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
2763
2812
|
}
|
@@ -2909,25 +2958,27 @@ ${errors}`);
|
|
2909
2958
|
const executionDump = {
|
2910
2959
|
name: screenshotTitle,
|
2911
2960
|
description: content,
|
2912
|
-
tasks: [
|
2913
|
-
|
2914
|
-
|
2915
|
-
|
2916
|
-
|
2917
|
-
|
2918
|
-
|
2919
|
-
|
2920
|
-
|
2921
|
-
|
2922
|
-
|
2923
|
-
|
2924
|
-
|
2925
|
-
|
2926
|
-
|
2927
|
-
|
2928
|
-
|
2961
|
+
tasks: [
|
2962
|
+
{
|
2963
|
+
type: "Screenshot",
|
2964
|
+
subType: "log",
|
2965
|
+
status: "finished",
|
2966
|
+
executor: null,
|
2967
|
+
param: {
|
2968
|
+
title: screenshotTitle,
|
2969
|
+
content
|
2970
|
+
},
|
2971
|
+
output: {
|
2972
|
+
screenshot
|
2973
|
+
},
|
2974
|
+
thought: `Logged screenshot: ${screenshotTitle}`,
|
2975
|
+
timing: {
|
2976
|
+
start: Date.now(),
|
2977
|
+
end: Date.now(),
|
2978
|
+
cost: 0
|
2979
|
+
}
|
2929
2980
|
}
|
2930
|
-
|
2981
|
+
],
|
2931
2982
|
sdkVersion: "1.0.0",
|
2932
2983
|
logTime: Date.now(),
|
2933
2984
|
model_name: "screenshot"
|
@@ -2979,7 +3030,9 @@ ${errors}`);
|
|
2979
3030
|
totalTasks: stats.analytics.totalTasks,
|
2980
3031
|
memoryHits: stats.analytics.memoryHits,
|
2981
3032
|
memoryMisses: stats.analytics.memoryMisses,
|
2982
|
-
memoryEffectiveness: Math.round(
|
3033
|
+
memoryEffectiveness: Math.round(
|
3034
|
+
stats.analytics.memoryEffectiveness * 100
|
3035
|
+
),
|
2983
3036
|
averageMemorySize: Math.round(stats.analytics.averageMemorySize * 100) / 100
|
2984
3037
|
},
|
2985
3038
|
config: stats.config,
|
@@ -3043,7 +3096,9 @@ ${errors}`);
|
|
3043
3096
|
calculateSuccessRate(memory) {
|
3044
3097
|
if (memory.length === 0)
|
3045
3098
|
return 0;
|
3046
|
-
const successCount = memory.filter(
|
3099
|
+
const successCount = memory.filter(
|
3100
|
+
(item) => item.metadata?.success !== false
|
3101
|
+
).length;
|
3047
3102
|
return Math.round(successCount / memory.length * 100);
|
3048
3103
|
}
|
3049
3104
|
calculateAverageExecutionTime(memory) {
|
@@ -3361,8 +3416,8 @@ var WebPage = class extends Page {
|
|
3361
3416
|
|
3362
3417
|
// src/playwright/ai-fixture.ts
|
3363
3418
|
var import_node_crypto = require("crypto");
|
3364
|
-
var import_logger6 = require("misoai-shared/logger");
|
3365
3419
|
var import_test = require("@playwright/test");
|
3420
|
+
var import_logger6 = require("misoai-shared/logger");
|
3366
3421
|
var debugPage2 = (0, import_logger6.getDebug)("web:playwright:ai-fixture");
|
3367
3422
|
var groupAndCaseForTest = (testInfo) => {
|
3368
3423
|
let taskFile;
|