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
package/dist/es/utils.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
// src/common/utils.ts
|
2
|
+
import dayjs from "dayjs";
|
2
3
|
import { elementByPositionWithElementInfo } from "misoai-core/ai-model";
|
3
4
|
import { uploadTestInfoToServer } from "misoai-core/utils";
|
4
5
|
import { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from "misoai-shared/env";
|
@@ -10,7 +11,6 @@ import {
|
|
10
11
|
} from "misoai-shared/extractor";
|
11
12
|
import { resizeImgBase64 } from "misoai-shared/img";
|
12
13
|
import { assert, logMsg, uuid } from "misoai-shared/utils";
|
13
|
-
import dayjs from "dayjs";
|
14
14
|
|
15
15
|
// src/web-element.ts
|
16
16
|
var WebElementInfo = class {
|
package/dist/es/utils.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/common/utils.ts","../../src/web-element.ts"],"sourcesContent":["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","import type { BaseElement, Rect } from 'misoai-core';\nimport type { NodeType } from 'misoai-shared/constants';\nexport interface WebElementInfoType extends BaseElement {\n id: string;\n locator: string;\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n}\n\nexport class WebElementInfo implements BaseElement {\n content: string;\n\n locator?: string;\n\n rect: Rect;\n\n center: [number, number];\n\n id: string;\n\n indexId: number;\n\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n\n xpaths?: string[];\n\n isVisible: boolean;\n\n constructor({\n content,\n rect,\n // page,\n locator,\n id,\n attributes,\n indexId,\n xpaths,\n isVisible,\n }: {\n content: string;\n rect: Rect;\n // page: WebPage;\n locator?: string;\n id: string;\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n indexId: number;\n xpaths?: string[];\n isVisible: boolean;\n }) {\n this.content = content;\n this.rect = rect;\n this.center = [\n Math.floor(rect.left + rect.width / 2),\n Math.floor(rect.top + rect.height / 2),\n ];\n // this.page = page;\n this.locator = locator;\n this.id = id;\n this.attributes = attributes;\n this.indexId = indexId;\n this.xpaths = xpaths;\n this.isVisible = isVisible;\n }\n}\n"]}
|
1
|
+
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/common/utils.ts","../../src/web-element.ts"],"sourcesContent":["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","import type { BaseElement, Rect } from 'misoai-core';\nimport type { NodeType } from 'misoai-shared/constants';\nexport interface WebElementInfoType extends BaseElement {\n id: string;\n locator: string;\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n}\n\nexport class WebElementInfo implements BaseElement {\n content: string;\n\n locator?: string;\n\n rect: Rect;\n\n center: [number, number];\n\n id: string;\n\n indexId: number;\n\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n\n xpaths?: string[];\n\n isVisible: boolean;\n\n constructor({\n content,\n rect,\n // page,\n locator,\n id,\n attributes,\n indexId,\n xpaths,\n isVisible,\n }: {\n content: string;\n rect: Rect;\n // page: WebPage;\n locator?: string;\n id: string;\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n indexId: number;\n xpaths?: string[];\n isVisible: boolean;\n }) {\n this.content = content;\n this.rect = rect;\n this.center = [\n Math.floor(rect.left + rect.width / 2),\n Math.floor(rect.top + rect.height / 2),\n ];\n // this.page = page;\n this.locator = locator;\n this.id = id;\n this.attributes = attributes;\n this.indexId = indexId;\n this.xpaths = xpaths;\n this.isVisible = isVisible;\n }\n}\n"]}
|
package/dist/es/yaml.js
CHANGED
@@ -311,8 +311,8 @@ function buildYaml(env, tasks) {
|
|
311
311
|
}
|
312
312
|
|
313
313
|
// src/yaml/utils.ts
|
314
|
-
import { assert as assert2 } from "misoai-shared/utils";
|
315
314
|
import yaml2 from "js-yaml";
|
315
|
+
import { assert as assert2 } from "misoai-shared/utils";
|
316
316
|
function interpolateEnvVars(content) {
|
317
317
|
return content.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
|
318
318
|
const value = process.env[envVar.trim()];
|
package/dist/es/yaml.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"mappings":"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","names":["resolve","assert","yaml"],"ignoreList":[],"sources":["../../src/yaml/player.ts","../../src/yaml/builder.ts","../../src/yaml/utils.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { assert, ifInBrowser } from 'misoai-shared/utils';\n\nimport type { PageAgent } from '@/common/agent';\nimport type {\n FreeFn,\n MidsceneYamlFlowItemAIAction,\n MidsceneYamlFlowItemAIAssert,\n MidsceneYamlFlowItemAIBoolean,\n MidsceneYamlFlowItemAIHover,\n MidsceneYamlFlowItemAIInput,\n MidsceneYamlFlowItemAIKeyboardPress,\n MidsceneYamlFlowItemAILocate,\n MidsceneYamlFlowItemAINString,\n MidsceneYamlFlowItemAINumber,\n MidsceneYamlFlowItemAIQuery,\n MidsceneYamlFlowItemAIRightClick,\n MidsceneYamlFlowItemAIScroll,\n MidsceneYamlFlowItemAITap,\n MidsceneYamlFlowItemAIWaitFor,\n MidsceneYamlFlowItemEvaluateJavaScript,\n MidsceneYamlFlowItemLogScreenshot,\n MidsceneYamlFlowItemSleep,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n} from 'misoai-core';\nimport { getMidsceneRunSubDir } from 'misoai-shared/common';\n\nexport class ScriptPlayer<T extends MidsceneYamlScriptEnv> {\n public currentTaskIndex?: number;\n public taskStatusList: ScriptPlayerTaskStatus[] = [];\n public status: ScriptPlayerStatusValue = 'init';\n public reportFile?: string | null;\n public result: Record<string, any>;\n private unnamedResultIndex = 0;\n public output?: string | null;\n public errorInSetup?: Error;\n private pageAgent: PageAgent | null = null;\n public agentStatusTip?: string;\n constructor(\n private script: MidsceneYamlScript,\n private setupAgent: (platform: T) => Promise<{\n agent: PageAgent;\n freeFn: FreeFn[];\n }>,\n public onTaskStatusChange?: (taskStatus: ScriptPlayerTaskStatus) => void,\n ) {\n this.result = {};\n\n const target = script.target || script.web || script.android;\n\n if (ifInBrowser) {\n this.output = undefined;\n } else if (target?.output) {\n this.output = resolve(process.cwd(), target.output);\n } else {\n this.output = join(getMidsceneRunSubDir('output'), `${process.pid}.json`);\n }\n\n this.taskStatusList = (script.tasks || []).map((task, taskIndex) => ({\n ...task,\n index: taskIndex,\n status: 'init',\n totalSteps: task.flow?.length || 0,\n }));\n }\n\n private setResult(key: string | undefined, value: any) {\n const keyToUse = key || this.unnamedResultIndex++;\n if (this.result[keyToUse]) {\n console.warn(`result key ${keyToUse} already exists, will overwrite`);\n }\n this.result[keyToUse] = value;\n\n this.flushResult();\n }\n\n private setPlayerStatus(status: ScriptPlayerStatusValue, error?: Error) {\n this.status = status;\n this.errorInSetup = error;\n }\n\n private notifyCurrentTaskStatusChange(taskIndex?: number) {\n const taskIndexToNotify =\n typeof taskIndex === 'number' ? taskIndex : this.currentTaskIndex;\n\n if (typeof taskIndexToNotify !== 'number') {\n return;\n }\n\n const taskStatus = this.taskStatusList[taskIndexToNotify];\n if (this.onTaskStatusChange) {\n this.onTaskStatusChange(taskStatus);\n }\n }\n\n private async setTaskStatus(\n index: number,\n statusValue: ScriptPlayerStatusValue,\n error?: Error,\n ) {\n this.taskStatusList[index].status = statusValue;\n if (error) {\n this.taskStatusList[index].error = error;\n }\n\n this.notifyCurrentTaskStatusChange(index);\n }\n\n private setTaskIndex(taskIndex: number) {\n this.currentTaskIndex = taskIndex;\n }\n\n private flushResult() {\n if (Object.keys(this.result).length && this.output) {\n const output = resolve(process.cwd(), this.output);\n const outputDir = dirname(output);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(output, JSON.stringify(this.result, undefined, 2));\n }\n }\n\n async playTask(taskStatus: ScriptPlayerTaskStatus, agent: PageAgent) {\n const { flow } = taskStatus;\n assert(flow, 'missing flow in task');\n\n for (const flowItemIndex in flow) {\n const currentStep = Number.parseInt(flowItemIndex, 10);\n taskStatus.currentStep = currentStep;\n const flowItem = flow[flowItemIndex];\n if (\n 'aiAction' in (flowItem as MidsceneYamlFlowItemAIAction) ||\n 'ai' in (flowItem as MidsceneYamlFlowItemAIAction)\n ) {\n const actionTask = flowItem as MidsceneYamlFlowItemAIAction;\n const prompt = actionTask.aiAction || actionTask.ai;\n assert(prompt, 'missing prompt for ai (aiAction)');\n assert(\n typeof prompt === 'string',\n 'prompt for aiAction must be a string',\n );\n await agent.aiAction(prompt, {\n cacheable: actionTask.cacheable,\n });\n } else if ('aiAssert' in (flowItem as MidsceneYamlFlowItemAIAssert)) {\n const assertTask = flowItem as MidsceneYamlFlowItemAIAssert;\n const prompt = assertTask.aiAssert;\n const msg = assertTask.errorMessage;\n assert(prompt, 'missing prompt for aiAssert');\n assert(\n typeof prompt === 'string',\n 'prompt for aiAssert must be a string',\n );\n await agent.aiAssert(prompt, msg);\n } else if ('aiQuery' in (flowItem as MidsceneYamlFlowItemAIQuery)) {\n const queryTask = flowItem as MidsceneYamlFlowItemAIQuery;\n const prompt = queryTask.aiQuery;\n const options = {\n domIncluded: queryTask.domIncluded,\n screenshotIncluded: queryTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiQuery');\n assert(\n typeof prompt === 'string',\n 'prompt for aiQuery must be a string',\n );\n const queryResult = await agent.aiQuery(prompt);\n this.setResult(queryTask.name, queryResult);\n } else if ('aiNumber' in (flowItem as MidsceneYamlFlowItemAINumber)) {\n const numberTask = flowItem as MidsceneYamlFlowItemAINumber;\n const prompt = numberTask.aiNumber;\n const options = {\n domIncluded: numberTask.domIncluded,\n screenshotIncluded: numberTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for number');\n assert(\n typeof prompt === 'string',\n 'prompt for number must be a string',\n );\n const numberResult = await agent.aiNumber(prompt);\n this.setResult(numberTask.name, numberResult);\n } else if ('aiString' in (flowItem as MidsceneYamlFlowItemAINString)) {\n const stringTask = flowItem as MidsceneYamlFlowItemAINString;\n const prompt = stringTask.aiString;\n const options = {\n domIncluded: stringTask.domIncluded,\n screenshotIncluded: stringTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for string');\n assert(\n typeof prompt === 'string',\n 'prompt for string must be a string',\n );\n const stringResult = await agent.aiString(prompt);\n this.setResult(stringTask.name, stringResult);\n } else if ('aiBoolean' in (flowItem as MidsceneYamlFlowItemAIBoolean)) {\n const booleanTask = flowItem as MidsceneYamlFlowItemAIBoolean;\n const prompt = booleanTask.aiBoolean;\n const options = {\n domIncluded: booleanTask.domIncluded,\n screenshotIncluded: booleanTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for boolean');\n assert(\n typeof prompt === 'string',\n 'prompt for boolean must be a string',\n );\n const booleanResult = await agent.aiBoolean(prompt);\n this.setResult(booleanTask.name, booleanResult);\n } else if ('aiLocate' in (flowItem as MidsceneYamlFlowItemAILocate)) {\n const locateTask = flowItem as MidsceneYamlFlowItemAILocate;\n const prompt = locateTask.aiLocate;\n assert(prompt, 'missing prompt for aiLocate');\n assert(\n typeof prompt === 'string',\n 'prompt for aiLocate must be a string',\n );\n const locateResult = await agent.aiLocate(prompt);\n this.setResult(locateTask.name, locateResult);\n } else if ('aiWaitFor' in (flowItem as MidsceneYamlFlowItemAIWaitFor)) {\n const waitForTask = flowItem as MidsceneYamlFlowItemAIWaitFor;\n const prompt = waitForTask.aiWaitFor;\n assert(prompt, 'missing prompt for aiWaitFor');\n assert(\n typeof prompt === 'string',\n 'prompt for aiWaitFor must be a string',\n );\n const timeout = waitForTask.timeout;\n await agent.aiWaitFor(prompt, { timeoutMs: timeout });\n } else if ('sleep' in (flowItem as MidsceneYamlFlowItemSleep)) {\n const sleepTask = flowItem as MidsceneYamlFlowItemSleep;\n const ms = sleepTask.sleep;\n let msNumber = ms;\n if (typeof ms === 'string') {\n msNumber = Number.parseInt(ms, 10);\n }\n assert(\n msNumber && msNumber > 0,\n `ms for sleep must be greater than 0, but got ${ms}`,\n );\n await new Promise((resolve) => setTimeout(resolve, msNumber));\n } else if ('aiTap' in (flowItem as MidsceneYamlFlowItemAITap)) {\n const tapTask = flowItem as MidsceneYamlFlowItemAITap;\n await agent.aiTap(tapTask.aiTap, tapTask);\n } else if (\n 'aiRightClick' in (flowItem as MidsceneYamlFlowItemAIRightClick)\n ) {\n const rightClickTask = flowItem as MidsceneYamlFlowItemAIRightClick;\n await agent.aiRightClick(rightClickTask.aiRightClick, rightClickTask);\n } else if ('aiHover' in (flowItem as MidsceneYamlFlowItemAIHover)) {\n const hoverTask = flowItem as MidsceneYamlFlowItemAIHover;\n await agent.aiHover(hoverTask.aiHover, hoverTask);\n } else if ('aiInput' in (flowItem as MidsceneYamlFlowItemAIInput)) {\n // may be input empty string ''\n const inputTask = flowItem as MidsceneYamlFlowItemAIInput;\n await agent.aiInput(inputTask.aiInput, inputTask.locate, inputTask);\n } else if (\n 'aiKeyboardPress' in (flowItem as MidsceneYamlFlowItemAIKeyboardPress)\n ) {\n const keyboardPressTask =\n flowItem as MidsceneYamlFlowItemAIKeyboardPress;\n await agent.aiKeyboardPress(\n keyboardPressTask.aiKeyboardPress,\n keyboardPressTask.locate,\n keyboardPressTask,\n );\n } else if ('aiScroll' in (flowItem as MidsceneYamlFlowItemAIScroll)) {\n const scrollTask = flowItem as MidsceneYamlFlowItemAIScroll;\n await agent.aiScroll(scrollTask, scrollTask.locate, scrollTask);\n } else if (\n 'javascript' in (flowItem as MidsceneYamlFlowItemEvaluateJavaScript)\n ) {\n const evaluateJavaScriptTask =\n flowItem as MidsceneYamlFlowItemEvaluateJavaScript;\n\n const result = await agent.evaluateJavaScript(\n evaluateJavaScriptTask.javascript,\n );\n this.setResult(evaluateJavaScriptTask.name, result);\n } else if (\n 'logScreenshot' in (flowItem as MidsceneYamlFlowItemLogScreenshot)\n ) {\n const logScreenshotTask = flowItem as MidsceneYamlFlowItemLogScreenshot;\n await agent.logScreenshot(logScreenshotTask.logScreenshot, {\n content: logScreenshotTask.content || '',\n });\n } else {\n throw new Error(`unknown flowItem: ${JSON.stringify(flowItem)}`);\n }\n }\n this.reportFile = agent.reportFile;\n }\n\n async run() {\n const { target, web, android, tasks } = this.script;\n const webEnv = web || target;\n const androidEnv = android;\n const platform = webEnv || androidEnv;\n\n this.setPlayerStatus('running');\n\n let agent: PageAgent | null = null;\n let freeFn: FreeFn[] = [];\n try {\n const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(\n platform as T,\n );\n agent = newAgent;\n const originalOnTaskStartTip = agent.onTaskStartTip;\n agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') {\n this.agentStatusTip = tip;\n }\n originalOnTaskStartTip?.(tip);\n };\n freeFn = [\n ...(newFreeFn || []),\n {\n name: 'restore-agent-onTaskStartTip',\n fn: () => {\n if (agent) {\n agent.onTaskStartTip = originalOnTaskStartTip;\n }\n },\n },\n ];\n } catch (e) {\n this.setPlayerStatus('error', e as Error);\n return;\n }\n this.pageAgent = agent;\n\n let taskIndex = 0;\n this.setPlayerStatus('running');\n let errorFlag = false;\n while (taskIndex < tasks.length) {\n const taskStatus = this.taskStatusList[taskIndex];\n this.setTaskStatus(taskIndex, 'running' as any);\n this.setTaskIndex(taskIndex);\n\n try {\n await this.playTask(taskStatus, this.pageAgent);\n this.setTaskStatus(taskIndex, 'done' as any);\n } catch (e) {\n this.setTaskStatus(taskIndex, 'error' as any, e as Error);\n\n if (taskStatus.continueOnError) {\n // nothing more to do\n } else {\n this.reportFile = agent.reportFile;\n errorFlag = true;\n break;\n }\n }\n this.reportFile = agent.reportFile;\n taskIndex++;\n }\n\n if (errorFlag) {\n this.setPlayerStatus('error');\n } else {\n this.setPlayerStatus('done');\n }\n this.agentStatusTip = '';\n\n // free the resources\n for (const fn of freeFn) {\n try {\n // console.log('freeing', fn.name);\n await fn.fn();\n // console.log('freed', fn.name);\n } catch (e) {\n // console.error('error freeing', fn.name, e);\n }\n }\n }\n}\n","import type {\n MidsceneYamlScript,\n MidsceneYamlScriptWebEnv,\n MidsceneYamlTask,\n} from 'misoai-core';\nimport yaml from 'js-yaml';\n\nexport function buildYaml(\n env: MidsceneYamlScriptWebEnv,\n tasks: MidsceneYamlTask[],\n) {\n const result: MidsceneYamlScript = {\n target: env,\n tasks,\n };\n\n return yaml.dump(result, {\n indent: 2,\n });\n}\n","import { assert } from 'misoai-shared/utils';\nimport yaml from 'js-yaml';\n\nimport type { MidsceneYamlScript } from 'misoai-core';\n\nfunction interpolateEnvVars(content: string): string {\n return content.replace(/\\$\\{([^}]+)\\}/g, (_, envVar) => {\n const value = process.env[envVar.trim()];\n if (value === undefined) {\n throw new Error(`Environment variable \"${envVar.trim()}\" is not defined`);\n }\n return value;\n });\n}\n\nexport function parseYamlScript(\n content: string,\n filePath?: string,\n ignoreCheckingTarget?: boolean,\n): MidsceneYamlScript {\n let processedContent = content;\n if (content.indexOf('android') !== -1 && content.match(/deviceId:\\s*(\\d+)/)) {\n let matchedDeviceId;\n processedContent = content.replace(\n /deviceId:\\s*(\\d+)/g,\n (match, deviceId) => {\n matchedDeviceId = deviceId;\n return `deviceId: '${deviceId}'`;\n },\n );\n console.warn(\n `please use string-style deviceId in yaml script, for example: deviceId: \"${matchedDeviceId}\"`,\n );\n }\n const interpolatedContent = interpolateEnvVars(processedContent);\n const obj = yaml.load(interpolatedContent, {\n schema: yaml.JSON_SCHEMA,\n }) as MidsceneYamlScript;\n\n const pathTip = filePath ? `, failed to load ${filePath}` : '';\n const android =\n typeof obj.android !== 'undefined'\n ? Object.assign({}, obj.android || {})\n : undefined;\n const webConfig = obj.web || obj.target; // no need to handle null case, because web has required parameters url\n const web =\n typeof webConfig !== 'undefined'\n ? Object.assign({}, webConfig || {})\n : undefined;\n\n if (!ignoreCheckingTarget) {\n // make sure at least one of target/web/android is provided\n assert(\n web || android,\n `at least one of \"target\", \"web\", or \"android\" properties is required in yaml script${pathTip}`,\n );\n\n // make sure only one of target/web/android is provided\n assert(\n (web && !android) || (!web && android),\n `only one of \"target\", \"web\", or \"android\" properties is allowed in yaml script${pathTip}`,\n );\n\n // make sure the config is valid\n if (web || android) {\n assert(\n typeof web === 'object' || typeof android === 'object',\n `property \"target/web/android\" must be an object${pathTip}`,\n );\n }\n }\n\n assert(obj.tasks, `property \"tasks\" is required in yaml script ${pathTip}`);\n assert(\n Array.isArray(obj.tasks),\n `property \"tasks\" must be an array in yaml script, but got ${obj.tasks}`,\n );\n return obj;\n}\n"]}
|
1
|
+
{"version":3,"mappings":";AAAA,SAAS,YAAY,WAAW,qBAAqB;AACrD,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,QAAQ,mBAAmB;AA2BpC,SAAS,4BAA4B;AAE9B,IAAM,eAAN,MAAoD;AAAA,EAWzD,YACU,QACA,YAID,oBACP;AANQ;AACA;AAID;AAfT,SAAO,iBAA2C,CAAC;AACnD,SAAO,SAAkC;AAGzC,SAAQ,qBAAqB;AAG7B,SAAQ,YAA8B;AAUpC,SAAK,SAAS,CAAC;AAEf,UAAM,SAAS,OAAO,UAAU,OAAO,OAAO,OAAO;AAErD,QAAI,aAAa;AACf,WAAK,SAAS;AAAA,IAChB,WAAW,QAAQ,QAAQ;AACzB,WAAK,SAAS,QAAQ,QAAQ,IAAI,GAAG,OAAO,MAAM;AAAA,IACpD,OAAO;AACL,WAAK,SAAS,KAAK,qBAAqB,QAAQ,GAAG,GAAG,QAAQ,GAAG,OAAO;AAAA,IAC1E;AAEA,SAAK,kBAAkB,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,eAAe;AAAA,MACnE,GAAG;AAAA,MACH,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY,KAAK,MAAM,UAAU;AAAA,IACnC,EAAE;AAAA,EACJ;AAAA,EAEQ,UAAU,KAAyB,OAAY;AACrD,UAAM,WAAW,OAAO,KAAK;AAC7B,QAAI,KAAK,OAAO,QAAQ,GAAG;AACzB,cAAQ,KAAK,cAAc,QAAQ,iCAAiC;AAAA,IACtE;AACA,SAAK,OAAO,QAAQ,IAAI;AAExB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,gBAAgB,QAAiC,OAAe;AACtE,SAAK,SAAS;AACd,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,8BAA8B,WAAoB;AACxD,UAAM,oBACJ,OAAO,cAAc,WAAW,YAAY,KAAK;AAEnD,QAAI,OAAO,sBAAsB,UAAU;AACzC;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,eAAe,iBAAiB;AACxD,QAAI,KAAK,oBAAoB;AAC3B,WAAK,mBAAmB,UAAU;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,MAAc,cACZ,OACA,aACA,OACA;AACA,SAAK,eAAe,KAAK,EAAE,SAAS;AACpC,QAAI,OAAO;AACT,WAAK,eAAe,KAAK,EAAE,QAAQ;AAAA,IACrC;AAEA,SAAK,8BAA8B,KAAK;AAAA,EAC1C;AAAA,EAEQ,aAAa,WAAmB;AACtC,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEQ,cAAc;AACpB,QAAI,OAAO,KAAK,KAAK,MAAM,EAAE,UAAU,KAAK,QAAQ;AAClD,YAAM,SAAS,QAAQ,QAAQ,IAAI,GAAG,KAAK,MAAM;AACjD,YAAM,YAAY,QAAQ,MAAM;AAChC,UAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,kBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,MAC1C;AACA,oBAAc,QAAQ,KAAK,UAAU,KAAK,QAAQ,QAAW,CAAC,CAAC;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,YAAoC,OAAkB;AACnE,UAAM,EAAE,KAAK,IAAI;AACjB,WAAO,MAAM,sBAAsB;AAEnC,eAAW,iBAAiB,MAAM;AAChC,YAAM,cAAc,OAAO,SAAS,eAAe,EAAE;AACrD,iBAAW,cAAc;AACzB,YAAM,WAAW,KAAK,aAAa;AACnC,UACE,cAAe,YACf,QAAS,UACT;AACA,cAAM,aAAa;AACnB,cAAM,SAAS,WAAW,YAAY,WAAW;AACjD,eAAO,QAAQ,kCAAkC;AACjD;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,MAAM,SAAS,QAAQ;AAAA,UAC3B,WAAW,WAAW;AAAA,QACxB,CAAC;AAAA,MACH,WAAW,cAAe,UAA2C;AACnE,cAAM,aAAa;AACnB,cAAM,SAAS,WAAW;AAC1B,cAAM,MAAM,WAAW;AACvB,eAAO,QAAQ,6BAA6B;AAC5C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,MAAM,SAAS,QAAQ,GAAG;AAAA,MAClC,WAAW,aAAc,UAA0C;AACjE,cAAM,YAAY;AAClB,cAAM,SAAS,UAAU;AACzB,cAAM,UAAU;AAAA,UACd,aAAa,UAAU;AAAA,UACvB,oBAAoB,UAAU;AAAA,QAChC;AACA,eAAO,QAAQ,4BAA4B;AAC3C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,cAAc,MAAM,MAAM,QAAQ,MAAM;AAC9C,aAAK,UAAU,UAAU,MAAM,WAAW;AAAA,MAC5C,WAAW,cAAe,UAA2C;AACnE,cAAM,aAAa;AACnB,cAAM,SAAS,WAAW;AAC1B,cAAM,UAAU;AAAA,UACd,aAAa,WAAW;AAAA,UACxB,oBAAoB,WAAW;AAAA,QACjC;AACA,eAAO,QAAQ,2BAA2B;AAC1C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,eAAe,MAAM,MAAM,SAAS,MAAM;AAChD,aAAK,UAAU,WAAW,MAAM,YAAY;AAAA,MAC9C,WAAW,cAAe,UAA4C;AACpE,cAAM,aAAa;AACnB,cAAM,SAAS,WAAW;AAC1B,cAAM,UAAU;AAAA,UACd,aAAa,WAAW;AAAA,UACxB,oBAAoB,WAAW;AAAA,QACjC;AACA,eAAO,QAAQ,2BAA2B;AAC1C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,eAAe,MAAM,MAAM,SAAS,MAAM;AAChD,aAAK,UAAU,WAAW,MAAM,YAAY;AAAA,MAC9C,WAAW,eAAgB,UAA4C;AACrE,cAAM,cAAc;AACpB,cAAM,SAAS,YAAY;AAC3B,cAAM,UAAU;AAAA,UACd,aAAa,YAAY;AAAA,UACzB,oBAAoB,YAAY;AAAA,QAClC;AACA,eAAO,QAAQ,4BAA4B;AAC3C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,gBAAgB,MAAM,MAAM,UAAU,MAAM;AAClD,aAAK,UAAU,YAAY,MAAM,aAAa;AAAA,MAChD,WAAW,cAAe,UAA2C;AACnE,cAAM,aAAa;AACnB,cAAM,SAAS,WAAW;AAC1B,eAAO,QAAQ,6BAA6B;AAC5C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,eAAe,MAAM,MAAM,SAAS,MAAM;AAChD,aAAK,UAAU,WAAW,MAAM,YAAY;AAAA,MAC9C,WAAW,eAAgB,UAA4C;AACrE,cAAM,cAAc;AACpB,cAAM,SAAS,YAAY;AAC3B,eAAO,QAAQ,8BAA8B;AAC7C;AAAA,UACE,OAAO,WAAW;AAAA,UAClB;AAAA,QACF;AACA,cAAM,UAAU,YAAY;AAC5B,cAAM,MAAM,UAAU,QAAQ,EAAE,WAAW,QAAQ,CAAC;AAAA,MACtD,WAAW,WAAY,UAAwC;AAC7D,cAAM,YAAY;AAClB,cAAM,KAAK,UAAU;AACrB,YAAI,WAAW;AACf,YAAI,OAAO,OAAO,UAAU;AAC1B,qBAAW,OAAO,SAAS,IAAI,EAAE;AAAA,QACnC;AACA;AAAA,UACE,YAAY,WAAW;AAAA,UACvB,gDAAgD,EAAE;AAAA,QACpD;AACA,cAAM,IAAI,QAAQ,CAACA,aAAY,WAAWA,UAAS,QAAQ,CAAC;AAAA,MAC9D,WAAW,WAAY,UAAwC;AAC7D,cAAM,UAAU;AAChB,cAAM,MAAM,MAAM,QAAQ,OAAO,OAAO;AAAA,MAC1C,WACE,kBAAmB,UACnB;AACA,cAAM,iBAAiB;AACvB,cAAM,MAAM,aAAa,eAAe,cAAc,cAAc;AAAA,MACtE,WAAW,aAAc,UAA0C;AACjE,cAAM,YAAY;AAClB,cAAM,MAAM,QAAQ,UAAU,SAAS,SAAS;AAAA,MAClD,WAAW,aAAc,UAA0C;AAEjE,cAAM,YAAY;AAClB,cAAM,MAAM,QAAQ,UAAU,SAAS,UAAU,QAAQ,SAAS;AAAA,MACpE,WACE,qBAAsB,UACtB;AACA,cAAM,oBACJ;AACF,cAAM,MAAM;AAAA,UACV,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,UAClB;AAAA,QACF;AAAA,MACF,WAAW,cAAe,UAA2C;AACnE,cAAM,aAAa;AACnB,cAAM,MAAM,SAAS,YAAY,WAAW,QAAQ,UAAU;AAAA,MAChE,WACE,gBAAiB,UACjB;AACA,cAAM,yBACJ;AAEF,cAAM,SAAS,MAAM,MAAM;AAAA,UACzB,uBAAuB;AAAA,QACzB;AACA,aAAK,UAAU,uBAAuB,MAAM,MAAM;AAAA,MACpD,WACE,mBAAoB,UACpB;AACA,cAAM,oBAAoB;AAC1B,cAAM,MAAM,cAAc,kBAAkB,eAAe;AAAA,UACzD,SAAS,kBAAkB,WAAW;AAAA,QACxC,CAAC;AAAA,MACH,OAAO;AACL,cAAM,IAAI,MAAM,qBAAqB,KAAK,UAAU,QAAQ,CAAC,EAAE;AAAA,MACjE;AAAA,IACF;AACA,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,MAAM;AACV,UAAM,EAAE,QAAQ,KAAK,SAAS,MAAM,IAAI,KAAK;AAC7C,UAAM,SAAS,OAAO;AACtB,UAAM,aAAa;AACnB,UAAM,WAAW,UAAU;AAE3B,SAAK,gBAAgB,SAAS;AAE9B,QAAI,QAA0B;AAC9B,QAAI,SAAmB,CAAC;AACxB,QAAI;AACF,YAAM,EAAE,OAAO,UAAU,QAAQ,UAAU,IAAI,MAAM,KAAK;AAAA,QACxD;AAAA,MACF;AACA,cAAQ;AACR,YAAM,yBAAyB,MAAM;AACrC,YAAM,iBAAiB,CAAC,QAAQ;AAC9B,YAAI,KAAK,WAAW,WAAW;AAC7B,eAAK,iBAAiB;AAAA,QACxB;AACA,iCAAyB,GAAG;AAAA,MAC9B;AACA,eAAS;AAAA,QACP,GAAI,aAAa,CAAC;AAAA,QAClB;AAAA,UACE,MAAM;AAAA,UACN,IAAI,MAAM;AACR,gBAAI,OAAO;AACT,oBAAM,iBAAiB;AAAA,YACzB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,WAAK,gBAAgB,SAAS,CAAU;AACxC;AAAA,IACF;AACA,SAAK,YAAY;AAEjB,QAAI,YAAY;AAChB,SAAK,gBAAgB,SAAS;AAC9B,QAAI,YAAY;AAChB,WAAO,YAAY,MAAM,QAAQ;AAC/B,YAAM,aAAa,KAAK,eAAe,SAAS;AAChD,WAAK,cAAc,WAAW,SAAgB;AAC9C,WAAK,aAAa,SAAS;AAE3B,UAAI;AACF,cAAM,KAAK,SAAS,YAAY,KAAK,SAAS;AAC9C,aAAK,cAAc,WAAW,MAAa;AAAA,MAC7C,SAAS,GAAG;AACV,aAAK,cAAc,WAAW,SAAgB,CAAU;AAExD,YAAI,WAAW,iBAAiB;AAAA,QAEhC,OAAO;AACL,eAAK,aAAa,MAAM;AACxB,sBAAY;AACZ;AAAA,QACF;AAAA,MACF;AACA,WAAK,aAAa,MAAM;AACxB;AAAA,IACF;AAEA,QAAI,WAAW;AACb,WAAK,gBAAgB,OAAO;AAAA,IAC9B,OAAO;AACL,WAAK,gBAAgB,MAAM;AAAA,IAC7B;AACA,SAAK,iBAAiB;AAGtB,eAAW,MAAM,QAAQ;AACvB,UAAI;AAEF,cAAM,GAAG,GAAG;AAAA,MAEd,SAAS,GAAG;AAAA,MAEZ;AAAA,IACF;AAAA,EACF;AACF;;;AC9XA,OAAO,UAAU;AAOV,SAAS,UACd,KACA,OACA;AACA,QAAM,SAA6B;AAAA,IACjC,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,SAAO,KAAK,KAAK,QAAQ;AAAA,IACvB,QAAQ;AAAA,EACV,CAAC;AACH;;;ACnBA,OAAOC,WAAU;AACjB,SAAS,UAAAC,eAAc;AAIvB,SAAS,mBAAmB,SAAyB;AACnD,SAAO,QAAQ,QAAQ,kBAAkB,CAAC,GAAG,WAAW;AACtD,UAAM,QAAQ,QAAQ,IAAI,OAAO,KAAK,CAAC;AACvC,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,MAAM,yBAAyB,OAAO,KAAK,CAAC,kBAAkB;AAAA,IAC1E;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEO,SAAS,gBACd,SACA,UACA,sBACoB;AACpB,MAAI,mBAAmB;AACvB,MAAI,QAAQ,QAAQ,SAAS,MAAM,MAAM,QAAQ,MAAM,mBAAmB,GAAG;AAC3E,QAAI;AACJ,uBAAmB,QAAQ;AAAA,MACzB;AAAA,MACA,CAAC,OAAO,aAAa;AACnB,0BAAkB;AAClB,eAAO,cAAc,QAAQ;AAAA,MAC/B;AAAA,IACF;AACA,YAAQ;AAAA,MACN,4EAA4E,eAAe;AAAA,IAC7F;AAAA,EACF;AACA,QAAM,sBAAsB,mBAAmB,gBAAgB;AAC/D,QAAM,MAAMD,MAAK,KAAK,qBAAqB;AAAA,IACzC,QAAQA,MAAK;AAAA,EACf,CAAC;AAED,QAAM,UAAU,WAAW,oBAAoB,QAAQ,KAAK;AAC5D,QAAM,UACJ,OAAO,IAAI,YAAY,cACnB,OAAO,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,IACnC;AACN,QAAM,YAAY,IAAI,OAAO,IAAI;AACjC,QAAM,MACJ,OAAO,cAAc,cACjB,OAAO,OAAO,CAAC,GAAG,aAAa,CAAC,CAAC,IACjC;AAEN,MAAI,CAAC,sBAAsB;AAEzB,IAAAC;AAAA,MACE,OAAO;AAAA,MACP,sFAAsF,OAAO;AAAA,IAC/F;AAGA,IAAAA;AAAA,MACG,OAAO,CAAC,WAAa,CAAC,OAAO;AAAA,MAC9B,iFAAiF,OAAO;AAAA,IAC1F;AAGA,QAAI,OAAO,SAAS;AAClB,MAAAA;AAAA,QACE,OAAO,QAAQ,YAAY,OAAO,YAAY;AAAA,QAC9C,kDAAkD,OAAO;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,EAAAA,QAAO,IAAI,OAAO,+CAA+C,OAAO,EAAE;AAC1E,EAAAA;AAAA,IACE,MAAM,QAAQ,IAAI,KAAK;AAAA,IACvB,6DAA6D,IAAI,KAAK;AAAA,EACxE;AACA,SAAO;AACT","names":["resolve","yaml","assert"],"ignoreList":[],"sources":["../../src/yaml/player.ts","../../src/yaml/builder.ts","../../src/yaml/utils.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { assert, ifInBrowser } from 'misoai-shared/utils';\n\nimport type { PageAgent } from '@/common/agent';\nimport type {\n FreeFn,\n MidsceneYamlFlowItemAIAction,\n MidsceneYamlFlowItemAIAssert,\n MidsceneYamlFlowItemAIBoolean,\n MidsceneYamlFlowItemAIHover,\n MidsceneYamlFlowItemAIInput,\n MidsceneYamlFlowItemAIKeyboardPress,\n MidsceneYamlFlowItemAILocate,\n MidsceneYamlFlowItemAINString,\n MidsceneYamlFlowItemAINumber,\n MidsceneYamlFlowItemAIQuery,\n MidsceneYamlFlowItemAIRightClick,\n MidsceneYamlFlowItemAIScroll,\n MidsceneYamlFlowItemAITap,\n MidsceneYamlFlowItemAIWaitFor,\n MidsceneYamlFlowItemEvaluateJavaScript,\n MidsceneYamlFlowItemLogScreenshot,\n MidsceneYamlFlowItemSleep,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n} from 'misoai-core';\nimport { getMidsceneRunSubDir } from 'misoai-shared/common';\n\nexport class ScriptPlayer<T extends MidsceneYamlScriptEnv> {\n public currentTaskIndex?: number;\n public taskStatusList: ScriptPlayerTaskStatus[] = [];\n public status: ScriptPlayerStatusValue = 'init';\n public reportFile?: string | null;\n public result: Record<string, any>;\n private unnamedResultIndex = 0;\n public output?: string | null;\n public errorInSetup?: Error;\n private pageAgent: PageAgent | null = null;\n public agentStatusTip?: string;\n constructor(\n private script: MidsceneYamlScript,\n private setupAgent: (platform: T) => Promise<{\n agent: PageAgent;\n freeFn: FreeFn[];\n }>,\n public onTaskStatusChange?: (taskStatus: ScriptPlayerTaskStatus) => void,\n ) {\n this.result = {};\n\n const target = script.target || script.web || script.android;\n\n if (ifInBrowser) {\n this.output = undefined;\n } else if (target?.output) {\n this.output = resolve(process.cwd(), target.output);\n } else {\n this.output = join(getMidsceneRunSubDir('output'), `${process.pid}.json`);\n }\n\n this.taskStatusList = (script.tasks || []).map((task, taskIndex) => ({\n ...task,\n index: taskIndex,\n status: 'init',\n totalSteps: task.flow?.length || 0,\n }));\n }\n\n private setResult(key: string | undefined, value: any) {\n const keyToUse = key || this.unnamedResultIndex++;\n if (this.result[keyToUse]) {\n console.warn(`result key ${keyToUse} already exists, will overwrite`);\n }\n this.result[keyToUse] = value;\n\n this.flushResult();\n }\n\n private setPlayerStatus(status: ScriptPlayerStatusValue, error?: Error) {\n this.status = status;\n this.errorInSetup = error;\n }\n\n private notifyCurrentTaskStatusChange(taskIndex?: number) {\n const taskIndexToNotify =\n typeof taskIndex === 'number' ? taskIndex : this.currentTaskIndex;\n\n if (typeof taskIndexToNotify !== 'number') {\n return;\n }\n\n const taskStatus = this.taskStatusList[taskIndexToNotify];\n if (this.onTaskStatusChange) {\n this.onTaskStatusChange(taskStatus);\n }\n }\n\n private async setTaskStatus(\n index: number,\n statusValue: ScriptPlayerStatusValue,\n error?: Error,\n ) {\n this.taskStatusList[index].status = statusValue;\n if (error) {\n this.taskStatusList[index].error = error;\n }\n\n this.notifyCurrentTaskStatusChange(index);\n }\n\n private setTaskIndex(taskIndex: number) {\n this.currentTaskIndex = taskIndex;\n }\n\n private flushResult() {\n if (Object.keys(this.result).length && this.output) {\n const output = resolve(process.cwd(), this.output);\n const outputDir = dirname(output);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(output, JSON.stringify(this.result, undefined, 2));\n }\n }\n\n async playTask(taskStatus: ScriptPlayerTaskStatus, agent: PageAgent) {\n const { flow } = taskStatus;\n assert(flow, 'missing flow in task');\n\n for (const flowItemIndex in flow) {\n const currentStep = Number.parseInt(flowItemIndex, 10);\n taskStatus.currentStep = currentStep;\n const flowItem = flow[flowItemIndex];\n if (\n 'aiAction' in (flowItem as MidsceneYamlFlowItemAIAction) ||\n 'ai' in (flowItem as MidsceneYamlFlowItemAIAction)\n ) {\n const actionTask = flowItem as MidsceneYamlFlowItemAIAction;\n const prompt = actionTask.aiAction || actionTask.ai;\n assert(prompt, 'missing prompt for ai (aiAction)');\n assert(\n typeof prompt === 'string',\n 'prompt for aiAction must be a string',\n );\n await agent.aiAction(prompt, {\n cacheable: actionTask.cacheable,\n });\n } else if ('aiAssert' in (flowItem as MidsceneYamlFlowItemAIAssert)) {\n const assertTask = flowItem as MidsceneYamlFlowItemAIAssert;\n const prompt = assertTask.aiAssert;\n const msg = assertTask.errorMessage;\n assert(prompt, 'missing prompt for aiAssert');\n assert(\n typeof prompt === 'string',\n 'prompt for aiAssert must be a string',\n );\n await agent.aiAssert(prompt, msg);\n } else if ('aiQuery' in (flowItem as MidsceneYamlFlowItemAIQuery)) {\n const queryTask = flowItem as MidsceneYamlFlowItemAIQuery;\n const prompt = queryTask.aiQuery;\n const options = {\n domIncluded: queryTask.domIncluded,\n screenshotIncluded: queryTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiQuery');\n assert(\n typeof prompt === 'string',\n 'prompt for aiQuery must be a string',\n );\n const queryResult = await agent.aiQuery(prompt);\n this.setResult(queryTask.name, queryResult);\n } else if ('aiNumber' in (flowItem as MidsceneYamlFlowItemAINumber)) {\n const numberTask = flowItem as MidsceneYamlFlowItemAINumber;\n const prompt = numberTask.aiNumber;\n const options = {\n domIncluded: numberTask.domIncluded,\n screenshotIncluded: numberTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for number');\n assert(\n typeof prompt === 'string',\n 'prompt for number must be a string',\n );\n const numberResult = await agent.aiNumber(prompt);\n this.setResult(numberTask.name, numberResult);\n } else if ('aiString' in (flowItem as MidsceneYamlFlowItemAINString)) {\n const stringTask = flowItem as MidsceneYamlFlowItemAINString;\n const prompt = stringTask.aiString;\n const options = {\n domIncluded: stringTask.domIncluded,\n screenshotIncluded: stringTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for string');\n assert(\n typeof prompt === 'string',\n 'prompt for string must be a string',\n );\n const stringResult = await agent.aiString(prompt);\n this.setResult(stringTask.name, stringResult);\n } else if ('aiBoolean' in (flowItem as MidsceneYamlFlowItemAIBoolean)) {\n const booleanTask = flowItem as MidsceneYamlFlowItemAIBoolean;\n const prompt = booleanTask.aiBoolean;\n const options = {\n domIncluded: booleanTask.domIncluded,\n screenshotIncluded: booleanTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for boolean');\n assert(\n typeof prompt === 'string',\n 'prompt for boolean must be a string',\n );\n const booleanResult = await agent.aiBoolean(prompt);\n this.setResult(booleanTask.name, booleanResult);\n } else if ('aiLocate' in (flowItem as MidsceneYamlFlowItemAILocate)) {\n const locateTask = flowItem as MidsceneYamlFlowItemAILocate;\n const prompt = locateTask.aiLocate;\n assert(prompt, 'missing prompt for aiLocate');\n assert(\n typeof prompt === 'string',\n 'prompt for aiLocate must be a string',\n );\n const locateResult = await agent.aiLocate(prompt);\n this.setResult(locateTask.name, locateResult);\n } else if ('aiWaitFor' in (flowItem as MidsceneYamlFlowItemAIWaitFor)) {\n const waitForTask = flowItem as MidsceneYamlFlowItemAIWaitFor;\n const prompt = waitForTask.aiWaitFor;\n assert(prompt, 'missing prompt for aiWaitFor');\n assert(\n typeof prompt === 'string',\n 'prompt for aiWaitFor must be a string',\n );\n const timeout = waitForTask.timeout;\n await agent.aiWaitFor(prompt, { timeoutMs: timeout });\n } else if ('sleep' in (flowItem as MidsceneYamlFlowItemSleep)) {\n const sleepTask = flowItem as MidsceneYamlFlowItemSleep;\n const ms = sleepTask.sleep;\n let msNumber = ms;\n if (typeof ms === 'string') {\n msNumber = Number.parseInt(ms, 10);\n }\n assert(\n msNumber && msNumber > 0,\n `ms for sleep must be greater than 0, but got ${ms}`,\n );\n await new Promise((resolve) => setTimeout(resolve, msNumber));\n } else if ('aiTap' in (flowItem as MidsceneYamlFlowItemAITap)) {\n const tapTask = flowItem as MidsceneYamlFlowItemAITap;\n await agent.aiTap(tapTask.aiTap, tapTask);\n } else if (\n 'aiRightClick' in (flowItem as MidsceneYamlFlowItemAIRightClick)\n ) {\n const rightClickTask = flowItem as MidsceneYamlFlowItemAIRightClick;\n await agent.aiRightClick(rightClickTask.aiRightClick, rightClickTask);\n } else if ('aiHover' in (flowItem as MidsceneYamlFlowItemAIHover)) {\n const hoverTask = flowItem as MidsceneYamlFlowItemAIHover;\n await agent.aiHover(hoverTask.aiHover, hoverTask);\n } else if ('aiInput' in (flowItem as MidsceneYamlFlowItemAIInput)) {\n // may be input empty string ''\n const inputTask = flowItem as MidsceneYamlFlowItemAIInput;\n await agent.aiInput(inputTask.aiInput, inputTask.locate, inputTask);\n } else if (\n 'aiKeyboardPress' in (flowItem as MidsceneYamlFlowItemAIKeyboardPress)\n ) {\n const keyboardPressTask =\n flowItem as MidsceneYamlFlowItemAIKeyboardPress;\n await agent.aiKeyboardPress(\n keyboardPressTask.aiKeyboardPress,\n keyboardPressTask.locate,\n keyboardPressTask,\n );\n } else if ('aiScroll' in (flowItem as MidsceneYamlFlowItemAIScroll)) {\n const scrollTask = flowItem as MidsceneYamlFlowItemAIScroll;\n await agent.aiScroll(scrollTask, scrollTask.locate, scrollTask);\n } else if (\n 'javascript' in (flowItem as MidsceneYamlFlowItemEvaluateJavaScript)\n ) {\n const evaluateJavaScriptTask =\n flowItem as MidsceneYamlFlowItemEvaluateJavaScript;\n\n const result = await agent.evaluateJavaScript(\n evaluateJavaScriptTask.javascript,\n );\n this.setResult(evaluateJavaScriptTask.name, result);\n } else if (\n 'logScreenshot' in (flowItem as MidsceneYamlFlowItemLogScreenshot)\n ) {\n const logScreenshotTask = flowItem as MidsceneYamlFlowItemLogScreenshot;\n await agent.logScreenshot(logScreenshotTask.logScreenshot, {\n content: logScreenshotTask.content || '',\n });\n } else {\n throw new Error(`unknown flowItem: ${JSON.stringify(flowItem)}`);\n }\n }\n this.reportFile = agent.reportFile;\n }\n\n async run() {\n const { target, web, android, tasks } = this.script;\n const webEnv = web || target;\n const androidEnv = android;\n const platform = webEnv || androidEnv;\n\n this.setPlayerStatus('running');\n\n let agent: PageAgent | null = null;\n let freeFn: FreeFn[] = [];\n try {\n const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(\n platform as T,\n );\n agent = newAgent;\n const originalOnTaskStartTip = agent.onTaskStartTip;\n agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') {\n this.agentStatusTip = tip;\n }\n originalOnTaskStartTip?.(tip);\n };\n freeFn = [\n ...(newFreeFn || []),\n {\n name: 'restore-agent-onTaskStartTip',\n fn: () => {\n if (agent) {\n agent.onTaskStartTip = originalOnTaskStartTip;\n }\n },\n },\n ];\n } catch (e) {\n this.setPlayerStatus('error', e as Error);\n return;\n }\n this.pageAgent = agent;\n\n let taskIndex = 0;\n this.setPlayerStatus('running');\n let errorFlag = false;\n while (taskIndex < tasks.length) {\n const taskStatus = this.taskStatusList[taskIndex];\n this.setTaskStatus(taskIndex, 'running' as any);\n this.setTaskIndex(taskIndex);\n\n try {\n await this.playTask(taskStatus, this.pageAgent);\n this.setTaskStatus(taskIndex, 'done' as any);\n } catch (e) {\n this.setTaskStatus(taskIndex, 'error' as any, e as Error);\n\n if (taskStatus.continueOnError) {\n // nothing more to do\n } else {\n this.reportFile = agent.reportFile;\n errorFlag = true;\n break;\n }\n }\n this.reportFile = agent.reportFile;\n taskIndex++;\n }\n\n if (errorFlag) {\n this.setPlayerStatus('error');\n } else {\n this.setPlayerStatus('done');\n }\n this.agentStatusTip = '';\n\n // free the resources\n for (const fn of freeFn) {\n try {\n // console.log('freeing', fn.name);\n await fn.fn();\n // console.log('freed', fn.name);\n } catch (e) {\n // console.error('error freeing', fn.name, e);\n }\n }\n }\n}\n","import yaml from 'js-yaml';\nimport type {\n MidsceneYamlScript,\n MidsceneYamlScriptWebEnv,\n MidsceneYamlTask,\n} from 'misoai-core';\n\nexport function buildYaml(\n env: MidsceneYamlScriptWebEnv,\n tasks: MidsceneYamlTask[],\n) {\n const result: MidsceneYamlScript = {\n target: env,\n tasks,\n };\n\n return yaml.dump(result, {\n indent: 2,\n });\n}\n","import yaml from 'js-yaml';\nimport { assert } from 'misoai-shared/utils';\n\nimport type { MidsceneYamlScript } from 'misoai-core';\n\nfunction interpolateEnvVars(content: string): string {\n return content.replace(/\\$\\{([^}]+)\\}/g, (_, envVar) => {\n const value = process.env[envVar.trim()];\n if (value === undefined) {\n throw new Error(`Environment variable \"${envVar.trim()}\" is not defined`);\n }\n return value;\n });\n}\n\nexport function parseYamlScript(\n content: string,\n filePath?: string,\n ignoreCheckingTarget?: boolean,\n): MidsceneYamlScript {\n let processedContent = content;\n if (content.indexOf('android') !== -1 && content.match(/deviceId:\\s*(\\d+)/)) {\n let matchedDeviceId;\n processedContent = content.replace(\n /deviceId:\\s*(\\d+)/g,\n (match, deviceId) => {\n matchedDeviceId = deviceId;\n return `deviceId: '${deviceId}'`;\n },\n );\n console.warn(\n `please use string-style deviceId in yaml script, for example: deviceId: \"${matchedDeviceId}\"`,\n );\n }\n const interpolatedContent = interpolateEnvVars(processedContent);\n const obj = yaml.load(interpolatedContent, {\n schema: yaml.JSON_SCHEMA,\n }) as MidsceneYamlScript;\n\n const pathTip = filePath ? `, failed to load ${filePath}` : '';\n const android =\n typeof obj.android !== 'undefined'\n ? Object.assign({}, obj.android || {})\n : undefined;\n const webConfig = obj.web || obj.target; // no need to handle null case, because web has required parameters url\n const web =\n typeof webConfig !== 'undefined'\n ? Object.assign({}, webConfig || {})\n : undefined;\n\n if (!ignoreCheckingTarget) {\n // make sure at least one of target/web/android is provided\n assert(\n web || android,\n `at least one of \"target\", \"web\", or \"android\" properties is required in yaml script${pathTip}`,\n );\n\n // make sure only one of target/web/android is provided\n assert(\n (web && !android) || (!web && android),\n `only one of \"target\", \"web\", or \"android\" properties is allowed in yaml script${pathTip}`,\n );\n\n // make sure the config is valid\n if (web || android) {\n assert(\n typeof web === 'object' || typeof android === 'object',\n `property \"target/web/android\" must be an object${pathTip}`,\n );\n }\n }\n\n assert(obj.tasks, `property \"tasks\" is required in yaml script ${pathTip}`);\n assert(\n Array.isArray(obj.tasks),\n `property \"tasks\" must be an array in yaml script, but got ${obj.tasks}`,\n );\n return obj;\n}\n"]}
|
package/dist/lib/agent.js
CHANGED
@@ -340,8 +340,8 @@ var ScriptPlayer = class {
|
|
340
340
|
var import_js_yaml = __toESM(require("js-yaml"));
|
341
341
|
|
342
342
|
// src/yaml/utils.ts
|
343
|
-
var import_utils2 = require("misoai-shared/utils");
|
344
343
|
var import_js_yaml2 = __toESM(require("js-yaml"));
|
344
|
+
var import_utils2 = require("misoai-shared/utils");
|
345
345
|
function interpolateEnvVars(content) {
|
346
346
|
return content.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
|
347
347
|
const value = process.env[envVar.trim()];
|
@@ -487,13 +487,13 @@ function paramStr(task) {
|
|
487
487
|
}
|
488
488
|
|
489
489
|
// src/common/utils.ts
|
490
|
+
var import_dayjs = __toESM(require("dayjs"));
|
490
491
|
var import_ai_model = require("misoai-core/ai-model");
|
491
492
|
var import_utils3 = require("misoai-core/utils");
|
492
493
|
var import_env = require("misoai-shared/env");
|
493
494
|
var import_extractor = require("misoai-shared/extractor");
|
494
495
|
var import_img = require("misoai-shared/img");
|
495
496
|
var import_utils4 = require("misoai-shared/utils");
|
496
|
-
var import_dayjs = __toESM(require("dayjs"));
|
497
497
|
|
498
498
|
// src/web-element.ts
|
499
499
|
var WebElementInfo = class {
|
@@ -634,8 +634,12 @@ var WorkflowMemory = class {
|
|
634
634
|
const workflow = this.workflows.get(workflowId) || this.createEmptyWorkflowData(workflowId);
|
635
635
|
workflow.memory = [...memory];
|
636
636
|
workflow.metadata.totalSteps = workflow.steps.length;
|
637
|
-
workflow.metadata.completedSteps = workflow.steps.filter(
|
638
|
-
|
637
|
+
workflow.metadata.completedSteps = workflow.steps.filter(
|
638
|
+
(s) => s.status === "completed"
|
639
|
+
).length;
|
640
|
+
workflow.metadata.failedSteps = workflow.steps.filter(
|
641
|
+
(s) => s.status === "failed"
|
642
|
+
).length;
|
639
643
|
this.workflows.set(workflowId, workflow);
|
640
644
|
this.enforceRetentionPolicy();
|
641
645
|
}
|
@@ -646,7 +650,9 @@ var WorkflowMemory = class {
|
|
646
650
|
const workflow = this.workflows.get(workflowId) || this.createEmptyWorkflowData(workflowId);
|
647
651
|
workflow.context = { ...workflow.context, ...context };
|
648
652
|
if (context.currentStep) {
|
649
|
-
const existingStep = workflow.steps.find(
|
653
|
+
const existingStep = workflow.steps.find(
|
654
|
+
(s) => s.stepName === context.currentStep
|
655
|
+
);
|
650
656
|
if (!existingStep) {
|
651
657
|
workflow.steps.push({
|
652
658
|
stepId: `step_${workflow.steps.length + 1}`,
|
@@ -691,7 +697,9 @@ var WorkflowMemory = class {
|
|
691
697
|
enforceRetentionPolicy() {
|
692
698
|
const maxWorkflows = 10;
|
693
699
|
if (this.workflows.size > maxWorkflows) {
|
694
|
-
const sortedWorkflows = Array.from(this.workflows.entries()).sort(
|
700
|
+
const sortedWorkflows = Array.from(this.workflows.entries()).sort(
|
701
|
+
([, a], [, b]) => (b.metadata.endTime || b.metadata.startTime) - (a.metadata.endTime || a.metadata.startTime)
|
702
|
+
);
|
695
703
|
const toDelete = sortedWorkflows.slice(maxWorkflows);
|
696
704
|
toDelete.forEach(([workflowId]) => this.workflows.delete(workflowId));
|
697
705
|
}
|
@@ -1430,7 +1438,9 @@ var PageTaskExecutor = class {
|
|
1430
1438
|
*/
|
1431
1439
|
getPersistentExecutor() {
|
1432
1440
|
if (!this.persistentExecutor || this.persistentExecutor.status === "error") {
|
1433
|
-
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1441
|
+
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1442
|
+
this.sessionContext.workflowId
|
1443
|
+
);
|
1434
1444
|
this.persistentExecutor = new import_misoai_core.Executor("Persistent Task Executor", {
|
1435
1445
|
onTaskStart: this.onTaskStartCallback,
|
1436
1446
|
initialMemory: previousMemory
|
@@ -1459,7 +1469,9 @@ var PageTaskExecutor = class {
|
|
1459
1469
|
if (this.persistentExecutor) {
|
1460
1470
|
this.persistentExecutor.clearMemory();
|
1461
1471
|
}
|
1462
|
-
this.workflowMemory.clearWorkflow(
|
1472
|
+
this.workflowMemory.clearWorkflow(
|
1473
|
+
this.sessionContext.workflowId || "default"
|
1474
|
+
);
|
1463
1475
|
}
|
1464
1476
|
/**
|
1465
1477
|
* Mevcut hafızayı döndürür
|
@@ -1471,7 +1483,9 @@ var PageTaskExecutor = class {
|
|
1471
1483
|
* İş akışı hafızasını döndürür
|
1472
1484
|
*/
|
1473
1485
|
getWorkflowMemory() {
|
1474
|
-
return this.workflowMemory.getWorkflowData(
|
1486
|
+
return this.workflowMemory.getWorkflowData(
|
1487
|
+
this.sessionContext.workflowId || "default"
|
1488
|
+
);
|
1475
1489
|
}
|
1476
1490
|
/**
|
1477
1491
|
* Hafıza istatistiklerini döndürür
|
@@ -1479,7 +1493,13 @@ var PageTaskExecutor = class {
|
|
1479
1493
|
getMemoryStats() {
|
1480
1494
|
return this.persistentExecutor?.getMemoryStats() || {
|
1481
1495
|
totalItems: 0,
|
1482
|
-
analytics: {
|
1496
|
+
analytics: {
|
1497
|
+
totalTasks: 0,
|
1498
|
+
memoryHits: 0,
|
1499
|
+
memoryMisses: 0,
|
1500
|
+
averageMemorySize: 0,
|
1501
|
+
memoryEffectiveness: 0
|
1502
|
+
},
|
1483
1503
|
config: this.memoryConfig
|
1484
1504
|
};
|
1485
1505
|
}
|
@@ -1515,11 +1535,14 @@ var PageTaskExecutor = class {
|
|
1515
1535
|
let taskExecutor;
|
1516
1536
|
if (useMemory) {
|
1517
1537
|
taskExecutor = this.getPersistentExecutor();
|
1518
|
-
this.workflowMemory.updateWorkflowContext(
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1538
|
+
this.workflowMemory.updateWorkflowContext(
|
1539
|
+
{
|
1540
|
+
currentStep: title,
|
1541
|
+
pageInfo: this.sessionContext.pageInfo,
|
1542
|
+
timestamp: Date.now()
|
1543
|
+
},
|
1544
|
+
this.sessionContext.workflowId || "default"
|
1545
|
+
);
|
1523
1546
|
} else {
|
1524
1547
|
taskExecutor = new import_misoai_core.Executor(title, {
|
1525
1548
|
onTaskStart: this.onTaskStartCallback
|
@@ -1885,14 +1908,19 @@ var PageTaskExecutor = class {
|
|
1885
1908
|
*/
|
1886
1909
|
addToMemory(memoryItem) {
|
1887
1910
|
if (!this.persistentExecutor || this.persistentExecutor.status === "error") {
|
1888
|
-
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1911
|
+
const previousMemory = this.workflowMemory.getWorkflowMemory(
|
1912
|
+
this.sessionContext.workflowId
|
1913
|
+
);
|
1889
1914
|
this.persistentExecutor = new import_misoai_core.Executor("Persistent Task Executor", {
|
1890
1915
|
onTaskStart: this.onTaskStartCallback,
|
1891
1916
|
initialMemory: previousMemory
|
1892
1917
|
});
|
1893
1918
|
}
|
1894
1919
|
this.persistentExecutor.memoryStore?.add(memoryItem);
|
1895
|
-
this.persistentExecutor.memoryAnalytics?.recordMemoryOperation(
|
1920
|
+
this.persistentExecutor.memoryAnalytics?.recordMemoryOperation(
|
1921
|
+
"add",
|
1922
|
+
memoryItem
|
1923
|
+
);
|
1896
1924
|
}
|
1897
1925
|
};
|
1898
1926
|
|
@@ -1981,14 +2009,14 @@ function buildPlans(type, locateParam, param) {
|
|
1981
2009
|
var import_node_assert = __toESM(require("assert"));
|
1982
2010
|
var import_node_fs2 = require("fs");
|
1983
2011
|
var import_node_path2 = require("path");
|
2012
|
+
var import_js_yaml3 = __toESM(require("js-yaml"));
|
1984
2013
|
var import_common2 = require("misoai-shared/common");
|
1985
2014
|
var import_logger3 = require("misoai-shared/logger");
|
1986
2015
|
var import_utils9 = require("misoai-shared/utils");
|
1987
|
-
var import_js_yaml3 = __toESM(require("js-yaml"));
|
1988
2016
|
var import_semver = __toESM(require("semver"));
|
1989
2017
|
|
1990
2018
|
// package.json
|
1991
|
-
var version = "1.6.
|
2019
|
+
var version = "1.6.1";
|
1992
2020
|
|
1993
2021
|
// src/common/task-cache.ts
|
1994
2022
|
var debug3 = (0, import_logger3.getDebug)("cache");
|
@@ -2283,22 +2311,28 @@ var PageAgent = class {
|
|
2283
2311
|
const allThoughts = executor.tasks.filter((task) => task.thought).map((task) => task.thought);
|
2284
2312
|
const allLocates = executor.tasks.filter((task) => task.locate).map((task) => task.locate);
|
2285
2313
|
const allPlans = executor.tasks.filter((task) => task.param?.plans).map((task) => task.param?.plans);
|
2286
|
-
const planningTasks = executor.tasks.filter(
|
2287
|
-
|
2314
|
+
const planningTasks = executor.tasks.filter(
|
2315
|
+
(task) => task.type === "Planning"
|
2316
|
+
);
|
2317
|
+
const insightTasks = executor.tasks.filter(
|
2318
|
+
(task) => task.type === "Insight"
|
2319
|
+
);
|
2288
2320
|
const actionTasks = executor.tasks.filter((task) => task.type === "Action");
|
2289
2321
|
const planning = planningTasks.length > 0 ? {
|
2290
2322
|
type: "Planning",
|
2291
|
-
description:
|
2323
|
+
description: "Planning for task execution",
|
2292
2324
|
steps: planningTasks.map((task) => task.thought || "Planning step")
|
2293
2325
|
} : void 0;
|
2294
2326
|
const insight = insightTasks.length > 0 ? {
|
2295
2327
|
type: "Insight",
|
2296
|
-
description:
|
2297
|
-
elements: insightTasks.map(
|
2328
|
+
description: "Insight for task execution",
|
2329
|
+
elements: insightTasks.map(
|
2330
|
+
(task) => task.thought || "Insight element"
|
2331
|
+
)
|
2298
2332
|
} : void 0;
|
2299
2333
|
const action = actionTasks.length > 0 ? {
|
2300
2334
|
type: "Action",
|
2301
|
-
description:
|
2335
|
+
description: "Action for task execution",
|
2302
2336
|
result: lastTask?.output
|
2303
2337
|
} : void 0;
|
2304
2338
|
const actionDetails = executor.tasks.map((task) => ({
|
@@ -2632,7 +2666,10 @@ ${memoryContext}` : void 0;
|
|
2632
2666
|
}
|
2633
2667
|
const memoryContext = this.getMemoryAsContext();
|
2634
2668
|
const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
|
2635
|
-
const { output, executor } = await this.taskExecutor.assert(
|
2669
|
+
const { output, executor } = await this.taskExecutor.assert(
|
2670
|
+
assertionWithContext,
|
2671
|
+
memoryContext
|
2672
|
+
);
|
2636
2673
|
const metadata = this.afterTaskRunning(executor, true);
|
2637
2674
|
if (output && opt?.keepRawResponse) {
|
2638
2675
|
return {
|
@@ -2671,7 +2708,10 @@ A complex CAPTCHA typically has one or more of these characteristics:
|
|
2671
2708
|
Return only "complex" or "simple" based on your analysis.
|
2672
2709
|
`;
|
2673
2710
|
const complexityMsgs = [
|
2674
|
-
{
|
2711
|
+
{
|
2712
|
+
role: "system",
|
2713
|
+
content: "You are an AI assistant that analyzes screenshots to determine CAPTCHA complexity."
|
2714
|
+
},
|
2675
2715
|
{
|
2676
2716
|
role: "user",
|
2677
2717
|
content: [
|
@@ -2695,7 +2735,12 @@ Return only "complex" or "simple" based on your analysis.
|
|
2695
2735
|
);
|
2696
2736
|
const responseText = typeof complexityResult.content === "string" ? complexityResult.content.toLowerCase() : JSON.stringify(complexityResult.content).toLowerCase();
|
2697
2737
|
shouldUseDeepThink = responseText.includes("complex");
|
2698
|
-
debug4(
|
2738
|
+
debug4(
|
2739
|
+
"CAPTCHA complexity analysis:",
|
2740
|
+
responseText,
|
2741
|
+
"Using deep think:",
|
2742
|
+
shouldUseDeepThink
|
2743
|
+
);
|
2699
2744
|
} catch (error) {
|
2700
2745
|
debug4("Failed to analyze CAPTCHA complexity:", error);
|
2701
2746
|
}
|
@@ -2712,7 +2757,9 @@ Return only "complex" or "simple" based on your analysis.
|
|
2712
2757
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
2713
2758
|
} else if (action.type === "input" && action.value) {
|
2714
2759
|
if (action.target) {
|
2715
|
-
await this.aiInput(action.value, action.target, {
|
2760
|
+
await this.aiInput(action.value, action.target, {
|
2761
|
+
deepThink: shouldUseDeepThink
|
2762
|
+
});
|
2716
2763
|
}
|
2717
2764
|
} else if (action.type === "verify" && action.target) {
|
2718
2765
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
@@ -2724,7 +2771,9 @@ Return only "complex" or "simple" based on your analysis.
|
|
2724
2771
|
if (action.coordinates) {
|
2725
2772
|
const x = action.coordinates[0];
|
2726
2773
|
const y = action.coordinates[1];
|
2727
|
-
await this.aiTap(`element at coordinates (${x}, ${y})`, {
|
2774
|
+
await this.aiTap(`element at coordinates (${x}, ${y})`, {
|
2775
|
+
deepThink: shouldUseDeepThink
|
2776
|
+
});
|
2728
2777
|
} else if (action.target) {
|
2729
2778
|
await this.aiTap(action.target, { deepThink: shouldUseDeepThink });
|
2730
2779
|
}
|
@@ -2876,25 +2925,27 @@ ${errors}`);
|
|
2876
2925
|
const executionDump = {
|
2877
2926
|
name: screenshotTitle,
|
2878
2927
|
description: content,
|
2879
|
-
tasks: [
|
2880
|
-
|
2881
|
-
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2928
|
+
tasks: [
|
2929
|
+
{
|
2930
|
+
type: "Screenshot",
|
2931
|
+
subType: "log",
|
2932
|
+
status: "finished",
|
2933
|
+
executor: null,
|
2934
|
+
param: {
|
2935
|
+
title: screenshotTitle,
|
2936
|
+
content
|
2937
|
+
},
|
2938
|
+
output: {
|
2939
|
+
screenshot
|
2940
|
+
},
|
2941
|
+
thought: `Logged screenshot: ${screenshotTitle}`,
|
2942
|
+
timing: {
|
2943
|
+
start: Date.now(),
|
2944
|
+
end: Date.now(),
|
2945
|
+
cost: 0
|
2946
|
+
}
|
2896
2947
|
}
|
2897
|
-
|
2948
|
+
],
|
2898
2949
|
sdkVersion: "1.0.0",
|
2899
2950
|
logTime: Date.now(),
|
2900
2951
|
model_name: "screenshot"
|
@@ -2946,7 +2997,9 @@ ${errors}`);
|
|
2946
2997
|
totalTasks: stats.analytics.totalTasks,
|
2947
2998
|
memoryHits: stats.analytics.memoryHits,
|
2948
2999
|
memoryMisses: stats.analytics.memoryMisses,
|
2949
|
-
memoryEffectiveness: Math.round(
|
3000
|
+
memoryEffectiveness: Math.round(
|
3001
|
+
stats.analytics.memoryEffectiveness * 100
|
3002
|
+
),
|
2950
3003
|
averageMemorySize: Math.round(stats.analytics.averageMemorySize * 100) / 100
|
2951
3004
|
},
|
2952
3005
|
config: stats.config,
|
@@ -3010,7 +3063,9 @@ ${errors}`);
|
|
3010
3063
|
calculateSuccessRate(memory) {
|
3011
3064
|
if (memory.length === 0)
|
3012
3065
|
return 0;
|
3013
|
-
const successCount = memory.filter(
|
3066
|
+
const successCount = memory.filter(
|
3067
|
+
(item) => item.metadata?.success !== false
|
3068
|
+
).length;
|
3014
3069
|
return Math.round(successCount / memory.length * 100);
|
3015
3070
|
}
|
3016
3071
|
calculateAverageExecutionTime(memory) {
|