@midscene/web 0.16.9 → 0.16.10

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.
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":["resolve","assert","yaml","stringifyDumpData","writeLogFile","vlLocateMode","getDebug","resizeImgBase64","existsSync","join","getMidsceneRunSubDir","ifInBrowser","debug","plan","log","sleep","locatePlan","logMsg"],"ignoreList":[],"sources":["../../src/common/agent.ts","../../src/yaml/player.ts","../../src/yaml/builder.ts","../../src/yaml/utils.ts","../../src/common/tasks.ts","../../src/common/task-cache.ts","../../src/common/utils.ts","../../src/web-element.ts","../../src/common/ui-utils.ts","../../src/common/plan-builder.ts","../../src/bridge-mode/agent-cli-side.ts","../../src/bridge-mode/common.ts","../../src/bridge-mode/io-server.ts","../../src/bridge-mode/index.ts"],"sourcesContent":["import type { WebPage } from '@/common/page';\nimport {\n type AgentAssertOpt,\n type AgentWaitForOpt,\n type ExecutionDump,\n type ExecutionTask,\n type Executor,\n type GroupedActionDump,\n Insight,\n type InsightAction,\n type LocateOption,\n type LocateResultElement,\n type OnTaskStartTip,\n type PlanningActionParamScroll,\n} from '@midscene/core';\n\nimport { ScriptPlayer, parseYamlScript } from '@/yaml/index';\nimport {\n groupedActionDumpFileExt,\n reportHTMLContent,\n stringifyDumpData,\n writeLogFile,\n} from '@midscene/core/utils';\nimport {\n DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT,\n DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,\n} from '@midscene/shared/constants';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { PageTaskExecutor } from '../common/tasks';\nimport type { PuppeteerWebPage } from '../puppeteer';\nimport type { WebElementInfo } from '../web-element';\nimport { buildPlans } from './plan-builder';\nimport type { AiTaskCache } from './task-cache';\nimport {\n locateParamStr,\n paramStr,\n scrollParamStr,\n taskTitleStr,\n typeStr,\n} from './ui-utils';\nimport { printReportMsg, reportFileName } from './utils';\nimport { type WebUIContext, parseContextFromWebPage } from './utils';\n\nconst debug = getDebug('web-integration');\n\nexport interface PageAgentOpt {\n forceSameTabNavigation?: boolean /* if limit the new tab to the current page, default true */;\n testId?: string;\n cacheId?: string;\n groupName?: string;\n groupDescription?: string;\n cache?: AiTaskCache;\n /* if auto generate report, default true */\n generateReport?: boolean;\n /* if auto print report msg, default true */\n autoPrintReportMsg?: boolean;\n onTaskStartTip?: OnTaskStartTip;\n aiActionContext?: string;\n waitForNavigationTimeout?: number;\n waitForNetworkIdleTimeout?: number;\n}\n\nexport class PageAgent<PageType extends WebPage = WebPage> {\n page: PageType;\n\n insight: Insight<WebElementInfo, WebUIContext>;\n\n dump: GroupedActionDump;\n\n reportFile?: string | null;\n\n reportFileName?: string;\n\n taskExecutor: PageTaskExecutor;\n\n opts: PageAgentOpt;\n\n /**\n * If true, the agent will not perform any actions\n */\n dryMode = false;\n\n onTaskStartTip?: OnTaskStartTip;\n\n constructor(page: PageType, opts?: PageAgentOpt) {\n this.page = page;\n this.opts = Object.assign(\n {\n generateReport: true,\n autoPrintReportMsg: true,\n groupName: 'Midscene Report',\n groupDescription: '',\n },\n opts || {},\n );\n\n if (\n this.page.pageType === 'puppeteer' ||\n this.page.pageType === 'playwright'\n ) {\n (this.page as PuppeteerWebPage).waitForNavigationTimeout =\n this.opts.waitForNavigationTimeout ||\n DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;\n (this.page as PuppeteerWebPage).waitForNetworkIdleTimeout =\n this.opts.waitForNetworkIdleTimeout ||\n DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;\n }\n\n this.onTaskStartTip = this.opts.onTaskStartTip;\n // get the parent browser of the puppeteer page\n // const browser = (this.page as PuppeteerWebPage).browser();\n\n this.insight = new Insight<WebElementInfo, WebUIContext>(\n async (action: InsightAction) => {\n return this.getUIContext(action);\n },\n );\n\n this.taskExecutor = new PageTaskExecutor(this.page, this.insight, {\n cacheId: opts?.cacheId,\n onTaskStart: this.callbackOnTaskStartTip.bind(this),\n });\n this.dump = this.resetDump();\n this.reportFileName = reportFileName(\n opts?.testId || this.page.pageType || 'web',\n );\n }\n\n async getUIContext(action?: InsightAction): Promise<WebUIContext> {\n if (action && (action === 'extract' || action === 'assert')) {\n return await parseContextFromWebPage(this.page, {\n ignoreMarker: true,\n });\n }\n return await parseContextFromWebPage(this.page, {\n ignoreMarker: !!vlLocateMode(),\n });\n }\n\n async setAIActionContext(prompt: string) {\n this.opts.aiActionContext = prompt;\n }\n\n resetDump() {\n this.dump = {\n groupName: this.opts.groupName!,\n groupDescription: this.opts.groupDescription,\n executions: [],\n };\n\n return this.dump;\n }\n\n appendExecutionDump(execution: ExecutionDump) {\n const currentDump = this.dump;\n currentDump.executions.push(execution);\n }\n\n dumpDataString() {\n // update dump info\n this.dump.groupName = this.opts.groupName!;\n this.dump.groupDescription = this.opts.groupDescription;\n return stringifyDumpData(this.dump);\n }\n\n reportHTMLString() {\n return reportHTMLContent(this.dumpDataString());\n }\n\n writeOutActionDumps() {\n const { generateReport, autoPrintReportMsg } = this.opts;\n this.reportFile = writeLogFile({\n fileName: this.reportFileName!,\n fileExt: groupedActionDumpFileExt,\n fileContent: this.dumpDataString(),\n type: 'dump',\n generateReport,\n });\n debug('writeOutActionDumps', this.reportFile);\n if (generateReport && autoPrintReportMsg && this.reportFile) {\n printReportMsg(this.reportFile);\n }\n }\n\n private async callbackOnTaskStartTip(task: ExecutionTask) {\n const param = paramStr(task);\n const tip = param ? `${typeStr(task)} - ${param}` : typeStr(task);\n if (this.onTaskStartTip) {\n await this.onTaskStartTip(tip);\n }\n }\n\n private afterTaskRunning(executor: Executor, doNotThrowError = false) {\n this.appendExecutionDump(executor.dump());\n this.writeOutActionDumps();\n\n if (executor.isInErrorState() && !doNotThrowError) {\n const errorTask = executor.latestErrorTask();\n throw new Error(`${errorTask?.error}\\n${errorTask?.errorStack}`);\n }\n }\n\n private buildDetailedLocateParam(locatePrompt: string, opt?: LocateOption) {\n assert(locatePrompt, 'missing locate prompt');\n if (typeof opt === 'object') {\n return {\n prompt: locatePrompt,\n ...opt,\n };\n }\n return {\n prompt: locatePrompt,\n };\n }\n\n async aiTap(locatePrompt: string, opt?: LocateOption) {\n const detailedLocateParam = this.buildDetailedLocateParam(\n locatePrompt,\n opt,\n );\n const plans = buildPlans('Tap', detailedLocateParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Tap', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiHover(locatePrompt: string, opt?: LocateOption) {\n const detailedLocateParam = this.buildDetailedLocateParam(\n locatePrompt,\n opt,\n );\n const plans = buildPlans('Hover', detailedLocateParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Hover', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiInput(value: string, locatePrompt: string, opt?: LocateOption) {\n assert(\n typeof value === 'string',\n 'input value must be a string, use empty string if you want to clear the input',\n );\n assert(locatePrompt, 'missing locate prompt for input');\n const detailedLocateParam = this.buildDetailedLocateParam(\n locatePrompt,\n opt,\n );\n const plans = buildPlans('Input', detailedLocateParam, {\n value,\n });\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Input', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiKeyboardPress(\n keyName: string,\n locatePrompt?: string,\n opt?: LocateOption,\n ) {\n assert(keyName, 'missing keyName for keyboard press');\n const detailedLocateParam = locatePrompt\n ? this.buildDetailedLocateParam(locatePrompt, opt)\n : undefined;\n const plans = buildPlans('KeyboardPress', detailedLocateParam, {\n value: keyName,\n });\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('KeyboardPress', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiScroll(\n scrollParam: PlanningActionParamScroll,\n locatePrompt?: string,\n opt?: LocateOption,\n ) {\n const detailedLocateParam = locatePrompt\n ? this.buildDetailedLocateParam(locatePrompt, opt)\n : undefined;\n const plans = buildPlans('Scroll', detailedLocateParam, scrollParam);\n const paramInTitle = locatePrompt\n ? `${locateParamStr(detailedLocateParam)} - ${scrollParamStr(scrollParam)}`\n : scrollParamStr(scrollParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Scroll', paramInTitle),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiAction(taskPrompt: string) {\n const { output, executor } = await (vlLocateMode() === 'vlm-ui-tars'\n ? this.taskExecutor.actionToGoal(taskPrompt)\n : this.taskExecutor.action(taskPrompt, this.opts.aiActionContext));\n\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiQuery(demand: any) {\n const { output, executor } = await this.taskExecutor.query(demand);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiBoolean(prompt: string) {\n const { output, executor } = await this.taskExecutor.boolean(prompt);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiNumber(prompt: string) {\n const { output, executor } = await this.taskExecutor.number(prompt);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiString(prompt: string) {\n const { output, executor } = await this.taskExecutor.string(prompt);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiLocate(prompt: string, opt?: LocateOption) {\n const detailedLocateParam = this.buildDetailedLocateParam(prompt, opt);\n const plans = buildPlans('Locate', detailedLocateParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Locate', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n\n const { element } = output;\n\n return {\n rect: element?.rect,\n center: element?.center,\n } as Pick<LocateResultElement, 'rect' | 'center'>;\n }\n\n async aiAssert(assertion: string, msg?: string, opt?: AgentAssertOpt) {\n const { output, executor } = await this.taskExecutor.assert(assertion);\n this.afterTaskRunning(executor, true);\n\n if (output && opt?.keepRawResponse) {\n return output;\n }\n\n if (!output?.pass) {\n const errMsg = msg || `Assertion failed: ${assertion}`;\n const reasonMsg = `Reason: ${\n output?.thought || executor.latestErrorTask()?.error || '(no_reason)'\n }`;\n throw new Error(`${errMsg}\\n${reasonMsg}`);\n }\n }\n\n async aiWaitFor(assertion: string, opt?: AgentWaitForOpt) {\n const { executor } = await this.taskExecutor.waitFor(assertion, {\n timeoutMs: opt?.timeoutMs || 15 * 1000,\n checkIntervalMs: opt?.checkIntervalMs || 3 * 1000,\n assertion,\n });\n this.appendExecutionDump(executor.dump());\n this.writeOutActionDumps();\n\n if (executor.isInErrorState()) {\n const errorTask = executor.latestErrorTask();\n throw new Error(`${errorTask?.error}\\n${errorTask?.errorStack}`);\n }\n }\n\n async ai(taskPrompt: string, type = 'action') {\n if (type === 'action') {\n return this.aiAction(taskPrompt);\n }\n if (type === 'query') {\n return this.aiQuery(taskPrompt);\n }\n\n if (type === 'assert') {\n return this.aiAssert(taskPrompt);\n }\n\n if (type === 'tap') {\n return this.aiTap(taskPrompt);\n }\n\n throw new Error(\n `Unknown type: ${type}, only support 'action', 'query', 'assert', 'tap'`,\n );\n }\n\n async runYaml(yamlScriptContent: string): Promise<{\n result: Record<string, any>;\n }> {\n const script = parseYamlScript(yamlScriptContent, 'yaml', true);\n const player = new ScriptPlayer(script, async (target) => {\n return { agent: this, freeFn: [] };\n });\n await player.run();\n\n if (player.status === 'error') {\n const errors = player.taskStatusList\n .filter((task) => task.status === 'error')\n .map((task) => {\n return `task - ${task.name}: ${task.error?.message}`;\n })\n .join('\\n');\n throw new Error(`Error(s) occurred in running yaml script:\\n${errors}`);\n }\n\n return {\n result: player.result,\n };\n }\n\n async evaluateJavaScript(script: string) {\n assert(\n this.page.evaluateJavaScript,\n 'evaluateJavaScript is not supported in current agent',\n );\n return this.page.evaluateJavaScript(script);\n }\n\n async destroy() {\n await this.page.destroy();\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { assert, ifInBrowser } from '@midscene/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 MidsceneYamlFlowItemAIScroll,\n MidsceneYamlFlowItemAITap,\n MidsceneYamlFlowItemAIWaitFor,\n MidsceneYamlFlowItemEvaluateJavaScript,\n MidsceneYamlFlowItemSleep,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n} from '@midscene/core';\nimport { getMidsceneRunSubDir } from '@midscene/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 if (ifInBrowser) {\n this.output = undefined;\n } else if (script.target?.output) {\n this.output = resolve(process.cwd(), script.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 (flowItem as MidsceneYamlFlowItemAIAction).aiAction ||\n (flowItem as MidsceneYamlFlowItemAIAction).ai\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 } else if ((flowItem as MidsceneYamlFlowItemAIAssert).aiAssert) {\n const assertTask = flowItem as MidsceneYamlFlowItemAIAssert;\n const prompt = assertTask.aiAssert;\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);\n } else if ((flowItem as MidsceneYamlFlowItemAIQuery).aiQuery) {\n const queryTask = flowItem as MidsceneYamlFlowItemAIQuery;\n const prompt = queryTask.aiQuery;\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 ((flowItem as MidsceneYamlFlowItemAINumber).aiNumber) {\n const numberTask = flowItem as MidsceneYamlFlowItemAINumber;\n const prompt = numberTask.aiNumber;\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 ((flowItem as MidsceneYamlFlowItemAINString).aiString) {\n const stringTask = flowItem as MidsceneYamlFlowItemAINString;\n const prompt = stringTask.aiString;\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 ((flowItem as MidsceneYamlFlowItemAIBoolean).aiBoolean) {\n const booleanTask = flowItem as MidsceneYamlFlowItemAIBoolean;\n const prompt = booleanTask.aiBoolean;\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 ((flowItem as MidsceneYamlFlowItemAILocate).aiLocate) {\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 ((flowItem as MidsceneYamlFlowItemAIWaitFor).aiWaitFor) {\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 ((flowItem as MidsceneYamlFlowItemSleep).sleep) {\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 ((flowItem as MidsceneYamlFlowItemAITap).aiTap) {\n const tapTask = flowItem as MidsceneYamlFlowItemAITap;\n await agent.aiTap(tapTask.aiTap, tapTask);\n } else if ((flowItem as MidsceneYamlFlowItemAIHover).aiHover) {\n const hoverTask = flowItem as MidsceneYamlFlowItemAIHover;\n await agent.aiHover(hoverTask.aiHover, hoverTask);\n } else if ((flowItem as MidsceneYamlFlowItemAIInput).aiInput) {\n const inputTask = flowItem as MidsceneYamlFlowItemAIInput;\n await agent.aiInput(inputTask.aiInput, inputTask.locate, inputTask);\n } else if (\n (flowItem as MidsceneYamlFlowItemAIKeyboardPress).aiKeyboardPress\n ) {\n const keyboardPressTask =\n flowItem as MidsceneYamlFlowItemAIKeyboardPress;\n await agent.aiKeyboardPress(\n keyboardPressTask.aiKeyboardPress,\n keyboardPressTask.locate,\n keyboardPressTask,\n );\n } else if (\n typeof (flowItem as MidsceneYamlFlowItemAIScroll).aiScroll !==\n 'undefined'\n ) {\n const scrollTask = flowItem as MidsceneYamlFlowItemAIScroll;\n await agent.aiScroll(scrollTask, scrollTask.locate, scrollTask);\n } else if (\n typeof (flowItem as MidsceneYamlFlowItemEvaluateJavaScript)\n .javascript !== 'undefined'\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 {\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 agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') {\n this.agentStatusTip = tip;\n }\n };\n freeFn = newFreeFn;\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 '@midscene/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 '@midscene/shared/utils';\nimport yaml from 'js-yaml';\n\nimport type { MidsceneYamlScript } from '@midscene/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 const interpolatedContent = interpolateEnvVars(content);\n const obj = yaml.load(interpolatedContent) as MidsceneYamlScript;\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","import type { AndroidDevicePage, WebPage } from '@/common/page';\nimport type { PuppeteerWebPage } from '@/puppeteer';\nimport {\n type AIUsageInfo,\n type DumpSubscriber,\n type ExecutionRecorderItem,\n type ExecutionTaskActionApply,\n type ExecutionTaskApply,\n type ExecutionTaskInsightLocateApply,\n type ExecutionTaskInsightQueryApply,\n type ExecutionTaskPlanningApply,\n type ExecutionTaskProgressOptions,\n Executor,\n type Insight,\n type InsightAssertionResponse,\n type InsightDump,\n type InsightExtractParam,\n type PageType,\n type PlanningAIResponse,\n type PlanningAction,\n type PlanningActionParamAssert,\n type PlanningActionParamError,\n type PlanningActionParamHover,\n type PlanningActionParamInputOrKeyPress,\n type PlanningActionParamScroll,\n type PlanningActionParamSleep,\n type PlanningActionParamTap,\n type PlanningActionParamWaitFor,\n plan,\n} from '@midscene/core';\nimport {\n type ChatCompletionMessageParam,\n vlmPlanning,\n} from '@midscene/core/ai-model';\nimport { sleep } from '@midscene/core/utils';\n\nimport { UITarsModelVersion } from '@midscene/shared/env';\nimport { uiTarsModelVersion } from '@midscene/shared/env';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { imageInfo, resizeImgBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { WebElementInfo } from '../web-element';\nimport { TaskCache } from './task-cache';\nimport { getKeyCommands, taskTitleStr } from './ui-utils';\nimport type { WebUIContext } from './utils';\n\ninterface ExecutionResult<OutputType = any> {\n output: OutputType;\n executor: Executor;\n}\n\nconst debug = getDebug('page-task-executor');\n\nconst replanningCountLimit = 10;\n\nconst isAndroidPage = (page: WebPage): page is AndroidDevicePage => {\n return page.pageType === 'android';\n};\n\nexport class PageTaskExecutor {\n page: WebPage;\n\n insight: Insight<WebElementInfo, WebUIContext>;\n\n taskCache: TaskCache;\n\n conversationHistory: ChatCompletionMessageParam[] = [];\n\n onTaskStartCallback?: ExecutionTaskProgressOptions['onTaskStart'];\n\n constructor(\n page: WebPage,\n insight: Insight<WebElementInfo, WebUIContext>,\n opts: {\n cacheId: string | undefined;\n onTaskStart?: ExecutionTaskProgressOptions['onTaskStart'];\n },\n ) {\n this.page = page;\n this.insight = insight;\n\n this.taskCache = new TaskCache({\n cacheId: opts?.cacheId,\n });\n\n this.onTaskStartCallback = opts?.onTaskStart;\n }\n\n private async recordScreenshot(timing: ExecutionRecorderItem['timing']) {\n const base64 = await this.page.screenshotBase64();\n const item: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: Date.now(),\n screenshot: base64,\n timing,\n };\n return item;\n }\n\n private prependExecutorWithScreenshot(\n taskApply: ExecutionTaskApply,\n appendAfterExecution = false,\n ): ExecutionTaskApply {\n const taskWithScreenshot: ExecutionTaskApply = {\n ...taskApply,\n executor: async (param, context, ...args) => {\n const recorder: ExecutionRecorderItem[] = [];\n const { task } = context;\n // set the recorder before executor in case of error\n task.recorder = recorder;\n const shot = await this.recordScreenshot(`before ${task.type}`);\n recorder.push(shot);\n const result = await taskApply.executor(param, context, ...args);\n if (taskApply.type === 'Action') {\n await Promise.all([\n (async () => {\n await sleep(100);\n if ((this.page as PuppeteerWebPage).waitUntilNetworkIdle) {\n try {\n await (this.page as PuppeteerWebPage).waitUntilNetworkIdle();\n } catch (error) {\n // console.error('waitUntilNetworkIdle error', error);\n }\n }\n })(),\n sleep(200),\n ]);\n }\n if (appendAfterExecution) {\n const shot2 = await this.recordScreenshot('after Action');\n recorder.push(shot2);\n }\n return result;\n },\n };\n return taskWithScreenshot;\n }\n\n private async convertPlanToExecutable(\n plans: PlanningAction[],\n cacheGroup?: ReturnType<TaskCache['getCacheGroupByPrompt']>,\n ) {\n const tasks: ExecutionTaskApply[] = [];\n plans.forEach((plan) => {\n if (plan.type === 'Locate') {\n if (\n plan.locate === null ||\n plan.locate?.id === null ||\n plan.locate?.id === 'null'\n ) {\n // console.warn('Locate action with id is null, will be ignored');\n return;\n }\n const taskFind: ExecutionTaskInsightLocateApply = {\n type: 'Insight',\n subType: 'Locate',\n param: plan.locate || undefined,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param, taskContext) => {\n const { task } = taskContext;\n assert(\n param?.prompt || param?.id || param?.bbox,\n 'No prompt or id or position or bbox to locate',\n );\n let insightDump: InsightDump | undefined;\n let usage: AIUsageInfo | undefined;\n const dumpCollector: DumpSubscriber = (dump) => {\n insightDump = dump;\n usage = dump?.taskInfo?.usage;\n\n task.log = {\n dump: insightDump,\n };\n\n task.usage = usage;\n };\n this.insight.onceDumpUpdatedFn = dumpCollector;\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('locate');\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before locate',\n };\n task.recorder = [recordItem];\n\n const cachePrompt = param.prompt;\n const locateCache = cacheGroup?.matchCache(\n pageContext,\n 'locate',\n cachePrompt,\n );\n const idInCache = locateCache?.elements?.[0]?.id;\n let cacheHitFlag = false;\n\n let quickAnswerId = param?.id;\n if (!quickAnswerId && idInCache) {\n quickAnswerId = idInCache;\n }\n\n const quickAnswer = {\n id: quickAnswerId,\n bbox: param?.bbox,\n };\n const startTime = Date.now();\n const { element } = await this.insight.locate(param, {\n quickAnswer,\n });\n const aiCost = Date.now() - startTime;\n\n if (element && element.id === quickAnswerId && idInCache) {\n cacheHitFlag = true;\n }\n\n if (element) {\n cacheGroup?.saveCache({\n type: 'locate',\n pageContext: {\n url: pageContext.url,\n size: pageContext.size,\n },\n prompt: cachePrompt,\n response: {\n elements: [\n {\n id: element.id,\n },\n ],\n },\n element,\n });\n }\n if (!element) {\n throw new Error(`Element not found: ${param.prompt}`);\n }\n\n return {\n output: {\n element,\n },\n pageContext,\n cache: {\n hit: cacheHitFlag,\n },\n aiCost,\n };\n },\n };\n tasks.push(taskFind);\n } else if (plan.type === 'Assert' || plan.type === 'AssertWithoutThrow') {\n const assertPlan = plan as PlanningAction<PlanningActionParamAssert>;\n const taskAssert: ExecutionTaskApply = {\n type: 'Insight',\n subType: 'Assert',\n param: assertPlan.param,\n thought: assertPlan.thought,\n locate: assertPlan.locate,\n executor: async (param, taskContext) => {\n const { task } = taskContext;\n let insightDump: InsightDump | undefined;\n const dumpCollector: DumpSubscriber = (dump) => {\n insightDump = dump;\n };\n this.insight.onceDumpUpdatedFn = dumpCollector;\n const assertion = await this.insight.assert(\n assertPlan.param.assertion,\n );\n\n if (!assertion.pass) {\n if (plan.type === 'Assert') {\n task.output = assertion;\n task.log = {\n dump: insightDump,\n };\n throw new Error(\n assertion.thought || 'Assertion failed without reason',\n );\n }\n\n task.error = assertion.thought;\n }\n\n return {\n output: assertion,\n log: {\n dump: insightDump,\n },\n usage: assertion.usage,\n };\n },\n };\n tasks.push(taskAssert);\n } else if (plan.type === 'Input') {\n const taskActionInput: ExecutionTaskActionApply<PlanningActionParamInputOrKeyPress> =\n {\n type: 'Action',\n subType: 'Input',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam, { element }) => {\n if (element) {\n await this.page.clearInput(element as ElementInfo);\n\n if (!taskParam || !taskParam.value) {\n return;\n }\n\n await this.page.keyboard.type(taskParam.value);\n } else {\n await this.page.keyboard.type(taskParam.value);\n }\n },\n };\n tasks.push(taskActionInput);\n } else if (plan.type === 'KeyboardPress') {\n const taskActionKeyboardPress: ExecutionTaskActionApply<PlanningActionParamInputOrKeyPress> =\n {\n type: 'Action',\n subType: 'KeyboardPress',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam) => {\n const keys = getKeyCommands(taskParam.value);\n\n await this.page.keyboard.press(keys);\n },\n };\n tasks.push(taskActionKeyboardPress);\n } else if (plan.type === 'Tap') {\n const taskActionTap: ExecutionTaskActionApply<PlanningActionParamTap> =\n {\n type: 'Action',\n subType: 'Tap',\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param, { element }) => {\n assert(element, 'Element not found, cannot tap');\n await this.page.mouse.click(element.center[0], element.center[1]);\n },\n };\n tasks.push(taskActionTap);\n } else if (plan.type === 'Drag') {\n const taskActionDrag: ExecutionTaskActionApply<{\n start_box: { x: number; y: number };\n end_box: { x: number; y: number };\n }> = {\n type: 'Action',\n subType: 'Drag',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam) => {\n assert(\n taskParam?.start_box && taskParam?.end_box,\n 'No start_box or end_box to drag',\n );\n await this.page.mouse.drag(taskParam.start_box, taskParam.end_box);\n },\n };\n tasks.push(taskActionDrag);\n } else if (plan.type === 'Hover') {\n const taskActionHover: ExecutionTaskActionApply<PlanningActionParamHover> =\n {\n type: 'Action',\n subType: 'Hover',\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param, { element }) => {\n assert(element, 'Element not found, cannot hover');\n await this.page.mouse.move(element.center[0], element.center[1]);\n },\n };\n tasks.push(taskActionHover);\n } else if (plan.type === 'Scroll') {\n const taskActionScroll: ExecutionTaskActionApply<PlanningActionParamScroll> =\n {\n type: 'Action',\n subType: 'Scroll',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam, { element }) => {\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = taskParam?.scrollType;\n if (scrollToEventName === 'untilTop') {\n await this.page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'untilBottom') {\n await this.page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'untilRight') {\n await this.page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'untilLeft') {\n await this.page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'once' || !scrollToEventName) {\n if (\n taskParam?.direction === 'down' ||\n !taskParam ||\n !taskParam.direction\n ) {\n await this.page.scrollDown(\n taskParam?.distance || undefined,\n startingPoint,\n );\n } else if (taskParam.direction === 'up') {\n await this.page.scrollUp(\n taskParam.distance || undefined,\n startingPoint,\n );\n } else if (taskParam.direction === 'left') {\n await this.page.scrollLeft(\n taskParam.distance || undefined,\n startingPoint,\n );\n } else if (taskParam.direction === 'right') {\n await this.page.scrollRight(\n taskParam.distance || undefined,\n startingPoint,\n );\n } else {\n throw new Error(\n `Unknown scroll direction: ${taskParam.direction}`,\n );\n }\n // until mouse event is done\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, taskParam: ${JSON.stringify(\n taskParam,\n )}`,\n );\n }\n },\n };\n tasks.push(taskActionScroll);\n } else if (plan.type === 'Sleep') {\n const taskActionSleep: ExecutionTaskActionApply<PlanningActionParamSleep> =\n {\n type: 'Action',\n subType: 'Sleep',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam) => {\n await sleep(taskParam?.timeMs || 3000);\n },\n };\n tasks.push(taskActionSleep);\n } else if (plan.type === 'Error') {\n const taskActionError: ExecutionTaskActionApply<PlanningActionParamError> =\n {\n type: 'Action',\n subType: 'Error',\n param: plan.param,\n thought: plan.thought || plan.param?.thought,\n locate: plan.locate,\n executor: async () => {\n throw new Error(\n plan?.thought || plan.param?.thought || 'error without thought',\n );\n },\n };\n tasks.push(taskActionError);\n } else if (plan.type === 'ExpectedFalsyCondition') {\n const taskActionFalsyConditionStatement: ExecutionTaskActionApply<null> =\n {\n type: 'Action',\n subType: 'ExpectedFalsyCondition',\n param: null,\n thought: plan.param?.reason,\n locate: plan.locate,\n executor: async () => {\n // console.warn(`[warn]falsy condition: ${plan.thought}`);\n },\n };\n tasks.push(taskActionFalsyConditionStatement);\n } else if (plan.type === 'Finished') {\n const taskActionFinished: ExecutionTaskActionApply<null> = {\n type: 'Action',\n subType: 'Finished',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {},\n };\n tasks.push(taskActionFinished);\n } else if (plan.type === 'AndroidHomeButton') {\n const taskActionAndroidHomeButton: ExecutionTaskActionApply<null> = {\n type: 'Action',\n subType: 'AndroidHomeButton',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {\n // Check if the page has back method (Android devices)\n assert(\n isAndroidPage(this.page),\n 'Cannot use home button on non-Android devices',\n );\n await this.page.home();\n },\n };\n tasks.push(taskActionAndroidHomeButton);\n } else if (plan.type === 'AndroidBackButton') {\n const taskActionAndroidBackButton: ExecutionTaskActionApply<null> = {\n type: 'Action',\n subType: 'AndroidBackButton',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {\n assert(\n isAndroidPage(this.page),\n 'Cannot use back button on non-Android devices',\n );\n await this.page.back();\n },\n };\n tasks.push(taskActionAndroidBackButton);\n } else if (plan.type === 'AndroidRecentAppsButton') {\n const taskActionAndroidRecentAppsButton: ExecutionTaskActionApply<null> =\n {\n type: 'Action',\n subType: 'AndroidRecentAppsButton',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {\n assert(\n isAndroidPage(this.page),\n 'Cannot use recent apps button on non-Android devices',\n );\n await this.page.recentApps();\n },\n };\n tasks.push(taskActionAndroidRecentAppsButton);\n } else {\n throw new Error(`Unknown or unsupported task type: ${plan.type}`);\n }\n });\n\n const wrappedTasks = tasks.map(\n (task: ExecutionTaskApply, index: number) => {\n if (task.type === 'Action') {\n return this.prependExecutorWithScreenshot(\n task,\n index === tasks.length - 1,\n );\n }\n return task;\n },\n );\n\n return {\n tasks: wrappedTasks,\n };\n }\n\n private planningTaskFromPrompt(\n userInstruction: string,\n cacheGroup: ReturnType<TaskCache['getCacheGroupByPrompt']>,\n log?: string,\n actionContext?: string,\n ) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n locate: null,\n param: {\n userInstruction,\n log,\n },\n executor: async (param, executorContext) => {\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('locate');\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before planning',\n };\n\n executorContext.task.recorder = [recordItem];\n (executorContext.task as any).pageContext = pageContext;\n\n const cachePrompt = `${param.userInstruction} @ ${param.log || ''}`;\n const planCache = cacheGroup.matchCache(\n pageContext,\n 'plan',\n cachePrompt,\n );\n let planResult: Awaited<ReturnType<typeof plan>>;\n if (planCache) {\n if ('actions' in planCache && Array.isArray(planCache.actions)) {\n planCache.actions = planCache.actions.map((action) => {\n // remove all bbox in actions cache while using\n if (action.locate) {\n // biome-ignore lint/performance/noDelete: intended to remove bbox\n delete action.locate.bbox;\n }\n return action;\n });\n }\n planResult = planCache;\n } else {\n planResult = await plan(param.userInstruction, {\n context: pageContext,\n log: param.log,\n actionContext,\n pageType: this.page.pageType as PageType,\n });\n }\n\n const {\n actions,\n log,\n more_actions_needed_by_instruction,\n error,\n usage,\n rawResponse,\n sleep,\n } = planResult;\n\n let stopCollecting = false;\n let bboxCollected = false;\n let planParsingError = '';\n const finalActions = (actions || []).reduce<PlanningAction[]>(\n (acc, planningAction) => {\n if (stopCollecting) {\n return acc;\n }\n\n if (planningAction.locate) {\n // we only collect bbox once, let qwen re-locate in the following steps\n if (bboxCollected && planningAction.locate.bbox) {\n // biome-ignore lint/performance/noDelete: <explanation>\n delete planningAction.locate.bbox;\n }\n\n if (planningAction.locate.bbox) {\n bboxCollected = true;\n }\n\n acc.push({\n type: 'Locate',\n locate: planningAction.locate,\n param: null,\n thought: planningAction.locate.prompt,\n });\n } else if (\n ['Tap', 'Hover', 'Input'].includes(planningAction.type)\n ) {\n planParsingError = `invalid planning response: ${JSON.stringify(planningAction)}`;\n // should include locate but get null\n stopCollecting = true;\n return acc;\n }\n acc.push(planningAction);\n return acc;\n },\n [],\n );\n\n if (sleep) {\n const timeNow = Date.now();\n const timeRemaining = sleep - (timeNow - shotTime);\n if (timeRemaining > 0) {\n finalActions.push({\n type: 'Sleep',\n param: {\n timeMs: timeRemaining,\n },\n locate: null,\n } as PlanningAction<PlanningActionParamSleep>);\n }\n }\n\n if (finalActions.length === 0) {\n assert(\n !more_actions_needed_by_instruction || sleep,\n error\n ? `Failed to plan: ${error}`\n : planParsingError || 'No plan found',\n );\n }\n\n cacheGroup.saveCache({\n type: 'plan',\n pageContext: {\n url: pageContext.url,\n size: pageContext.size,\n },\n prompt: cachePrompt,\n response: planResult,\n });\n\n return {\n output: {\n actions: finalActions,\n more_actions_needed_by_instruction,\n log,\n },\n cache: {\n hit: Boolean(planCache),\n },\n pageContext,\n recorder: [recordItem],\n usage,\n rawResponse,\n };\n },\n };\n\n return task;\n }\n\n private planningTaskToGoal(\n userInstruction: string,\n cacheGroup: ReturnType<TaskCache['getCacheGroupByPrompt']>,\n ) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n locate: null,\n param: {\n userInstruction,\n },\n executor: async (param, executorContext) => {\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('locate');\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before planning',\n };\n executorContext.task.recorder = [recordItem];\n (executorContext.task as any).pageContext = pageContext;\n\n let imagePayload = pageContext.screenshotBase64;\n if (\n vlLocateMode() === 'vlm-ui-tars' &&\n uiTarsModelVersion() === UITarsModelVersion.V1_5\n ) {\n const size = pageContext.size;\n // const imageInfo = await imageInfoOfBase64(imagePayload);\n debug('ui-tars-v1.5, will check image size', size);\n const currentPixels = size.width * size.height;\n const maxPixels = 16384 * 28 * 28; //\n if (currentPixels > maxPixels) {\n const resizeFactor = Math.sqrt(maxPixels / currentPixels);\n const newWidth = Math.floor(size.width * resizeFactor);\n const newHeight = Math.floor(size.height * resizeFactor);\n debug(\n 'resize image',\n imageInfo,\n 'new width',\n newWidth,\n 'new height',\n newHeight,\n );\n imagePayload = await resizeImgBase64(imagePayload, {\n width: newWidth,\n height: newHeight,\n });\n }\n }\n\n this.appendConversationHistory({\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n },\n },\n ],\n });\n const startTime = Date.now();\n\n const planCache = cacheGroup.matchCache(\n pageContext,\n 'ui-tars-plan',\n userInstruction,\n );\n let planResult: Awaited<ReturnType<typeof vlmPlanning>>;\n if (planCache) {\n planResult = planCache;\n } else {\n planResult = await vlmPlanning({\n userInstruction: param.userInstruction,\n conversationHistory: this.conversationHistory,\n size: pageContext.size,\n });\n }\n cacheGroup.saveCache({\n type: 'ui-tars-plan',\n pageContext: {\n url: pageContext.url,\n size: pageContext.size,\n },\n prompt: userInstruction,\n response: planResult,\n });\n const aiCost = Date.now() - startTime;\n const { actions, action_summary } = planResult;\n this.appendConversationHistory({\n role: 'assistant',\n content: action_summary,\n });\n return {\n output: {\n actions,\n thought: actions[0]?.thought,\n actionType: actions[0].type,\n more_actions_needed_by_instruction: true,\n log: '',\n },\n log: {\n rawResponse: planResult,\n },\n cache: {\n hit: Boolean(planCache),\n },\n aiCost,\n };\n },\n };\n\n return task;\n }\n\n async runPlans(\n title: string,\n plans: PlanningAction[],\n ): Promise<ExecutionResult> {\n const taskExecutor = new Executor(title, {\n onTaskStart: this.onTaskStartCallback,\n });\n const cacheGroup = this.taskCache.getCacheGroupByPrompt(title);\n const { tasks } = await this.convertPlanToExecutable(plans, cacheGroup);\n await taskExecutor.append(tasks);\n const result = await taskExecutor.flush();\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n\n async action(\n userPrompt: string,\n actionContext?: string,\n ): Promise<ExecutionResult> {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n\n const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);\n let planningTask: ExecutionTaskPlanningApply | null =\n this.planningTaskFromPrompt(\n userPrompt,\n cacheGroup,\n undefined,\n actionContext,\n );\n let result: any;\n let replanCount = 0;\n const logList: string[] = [];\n while (planningTask) {\n if (replanCount > replanningCountLimit) {\n const errorMsg =\n 'Replanning too many times, please split the task into multiple steps';\n\n return this.appendErrorPlan(taskExecutor, errorMsg);\n }\n\n // plan\n await taskExecutor.append(planningTask);\n const planResult: PlanningAIResponse = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: planResult,\n executor: taskExecutor,\n };\n }\n\n const plans = planResult.actions || [];\n\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans, cacheGroup);\n taskExecutor.append(executables.tasks);\n } catch (error) {\n return this.appendErrorPlan(\n taskExecutor,\n `Error converting plans to executable tasks: ${error}, plans: ${JSON.stringify(\n plans,\n )}`,\n );\n }\n\n result = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n if (planResult?.log) {\n logList.push(planResult.log);\n }\n\n if (!planResult.more_actions_needed_by_instruction) {\n planningTask = null;\n break;\n }\n planningTask = this.planningTaskFromPrompt(\n userPrompt,\n cacheGroup,\n logList.length > 0 ? `- ${logList.join('\\n- ')}` : undefined,\n actionContext,\n );\n replanCount++;\n }\n\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n\n async actionToGoal(userPrompt: string) {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n this.conversationHistory = [];\n const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);\n const isCompleted = false;\n let currentActionNumber = 0;\n const maxActionNumber = 40;\n\n while (!isCompleted && currentActionNumber < maxActionNumber) {\n currentActionNumber++;\n const planningTask: ExecutionTaskPlanningApply = this.planningTaskToGoal(\n userPrompt,\n cacheGroup,\n );\n await taskExecutor.append(planningTask);\n const output = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: output,\n executor: taskExecutor,\n };\n }\n const plans = output.actions;\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans);\n taskExecutor.append(executables.tasks);\n } catch (error) {\n return this.appendErrorPlan(\n taskExecutor,\n `Error converting plans to executable tasks: ${error}, plans: ${JSON.stringify(\n plans,\n )}`,\n );\n }\n\n const result = await taskExecutor.flush();\n\n if (taskExecutor.isInErrorState()) {\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n\n if (plans[0].type === 'Finished') {\n break;\n }\n }\n return {\n output: {},\n executor: taskExecutor,\n };\n }\n\n private async createTypeQueryTask<T>(\n type: 'Query' | 'Boolean' | 'Number' | 'String',\n demand: InsightExtractParam,\n ): Promise<ExecutionResult<T>> {\n const taskExecutor = new Executor(\n taskTitleStr(\n type,\n typeof demand === 'string' ? demand : JSON.stringify(demand),\n ),\n {\n onTaskStart: this.onTaskStartCallback,\n },\n );\n\n const queryTask: ExecutionTaskInsightQueryApply = {\n type: 'Insight',\n subType: type,\n locate: null,\n param: {\n dataDemand: demand, // for user param presentation in report right sidebar\n },\n executor: async (param) => {\n let insightDump: InsightDump | undefined;\n const dumpCollector: DumpSubscriber = (dump) => {\n insightDump = dump;\n };\n this.insight.onceDumpUpdatedFn = dumpCollector;\n\n const ifTypeRestricted = type !== 'Query';\n let demandInput = demand;\n if (ifTypeRestricted) {\n demandInput = {\n result: `${type}, ${demand}`,\n };\n }\n\n const { data, usage } = await this.insight.extract<any>(demandInput);\n\n let outputResult = data;\n if (ifTypeRestricted) {\n assert(data?.result !== undefined, 'No result in query data');\n outputResult = (data as any).result;\n }\n\n return {\n output: outputResult,\n log: { dump: insightDump },\n usage,\n };\n },\n };\n\n await taskExecutor.append(this.prependExecutorWithScreenshot(queryTask));\n const output = await taskExecutor.flush();\n return {\n output,\n executor: taskExecutor,\n };\n }\n\n async query(demand: InsightExtractParam): Promise<ExecutionResult> {\n return this.createTypeQueryTask('Query', demand);\n }\n\n async boolean(prompt: string): Promise<ExecutionResult<boolean>> {\n return this.createTypeQueryTask<boolean>('Boolean', prompt);\n }\n\n async number(prompt: string): Promise<ExecutionResult<number>> {\n return this.createTypeQueryTask<number>('Number', prompt);\n }\n\n async string(prompt: string): Promise<ExecutionResult<string>> {\n return this.createTypeQueryTask<string>('String', prompt);\n }\n\n async assert(\n assertion: string,\n ): Promise<ExecutionResult<InsightAssertionResponse>> {\n const description = `assert: ${assertion}`;\n const taskExecutor = new Executor(taskTitleStr('Assert', description), {\n onTaskStart: this.onTaskStartCallback,\n });\n const assertionPlan: PlanningAction<PlanningActionParamAssert> = {\n type: 'Assert',\n param: {\n assertion,\n },\n locate: null,\n };\n const { tasks } = await this.convertPlanToExecutable([assertionPlan]);\n\n await taskExecutor.append(this.prependExecutorWithScreenshot(tasks[0]));\n const output: InsightAssertionResponse = await taskExecutor.flush();\n\n return {\n output,\n executor: taskExecutor,\n };\n }\n\n /**\n * Append a message to the conversation history\n * For user messages with images:\n * - Keep max 4 user image messages in history\n * - Remove oldest user image message when limit reached\n * For assistant messages:\n * - Simply append to history\n * @param conversationHistory Message to append\n */\n private appendConversationHistory(\n conversationHistory: ChatCompletionMessageParam,\n ) {\n if (conversationHistory.role === 'user') {\n // Get all existing user messages with images\n const userImgItems = this.conversationHistory.filter(\n (item) => item.role === 'user',\n );\n\n // If we already have 4 user image messages\n if (userImgItems.length >= 4 && conversationHistory.role === 'user') {\n // Remove first user image message when we already have 4, before adding new one\n const firstUserImgIndex = this.conversationHistory.findIndex(\n (item) => item.role === 'user',\n );\n if (firstUserImgIndex >= 0) {\n this.conversationHistory.splice(firstUserImgIndex, 1);\n }\n }\n }\n // For non-user messages, simply append to history\n this.conversationHistory.push(conversationHistory);\n }\n\n private async appendErrorPlan(taskExecutor: Executor, errorMsg: string) {\n const errorPlan: PlanningAction<PlanningActionParamError> = {\n type: 'Error',\n param: {\n thought: errorMsg,\n },\n locate: null,\n };\n const { tasks } = await this.convertPlanToExecutable([errorPlan]);\n await taskExecutor.append(this.prependExecutorWithScreenshot(tasks[0]));\n await taskExecutor.flush();\n\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n\n async waitFor(\n assertion: string,\n opt: PlanningActionParamWaitFor,\n ): Promise<ExecutionResult<void>> {\n const description = `waitFor: ${assertion}`;\n const taskExecutor = new Executor(taskTitleStr('WaitFor', description), {\n onTaskStart: this.onTaskStartCallback,\n });\n const { timeoutMs, checkIntervalMs } = opt;\n\n assert(assertion, 'No assertion for waitFor');\n assert(timeoutMs, 'No timeoutMs for waitFor');\n assert(checkIntervalMs, 'No checkIntervalMs for waitFor');\n\n const overallStartTime = Date.now();\n let startTime = Date.now();\n let errorThought = '';\n while (Date.now() - overallStartTime < timeoutMs) {\n startTime = Date.now();\n const assertPlan: PlanningAction<PlanningActionParamAssert> = {\n type: 'AssertWithoutThrow',\n param: {\n assertion,\n },\n locate: null,\n };\n const { tasks: assertTasks } = await this.convertPlanToExecutable([\n assertPlan,\n ]);\n await taskExecutor.append(\n this.prependExecutorWithScreenshot(assertTasks[0]),\n );\n const output: InsightAssertionResponse = await taskExecutor.flush();\n\n if (output?.pass) {\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n\n errorThought =\n output?.thought ||\n `unknown error when waiting for assertion: ${assertion}`;\n const now = Date.now();\n if (now - startTime < checkIntervalMs) {\n const timeRemaining = checkIntervalMs - (now - startTime);\n const sleepPlan: PlanningAction<PlanningActionParamSleep> = {\n type: 'Sleep',\n param: {\n timeMs: timeRemaining,\n },\n locate: null,\n };\n const { tasks: sleepTasks } = await this.convertPlanToExecutable([\n sleepPlan,\n ]);\n await taskExecutor.append(\n this.prependExecutorWithScreenshot(sleepTasks[0]),\n );\n await taskExecutor.flush();\n }\n }\n\n return this.appendErrorPlan(\n taskExecutor,\n `waitFor timeout: ${errorThought}`,\n );\n }\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type {\n AIElementLocatorResponse,\n LocateResultElement,\n PlanningAIResponse,\n} from '@midscene/core';\nimport type { vlmPlanning } from '@midscene/core/ai-model';\nimport { stringifyDumpData, writeLogFile } from '@midscene/core/utils';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport { getAIConfigInBoolean } from '@midscene/shared/env';\nimport { getRunningPkgInfo } from '@midscene/shared/fs';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport { type WebUIContext, replaceIllegalPathCharsAndSpace } from './utils';\n\nconst debug = getDebug('cache');\n\nexport type PlanTask = {\n type: 'plan';\n prompt: string;\n pageContext: {\n url: string;\n size: {\n width: number;\n height: number;\n };\n };\n response: PlanningAIResponse;\n};\n\nexport type UITarsPlanTask = {\n type: 'ui-tars-plan';\n prompt: string;\n pageContext: {\n url: string;\n size: {\n width: number;\n height: number;\n };\n };\n response: Awaited<ReturnType<typeof vlmPlanning>>;\n};\n\nexport type LocateTask = {\n type: 'locate';\n prompt: string;\n pageContext: {\n url: string;\n size: {\n width: number;\n height: number;\n };\n };\n response: AIElementLocatorResponse;\n element: LocateResultElement;\n};\n\nexport type AiTasks = Array<PlanTask | LocateTask | UITarsPlanTask>;\n\nexport type AiTaskCache = {\n aiTasks: Array<{\n prompt: string;\n tasks: AiTasks;\n }>;\n};\n\nexport type CacheGroup = {\n matchCache: <T extends 'plan' | 'locate' | 'ui-tars-plan'>(\n pageContext: WebUIContext,\n type: T,\n actionPrompt: string,\n ) => T extends 'plan'\n ? PlanTask['response']\n : T extends 'locate'\n ? LocateTask['response']\n : UITarsPlanTask['response'];\n saveCache: (cache: UITarsPlanTask | PlanTask | LocateTask) => void;\n};\n\nexport class TaskCache {\n cache: AiTaskCache;\n\n cacheId: string;\n\n newCache: AiTaskCache;\n\n midscenePkgInfo: ReturnType<typeof getRunningPkgInfo> | null;\n\n constructor(opts?: { cacheId?: string }) {\n this.midscenePkgInfo = getRunningPkgInfo();\n this.cacheId = replaceIllegalPathCharsAndSpace(opts?.cacheId || '');\n this.cache = this.readCacheFromFile() || {\n aiTasks: [],\n };\n this.newCache = {\n aiTasks: [],\n };\n }\n\n getCacheGroupByPrompt(aiActionPrompt: string): CacheGroup {\n const { aiTasks = [] } = this.cache || { aiTasks: [] };\n const index = aiTasks.findIndex((item) => item.prompt === aiActionPrompt);\n const newCacheGroup: AiTasks = [];\n this.newCache.aiTasks.push({\n prompt: aiActionPrompt,\n tasks: newCacheGroup,\n });\n return {\n matchCache: <T extends 'plan' | 'locate' | 'ui-tars-plan'>(\n pageContext: WebUIContext,\n type: T,\n actionPrompt: string,\n ) => {\n if (index === -1) {\n return false as any;\n }\n if (type === 'plan') {\n return this.matchCache(\n pageContext,\n type,\n actionPrompt,\n aiTasks[index].tasks,\n ) as PlanTask['response'];\n }\n if (type === 'ui-tars-plan') {\n return this.matchCache(\n pageContext,\n type,\n actionPrompt,\n aiTasks[index].tasks,\n ) as UITarsPlanTask['response'];\n }\n\n return this.matchCache(\n pageContext,\n type,\n actionPrompt,\n aiTasks[index].tasks,\n ) as T extends 'plan'\n ? PlanTask['response']\n : T extends 'locate'\n ? LocateTask['response']\n : UITarsPlanTask['response'];\n },\n saveCache: (cache: PlanTask | LocateTask | UITarsPlanTask) => {\n newCacheGroup.push(cache);\n debug(\n 'saving cache to file, type: %s, cacheId: %s',\n cache.type,\n this.cacheId,\n );\n this.writeCacheToFile();\n },\n };\n }\n\n /**\n * Read and return cached responses asynchronously based on specific criteria\n * This function is mainly used to read cached responses from a certain storage medium.\n * It accepts three parameters: the page context information, the task type, and the user's prompt information.\n * In the function, it first checks whether there is cached data. If there is, it retrieves the first task response from the cache.\n * It then checks whether the task type is 'locate' and whether the corresponding element can be found in the new context.\n * If the element cannot be found, it returns false, indicating that the cache is invalid.\n * If the task type is correct and the user prompt matches, it checks whether the page context is the same.\n * If the page context is the same, it returns the cached response, indicating that the cache hit is successful.\n * If there is no cached data or the conditions are not met, the function returns false, indicating that no cache is available or the cache is not hit.\n *\n * @param pageContext UIContext<WebElementInfo> type, representing the context information of the current page\n * @param type String type, specifying the task type, can be 'plan' or 'locate'\n * @param userPrompt String type, representing user prompt information\n * @return Returns a Promise object that resolves to a boolean or object\n */\n matchCache(\n pageContext: WebUIContext,\n type: 'plan',\n userPrompt: string,\n cacheGroup: AiTasks,\n ): PlanTask['response'];\n matchCache(\n pageContext: WebUIContext,\n type: 'ui-tars-plan',\n userPrompt: string,\n cacheGroup: AiTasks,\n ): UITarsPlanTask['response'];\n matchCache(\n pageContext: WebUIContext,\n type: 'locate',\n userPrompt: string,\n cacheGroup: AiTasks,\n ): LocateTask['response'];\n matchCache(\n pageContext: WebUIContext,\n type: 'plan' | 'locate' | 'ui-tars-plan',\n userPrompt: string,\n cacheGroup: AiTasks,\n ):\n | PlanTask['response']\n | LocateTask['response']\n | UITarsPlanTask['response']\n | false {\n debug(\n 'will read cache, type: %s, prompt: %s, cacheGroupLength: %s',\n type,\n userPrompt,\n cacheGroup.length,\n );\n if (cacheGroup.length > 0) {\n const index = cacheGroup.findIndex((item) => item.prompt === userPrompt);\n\n if (index === -1) {\n debug('cannot find any cache matching prompt: %s', userPrompt);\n return false;\n }\n\n const taskRes = cacheGroup.splice(index, 1)[0];\n debug(\n 'found cache with same prompt, type: %s, prompt: %s, cached response is %j',\n type,\n userPrompt,\n taskRes?.response,\n );\n\n // The corresponding element cannot be found in the new context\n if (taskRes?.type === 'locate') {\n const id = taskRes.response?.elements[0].id;\n if (!id) {\n debug('no id in cached response');\n return false;\n }\n\n const foundInContext = pageContext.content.find(\n (contentElement) => contentElement.id === id,\n );\n if (!foundInContext) {\n debug('cannot match element with same id in current page', {\n element: taskRes.element,\n });\n return false;\n }\n\n return taskRes.response;\n }\n\n if (taskRes && taskRes.type === type && taskRes.prompt === userPrompt) {\n const contextEqual = this.pageContextEqual(\n taskRes.pageContext,\n pageContext,\n );\n if (!contextEqual) {\n debug(\n 'cache almost hit, type: %s, prompt: %s, but context not equal, will not use cache',\n type,\n userPrompt,\n );\n return false;\n }\n debug('cache hit, type: %s, prompt: %s', type, userPrompt);\n return taskRes.response;\n }\n }\n debug('no cache hit, type: %s, prompt: %s', type, userPrompt);\n return false;\n }\n\n pageContextEqual(\n taskPageContext: LocateTask['pageContext'],\n pageContext: WebUIContext,\n ) {\n debug(\n 'comparing page context size: %s x %s, %s x %s',\n taskPageContext.size.width,\n taskPageContext.size.height,\n pageContext.size.width,\n pageContext.size.height,\n );\n return (\n taskPageContext.size.width === pageContext.size.width &&\n taskPageContext.size.height === pageContext.size.height\n );\n }\n\n /**\n * Generate task cache data.\n * This method is mainly used to create or obtain some cached data for tasks, and it returns a new cache object.\n * In the cache object, it may contain task-related information, states, or other necessary data.\n * It is assumed that the `newCache` property already exists in the current class or object and is a data structure used to store task cache.\n * @returns {Object} Returns a new cache object, which may include task cache data.\n */\n generateTaskCache() {\n return this.newCache;\n }\n\n readCacheFromFile() {\n if (ifInBrowser || !this.cacheId) {\n return undefined;\n }\n const cacheFile = join(\n getMidsceneRunSubDir('cache'),\n `${this.cacheId}.json`,\n );\n if (!getAIConfigInBoolean('MIDSCENE_CACHE')) {\n return undefined;\n }\n\n if (existsSync(cacheFile)) {\n try {\n const data = readFileSync(cacheFile, 'utf8');\n const jsonData = JSON.parse(data);\n if (!this.midscenePkgInfo) {\n return undefined;\n }\n const jsonDataPkgVersion = jsonData.pkgVersion.split('.');\n const midscenePkgInfoPkgVersion =\n this.midscenePkgInfo.version.split('.');\n if (\n jsonDataPkgVersion[0] !== midscenePkgInfoPkgVersion[0] ||\n jsonDataPkgVersion[1] !== midscenePkgInfoPkgVersion[1]\n ) {\n return undefined;\n }\n debug('read cache from file: %s', cacheFile);\n return jsonData as AiTaskCache;\n } catch (err) {\n debug(\n 'cache file exists but parse failed, path: %s, error: %s',\n cacheFile,\n err,\n );\n return undefined;\n }\n }\n debug('no cache file found, path: %s', cacheFile);\n return undefined;\n }\n\n writeCacheToFile() {\n const midscenePkgInfo = getRunningPkgInfo();\n if (!midscenePkgInfo) {\n debug('no midscene pkg info, will not write cache to file');\n return;\n }\n\n if (!this.cacheId) {\n debug('no cache id, will not write cache to file');\n return;\n }\n\n if (!ifInBrowser) {\n writeLogFile({\n fileName: `${this.cacheId}`,\n fileExt: 'json',\n fileContent: stringifyDumpData(\n {\n pkgName: midscenePkgInfo.name,\n pkgVersion: midscenePkgInfo.version,\n cacheId: this.cacheId,\n ...this.newCache,\n },\n 2,\n ),\n type: 'cache',\n });\n }\n }\n}\n","import type { StaticPage } from '@/playground';\nimport type {\n ElementTreeNode,\n PlaywrightParserOpt,\n UIContext,\n} from '@midscene/core';\nimport { uploadTestInfoToServer } from '@midscene/core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { traverseTree, treeToList } from '@midscene/shared/extractor';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport type { DebugFunction } from '@midscene/shared/logger';\nimport { assert, logMsg, uuid } from '@midscene/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 } = elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\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 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","import type { BaseElement, Rect } from '@midscene/core';\nimport type { NodeType } from '@midscene/shared/constants';\n\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 // page: WebPage;\n\n id: string;\n\n indexId: number;\n\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n\n constructor({\n content,\n rect,\n // page,\n locator,\n id,\n attributes,\n indexId,\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 }) {\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 }\n}\n","import type {\n DetailedLocateParam,\n ExecutionTask,\n ExecutionTaskAction,\n ExecutionTaskInsightAssertion,\n ExecutionTaskInsightLocate,\n ExecutionTaskInsightQuery,\n ExecutionTaskPlanning,\n PlanningActionParamScroll,\n} from '@midscene/core';\n\nexport function typeStr(task: ExecutionTask) {\n return task.subType ? `${task.type} / ${task.subType || ''}` : task.type;\n}\n\nexport function getKeyCommands(\n value: string | string[],\n): Array<{ key: string; command?: string }> {\n // Ensure value is an array of keys\n const keys = Array.isArray(value) ? value : [value];\n\n // Process each key to attach a corresponding command if needed, based on the presence of 'Meta' or 'Control' in the keys array.\n // ref: https://github.com/puppeteer/puppeteer/pull/9357/files#diff-32cf475237b000f980eb214a0a823e45a902bddb7d2426d677cae96397aa0ae4R94\n return keys.reduce((acc: Array<{ key: string; command?: string }>, k) => {\n const includeMeta = keys.includes('Meta') || keys.includes('Control');\n if (includeMeta && (k === 'a' || k === 'A')) {\n return acc.concat([{ key: k, command: 'SelectAll' }]);\n }\n if (includeMeta && (k === 'c' || k === 'C')) {\n return acc.concat([{ key: k, command: 'Copy' }]);\n }\n if (includeMeta && (k === 'v' || k === 'V')) {\n return acc.concat([{ key: k, command: 'Paste' }]);\n }\n return acc.concat([{ key: k }]);\n }, []);\n}\n\nexport function locateParamStr(locate?: DetailedLocateParam) {\n if (!locate) {\n return '';\n }\n\n if (typeof locate === 'string') {\n return locate;\n }\n\n return locate.prompt;\n}\n\nexport function scrollParamStr(scrollParam?: PlanningActionParamScroll) {\n if (!scrollParam) {\n return '';\n }\n return `${scrollParam.direction || 'down'}, ${scrollParam.scrollType || 'once'}, ${scrollParam.distance || 'distance-not-set'}`;\n}\n\nexport function taskTitleStr(\n type:\n | 'Tap'\n | 'Hover'\n | 'Input'\n | 'KeyboardPress'\n | 'Scroll'\n | 'Action'\n | 'Query'\n | 'Assert'\n | 'WaitFor'\n | 'Locate'\n | 'Boolean'\n | 'Number'\n | 'String',\n prompt: string,\n) {\n if (prompt) {\n return `${type} - ${prompt}`;\n }\n return type;\n}\n\nexport function paramStr(task: ExecutionTask) {\n let value: string | undefined | object;\n if (task.type === 'Planning') {\n value = (task as ExecutionTaskPlanning)?.param?.userInstruction;\n }\n\n if (task.type === 'Insight') {\n value =\n (task as ExecutionTaskInsightLocate)?.param?.prompt ||\n (task as ExecutionTaskInsightLocate)?.param?.id ||\n (task as ExecutionTaskInsightQuery)?.param?.dataDemand ||\n (task as ExecutionTaskInsightAssertion)?.param?.assertion;\n }\n\n if (task.type === 'Action') {\n const locate = (task as ExecutionTaskAction)?.locate;\n const locateStr = locate ? locateParamStr(locate) : '';\n\n value = task.thought || '';\n if (typeof (task as ExecutionTaskAction)?.param?.timeMs === 'number') {\n value = `${(task as ExecutionTaskAction)?.param?.timeMs}ms`;\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.scrollType === 'string'\n ) {\n value = scrollParamStr((task as ExecutionTaskAction)?.param);\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.value !== 'undefined'\n ) {\n value = (task as ExecutionTaskAction)?.param?.value;\n }\n\n if (locateStr) {\n if (value) {\n value = `${locateStr} - ${value}`;\n } else {\n value = locateStr;\n }\n }\n }\n\n if (typeof value === 'undefined') return '';\n return typeof value === 'string'\n ? value\n : JSON.stringify(value, undefined, 2);\n}\n\nexport const limitOpenNewTabScript = `\nif (!window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__) {\n window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__ = true;\n\n // Intercept the window.open method (only once)\n window.open = function(url) {\n console.log('Blocked window.open:', url);\n window.location.href = url;\n return null;\n };\n\n // Block all a tag clicks with target=\"_blank\" (only once)\n document.addEventListener('click', function(e) {\n const target = e.target.closest('a');\n if (target && target.target === '_blank') {\n e.preventDefault();\n console.log('Blocked new tab:', target.href);\n window.location.href = target.href;\n target.removeAttribute('target');\n }\n }, true);\n}\n`;\n","import type {\n DetailedLocateParam,\n PlanningAction,\n PlanningActionParamHover,\n PlanningActionParamInputOrKeyPress,\n PlanningActionParamScroll,\n PlanningActionParamSleep,\n PlanningActionParamTap,\n PlanningLocateParam,\n} from '@midscene/core';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\n\nconst debug = getDebug('plan-builder');\n\nexport function buildPlans(\n type: PlanningAction['type'],\n locateParam?: DetailedLocateParam,\n param?:\n | PlanningActionParamInputOrKeyPress\n | PlanningActionParamScroll\n | PlanningActionParamSleep,\n): PlanningAction[] {\n let returnPlans: PlanningAction[] = [];\n const locatePlan: PlanningAction<PlanningLocateParam> | null = locateParam\n ? {\n type: 'Locate',\n locate: locateParam,\n param: locateParam,\n thought: '',\n }\n : null;\n if (type === 'Tap' || type === 'Hover') {\n assert(locateParam, `missing locate info for action \"${type}\"`);\n assert(locatePlan, `missing locate info for action \"${type}\"`);\n const tapPlan: PlanningAction<PlanningActionParamTap> = {\n type,\n param: null,\n thought: '',\n locate: locateParam,\n };\n\n returnPlans = [locatePlan, tapPlan];\n }\n if (type === 'Input' || type === 'KeyboardPress') {\n if (type === 'Input') {\n assert(locateParam, `missing locate info for action \"${type}\"`);\n }\n assert(param, `missing param for action \"${type}\"`);\n\n const inputPlan: PlanningAction<PlanningActionParamInputOrKeyPress> = {\n type,\n param: param as PlanningActionParamInputOrKeyPress,\n thought: '',\n locate: locateParam!,\n };\n\n if (locatePlan) {\n returnPlans = [locatePlan, inputPlan];\n } else {\n returnPlans = [inputPlan];\n }\n }\n\n if (type === 'Scroll') {\n assert(param, `missing param for action \"${type}\"`);\n\n const scrollPlan: PlanningAction<PlanningActionParamScroll> = {\n type,\n param: param as PlanningActionParamScroll,\n thought: '',\n locate: locateParam,\n };\n\n if (locatePlan) {\n returnPlans = [locatePlan, scrollPlan];\n } else {\n returnPlans = [scrollPlan];\n }\n }\n\n if (type === 'Sleep') {\n assert(param, `missing param for action \"${type}\"`);\n\n const sleepPlan: PlanningAction<PlanningActionParamSleep> = {\n type,\n param: param as PlanningActionParamSleep,\n thought: '',\n locate: null,\n };\n\n returnPlans = [sleepPlan];\n }\n\n if (type === 'Locate') {\n assert(locateParam, `missing locate info for action \"${type}\"`);\n const locatePlan: PlanningAction<PlanningLocateParam> = {\n type,\n param: locateParam as PlanningLocateParam,\n locate: locateParam,\n thought: '',\n };\n returnPlans = [locatePlan];\n }\n\n if (returnPlans) {\n debug('buildPlans', returnPlans);\n return returnPlans;\n }\n\n throw new Error(`Not supported type: ${type}`);\n}\n","import { PageAgent, type PageAgentOpt } from '@/common/agent';\nimport type { KeyboardAction, MouseAction } from '@/page';\nimport { assert } from '@midscene/shared/utils';\nimport {\n type BridgeConnectTabOptions,\n BridgeEvent,\n BridgePageType,\n DefaultBridgeServerPort,\n KeyboardEvent,\n MouseEvent,\n} from './common';\nimport { BridgeServer } from './io-server';\nimport type { ExtensionBridgePageBrowserSide } from './page-browser-side';\n\ninterface ChromeExtensionPageCliSide extends ExtensionBridgePageBrowserSide {\n showStatusMessage: (message: string) => Promise<void>;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n// actually, this is a proxy to the page in browser side\nexport const getBridgePageInCliSide = (\n timeout?: number | false,\n closeConflictServer?: boolean,\n): ChromeExtensionPageCliSide => {\n const server = new BridgeServer(\n DefaultBridgeServerPort,\n undefined,\n undefined,\n closeConflictServer,\n );\n server.listen({\n timeout,\n });\n const bridgeCaller = (method: string) => {\n return async (...args: any[]) => {\n const response = await server.call(method, args);\n return response;\n };\n };\n const page = {\n showStatusMessage: async (message: string) => {\n await server.call(BridgeEvent.UpdateAgentStatus, [message]);\n },\n };\n\n return new Proxy(page, {\n get(target, prop, receiver) {\n assert(typeof prop === 'string', 'prop must be a string');\n\n if (prop === 'toJSON') {\n return () => {\n return {\n pageType: BridgePageType,\n };\n };\n }\n\n if (prop === 'pageType') {\n return BridgePageType;\n }\n\n if (prop === '_forceUsePageContext') {\n return undefined;\n }\n\n if (Object.keys(page).includes(prop)) {\n return page[prop as keyof typeof page];\n }\n\n if (prop === 'mouse') {\n const mouse: MouseAction = {\n click: bridgeCaller(MouseEvent.Click),\n wheel: bridgeCaller(MouseEvent.Wheel),\n move: bridgeCaller(MouseEvent.Move),\n drag: bridgeCaller(MouseEvent.Drag),\n };\n return mouse;\n }\n\n if (prop === 'keyboard') {\n const keyboard: KeyboardAction = {\n type: bridgeCaller(KeyboardEvent.Type),\n press: bridgeCaller(KeyboardEvent.Press),\n };\n return keyboard;\n }\n\n if (prop === 'destroy') {\n return async (...args: any[]) => {\n try {\n const caller = bridgeCaller('destroy');\n await caller(...args);\n } catch (e) {\n // console.error('error calling destroy', e);\n }\n return server.close();\n };\n }\n\n return bridgeCaller(prop);\n },\n }) as ChromeExtensionPageCliSide;\n};\n\nexport class AgentOverChromeBridge extends PageAgent<ChromeExtensionPageCliSide> {\n private destroyAfterDisconnectFlag?: boolean;\n\n constructor(\n opts?: PageAgentOpt & {\n closeNewTabsAfterDisconnect?: boolean;\n serverListeningTimeout?: number | false;\n closeConflictServer?: boolean;\n },\n ) {\n const page = getBridgePageInCliSide(opts?.serverListeningTimeout);\n super(\n page,\n Object.assign(opts || {}, {\n onTaskStartTip: (tip: string) => {\n this.page.showStatusMessage(tip);\n },\n }),\n );\n this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;\n }\n\n async setDestroyOptionsAfterConnect() {\n if (this.destroyAfterDisconnectFlag) {\n this.page.setDestroyOptions({\n closeTab: true,\n });\n }\n }\n\n async connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions) {\n await this.page.connectNewTabWithUrl(url, options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async getBrowserTabList() {\n return await this.page.getBrowserTabList();\n }\n\n async setActiveTabId(tabId: string) {\n return await this.page.setActiveTabId(Number.parseInt(tabId));\n }\n\n async connectCurrentTab(options?: BridgeConnectTabOptions) {\n await this.page.connectCurrentTab(options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async aiAction(prompt: string, options?: any) {\n if (options) {\n console.warn(\n 'the `options` parameter of aiAction is not supported in cli side',\n );\n }\n return await super.aiAction(prompt);\n }\n\n async destroy(closeNewTabsAfterDisconnect?: boolean) {\n if (typeof closeNewTabsAfterDisconnect === 'boolean') {\n await this.page.setDestroyOptions({\n closeTab: closeNewTabsAfterDisconnect,\n });\n }\n await super.destroy();\n }\n}\n","export const DefaultBridgeServerPort = 3766;\nexport const DefaultLocalEndpoint = `http://127.0.0.1:${DefaultBridgeServerPort}`;\nexport const BridgeCallTimeout = 30000;\n\nexport enum BridgeEvent {\n Call = 'bridge-call',\n CallResponse = 'bridge-call-response',\n UpdateAgentStatus = 'bridge-update-agent-status',\n Message = 'bridge-message',\n Connected = 'bridge-connected',\n Refused = 'bridge-refused',\n ConnectNewTabWithUrl = 'connectNewTabWithUrl',\n ConnectCurrentTab = 'connectCurrentTab',\n GetBrowserTabList = 'getBrowserTabList',\n SetDestroyOptions = 'setDestroyOptions',\n SetActiveTabId = 'setActiveTabId',\n}\n\nexport const BridgeSignalKill = 'MIDSCENE_BRIDGE_SIGNAL_KILL';\n\nexport interface BridgeConnectTabOptions {\n /**\n * If true, the page will always track the active tab.\n * @default true\n */\n forceSameTabNavigation?: boolean;\n}\n\nexport enum MouseEvent {\n PREFIX = 'mouse.',\n Click = 'mouse.click',\n Wheel = 'mouse.wheel',\n Move = 'mouse.move',\n Drag = 'mouse.drag',\n}\n\nexport enum KeyboardEvent {\n PREFIX = 'keyboard.',\n Type = 'keyboard.type',\n Press = 'keyboard.press',\n}\n\nexport const BridgePageType = 'page-over-chrome-extension-bridge';\n\nexport const BridgeErrorCodeNoClientConnected = 'no-client-connected';\n\nexport interface BridgeCall {\n method: string;\n args: any[];\n response: any;\n callTime: number;\n responseTime: number;\n callback: (error: Error | undefined, response: any) => void;\n error?: Error;\n}\n\nexport interface BridgeCallRequest {\n id: string;\n method: string;\n args: any[];\n}\n\nexport interface BridgeCallResponse {\n id: string;\n response: any;\n error?: any;\n}\n\nexport interface BridgeConnectedEventPayload {\n version: string;\n}\n","import { sleep } from '@midscene/core/utils';\nimport { logMsg } from '@midscene/shared/utils';\nimport { Server, type Socket as ServerSocket } from 'socket.io';\nimport { io as ClientIO, type Socket as ClientSocket } from 'socket.io-client';\n\nimport {\n type BridgeCall,\n type BridgeCallResponse,\n BridgeCallTimeout,\n type BridgeConnectedEventPayload,\n BridgeErrorCodeNoClientConnected,\n BridgeEvent,\n BridgeSignalKill,\n DefaultBridgeServerPort,\n} from './common';\n\ndeclare const __VERSION__: string;\n\nexport const killRunningServer = async (port?: number) => {\n try {\n const client = ClientIO(\n `ws://localhost:${port || DefaultBridgeServerPort}`,\n {\n query: {\n [BridgeSignalKill]: 1,\n },\n },\n );\n await sleep(100);\n await client.close();\n } catch (e) {\n // console.error('failed to kill port', e);\n }\n};\n\n// ws server, this is where the request is sent\nexport class BridgeServer {\n private callId = 0;\n private io: Server | null = null;\n private socket: ServerSocket | null = null;\n private listeningTimeoutId: NodeJS.Timeout | null = null;\n private listeningTimerFlag = false;\n private connectionTipTimer: NodeJS.Timeout | null = null;\n public calls: Record<string, BridgeCall> = {};\n\n private connectionLost = false;\n private connectionLostReason = '';\n\n constructor(\n public port: number,\n public onConnect?: () => void,\n public onDisconnect?: (reason: string) => void,\n public closeConflictServer?: boolean,\n ) {}\n\n async listen(\n opts: {\n timeout?: number | false;\n } = {},\n ): Promise<void> {\n const { timeout = 30000 } = opts;\n\n if (this.closeConflictServer) {\n await killRunningServer(this.port);\n }\n\n return new Promise((resolve, reject) => {\n if (this.listeningTimerFlag) {\n return reject(new Error('already listening'));\n }\n this.listeningTimerFlag = true;\n\n this.listeningTimeoutId = timeout\n ? setTimeout(() => {\n reject(\n new Error(\n `no extension connected after ${timeout}ms (${BridgeErrorCodeNoClientConnected})`,\n ),\n );\n }, timeout)\n : null;\n\n this.connectionTipTimer =\n !timeout || timeout > 3000\n ? setTimeout(() => {\n logMsg('waiting for bridge to connect...');\n }, 2000)\n : null;\n this.io = new Server(this.port, {\n maxHttpBufferSize: 100 * 1024 * 1024, // 100MB\n });\n\n // Listen for the native HTTP server 'listening' event\n this.io.httpServer.once('listening', () => {\n resolve();\n });\n\n this.io.httpServer.once('error', (err: Error) => {\n reject(new Error(`Bridge Listening Error: ${err.message}`));\n });\n\n this.io.use((socket, next) => {\n if (this.socket) {\n next(new Error('server already connected by another client'));\n }\n next();\n });\n\n this.io.on('connection', (socket) => {\n // check the connection url\n const url = socket.handshake.url;\n if (url.includes(BridgeSignalKill)) {\n console.warn('kill signal received, closing bridge server');\n return this.close();\n }\n\n this.connectionLost = false;\n this.connectionLostReason = '';\n this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);\n this.listeningTimeoutId = null;\n this.connectionTipTimer && clearTimeout(this.connectionTipTimer);\n this.connectionTipTimer = null;\n if (this.socket) {\n socket.emit(BridgeEvent.Refused);\n // close the socket\n socket.disconnect();\n\n return reject(\n new Error('server already connected by another client'),\n );\n }\n\n try {\n logMsg('one client connected');\n this.socket = socket;\n\n const clientVersion = socket.handshake.query.version;\n logMsg(\n `Bridge connected, cli-side version v${__VERSION__}, browser-side version v${clientVersion}`,\n );\n\n socket.on(BridgeEvent.CallResponse, (params: BridgeCallResponse) => {\n const id = params.id;\n const response = params.response;\n const error = params.error;\n\n this.triggerCallResponseCallback(id, error, response);\n });\n\n socket.on('disconnect', (reason: string) => {\n this.connectionLost = true;\n this.connectionLostReason = reason;\n\n try {\n this.io?.close();\n } catch (e) {\n // ignore\n }\n\n // flush all pending calls as error\n for (const id in this.calls) {\n const call = this.calls[id];\n\n if (!call.responseTime) {\n const errorMessage = this.connectionLostErrorMsg();\n this.triggerCallResponseCallback(\n id,\n new Error(errorMessage),\n null,\n );\n }\n }\n\n this.onDisconnect?.(reason);\n });\n\n setTimeout(() => {\n this.onConnect?.();\n\n const payload = {\n version: __VERSION__,\n } as BridgeConnectedEventPayload;\n socket.emit(BridgeEvent.Connected, payload);\n Promise.resolve().then(() => {\n for (const id in this.calls) {\n if (this.calls[id].callTime === 0) {\n this.emitCall(id);\n }\n }\n });\n }, 0);\n } catch (e) {\n console.error('failed to handle connection event', e);\n reject(e);\n }\n });\n\n this.io.on('close', () => {\n this.close();\n });\n });\n }\n\n private connectionLostErrorMsg = () => {\n return `Connection lost, reason: ${this.connectionLostReason}`;\n };\n\n private async triggerCallResponseCallback(\n id: string | number,\n error: Error | null,\n response: any,\n ) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n call.error = error || undefined;\n call.response = response;\n call.responseTime = Date.now();\n\n call.callback(call.error, response);\n }\n\n private async emitCall(id: string) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n\n if (this.connectionLost) {\n const message = `Connection lost, reason: ${this.connectionLostReason}`;\n call.callback(new Error(message), null);\n return;\n }\n\n if (this.socket) {\n this.socket.emit(BridgeEvent.Call, {\n id,\n method: call.method,\n args: call.args,\n });\n call.callTime = Date.now();\n }\n }\n\n async call<T = any>(\n method: string,\n args: any[],\n timeout = BridgeCallTimeout,\n ): Promise<T> {\n const id = `${this.callId++}`;\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n logMsg(`bridge call timeout, id=${id}, method=${method}, args=`, args);\n this.calls[id].error = new Error(\n `Bridge call timeout after ${timeout}ms: ${method}`,\n );\n reject(this.calls[id].error);\n }, timeout);\n\n this.calls[id] = {\n method,\n args,\n response: null,\n callTime: 0,\n responseTime: 0,\n callback: (error: Error | undefined, response: any) => {\n clearTimeout(timeoutId);\n if (error) {\n reject(error);\n } else {\n resolve(response);\n }\n },\n };\n\n this.emitCall(id);\n });\n }\n\n // do NOT restart after close\n async close() {\n this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);\n this.connectionTipTimer && clearTimeout(this.connectionTipTimer);\n const closeProcess = this.io?.close();\n this.io = null;\n\n return closeProcess;\n }\n}\n","import { AgentOverChromeBridge } from './agent-cli-side';\n\nexport { AgentOverChromeBridge };\n\nexport { overrideAIConfig, allConfigFromEnv } from '@midscene/shared/env';\n\nexport { killRunningServer } from './io-server';\n"]}
1
+ {"version":3,"mappings":"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","names":["resolve","assert","yaml","stringifyDumpData","writeLogFile","vlLocateMode","getDebug","resizeImgBase64","existsSync","join","getMidsceneRunSubDir","ifInBrowser","debug","plan","log","sleep","locatePlan","logMsg"],"ignoreList":[],"sources":["../../src/common/agent.ts","../../src/yaml/player.ts","../../src/yaml/builder.ts","../../src/yaml/utils.ts","../../src/common/tasks.ts","../../src/common/task-cache.ts","../../src/common/utils.ts","../../src/web-element.ts","../../src/common/ui-utils.ts","../../src/common/plan-builder.ts","../../src/bridge-mode/agent-cli-side.ts","../../src/bridge-mode/common.ts","../../src/bridge-mode/io-server.ts","../../src/bridge-mode/index.ts"],"sourcesContent":["import type { WebPage } from '@/common/page';\nimport {\n type AgentAssertOpt,\n type AgentWaitForOpt,\n type ExecutionDump,\n type ExecutionTask,\n type Executor,\n type GroupedActionDump,\n Insight,\n type InsightAction,\n type LocateOption,\n type LocateResultElement,\n type OnTaskStartTip,\n type PlanningActionParamScroll,\n} from '@midscene/core';\n\nimport { ScriptPlayer, parseYamlScript } from '@/yaml/index';\nimport {\n groupedActionDumpFileExt,\n reportHTMLContent,\n stringifyDumpData,\n writeLogFile,\n} from '@midscene/core/utils';\nimport {\n DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT,\n DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,\n} from '@midscene/shared/constants';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { PageTaskExecutor } from '../common/tasks';\nimport type { PuppeteerWebPage } from '../puppeteer';\nimport type { WebElementInfo } from '../web-element';\nimport { buildPlans } from './plan-builder';\nimport type { AiTaskCache } from './task-cache';\nimport {\n locateParamStr,\n paramStr,\n scrollParamStr,\n taskTitleStr,\n typeStr,\n} from './ui-utils';\nimport { printReportMsg, reportFileName } from './utils';\nimport { type WebUIContext, parseContextFromWebPage } from './utils';\n\nconst debug = getDebug('web-integration');\n\nexport interface PageAgentOpt {\n forceSameTabNavigation?: boolean /* if limit the new tab to the current page, default true */;\n testId?: string;\n cacheId?: string;\n groupName?: string;\n groupDescription?: string;\n cache?: AiTaskCache;\n /* if auto generate report, default true */\n generateReport?: boolean;\n /* if auto print report msg, default true */\n autoPrintReportMsg?: boolean;\n onTaskStartTip?: OnTaskStartTip;\n aiActionContext?: string;\n waitForNavigationTimeout?: number;\n waitForNetworkIdleTimeout?: number;\n}\n\nexport class PageAgent<PageType extends WebPage = WebPage> {\n page: PageType;\n\n insight: Insight<WebElementInfo, WebUIContext>;\n\n dump: GroupedActionDump;\n\n reportFile?: string | null;\n\n reportFileName?: string;\n\n taskExecutor: PageTaskExecutor;\n\n opts: PageAgentOpt;\n\n /**\n * If true, the agent will not perform any actions\n */\n dryMode = false;\n\n onTaskStartTip?: OnTaskStartTip;\n\n constructor(page: PageType, opts?: PageAgentOpt) {\n this.page = page;\n this.opts = Object.assign(\n {\n generateReport: true,\n autoPrintReportMsg: true,\n groupName: 'Midscene Report',\n groupDescription: '',\n },\n opts || {},\n );\n\n if (\n this.page.pageType === 'puppeteer' ||\n this.page.pageType === 'playwright'\n ) {\n (this.page as PuppeteerWebPage).waitForNavigationTimeout =\n this.opts.waitForNavigationTimeout ||\n DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;\n (this.page as PuppeteerWebPage).waitForNetworkIdleTimeout =\n this.opts.waitForNetworkIdleTimeout ||\n DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;\n }\n\n this.onTaskStartTip = this.opts.onTaskStartTip;\n // get the parent browser of the puppeteer page\n // const browser = (this.page as PuppeteerWebPage).browser();\n\n this.insight = new Insight<WebElementInfo, WebUIContext>(\n async (action: InsightAction) => {\n return this.getUIContext(action);\n },\n );\n\n this.taskExecutor = new PageTaskExecutor(this.page, this.insight, {\n cacheId: opts?.cacheId,\n onTaskStart: this.callbackOnTaskStartTip.bind(this),\n });\n this.dump = this.resetDump();\n this.reportFileName = reportFileName(\n opts?.testId || this.page.pageType || 'web',\n );\n }\n\n async getUIContext(action?: InsightAction): Promise<WebUIContext> {\n if (action && (action === 'extract' || action === 'assert')) {\n return await parseContextFromWebPage(this.page, {\n ignoreMarker: true,\n });\n }\n return await parseContextFromWebPage(this.page, {\n ignoreMarker: !!vlLocateMode(),\n });\n }\n\n async setAIActionContext(prompt: string) {\n this.opts.aiActionContext = prompt;\n }\n\n resetDump() {\n this.dump = {\n groupName: this.opts.groupName!,\n groupDescription: this.opts.groupDescription,\n executions: [],\n };\n\n return this.dump;\n }\n\n appendExecutionDump(execution: ExecutionDump) {\n const currentDump = this.dump;\n currentDump.executions.push(execution);\n }\n\n dumpDataString() {\n // update dump info\n this.dump.groupName = this.opts.groupName!;\n this.dump.groupDescription = this.opts.groupDescription;\n return stringifyDumpData(this.dump);\n }\n\n reportHTMLString() {\n return reportHTMLContent(this.dumpDataString());\n }\n\n writeOutActionDumps() {\n const { generateReport, autoPrintReportMsg } = this.opts;\n this.reportFile = writeLogFile({\n fileName: this.reportFileName!,\n fileExt: groupedActionDumpFileExt,\n fileContent: this.dumpDataString(),\n type: 'dump',\n generateReport,\n });\n debug('writeOutActionDumps', this.reportFile);\n if (generateReport && autoPrintReportMsg && this.reportFile) {\n printReportMsg(this.reportFile);\n }\n }\n\n private async callbackOnTaskStartTip(task: ExecutionTask) {\n const param = paramStr(task);\n const tip = param ? `${typeStr(task)} - ${param}` : typeStr(task);\n if (this.onTaskStartTip) {\n await this.onTaskStartTip(tip);\n }\n }\n\n private afterTaskRunning(executor: Executor, doNotThrowError = false) {\n this.appendExecutionDump(executor.dump());\n this.writeOutActionDumps();\n\n if (executor.isInErrorState() && !doNotThrowError) {\n const errorTask = executor.latestErrorTask();\n throw new Error(`${errorTask?.error}\\n${errorTask?.errorStack}`);\n }\n }\n\n private buildDetailedLocateParam(locatePrompt: string, opt?: LocateOption) {\n assert(locatePrompt, 'missing locate prompt');\n if (typeof opt === 'object') {\n return {\n prompt: locatePrompt,\n ...opt,\n };\n }\n return {\n prompt: locatePrompt,\n };\n }\n\n async aiTap(locatePrompt: string, opt?: LocateOption) {\n const detailedLocateParam = this.buildDetailedLocateParam(\n locatePrompt,\n opt,\n );\n const plans = buildPlans('Tap', detailedLocateParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Tap', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiHover(locatePrompt: string, opt?: LocateOption) {\n const detailedLocateParam = this.buildDetailedLocateParam(\n locatePrompt,\n opt,\n );\n const plans = buildPlans('Hover', detailedLocateParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Hover', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiInput(value: string, locatePrompt: string, opt?: LocateOption) {\n assert(\n typeof value === 'string',\n 'input value must be a string, use empty string if you want to clear the input',\n );\n assert(locatePrompt, 'missing locate prompt for input');\n const detailedLocateParam = this.buildDetailedLocateParam(\n locatePrompt,\n opt,\n );\n const plans = buildPlans('Input', detailedLocateParam, {\n value,\n });\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Input', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiKeyboardPress(\n keyName: string,\n locatePrompt?: string,\n opt?: LocateOption,\n ) {\n assert(keyName, 'missing keyName for keyboard press');\n const detailedLocateParam = locatePrompt\n ? this.buildDetailedLocateParam(locatePrompt, opt)\n : undefined;\n const plans = buildPlans('KeyboardPress', detailedLocateParam, {\n value: keyName,\n });\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('KeyboardPress', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiScroll(\n scrollParam: PlanningActionParamScroll,\n locatePrompt?: string,\n opt?: LocateOption,\n ) {\n const detailedLocateParam = locatePrompt\n ? this.buildDetailedLocateParam(locatePrompt, opt)\n : undefined;\n const plans = buildPlans('Scroll', detailedLocateParam, scrollParam);\n const paramInTitle = locatePrompt\n ? `${locateParamStr(detailedLocateParam)} - ${scrollParamStr(scrollParam)}`\n : scrollParamStr(scrollParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Scroll', paramInTitle),\n plans,\n );\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiAction(taskPrompt: string) {\n const { output, executor } = await (vlLocateMode() === 'vlm-ui-tars'\n ? this.taskExecutor.actionToGoal(taskPrompt)\n : this.taskExecutor.action(taskPrompt, this.opts.aiActionContext));\n\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiQuery(demand: any) {\n const { output, executor } = await this.taskExecutor.query(demand);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiBoolean(prompt: string) {\n const { output, executor } = await this.taskExecutor.boolean(prompt);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiNumber(prompt: string) {\n const { output, executor } = await this.taskExecutor.number(prompt);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiString(prompt: string) {\n const { output, executor } = await this.taskExecutor.string(prompt);\n this.afterTaskRunning(executor);\n return output;\n }\n\n async aiLocate(prompt: string, opt?: LocateOption) {\n const detailedLocateParam = this.buildDetailedLocateParam(prompt, opt);\n const plans = buildPlans('Locate', detailedLocateParam);\n const { executor, output } = await this.taskExecutor.runPlans(\n taskTitleStr('Locate', locateParamStr(detailedLocateParam)),\n plans,\n );\n this.afterTaskRunning(executor);\n\n const { element } = output;\n\n return {\n rect: element?.rect,\n center: element?.center,\n } as Pick<LocateResultElement, 'rect' | 'center'>;\n }\n\n async aiAssert(assertion: string, msg?: string, opt?: AgentAssertOpt) {\n const { output, executor } = await this.taskExecutor.assert(assertion);\n this.afterTaskRunning(executor, true);\n\n if (output && opt?.keepRawResponse) {\n return output;\n }\n\n if (!output?.pass) {\n const errMsg = msg || `Assertion failed: ${assertion}`;\n const reasonMsg = `Reason: ${\n output?.thought || executor.latestErrorTask()?.error || '(no_reason)'\n }`;\n throw new Error(`${errMsg}\\n${reasonMsg}`);\n }\n }\n\n async aiWaitFor(assertion: string, opt?: AgentWaitForOpt) {\n const { executor } = await this.taskExecutor.waitFor(assertion, {\n timeoutMs: opt?.timeoutMs || 15 * 1000,\n checkIntervalMs: opt?.checkIntervalMs || 3 * 1000,\n assertion,\n });\n this.appendExecutionDump(executor.dump());\n this.writeOutActionDumps();\n\n if (executor.isInErrorState()) {\n const errorTask = executor.latestErrorTask();\n throw new Error(`${errorTask?.error}\\n${errorTask?.errorStack}`);\n }\n }\n\n async ai(taskPrompt: string, type = 'action') {\n if (type === 'action') {\n return this.aiAction(taskPrompt);\n }\n if (type === 'query') {\n return this.aiQuery(taskPrompt);\n }\n\n if (type === 'assert') {\n return this.aiAssert(taskPrompt);\n }\n\n if (type === 'tap') {\n return this.aiTap(taskPrompt);\n }\n\n throw new Error(\n `Unknown type: ${type}, only support 'action', 'query', 'assert', 'tap'`,\n );\n }\n\n async runYaml(yamlScriptContent: string): Promise<{\n result: Record<string, any>;\n }> {\n const script = parseYamlScript(yamlScriptContent, 'yaml', true);\n const player = new ScriptPlayer(script, async (target) => {\n return { agent: this, freeFn: [] };\n });\n await player.run();\n\n if (player.status === 'error') {\n const errors = player.taskStatusList\n .filter((task) => task.status === 'error')\n .map((task) => {\n return `task - ${task.name}: ${task.error?.message}`;\n })\n .join('\\n');\n throw new Error(`Error(s) occurred in running yaml script:\\n${errors}`);\n }\n\n return {\n result: player.result,\n };\n }\n\n async evaluateJavaScript(script: string) {\n assert(\n this.page.evaluateJavaScript,\n 'evaluateJavaScript is not supported in current agent',\n );\n return this.page.evaluateJavaScript(script);\n }\n\n async destroy() {\n await this.page.destroy();\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { assert, ifInBrowser } from '@midscene/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 MidsceneYamlFlowItemAIScroll,\n MidsceneYamlFlowItemAITap,\n MidsceneYamlFlowItemAIWaitFor,\n MidsceneYamlFlowItemEvaluateJavaScript,\n MidsceneYamlFlowItemSleep,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n} from '@midscene/core';\nimport { getMidsceneRunSubDir } from '@midscene/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 if (ifInBrowser) {\n this.output = undefined;\n } else if (script.target?.output) {\n this.output = resolve(process.cwd(), script.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 (flowItem as MidsceneYamlFlowItemAIAction).aiAction ||\n (flowItem as MidsceneYamlFlowItemAIAction).ai\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 } else if ((flowItem as MidsceneYamlFlowItemAIAssert).aiAssert) {\n const assertTask = flowItem as MidsceneYamlFlowItemAIAssert;\n const prompt = assertTask.aiAssert;\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);\n } else if ((flowItem as MidsceneYamlFlowItemAIQuery).aiQuery) {\n const queryTask = flowItem as MidsceneYamlFlowItemAIQuery;\n const prompt = queryTask.aiQuery;\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 ((flowItem as MidsceneYamlFlowItemAINumber).aiNumber) {\n const numberTask = flowItem as MidsceneYamlFlowItemAINumber;\n const prompt = numberTask.aiNumber;\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 ((flowItem as MidsceneYamlFlowItemAINString).aiString) {\n const stringTask = flowItem as MidsceneYamlFlowItemAINString;\n const prompt = stringTask.aiString;\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 ((flowItem as MidsceneYamlFlowItemAIBoolean).aiBoolean) {\n const booleanTask = flowItem as MidsceneYamlFlowItemAIBoolean;\n const prompt = booleanTask.aiBoolean;\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 ((flowItem as MidsceneYamlFlowItemAILocate).aiLocate) {\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 ((flowItem as MidsceneYamlFlowItemAIWaitFor).aiWaitFor) {\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 ((flowItem as MidsceneYamlFlowItemSleep).sleep) {\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 ((flowItem as MidsceneYamlFlowItemAITap).aiTap) {\n const tapTask = flowItem as MidsceneYamlFlowItemAITap;\n await agent.aiTap(tapTask.aiTap, tapTask);\n } else if ((flowItem as MidsceneYamlFlowItemAIHover).aiHover) {\n const hoverTask = flowItem as MidsceneYamlFlowItemAIHover;\n await agent.aiHover(hoverTask.aiHover, hoverTask);\n } else if ((flowItem as MidsceneYamlFlowItemAIInput).aiInput) {\n const inputTask = flowItem as MidsceneYamlFlowItemAIInput;\n await agent.aiInput(inputTask.aiInput, inputTask.locate, inputTask);\n } else if (\n (flowItem as MidsceneYamlFlowItemAIKeyboardPress).aiKeyboardPress\n ) {\n const keyboardPressTask =\n flowItem as MidsceneYamlFlowItemAIKeyboardPress;\n await agent.aiKeyboardPress(\n keyboardPressTask.aiKeyboardPress,\n keyboardPressTask.locate,\n keyboardPressTask,\n );\n } else if (\n typeof (flowItem as MidsceneYamlFlowItemAIScroll).aiScroll !==\n 'undefined'\n ) {\n const scrollTask = flowItem as MidsceneYamlFlowItemAIScroll;\n await agent.aiScroll(scrollTask, scrollTask.locate, scrollTask);\n } else if (\n typeof (flowItem as MidsceneYamlFlowItemEvaluateJavaScript)\n .javascript !== 'undefined'\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 {\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 agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') {\n this.agentStatusTip = tip;\n }\n };\n freeFn = newFreeFn;\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 '@midscene/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 '@midscene/shared/utils';\nimport yaml from 'js-yaml';\n\nimport type { MidsceneYamlScript } from '@midscene/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 const interpolatedContent = interpolateEnvVars(content);\n const obj = yaml.load(interpolatedContent) as MidsceneYamlScript;\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","import type { AndroidDevicePage, WebPage } from '@/common/page';\nimport type { PuppeteerWebPage } from '@/puppeteer';\nimport {\n type AIUsageInfo,\n type DumpSubscriber,\n type ExecutionRecorderItem,\n type ExecutionTaskActionApply,\n type ExecutionTaskApply,\n type ExecutionTaskInsightLocateApply,\n type ExecutionTaskInsightQueryApply,\n type ExecutionTaskPlanningApply,\n type ExecutionTaskProgressOptions,\n Executor,\n type Insight,\n type InsightAssertionResponse,\n type InsightDump,\n type InsightExtractParam,\n type PageType,\n type PlanningAIResponse,\n type PlanningAction,\n type PlanningActionParamAssert,\n type PlanningActionParamError,\n type PlanningActionParamHover,\n type PlanningActionParamInputOrKeyPress,\n type PlanningActionParamScroll,\n type PlanningActionParamSleep,\n type PlanningActionParamTap,\n type PlanningActionParamWaitFor,\n plan,\n} from '@midscene/core';\nimport {\n type ChatCompletionMessageParam,\n vlmPlanning,\n} from '@midscene/core/ai-model';\nimport { sleep } from '@midscene/core/utils';\n\nimport { UITarsModelVersion } from '@midscene/shared/env';\nimport { uiTarsModelVersion } from '@midscene/shared/env';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { imageInfo, resizeImgBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { WebElementInfo } from '../web-element';\nimport { TaskCache } from './task-cache';\nimport { getKeyCommands, taskTitleStr } from './ui-utils';\nimport type { WebUIContext } from './utils';\n\ninterface ExecutionResult<OutputType = any> {\n output: OutputType;\n executor: Executor;\n}\n\nconst debug = getDebug('page-task-executor');\n\nconst replanningCountLimit = 10;\n\nconst isAndroidPage = (page: WebPage): page is AndroidDevicePage => {\n return page.pageType === 'android';\n};\n\nexport class PageTaskExecutor {\n page: WebPage;\n\n insight: Insight<WebElementInfo, WebUIContext>;\n\n taskCache: TaskCache;\n\n conversationHistory: ChatCompletionMessageParam[] = [];\n\n onTaskStartCallback?: ExecutionTaskProgressOptions['onTaskStart'];\n\n constructor(\n page: WebPage,\n insight: Insight<WebElementInfo, WebUIContext>,\n opts: {\n cacheId: string | undefined;\n onTaskStart?: ExecutionTaskProgressOptions['onTaskStart'];\n },\n ) {\n this.page = page;\n this.insight = insight;\n\n this.taskCache = new TaskCache({\n cacheId: opts?.cacheId,\n });\n\n this.onTaskStartCallback = opts?.onTaskStart;\n }\n\n private async recordScreenshot(timing: ExecutionRecorderItem['timing']) {\n const base64 = await this.page.screenshotBase64();\n const item: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: Date.now(),\n screenshot: base64,\n timing,\n };\n return item;\n }\n\n private prependExecutorWithScreenshot(\n taskApply: ExecutionTaskApply,\n appendAfterExecution = false,\n ): ExecutionTaskApply {\n const taskWithScreenshot: ExecutionTaskApply = {\n ...taskApply,\n executor: async (param, context, ...args) => {\n const recorder: ExecutionRecorderItem[] = [];\n const { task } = context;\n // set the recorder before executor in case of error\n task.recorder = recorder;\n const shot = await this.recordScreenshot(`before ${task.type}`);\n recorder.push(shot);\n const result = await taskApply.executor(param, context, ...args);\n if (taskApply.type === 'Action') {\n await Promise.all([\n (async () => {\n await sleep(100);\n if ((this.page as PuppeteerWebPage).waitUntilNetworkIdle) {\n try {\n await (this.page as PuppeteerWebPage).waitUntilNetworkIdle();\n } catch (error) {\n // console.error('waitUntilNetworkIdle error', error);\n }\n }\n })(),\n sleep(200),\n ]);\n }\n if (appendAfterExecution) {\n const shot2 = await this.recordScreenshot('after Action');\n recorder.push(shot2);\n }\n return result;\n },\n };\n return taskWithScreenshot;\n }\n\n private async convertPlanToExecutable(\n plans: PlanningAction[],\n cacheGroup?: ReturnType<TaskCache['getCacheGroupByPrompt']>,\n ) {\n const tasks: ExecutionTaskApply[] = [];\n plans.forEach((plan) => {\n if (plan.type === 'Locate') {\n if (\n plan.locate === null ||\n plan.locate?.id === null ||\n plan.locate?.id === 'null'\n ) {\n // console.warn('Locate action with id is null, will be ignored');\n return;\n }\n const taskFind: ExecutionTaskInsightLocateApply = {\n type: 'Insight',\n subType: 'Locate',\n param: plan.locate || undefined,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param, taskContext) => {\n const { task } = taskContext;\n assert(\n param?.prompt || param?.id || param?.bbox,\n 'No prompt or id or position or bbox to locate',\n );\n let insightDump: InsightDump | undefined;\n let usage: AIUsageInfo | undefined;\n const dumpCollector: DumpSubscriber = (dump) => {\n insightDump = dump;\n usage = dump?.taskInfo?.usage;\n\n task.log = {\n dump: insightDump,\n };\n\n task.usage = usage;\n };\n this.insight.onceDumpUpdatedFn = dumpCollector;\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('locate');\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before locate',\n };\n task.recorder = [recordItem];\n\n const cachePrompt = param.prompt;\n const locateCache = cacheGroup?.matchCache(\n pageContext,\n 'locate',\n cachePrompt,\n );\n const idInCache = locateCache?.elements?.[0]?.id;\n let cacheHitFlag = false;\n\n let quickAnswerId = param?.id;\n if (!quickAnswerId && idInCache) {\n quickAnswerId = idInCache;\n }\n\n const quickAnswer = {\n id: quickAnswerId,\n bbox: param?.bbox,\n };\n const startTime = Date.now();\n const { element } = await this.insight.locate(param, {\n quickAnswer,\n });\n const aiCost = Date.now() - startTime;\n\n if (element && element.id === quickAnswerId && idInCache) {\n cacheHitFlag = true;\n }\n\n if (element) {\n cacheGroup?.saveCache({\n type: 'locate',\n pageContext: {\n url: pageContext.url,\n size: pageContext.size,\n },\n prompt: cachePrompt,\n response: {\n elements: [\n {\n id: element.id,\n },\n ],\n },\n element,\n });\n }\n if (!element) {\n throw new Error(`Element not found: ${param.prompt}`);\n }\n\n return {\n output: {\n element,\n },\n pageContext,\n cache: {\n hit: cacheHitFlag,\n },\n aiCost,\n };\n },\n };\n tasks.push(taskFind);\n } else if (plan.type === 'Assert' || plan.type === 'AssertWithoutThrow') {\n const assertPlan = plan as PlanningAction<PlanningActionParamAssert>;\n const taskAssert: ExecutionTaskApply = {\n type: 'Insight',\n subType: 'Assert',\n param: assertPlan.param,\n thought: assertPlan.thought,\n locate: assertPlan.locate,\n executor: async (param, taskContext) => {\n const { task } = taskContext;\n let insightDump: InsightDump | undefined;\n const dumpCollector: DumpSubscriber = (dump) => {\n insightDump = dump;\n };\n this.insight.onceDumpUpdatedFn = dumpCollector;\n const assertion = await this.insight.assert(\n assertPlan.param.assertion,\n );\n\n if (!assertion.pass) {\n if (plan.type === 'Assert') {\n task.output = assertion;\n task.log = {\n dump: insightDump,\n };\n throw new Error(\n assertion.thought || 'Assertion failed without reason',\n );\n }\n\n task.error = assertion.thought;\n }\n\n return {\n output: assertion,\n log: {\n dump: insightDump,\n },\n usage: assertion.usage,\n };\n },\n };\n tasks.push(taskAssert);\n } else if (plan.type === 'Input') {\n const taskActionInput: ExecutionTaskActionApply<PlanningActionParamInputOrKeyPress> =\n {\n type: 'Action',\n subType: 'Input',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam, { element }) => {\n if (element) {\n await this.page.clearInput(element as ElementInfo);\n\n if (!taskParam || !taskParam.value) {\n return;\n }\n\n await this.page.keyboard.type(taskParam.value);\n } else {\n await this.page.keyboard.type(taskParam.value);\n }\n },\n };\n tasks.push(taskActionInput);\n } else if (plan.type === 'KeyboardPress') {\n const taskActionKeyboardPress: ExecutionTaskActionApply<PlanningActionParamInputOrKeyPress> =\n {\n type: 'Action',\n subType: 'KeyboardPress',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam) => {\n const keys = getKeyCommands(taskParam.value);\n\n await this.page.keyboard.press(keys);\n },\n };\n tasks.push(taskActionKeyboardPress);\n } else if (plan.type === 'Tap') {\n const taskActionTap: ExecutionTaskActionApply<PlanningActionParamTap> =\n {\n type: 'Action',\n subType: 'Tap',\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param, { element }) => {\n assert(element, 'Element not found, cannot tap');\n await this.page.mouse.click(element.center[0], element.center[1]);\n },\n };\n tasks.push(taskActionTap);\n } else if (plan.type === 'Drag') {\n const taskActionDrag: ExecutionTaskActionApply<{\n start_box: { x: number; y: number };\n end_box: { x: number; y: number };\n }> = {\n type: 'Action',\n subType: 'Drag',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam) => {\n assert(\n taskParam?.start_box && taskParam?.end_box,\n 'No start_box or end_box to drag',\n );\n await this.page.mouse.drag(taskParam.start_box, taskParam.end_box);\n },\n };\n tasks.push(taskActionDrag);\n } else if (plan.type === 'Hover') {\n const taskActionHover: ExecutionTaskActionApply<PlanningActionParamHover> =\n {\n type: 'Action',\n subType: 'Hover',\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param, { element }) => {\n assert(element, 'Element not found, cannot hover');\n await this.page.mouse.move(element.center[0], element.center[1]);\n },\n };\n tasks.push(taskActionHover);\n } else if (plan.type === 'Scroll') {\n const taskActionScroll: ExecutionTaskActionApply<PlanningActionParamScroll> =\n {\n type: 'Action',\n subType: 'Scroll',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam, { element }) => {\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = taskParam?.scrollType;\n if (scrollToEventName === 'untilTop') {\n await this.page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'untilBottom') {\n await this.page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'untilRight') {\n await this.page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'untilLeft') {\n await this.page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'once' || !scrollToEventName) {\n if (\n taskParam?.direction === 'down' ||\n !taskParam ||\n !taskParam.direction\n ) {\n await this.page.scrollDown(\n taskParam?.distance || undefined,\n startingPoint,\n );\n } else if (taskParam.direction === 'up') {\n await this.page.scrollUp(\n taskParam.distance || undefined,\n startingPoint,\n );\n } else if (taskParam.direction === 'left') {\n await this.page.scrollLeft(\n taskParam.distance || undefined,\n startingPoint,\n );\n } else if (taskParam.direction === 'right') {\n await this.page.scrollRight(\n taskParam.distance || undefined,\n startingPoint,\n );\n } else {\n throw new Error(\n `Unknown scroll direction: ${taskParam.direction}`,\n );\n }\n // until mouse event is done\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, taskParam: ${JSON.stringify(\n taskParam,\n )}`,\n );\n }\n },\n };\n tasks.push(taskActionScroll);\n } else if (plan.type === 'Sleep') {\n const taskActionSleep: ExecutionTaskActionApply<PlanningActionParamSleep> =\n {\n type: 'Action',\n subType: 'Sleep',\n param: plan.param,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (taskParam) => {\n await sleep(taskParam?.timeMs || 3000);\n },\n };\n tasks.push(taskActionSleep);\n } else if (plan.type === 'Error') {\n const taskActionError: ExecutionTaskActionApply<PlanningActionParamError> =\n {\n type: 'Action',\n subType: 'Error',\n param: plan.param,\n thought: plan.thought || plan.param?.thought,\n locate: plan.locate,\n executor: async () => {\n throw new Error(\n plan?.thought || plan.param?.thought || 'error without thought',\n );\n },\n };\n tasks.push(taskActionError);\n } else if (plan.type === 'ExpectedFalsyCondition') {\n const taskActionFalsyConditionStatement: ExecutionTaskActionApply<null> =\n {\n type: 'Action',\n subType: 'ExpectedFalsyCondition',\n param: null,\n thought: plan.param?.reason,\n locate: plan.locate,\n executor: async () => {\n // console.warn(`[warn]falsy condition: ${plan.thought}`);\n },\n };\n tasks.push(taskActionFalsyConditionStatement);\n } else if (plan.type === 'Finished') {\n const taskActionFinished: ExecutionTaskActionApply<null> = {\n type: 'Action',\n subType: 'Finished',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {},\n };\n tasks.push(taskActionFinished);\n } else if (plan.type === 'AndroidHomeButton') {\n const taskActionAndroidHomeButton: ExecutionTaskActionApply<null> = {\n type: 'Action',\n subType: 'AndroidHomeButton',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {\n // Check if the page has back method (Android devices)\n assert(\n isAndroidPage(this.page),\n 'Cannot use home button on non-Android devices',\n );\n await this.page.home();\n },\n };\n tasks.push(taskActionAndroidHomeButton);\n } else if (plan.type === 'AndroidBackButton') {\n const taskActionAndroidBackButton: ExecutionTaskActionApply<null> = {\n type: 'Action',\n subType: 'AndroidBackButton',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {\n assert(\n isAndroidPage(this.page),\n 'Cannot use back button on non-Android devices',\n );\n await this.page.back();\n },\n };\n tasks.push(taskActionAndroidBackButton);\n } else if (plan.type === 'AndroidRecentAppsButton') {\n const taskActionAndroidRecentAppsButton: ExecutionTaskActionApply<null> =\n {\n type: 'Action',\n subType: 'AndroidRecentAppsButton',\n param: null,\n thought: plan.thought,\n locate: plan.locate,\n executor: async (param) => {\n assert(\n isAndroidPage(this.page),\n 'Cannot use recent apps button on non-Android devices',\n );\n await this.page.recentApps();\n },\n };\n tasks.push(taskActionAndroidRecentAppsButton);\n } else {\n throw new Error(`Unknown or unsupported task type: ${plan.type}`);\n }\n });\n\n const wrappedTasks = tasks.map(\n (task: ExecutionTaskApply, index: number) => {\n if (task.type === 'Action') {\n return this.prependExecutorWithScreenshot(\n task,\n index === tasks.length - 1,\n );\n }\n return task;\n },\n );\n\n return {\n tasks: wrappedTasks,\n };\n }\n\n private planningTaskFromPrompt(\n userInstruction: string,\n cacheGroup: ReturnType<TaskCache['getCacheGroupByPrompt']>,\n log?: string,\n actionContext?: string,\n ) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n locate: null,\n param: {\n userInstruction,\n log,\n },\n executor: async (param, executorContext) => {\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('locate');\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before planning',\n };\n\n executorContext.task.recorder = [recordItem];\n (executorContext.task as any).pageContext = pageContext;\n\n const cachePrompt = `${param.userInstruction} @ ${param.log || ''}`;\n const planCache = cacheGroup.matchCache(\n pageContext,\n 'plan',\n cachePrompt,\n );\n let planResult: Awaited<ReturnType<typeof plan>>;\n if (planCache) {\n if ('actions' in planCache && Array.isArray(planCache.actions)) {\n planCache.actions = planCache.actions.map((action) => {\n // remove all bbox in actions cache while using\n if (action.locate) {\n // biome-ignore lint/performance/noDelete: intended to remove bbox\n delete action.locate.bbox;\n }\n return action;\n });\n }\n planResult = planCache;\n } else {\n planResult = await plan(param.userInstruction, {\n context: pageContext,\n log: param.log,\n actionContext,\n pageType: this.page.pageType as PageType,\n });\n }\n\n const {\n actions,\n log,\n more_actions_needed_by_instruction,\n error,\n usage,\n rawResponse,\n sleep,\n } = planResult;\n\n let stopCollecting = false;\n let bboxCollected = false;\n let planParsingError = '';\n const finalActions = (actions || []).reduce<PlanningAction[]>(\n (acc, planningAction) => {\n if (stopCollecting) {\n return acc;\n }\n\n if (planningAction.locate) {\n // we only collect bbox once, let qwen re-locate in the following steps\n if (bboxCollected && planningAction.locate.bbox) {\n // biome-ignore lint/performance/noDelete: <explanation>\n delete planningAction.locate.bbox;\n }\n\n if (planningAction.locate.bbox) {\n bboxCollected = true;\n }\n\n acc.push({\n type: 'Locate',\n locate: planningAction.locate,\n param: null,\n thought: planningAction.locate.prompt,\n });\n } else if (\n ['Tap', 'Hover', 'Input'].includes(planningAction.type)\n ) {\n planParsingError = `invalid planning response: ${JSON.stringify(planningAction)}`;\n // should include locate but get null\n stopCollecting = true;\n return acc;\n }\n acc.push(planningAction);\n return acc;\n },\n [],\n );\n\n if (sleep) {\n const timeNow = Date.now();\n const timeRemaining = sleep - (timeNow - shotTime);\n if (timeRemaining > 0) {\n finalActions.push({\n type: 'Sleep',\n param: {\n timeMs: timeRemaining,\n },\n locate: null,\n } as PlanningAction<PlanningActionParamSleep>);\n }\n }\n\n if (finalActions.length === 0) {\n assert(\n !more_actions_needed_by_instruction || sleep,\n error\n ? `Failed to plan: ${error}`\n : planParsingError || 'No plan found',\n );\n }\n\n cacheGroup.saveCache({\n type: 'plan',\n pageContext: {\n url: pageContext.url,\n size: pageContext.size,\n },\n prompt: cachePrompt,\n response: planResult,\n });\n\n return {\n output: {\n actions: finalActions,\n more_actions_needed_by_instruction,\n log,\n },\n cache: {\n hit: Boolean(planCache),\n },\n pageContext,\n recorder: [recordItem],\n usage,\n rawResponse,\n };\n },\n };\n\n return task;\n }\n\n private planningTaskToGoal(\n userInstruction: string,\n cacheGroup: ReturnType<TaskCache['getCacheGroupByPrompt']>,\n ) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n locate: null,\n param: {\n userInstruction,\n },\n executor: async (param, executorContext) => {\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('locate');\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before planning',\n };\n executorContext.task.recorder = [recordItem];\n (executorContext.task as any).pageContext = pageContext;\n\n let imagePayload = pageContext.screenshotBase64;\n if (\n vlLocateMode() === 'vlm-ui-tars' &&\n uiTarsModelVersion() === UITarsModelVersion.V1_5\n ) {\n const size = pageContext.size;\n // const imageInfo = await imageInfoOfBase64(imagePayload);\n debug('ui-tars-v1.5, will check image size', size);\n const currentPixels = size.width * size.height;\n const maxPixels = 16384 * 28 * 28; //\n if (currentPixels > maxPixels) {\n const resizeFactor = Math.sqrt(maxPixels / currentPixels);\n const newWidth = Math.floor(size.width * resizeFactor);\n const newHeight = Math.floor(size.height * resizeFactor);\n debug(\n 'resize image',\n imageInfo,\n 'new width',\n newWidth,\n 'new height',\n newHeight,\n );\n imagePayload = await resizeImgBase64(imagePayload, {\n width: newWidth,\n height: newHeight,\n });\n }\n }\n\n this.appendConversationHistory({\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n },\n },\n ],\n });\n const startTime = Date.now();\n\n const planCache = cacheGroup.matchCache(\n pageContext,\n 'ui-tars-plan',\n userInstruction,\n );\n let planResult: Awaited<ReturnType<typeof vlmPlanning>>;\n if (planCache) {\n planResult = planCache;\n } else {\n planResult = await vlmPlanning({\n userInstruction: param.userInstruction,\n conversationHistory: this.conversationHistory,\n size: pageContext.size,\n });\n }\n cacheGroup.saveCache({\n type: 'ui-tars-plan',\n pageContext: {\n url: pageContext.url,\n size: pageContext.size,\n },\n prompt: userInstruction,\n response: planResult,\n });\n const aiCost = Date.now() - startTime;\n const { actions, action_summary } = planResult;\n this.appendConversationHistory({\n role: 'assistant',\n content: action_summary,\n });\n return {\n output: {\n actions,\n thought: actions[0]?.thought,\n actionType: actions[0].type,\n more_actions_needed_by_instruction: true,\n log: '',\n },\n log: {\n rawResponse: planResult,\n },\n cache: {\n hit: Boolean(planCache),\n },\n aiCost,\n };\n },\n };\n\n return task;\n }\n\n async runPlans(\n title: string,\n plans: PlanningAction[],\n ): Promise<ExecutionResult> {\n const taskExecutor = new Executor(title, {\n onTaskStart: this.onTaskStartCallback,\n });\n const cacheGroup = this.taskCache.getCacheGroupByPrompt(title);\n const { tasks } = await this.convertPlanToExecutable(plans, cacheGroup);\n await taskExecutor.append(tasks);\n const result = await taskExecutor.flush();\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n\n async action(\n userPrompt: string,\n actionContext?: string,\n ): Promise<ExecutionResult> {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n\n const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);\n let planningTask: ExecutionTaskPlanningApply | null =\n this.planningTaskFromPrompt(\n userPrompt,\n cacheGroup,\n undefined,\n actionContext,\n );\n let result: any;\n let replanCount = 0;\n const logList: string[] = [];\n while (planningTask) {\n if (replanCount > replanningCountLimit) {\n const errorMsg =\n 'Replanning too many times, please split the task into multiple steps';\n\n return this.appendErrorPlan(taskExecutor, errorMsg);\n }\n\n // plan\n await taskExecutor.append(planningTask);\n const planResult: PlanningAIResponse = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: planResult,\n executor: taskExecutor,\n };\n }\n\n const plans = planResult.actions || [];\n\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans, cacheGroup);\n taskExecutor.append(executables.tasks);\n } catch (error) {\n return this.appendErrorPlan(\n taskExecutor,\n `Error converting plans to executable tasks: ${error}, plans: ${JSON.stringify(\n plans,\n )}`,\n );\n }\n\n result = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n if (planResult?.log) {\n logList.push(planResult.log);\n }\n\n if (!planResult.more_actions_needed_by_instruction) {\n planningTask = null;\n break;\n }\n planningTask = this.planningTaskFromPrompt(\n userPrompt,\n cacheGroup,\n logList.length > 0 ? `- ${logList.join('\\n- ')}` : undefined,\n actionContext,\n );\n replanCount++;\n }\n\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n\n async actionToGoal(userPrompt: string) {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n this.conversationHistory = [];\n const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);\n const isCompleted = false;\n let currentActionNumber = 0;\n const maxActionNumber = 40;\n\n while (!isCompleted && currentActionNumber < maxActionNumber) {\n currentActionNumber++;\n const planningTask: ExecutionTaskPlanningApply = this.planningTaskToGoal(\n userPrompt,\n cacheGroup,\n );\n await taskExecutor.append(planningTask);\n const output = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: output,\n executor: taskExecutor,\n };\n }\n const plans = output.actions;\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans);\n taskExecutor.append(executables.tasks);\n } catch (error) {\n return this.appendErrorPlan(\n taskExecutor,\n `Error converting plans to executable tasks: ${error}, plans: ${JSON.stringify(\n plans,\n )}`,\n );\n }\n\n const result = await taskExecutor.flush();\n\n if (taskExecutor.isInErrorState()) {\n return {\n output: result,\n executor: taskExecutor,\n };\n }\n\n if (plans[0].type === 'Finished') {\n break;\n }\n }\n return {\n output: {},\n executor: taskExecutor,\n };\n }\n\n private async createTypeQueryTask<T>(\n type: 'Query' | 'Boolean' | 'Number' | 'String',\n demand: InsightExtractParam,\n ): Promise<ExecutionResult<T>> {\n const taskExecutor = new Executor(\n taskTitleStr(\n type,\n typeof demand === 'string' ? demand : JSON.stringify(demand),\n ),\n {\n onTaskStart: this.onTaskStartCallback,\n },\n );\n\n const queryTask: ExecutionTaskInsightQueryApply = {\n type: 'Insight',\n subType: type,\n locate: null,\n param: {\n dataDemand: demand, // for user param presentation in report right sidebar\n },\n executor: async (param) => {\n let insightDump: InsightDump | undefined;\n const dumpCollector: DumpSubscriber = (dump) => {\n insightDump = dump;\n };\n this.insight.onceDumpUpdatedFn = dumpCollector;\n\n const ifTypeRestricted = type !== 'Query';\n let demandInput = demand;\n if (ifTypeRestricted) {\n demandInput = {\n result: `${type}, ${demand}`,\n };\n }\n\n const { data, usage } = await this.insight.extract<any>(demandInput);\n\n let outputResult = data;\n if (ifTypeRestricted) {\n assert(data?.result !== undefined, 'No result in query data');\n outputResult = (data as any).result;\n }\n\n return {\n output: outputResult,\n log: { dump: insightDump },\n usage,\n };\n },\n };\n\n await taskExecutor.append(this.prependExecutorWithScreenshot(queryTask));\n const output = await taskExecutor.flush();\n return {\n output,\n executor: taskExecutor,\n };\n }\n\n async query(demand: InsightExtractParam): Promise<ExecutionResult> {\n return this.createTypeQueryTask('Query', demand);\n }\n\n async boolean(prompt: string): Promise<ExecutionResult<boolean>> {\n return this.createTypeQueryTask<boolean>('Boolean', prompt);\n }\n\n async number(prompt: string): Promise<ExecutionResult<number>> {\n return this.createTypeQueryTask<number>('Number', prompt);\n }\n\n async string(prompt: string): Promise<ExecutionResult<string>> {\n return this.createTypeQueryTask<string>('String', prompt);\n }\n\n async assert(\n assertion: string,\n ): Promise<ExecutionResult<InsightAssertionResponse>> {\n const description = `assert: ${assertion}`;\n const taskExecutor = new Executor(taskTitleStr('Assert', description), {\n onTaskStart: this.onTaskStartCallback,\n });\n const assertionPlan: PlanningAction<PlanningActionParamAssert> = {\n type: 'Assert',\n param: {\n assertion,\n },\n locate: null,\n };\n const { tasks } = await this.convertPlanToExecutable([assertionPlan]);\n\n await taskExecutor.append(this.prependExecutorWithScreenshot(tasks[0]));\n const output: InsightAssertionResponse = await taskExecutor.flush();\n\n return {\n output,\n executor: taskExecutor,\n };\n }\n\n /**\n * Append a message to the conversation history\n * For user messages with images:\n * - Keep max 4 user image messages in history\n * - Remove oldest user image message when limit reached\n * For assistant messages:\n * - Simply append to history\n * @param conversationHistory Message to append\n */\n private appendConversationHistory(\n conversationHistory: ChatCompletionMessageParam,\n ) {\n if (conversationHistory.role === 'user') {\n // Get all existing user messages with images\n const userImgItems = this.conversationHistory.filter(\n (item) => item.role === 'user',\n );\n\n // If we already have 4 user image messages\n if (userImgItems.length >= 4 && conversationHistory.role === 'user') {\n // Remove first user image message when we already have 4, before adding new one\n const firstUserImgIndex = this.conversationHistory.findIndex(\n (item) => item.role === 'user',\n );\n if (firstUserImgIndex >= 0) {\n this.conversationHistory.splice(firstUserImgIndex, 1);\n }\n }\n }\n // For non-user messages, simply append to history\n this.conversationHistory.push(conversationHistory);\n }\n\n private async appendErrorPlan(taskExecutor: Executor, errorMsg: string) {\n const errorPlan: PlanningAction<PlanningActionParamError> = {\n type: 'Error',\n param: {\n thought: errorMsg,\n },\n locate: null,\n };\n const { tasks } = await this.convertPlanToExecutable([errorPlan]);\n await taskExecutor.append(this.prependExecutorWithScreenshot(tasks[0]));\n await taskExecutor.flush();\n\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n\n async waitFor(\n assertion: string,\n opt: PlanningActionParamWaitFor,\n ): Promise<ExecutionResult<void>> {\n const description = `waitFor: ${assertion}`;\n const taskExecutor = new Executor(taskTitleStr('WaitFor', description), {\n onTaskStart: this.onTaskStartCallback,\n });\n const { timeoutMs, checkIntervalMs } = opt;\n\n assert(assertion, 'No assertion for waitFor');\n assert(timeoutMs, 'No timeoutMs for waitFor');\n assert(checkIntervalMs, 'No checkIntervalMs for waitFor');\n\n const overallStartTime = Date.now();\n let startTime = Date.now();\n let errorThought = '';\n while (Date.now() - overallStartTime < timeoutMs) {\n startTime = Date.now();\n const assertPlan: PlanningAction<PlanningActionParamAssert> = {\n type: 'AssertWithoutThrow',\n param: {\n assertion,\n },\n locate: null,\n };\n const { tasks: assertTasks } = await this.convertPlanToExecutable([\n assertPlan,\n ]);\n await taskExecutor.append(\n this.prependExecutorWithScreenshot(assertTasks[0]),\n );\n const output: InsightAssertionResponse = await taskExecutor.flush();\n\n if (output?.pass) {\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n\n errorThought =\n output?.thought ||\n `unknown error when waiting for assertion: ${assertion}`;\n const now = Date.now();\n if (now - startTime < checkIntervalMs) {\n const timeRemaining = checkIntervalMs - (now - startTime);\n const sleepPlan: PlanningAction<PlanningActionParamSleep> = {\n type: 'Sleep',\n param: {\n timeMs: timeRemaining,\n },\n locate: null,\n };\n const { tasks: sleepTasks } = await this.convertPlanToExecutable([\n sleepPlan,\n ]);\n await taskExecutor.append(\n this.prependExecutorWithScreenshot(sleepTasks[0]),\n );\n await taskExecutor.flush();\n }\n }\n\n return this.appendErrorPlan(\n taskExecutor,\n `waitFor timeout: ${errorThought}`,\n );\n }\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type {\n AIElementLocatorResponse,\n LocateResultElement,\n PlanningAIResponse,\n} from '@midscene/core';\nimport type { vlmPlanning } from '@midscene/core/ai-model';\nimport { stringifyDumpData, writeLogFile } from '@midscene/core/utils';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport { getAIConfigInBoolean } from '@midscene/shared/env';\nimport { getRunningPkgInfo } from '@midscene/shared/fs';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport { type WebUIContext, replaceIllegalPathCharsAndSpace } from './utils';\n\nconst debug = getDebug('cache');\n\nexport type PlanTask = {\n type: 'plan';\n prompt: string;\n pageContext: {\n url: string;\n size: {\n width: number;\n height: number;\n };\n };\n response: PlanningAIResponse;\n};\n\nexport type UITarsPlanTask = {\n type: 'ui-tars-plan';\n prompt: string;\n pageContext: {\n url: string;\n size: {\n width: number;\n height: number;\n };\n };\n response: Awaited<ReturnType<typeof vlmPlanning>>;\n};\n\nexport type LocateTask = {\n type: 'locate';\n prompt: string;\n pageContext: {\n url: string;\n size: {\n width: number;\n height: number;\n };\n };\n response: AIElementLocatorResponse;\n element: LocateResultElement;\n};\n\nexport type AiTasks = Array<PlanTask | LocateTask | UITarsPlanTask>;\n\nexport type AiTaskCache = {\n aiTasks: Array<{\n prompt: string;\n tasks: AiTasks;\n }>;\n};\n\nexport type CacheGroup = {\n matchCache: <T extends 'plan' | 'locate' | 'ui-tars-plan'>(\n pageContext: WebUIContext,\n type: T,\n actionPrompt: string,\n ) => T extends 'plan'\n ? PlanTask['response']\n : T extends 'locate'\n ? LocateTask['response']\n : UITarsPlanTask['response'];\n saveCache: (cache: UITarsPlanTask | PlanTask | LocateTask) => void;\n};\n\nexport class TaskCache {\n cache: AiTaskCache;\n\n cacheId: string;\n\n newCache: AiTaskCache;\n\n midscenePkgInfo: ReturnType<typeof getRunningPkgInfo> | null;\n\n constructor(opts?: { cacheId?: string }) {\n this.midscenePkgInfo = getRunningPkgInfo();\n this.cacheId = replaceIllegalPathCharsAndSpace(opts?.cacheId || '');\n this.cache = this.readCacheFromFile() || {\n aiTasks: [],\n };\n this.newCache = {\n aiTasks: [],\n };\n }\n\n getCacheGroupByPrompt(aiActionPrompt: string): CacheGroup {\n const { aiTasks = [] } = this.cache || { aiTasks: [] };\n const index = aiTasks.findIndex((item) => item.prompt === aiActionPrompt);\n const newCacheGroup: AiTasks = [];\n this.newCache.aiTasks.push({\n prompt: aiActionPrompt,\n tasks: newCacheGroup,\n });\n return {\n matchCache: <T extends 'plan' | 'locate' | 'ui-tars-plan'>(\n pageContext: WebUIContext,\n type: T,\n actionPrompt: string,\n ) => {\n if (index === -1) {\n return false as any;\n }\n if (type === 'plan') {\n return this.matchCache(\n pageContext,\n type,\n actionPrompt,\n aiTasks[index].tasks,\n ) as PlanTask['response'];\n }\n if (type === 'ui-tars-plan') {\n return this.matchCache(\n pageContext,\n type,\n actionPrompt,\n aiTasks[index].tasks,\n ) as UITarsPlanTask['response'];\n }\n\n return this.matchCache(\n pageContext,\n type,\n actionPrompt,\n aiTasks[index].tasks,\n ) as T extends 'plan'\n ? PlanTask['response']\n : T extends 'locate'\n ? LocateTask['response']\n : UITarsPlanTask['response'];\n },\n saveCache: (cache: PlanTask | LocateTask | UITarsPlanTask) => {\n newCacheGroup.push(cache);\n debug(\n 'saving cache to file, type: %s, cacheId: %s',\n cache.type,\n this.cacheId,\n );\n this.writeCacheToFile();\n },\n };\n }\n\n /**\n * Read and return cached responses asynchronously based on specific criteria\n * This function is mainly used to read cached responses from a certain storage medium.\n * It accepts three parameters: the page context information, the task type, and the user's prompt information.\n * In the function, it first checks whether there is cached data. If there is, it retrieves the first task response from the cache.\n * It then checks whether the task type is 'locate' and whether the corresponding element can be found in the new context.\n * If the element cannot be found, it returns false, indicating that the cache is invalid.\n * If the task type is correct and the user prompt matches, it checks whether the page context is the same.\n * If the page context is the same, it returns the cached response, indicating that the cache hit is successful.\n * If there is no cached data or the conditions are not met, the function returns false, indicating that no cache is available or the cache is not hit.\n *\n * @param pageContext UIContext<WebElementInfo> type, representing the context information of the current page\n * @param type String type, specifying the task type, can be 'plan' or 'locate'\n * @param userPrompt String type, representing user prompt information\n * @return Returns a Promise object that resolves to a boolean or object\n */\n matchCache(\n pageContext: WebUIContext,\n type: 'plan',\n userPrompt: string,\n cacheGroup: AiTasks,\n ): PlanTask['response'];\n matchCache(\n pageContext: WebUIContext,\n type: 'ui-tars-plan',\n userPrompt: string,\n cacheGroup: AiTasks,\n ): UITarsPlanTask['response'];\n matchCache(\n pageContext: WebUIContext,\n type: 'locate',\n userPrompt: string,\n cacheGroup: AiTasks,\n ): LocateTask['response'];\n matchCache(\n pageContext: WebUIContext,\n type: 'plan' | 'locate' | 'ui-tars-plan',\n userPrompt: string,\n cacheGroup: AiTasks,\n ):\n | PlanTask['response']\n | LocateTask['response']\n | UITarsPlanTask['response']\n | false {\n debug(\n 'will read cache, type: %s, prompt: %s, cacheGroupLength: %s',\n type,\n userPrompt,\n cacheGroup.length,\n );\n if (cacheGroup.length > 0) {\n const index = cacheGroup.findIndex((item) => item.prompt === userPrompt);\n\n if (index === -1) {\n debug('cannot find any cache matching prompt: %s', userPrompt);\n return false;\n }\n\n const taskRes = cacheGroup.splice(index, 1)[0];\n debug(\n 'found cache with same prompt, type: %s, prompt: %s, cached response is %j',\n type,\n userPrompt,\n taskRes?.response,\n );\n\n // The corresponding element cannot be found in the new context\n if (taskRes?.type === 'locate') {\n const id = taskRes.response?.elements[0].id;\n if (!id) {\n debug('no id in cached response');\n return false;\n }\n\n const foundInContext = pageContext.content.find(\n (contentElement) => contentElement.id === id,\n );\n if (!foundInContext) {\n debug('cannot match element with same id in current page', {\n element: taskRes.element,\n });\n return false;\n }\n\n return taskRes.response;\n }\n\n if (taskRes && taskRes.type === type && taskRes.prompt === userPrompt) {\n const contextEqual = this.pageContextEqual(\n taskRes.pageContext,\n pageContext,\n );\n if (!contextEqual) {\n debug(\n 'cache almost hit, type: %s, prompt: %s, but context not equal, will not use cache',\n type,\n userPrompt,\n );\n return false;\n }\n debug('cache hit, type: %s, prompt: %s', type, userPrompt);\n return taskRes.response;\n }\n }\n debug('no cache hit, type: %s, prompt: %s', type, userPrompt);\n return false;\n }\n\n pageContextEqual(\n taskPageContext: LocateTask['pageContext'],\n pageContext: WebUIContext,\n ) {\n debug(\n 'comparing page context size: %s x %s, %s x %s',\n taskPageContext.size.width,\n taskPageContext.size.height,\n pageContext.size.width,\n pageContext.size.height,\n );\n return (\n taskPageContext.size.width === pageContext.size.width &&\n taskPageContext.size.height === pageContext.size.height\n );\n }\n\n /**\n * Generate task cache data.\n * This method is mainly used to create or obtain some cached data for tasks, and it returns a new cache object.\n * In the cache object, it may contain task-related information, states, or other necessary data.\n * It is assumed that the `newCache` property already exists in the current class or object and is a data structure used to store task cache.\n * @returns {Object} Returns a new cache object, which may include task cache data.\n */\n generateTaskCache() {\n return this.newCache;\n }\n\n readCacheFromFile() {\n if (ifInBrowser || !this.cacheId) {\n return undefined;\n }\n const cacheFile = join(\n getMidsceneRunSubDir('cache'),\n `${this.cacheId}.json`,\n );\n if (!getAIConfigInBoolean('MIDSCENE_CACHE')) {\n return undefined;\n }\n\n if (existsSync(cacheFile)) {\n try {\n const data = readFileSync(cacheFile, 'utf8');\n const jsonData = JSON.parse(data);\n if (!this.midscenePkgInfo) {\n return undefined;\n }\n const jsonDataPkgVersion = jsonData.pkgVersion.split('.');\n const midscenePkgInfoPkgVersion =\n this.midscenePkgInfo.version.split('.');\n if (\n jsonDataPkgVersion[0] !== midscenePkgInfoPkgVersion[0] ||\n jsonDataPkgVersion[1] !== midscenePkgInfoPkgVersion[1]\n ) {\n return undefined;\n }\n debug('read cache from file: %s', cacheFile);\n return jsonData as AiTaskCache;\n } catch (err) {\n debug(\n 'cache file exists but parse failed, path: %s, error: %s',\n cacheFile,\n err,\n );\n return undefined;\n }\n }\n debug('no cache file found, path: %s', cacheFile);\n return undefined;\n }\n\n writeCacheToFile() {\n const midscenePkgInfo = getRunningPkgInfo();\n if (!midscenePkgInfo) {\n debug('no midscene pkg info, will not write cache to file');\n return;\n }\n\n if (!this.cacheId) {\n debug('no cache id, will not write cache to file');\n return;\n }\n\n if (!ifInBrowser) {\n writeLogFile({\n fileName: `${this.cacheId}`,\n fileExt: 'json',\n fileContent: stringifyDumpData(\n {\n pkgName: midscenePkgInfo.name,\n pkgVersion: midscenePkgInfo.version,\n cacheId: this.cacheId,\n ...this.newCache,\n },\n 2,\n ),\n type: 'cache',\n });\n }\n }\n}\n","import type { StaticPage } from '@/playground';\nimport type {\n ElementTreeNode,\n PlaywrightParserOpt,\n UIContext,\n} from '@midscene/core';\nimport { uploadTestInfoToServer } from '@midscene/core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport { traverseTree, treeToList } from '@midscene/shared/extractor';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport type { DebugFunction } from '@midscene/shared/logger';\nimport { assert, logMsg, uuid } from '@midscene/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 } = elementInfo;\n return new WebElementInfo({\n rect,\n locator,\n id,\n content,\n attributes,\n indexId,\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 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","import type { BaseElement, Rect } from '@midscene/core';\nimport type { NodeType } from '@midscene/shared/constants';\n\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 // page: WebPage;\n\n id: string;\n\n indexId: number;\n\n attributes: {\n nodeType: NodeType;\n [key: string]: string;\n };\n\n constructor({\n content,\n rect,\n // page,\n locator,\n id,\n attributes,\n indexId,\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 }) {\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 }\n}\n","import type {\n DetailedLocateParam,\n ExecutionTask,\n ExecutionTaskAction,\n ExecutionTaskInsightAssertion,\n ExecutionTaskInsightLocate,\n ExecutionTaskInsightQuery,\n ExecutionTaskPlanning,\n PlanningActionParamScroll,\n} from '@midscene/core';\n\nexport function typeStr(task: ExecutionTask) {\n return task.subType ? `${task.type} / ${task.subType || ''}` : task.type;\n}\n\nexport function getKeyCommands(\n value: string | string[],\n): Array<{ key: string; command?: string }> {\n // Ensure value is an array of keys\n const keys = Array.isArray(value) ? value : [value];\n\n // Process each key to attach a corresponding command if needed, based on the presence of 'Meta' or 'Control' in the keys array.\n // ref: https://github.com/puppeteer/puppeteer/pull/9357/files#diff-32cf475237b000f980eb214a0a823e45a902bddb7d2426d677cae96397aa0ae4R94\n return keys.reduce((acc: Array<{ key: string; command?: string }>, k) => {\n const includeMeta = keys.includes('Meta') || keys.includes('Control');\n if (includeMeta && (k === 'a' || k === 'A')) {\n return acc.concat([{ key: k, command: 'SelectAll' }]);\n }\n if (includeMeta && (k === 'c' || k === 'C')) {\n return acc.concat([{ key: k, command: 'Copy' }]);\n }\n if (includeMeta && (k === 'v' || k === 'V')) {\n return acc.concat([{ key: k, command: 'Paste' }]);\n }\n return acc.concat([{ key: k }]);\n }, []);\n}\n\nexport function locateParamStr(locate?: DetailedLocateParam) {\n if (!locate) {\n return '';\n }\n\n if (typeof locate === 'string') {\n return locate;\n }\n\n return locate.prompt;\n}\n\nexport function scrollParamStr(scrollParam?: PlanningActionParamScroll) {\n if (!scrollParam) {\n return '';\n }\n return `${scrollParam.direction || 'down'}, ${scrollParam.scrollType || 'once'}, ${scrollParam.distance || 'distance-not-set'}`;\n}\n\nexport function taskTitleStr(\n type:\n | 'Tap'\n | 'Hover'\n | 'Input'\n | 'KeyboardPress'\n | 'Scroll'\n | 'Action'\n | 'Query'\n | 'Assert'\n | 'WaitFor'\n | 'Locate'\n | 'Boolean'\n | 'Number'\n | 'String',\n prompt: string,\n) {\n if (prompt) {\n return `${type} - ${prompt}`;\n }\n return type;\n}\n\nexport function paramStr(task: ExecutionTask) {\n let value: string | undefined | object;\n if (task.type === 'Planning') {\n value = (task as ExecutionTaskPlanning)?.param?.userInstruction;\n }\n\n if (task.type === 'Insight') {\n value =\n (task as ExecutionTaskInsightLocate)?.param?.prompt ||\n (task as ExecutionTaskInsightLocate)?.param?.id ||\n (task as ExecutionTaskInsightQuery)?.param?.dataDemand ||\n (task as ExecutionTaskInsightAssertion)?.param?.assertion;\n }\n\n if (task.type === 'Action') {\n const locate = (task as ExecutionTaskAction)?.locate;\n const locateStr = locate ? locateParamStr(locate) : '';\n\n value = task.thought || '';\n if (typeof (task as ExecutionTaskAction)?.param?.timeMs === 'number') {\n value = `${(task as ExecutionTaskAction)?.param?.timeMs}ms`;\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.scrollType === 'string'\n ) {\n value = scrollParamStr((task as ExecutionTaskAction)?.param);\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.value !== 'undefined'\n ) {\n value = (task as ExecutionTaskAction)?.param?.value;\n }\n\n if (locateStr) {\n if (value) {\n value = `${locateStr} - ${value}`;\n } else {\n value = locateStr;\n }\n }\n }\n\n if (typeof value === 'undefined') return '';\n return typeof value === 'string'\n ? value\n : JSON.stringify(value, undefined, 2);\n}\n\nexport const limitOpenNewTabScript = `\nif (!window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__) {\n window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__ = true;\n\n // Intercept the window.open method (only once)\n window.open = function(url) {\n console.log('Blocked window.open:', url);\n window.location.href = url;\n return null;\n };\n\n // Block all a tag clicks with target=\"_blank\" (only once)\n document.addEventListener('click', function(e) {\n const target = e.target.closest('a');\n if (target && target.target === '_blank') {\n e.preventDefault();\n console.log('Blocked new tab:', target.href);\n window.location.href = target.href;\n target.removeAttribute('target');\n }\n }, true);\n}\n`;\n","import type {\n DetailedLocateParam,\n PlanningAction,\n PlanningActionParamHover,\n PlanningActionParamInputOrKeyPress,\n PlanningActionParamScroll,\n PlanningActionParamSleep,\n PlanningActionParamTap,\n PlanningLocateParam,\n} from '@midscene/core';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\n\nconst debug = getDebug('plan-builder');\n\nexport function buildPlans(\n type: PlanningAction['type'],\n locateParam?: DetailedLocateParam,\n param?:\n | PlanningActionParamInputOrKeyPress\n | PlanningActionParamScroll\n | PlanningActionParamSleep,\n): PlanningAction[] {\n let returnPlans: PlanningAction[] = [];\n const locatePlan: PlanningAction<PlanningLocateParam> | null = locateParam\n ? {\n type: 'Locate',\n locate: locateParam,\n param: locateParam,\n thought: '',\n }\n : null;\n if (type === 'Tap' || type === 'Hover') {\n assert(locateParam, `missing locate info for action \"${type}\"`);\n assert(locatePlan, `missing locate info for action \"${type}\"`);\n const tapPlan: PlanningAction<PlanningActionParamTap> = {\n type,\n param: null,\n thought: '',\n locate: locateParam,\n };\n\n returnPlans = [locatePlan, tapPlan];\n }\n if (type === 'Input' || type === 'KeyboardPress') {\n if (type === 'Input') {\n assert(locateParam, `missing locate info for action \"${type}\"`);\n }\n assert(param, `missing param for action \"${type}\"`);\n\n const inputPlan: PlanningAction<PlanningActionParamInputOrKeyPress> = {\n type,\n param: param as PlanningActionParamInputOrKeyPress,\n thought: '',\n locate: locateParam!,\n };\n\n if (locatePlan) {\n returnPlans = [locatePlan, inputPlan];\n } else {\n returnPlans = [inputPlan];\n }\n }\n\n if (type === 'Scroll') {\n assert(param, `missing param for action \"${type}\"`);\n\n const scrollPlan: PlanningAction<PlanningActionParamScroll> = {\n type,\n param: param as PlanningActionParamScroll,\n thought: '',\n locate: locateParam,\n };\n\n if (locatePlan) {\n returnPlans = [locatePlan, scrollPlan];\n } else {\n returnPlans = [scrollPlan];\n }\n }\n\n if (type === 'Sleep') {\n assert(param, `missing param for action \"${type}\"`);\n\n const sleepPlan: PlanningAction<PlanningActionParamSleep> = {\n type,\n param: param as PlanningActionParamSleep,\n thought: '',\n locate: null,\n };\n\n returnPlans = [sleepPlan];\n }\n\n if (type === 'Locate') {\n assert(locateParam, `missing locate info for action \"${type}\"`);\n const locatePlan: PlanningAction<PlanningLocateParam> = {\n type,\n param: locateParam as PlanningLocateParam,\n locate: locateParam,\n thought: '',\n };\n returnPlans = [locatePlan];\n }\n\n if (returnPlans) {\n debug('buildPlans', returnPlans);\n return returnPlans;\n }\n\n throw new Error(`Not supported type: ${type}`);\n}\n","import { PageAgent, type PageAgentOpt } from '@/common/agent';\nimport type { KeyboardAction, MouseAction } from '@/page';\nimport { assert } from '@midscene/shared/utils';\nimport {\n type BridgeConnectTabOptions,\n BridgeEvent,\n BridgePageType,\n DefaultBridgeServerPort,\n KeyboardEvent,\n MouseEvent,\n} from './common';\nimport { BridgeServer } from './io-server';\nimport type { ExtensionBridgePageBrowserSide } from './page-browser-side';\n\ninterface ChromeExtensionPageCliSide extends ExtensionBridgePageBrowserSide {\n showStatusMessage: (message: string) => Promise<void>;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n// actually, this is a proxy to the page in browser side\nexport const getBridgePageInCliSide = (\n timeout?: number | false,\n closeConflictServer?: boolean,\n): ChromeExtensionPageCliSide => {\n const server = new BridgeServer(\n DefaultBridgeServerPort,\n undefined,\n undefined,\n closeConflictServer,\n );\n server.listen({\n timeout,\n });\n const bridgeCaller = (method: string) => {\n return async (...args: any[]) => {\n const response = await server.call(method, args);\n return response;\n };\n };\n const page = {\n showStatusMessage: async (message: string) => {\n await server.call(BridgeEvent.UpdateAgentStatus, [message]);\n },\n };\n\n return new Proxy(page, {\n get(target, prop, receiver) {\n assert(typeof prop === 'string', 'prop must be a string');\n\n if (prop === 'toJSON') {\n return () => {\n return {\n pageType: BridgePageType,\n };\n };\n }\n\n if (prop === 'pageType') {\n return BridgePageType;\n }\n\n if (prop === '_forceUsePageContext') {\n return undefined;\n }\n\n if (Object.keys(page).includes(prop)) {\n return page[prop as keyof typeof page];\n }\n\n if (prop === 'mouse') {\n const mouse: MouseAction = {\n click: bridgeCaller(MouseEvent.Click),\n wheel: bridgeCaller(MouseEvent.Wheel),\n move: bridgeCaller(MouseEvent.Move),\n drag: bridgeCaller(MouseEvent.Drag),\n };\n return mouse;\n }\n\n if (prop === 'keyboard') {\n const keyboard: KeyboardAction = {\n type: bridgeCaller(KeyboardEvent.Type),\n press: bridgeCaller(KeyboardEvent.Press),\n };\n return keyboard;\n }\n\n if (prop === 'destroy') {\n return async (...args: any[]) => {\n try {\n const caller = bridgeCaller('destroy');\n await caller(...args);\n } catch (e) {\n // console.error('error calling destroy', e);\n }\n return server.close();\n };\n }\n\n return bridgeCaller(prop);\n },\n }) as ChromeExtensionPageCliSide;\n};\n\nexport class AgentOverChromeBridge extends PageAgent<ChromeExtensionPageCliSide> {\n private destroyAfterDisconnectFlag?: boolean;\n\n constructor(\n opts?: PageAgentOpt & {\n closeNewTabsAfterDisconnect?: boolean;\n serverListeningTimeout?: number | false;\n closeConflictServer?: boolean;\n },\n ) {\n const page = getBridgePageInCliSide(opts?.serverListeningTimeout);\n super(\n page,\n Object.assign(opts || {}, {\n onTaskStartTip: (tip: string) => {\n this.page.showStatusMessage(tip);\n },\n }),\n );\n this.destroyAfterDisconnectFlag = opts?.closeNewTabsAfterDisconnect;\n }\n\n async setDestroyOptionsAfterConnect() {\n if (this.destroyAfterDisconnectFlag) {\n this.page.setDestroyOptions({\n closeTab: true,\n });\n }\n }\n\n async connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions) {\n await this.page.connectNewTabWithUrl(url, options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async getBrowserTabList() {\n return await this.page.getBrowserTabList();\n }\n\n async setActiveTabId(tabId: string) {\n return await this.page.setActiveTabId(Number.parseInt(tabId));\n }\n\n async connectCurrentTab(options?: BridgeConnectTabOptions) {\n await this.page.connectCurrentTab(options);\n await sleep(500);\n await this.setDestroyOptionsAfterConnect();\n }\n\n async aiAction(prompt: string, options?: any) {\n if (options) {\n console.warn(\n 'the `options` parameter of aiAction is not supported in cli side',\n );\n }\n return await super.aiAction(prompt);\n }\n\n async destroy(closeNewTabsAfterDisconnect?: boolean) {\n if (typeof closeNewTabsAfterDisconnect === 'boolean') {\n await this.page.setDestroyOptions({\n closeTab: closeNewTabsAfterDisconnect,\n });\n }\n await super.destroy();\n }\n}\n","export const DefaultBridgeServerPort = 3766;\nexport const DefaultLocalEndpoint = `http://127.0.0.1:${DefaultBridgeServerPort}`;\nexport const BridgeCallTimeout = 30000;\n\nexport enum BridgeEvent {\n Call = 'bridge-call',\n CallResponse = 'bridge-call-response',\n UpdateAgentStatus = 'bridge-update-agent-status',\n Message = 'bridge-message',\n Connected = 'bridge-connected',\n Refused = 'bridge-refused',\n ConnectNewTabWithUrl = 'connectNewTabWithUrl',\n ConnectCurrentTab = 'connectCurrentTab',\n GetBrowserTabList = 'getBrowserTabList',\n SetDestroyOptions = 'setDestroyOptions',\n SetActiveTabId = 'setActiveTabId',\n}\n\nexport const BridgeSignalKill = 'MIDSCENE_BRIDGE_SIGNAL_KILL';\n\nexport interface BridgeConnectTabOptions {\n /**\n * If true, the page will always track the active tab.\n * @default true\n */\n forceSameTabNavigation?: boolean;\n}\n\nexport enum MouseEvent {\n PREFIX = 'mouse.',\n Click = 'mouse.click',\n Wheel = 'mouse.wheel',\n Move = 'mouse.move',\n Drag = 'mouse.drag',\n}\n\nexport enum KeyboardEvent {\n PREFIX = 'keyboard.',\n Type = 'keyboard.type',\n Press = 'keyboard.press',\n}\n\nexport const BridgePageType = 'page-over-chrome-extension-bridge';\n\nexport const BridgeErrorCodeNoClientConnected = 'no-client-connected';\n\nexport interface BridgeCall {\n method: string;\n args: any[];\n response: any;\n callTime: number;\n responseTime: number;\n callback: (error: Error | undefined, response: any) => void;\n error?: Error;\n}\n\nexport interface BridgeCallRequest {\n id: string;\n method: string;\n args: any[];\n}\n\nexport interface BridgeCallResponse {\n id: string;\n response: any;\n error?: any;\n}\n\nexport interface BridgeConnectedEventPayload {\n version: string;\n}\n","import { sleep } from '@midscene/core/utils';\nimport { logMsg } from '@midscene/shared/utils';\nimport { Server, type Socket as ServerSocket } from 'socket.io';\nimport { io as ClientIO, type Socket as ClientSocket } from 'socket.io-client';\n\nimport {\n type BridgeCall,\n type BridgeCallResponse,\n BridgeCallTimeout,\n type BridgeConnectedEventPayload,\n BridgeErrorCodeNoClientConnected,\n BridgeEvent,\n BridgeSignalKill,\n DefaultBridgeServerPort,\n} from './common';\n\ndeclare const __VERSION__: string;\n\nexport const killRunningServer = async (port?: number) => {\n try {\n const client = ClientIO(\n `ws://localhost:${port || DefaultBridgeServerPort}`,\n {\n query: {\n [BridgeSignalKill]: 1,\n },\n },\n );\n await sleep(100);\n await client.close();\n } catch (e) {\n // console.error('failed to kill port', e);\n }\n};\n\n// ws server, this is where the request is sent\nexport class BridgeServer {\n private callId = 0;\n private io: Server | null = null;\n private socket: ServerSocket | null = null;\n private listeningTimeoutId: NodeJS.Timeout | null = null;\n private listeningTimerFlag = false;\n private connectionTipTimer: NodeJS.Timeout | null = null;\n public calls: Record<string, BridgeCall> = {};\n\n private connectionLost = false;\n private connectionLostReason = '';\n\n constructor(\n public port: number,\n public onConnect?: () => void,\n public onDisconnect?: (reason: string) => void,\n public closeConflictServer?: boolean,\n ) {}\n\n async listen(\n opts: {\n timeout?: number | false;\n } = {},\n ): Promise<void> {\n const { timeout = 30000 } = opts;\n\n if (this.closeConflictServer) {\n await killRunningServer(this.port);\n }\n\n return new Promise((resolve, reject) => {\n if (this.listeningTimerFlag) {\n return reject(new Error('already listening'));\n }\n this.listeningTimerFlag = true;\n\n this.listeningTimeoutId = timeout\n ? setTimeout(() => {\n reject(\n new Error(\n `no extension connected after ${timeout}ms (${BridgeErrorCodeNoClientConnected})`,\n ),\n );\n }, timeout)\n : null;\n\n this.connectionTipTimer =\n !timeout || timeout > 3000\n ? setTimeout(() => {\n logMsg('waiting for bridge to connect...');\n }, 2000)\n : null;\n this.io = new Server(this.port, {\n maxHttpBufferSize: 100 * 1024 * 1024, // 100MB\n });\n\n // Listen for the native HTTP server 'listening' event\n this.io.httpServer.once('listening', () => {\n resolve();\n });\n\n this.io.httpServer.once('error', (err: Error) => {\n reject(new Error(`Bridge Listening Error: ${err.message}`));\n });\n\n this.io.use((socket, next) => {\n if (this.socket) {\n next(new Error('server already connected by another client'));\n }\n next();\n });\n\n this.io.on('connection', (socket) => {\n // check the connection url\n const url = socket.handshake.url;\n if (url.includes(BridgeSignalKill)) {\n console.warn('kill signal received, closing bridge server');\n return this.close();\n }\n\n this.connectionLost = false;\n this.connectionLostReason = '';\n this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);\n this.listeningTimeoutId = null;\n this.connectionTipTimer && clearTimeout(this.connectionTipTimer);\n this.connectionTipTimer = null;\n if (this.socket) {\n socket.emit(BridgeEvent.Refused);\n // close the socket\n socket.disconnect();\n\n return reject(\n new Error('server already connected by another client'),\n );\n }\n\n try {\n logMsg('one client connected');\n this.socket = socket;\n\n const clientVersion = socket.handshake.query.version;\n logMsg(\n `Bridge connected, cli-side version v${__VERSION__}, browser-side version v${clientVersion}`,\n );\n\n socket.on(BridgeEvent.CallResponse, (params: BridgeCallResponse) => {\n const id = params.id;\n const response = params.response;\n const error = params.error;\n\n this.triggerCallResponseCallback(id, error, response);\n });\n\n socket.on('disconnect', (reason: string) => {\n this.connectionLost = true;\n this.connectionLostReason = reason;\n\n try {\n this.io?.close();\n } catch (e) {\n // ignore\n }\n\n // flush all pending calls as error\n for (const id in this.calls) {\n const call = this.calls[id];\n\n if (!call.responseTime) {\n const errorMessage = this.connectionLostErrorMsg();\n this.triggerCallResponseCallback(\n id,\n new Error(errorMessage),\n null,\n );\n }\n }\n\n this.onDisconnect?.(reason);\n });\n\n setTimeout(() => {\n this.onConnect?.();\n\n const payload = {\n version: __VERSION__,\n } as BridgeConnectedEventPayload;\n socket.emit(BridgeEvent.Connected, payload);\n Promise.resolve().then(() => {\n for (const id in this.calls) {\n if (this.calls[id].callTime === 0) {\n this.emitCall(id);\n }\n }\n });\n }, 0);\n } catch (e) {\n console.error('failed to handle connection event', e);\n reject(e);\n }\n });\n\n this.io.on('close', () => {\n this.close();\n });\n });\n }\n\n private connectionLostErrorMsg = () => {\n return `Connection lost, reason: ${this.connectionLostReason}`;\n };\n\n private async triggerCallResponseCallback(\n id: string | number,\n error: Error | null,\n response: any,\n ) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n call.error = error || undefined;\n call.response = response;\n call.responseTime = Date.now();\n\n call.callback(call.error, response);\n }\n\n private async emitCall(id: string) {\n const call = this.calls[id];\n if (!call) {\n throw new Error(`call ${id} not found`);\n }\n\n if (this.connectionLost) {\n const message = `Connection lost, reason: ${this.connectionLostReason}`;\n call.callback(new Error(message), null);\n return;\n }\n\n if (this.socket) {\n this.socket.emit(BridgeEvent.Call, {\n id,\n method: call.method,\n args: call.args,\n });\n call.callTime = Date.now();\n }\n }\n\n async call<T = any>(\n method: string,\n args: any[],\n timeout = BridgeCallTimeout,\n ): Promise<T> {\n const id = `${this.callId++}`;\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n logMsg(`bridge call timeout, id=${id}, method=${method}, args=`, args);\n this.calls[id].error = new Error(\n `Bridge call timeout after ${timeout}ms: ${method}`,\n );\n reject(this.calls[id].error);\n }, timeout);\n\n this.calls[id] = {\n method,\n args,\n response: null,\n callTime: 0,\n responseTime: 0,\n callback: (error: Error | undefined, response: any) => {\n clearTimeout(timeoutId);\n if (error) {\n reject(error);\n } else {\n resolve(response);\n }\n },\n };\n\n this.emitCall(id);\n });\n }\n\n // do NOT restart after close\n async close() {\n this.listeningTimeoutId && clearTimeout(this.listeningTimeoutId);\n this.connectionTipTimer && clearTimeout(this.connectionTipTimer);\n const closeProcess = this.io?.close();\n this.io = null;\n\n return closeProcess;\n }\n}\n","import { AgentOverChromeBridge } from './agent-cli-side';\n\nexport { AgentOverChromeBridge };\n\nexport { overrideAIConfig, allConfigFromEnv } from '@midscene/shared/env';\n\nexport { killRunningServer } from './io-server';\n"]}