@midscene/web 0.26.6 → 0.26.7-beta-20250815153024.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/es/bridge-mode/io-client.mjs +1 -1
  2. package/dist/es/bridge-mode/io-server.mjs +2 -2
  3. package/dist/es/bridge-mode/io-server.mjs.map +1 -1
  4. package/dist/es/bridge-mode/page-browser-side.mjs +1 -1
  5. package/dist/es/bridge-mode/page-browser-side.mjs.map +1 -1
  6. package/dist/es/chrome-extension/page.mjs +1 -1
  7. package/dist/es/common/agent.mjs +95 -59
  8. package/dist/es/common/agent.mjs.map +1 -1
  9. package/dist/es/common/tasks.mjs +8 -8
  10. package/dist/es/common/tasks.mjs.map +1 -1
  11. package/dist/es/common/utils.mjs +6 -1
  12. package/dist/es/common/utils.mjs.map +1 -1
  13. package/dist/es/yaml/player.mjs +75 -13
  14. package/dist/es/yaml/player.mjs.map +1 -1
  15. package/dist/lib/bridge-mode/io-client.js +1 -1
  16. package/dist/lib/bridge-mode/io-server.js +2 -2
  17. package/dist/lib/bridge-mode/io-server.js.map +1 -1
  18. package/dist/lib/bridge-mode/page-browser-side.js +1 -1
  19. package/dist/lib/bridge-mode/page-browser-side.js.map +1 -1
  20. package/dist/lib/chrome-extension/page.js +1 -1
  21. package/dist/lib/common/agent.js +94 -58
  22. package/dist/lib/common/agent.js.map +1 -1
  23. package/dist/lib/common/tasks.js +8 -8
  24. package/dist/lib/common/tasks.js.map +1 -1
  25. package/dist/lib/common/utils.js +6 -1
  26. package/dist/lib/common/utils.js.map +1 -1
  27. package/dist/lib/yaml/player.js +75 -13
  28. package/dist/lib/yaml/player.js.map +1 -1
  29. package/dist/types/common/agent.d.ts +23 -4
  30. package/dist/types/yaml/player.d.ts +1 -0
  31. package/package.json +3 -3
  32. package/dist/es/common/plan-builder.mjs +0 -89
  33. package/dist/es/common/plan-builder.mjs.map +0 -1
  34. package/dist/lib/common/plan-builder.js +0 -123
  35. package/dist/lib/common/plan-builder.js.map +0 -1
  36. package/dist/types/common/plan-builder.d.ts +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"common/tasks.mjs","sources":["webpack://@midscene/web/./src/common/tasks.ts"],"sourcesContent":["import type { AndroidDevicePage, WebPage } from '@/common/page';\nimport type { PuppeteerWebPage } from '@/puppeteer';\nimport {\n type AIUsageInfo,\n type BaseElement,\n type DeviceAction,\n type DumpSubscriber,\n type ExecutionRecorderItem,\n type ExecutionTaskActionApply,\n type ExecutionTaskApply,\n type ExecutionTaskHitBy,\n type ExecutionTaskInsightLocateApply,\n type ExecutionTaskInsightQueryApply,\n type ExecutionTaskPlanning,\n type ExecutionTaskPlanningApply,\n type ExecutionTaskProgressOptions,\n Executor,\n type ExecutorContext,\n type Insight,\n type InsightAssertionResponse,\n type InsightDump,\n type InsightExtractOption,\n type InsightExtractParam,\n type LocateResultElement,\n type MidsceneYamlFlowItem,\n type PageType,\n type PlanningAIResponse,\n type PlanningAction,\n type PlanningActionParamAssert,\n type PlanningActionParamError,\n type PlanningActionParamSleep,\n type PlanningActionParamWaitFor,\n type TMultimodalPrompt,\n type TUserPrompt,\n type UIContext,\n plan,\n} from '@midscene/core';\nimport {\n type ChatCompletionMessageParam,\n elementByPositionWithElementInfo,\n resizeImageForUiTars,\n vlmPlanning,\n} from '@midscene/core/ai-model';\nimport { sleep } from '@midscene/core/utils';\nimport { NodeType } from '@midscene/shared/constants';\nimport {\n MIDSCENE_REPLANNING_CYCLE_LIMIT,\n getAIConfigInNumber,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { WebElementInfo, WebUIContext } from '../web-element';\nimport type { TaskCache } from './task-cache';\nimport { taskTitleStr } from './ui-utils';\nimport {\n matchElementFromCache,\n matchElementFromPlan,\n parsePrompt,\n} from './utils';\n\ninterface ExecutionResult<OutputType = any> {\n output: OutputType;\n thought?: string;\n executor: Executor;\n}\n\nconst debug = getDebug('device-task-executor');\nconst defaultReplanningCycleLimit = 10;\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 taskCache?: TaskCache;\n onTaskStart?: ExecutionTaskProgressOptions['onTaskStart'];\n },\n ) {\n this.page = page;\n this.insight = insight;\n\n this.taskCache = opts.taskCache;\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 async getElementXpath(\n pageContext: UIContext<BaseElement>,\n element: LocateResultElement,\n ): Promise<string[] | undefined> {\n let elementId = element?.id;\n if (element?.isOrderSensitive !== undefined) {\n const xpaths = await this.page.getXpathsByPoint(\n {\n left: element.center[0],\n top: element.center[1],\n },\n element?.isOrderSensitive,\n );\n\n return xpaths;\n }\n\n // find the nearest xpath for the element\n if (element?.attributes?.nodeType === NodeType.POSITION) {\n await this.insight.contextRetrieverFn('locate');\n const info = elementByPositionWithElementInfo(\n pageContext.tree,\n {\n x: element.center[0],\n y: element.center[1],\n },\n {\n requireStrictDistance: false,\n filterPositionElements: true,\n },\n );\n if (info?.id) {\n elementId = info.id;\n } else {\n debug(\n 'no element id found for position node, will not update cache',\n element,\n );\n }\n }\n\n if (!elementId) {\n return undefined;\n }\n try {\n const result = await this.page.getXpathsById(elementId);\n return result;\n } catch (error) {\n debug('getXpathsById error: ', error);\n }\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 public async convertPlanToExecutable(\n plans: PlanningAction[],\n opts?: {\n cacheable?: boolean;\n },\n ) {\n const tasks: ExecutionTaskApply[] = [];\n for (const plan of plans) {\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 continue;\n }\n const taskFind: ExecutionTaskInsightLocateApply = {\n type: 'Insight',\n subType: 'Locate',\n param: plan.locate\n ? {\n ...plan.locate,\n cacheable: opts?.cacheable,\n }\n : 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\n // Get context through contextRetrieverFn which handles frozen context\n const pageContext = await this.insight.contextRetrieverFn('locate');\n task.pageContext = pageContext;\n\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before Insight',\n };\n task.recorder = [recordItem];\n\n // try matching xpath\n const elementFromXpath = param.xpath\n ? await this.page.getElementInfoByXpath(param.xpath)\n : undefined;\n const userExpectedPathHitFlag = !!elementFromXpath;\n\n // try matching cache\n const cachePrompt = param.prompt;\n const locateCacheRecord =\n this.taskCache?.matchLocateCache(cachePrompt);\n const xpaths = locateCacheRecord?.cacheContent?.xpaths;\n const elementFromCache = userExpectedPathHitFlag\n ? null\n : await matchElementFromCache(\n this,\n xpaths,\n cachePrompt,\n param.cacheable,\n );\n const cacheHitFlag = !!elementFromCache;\n\n // try matching plan\n const elementFromPlan =\n !userExpectedPathHitFlag && !cacheHitFlag\n ? matchElementFromPlan(param, pageContext.tree)\n : undefined;\n const planHitFlag = !!elementFromPlan;\n\n // try ai locate\n const elementFromAiLocate =\n !userExpectedPathHitFlag && !cacheHitFlag && !planHitFlag\n ? (\n await this.insight.locate(param, {\n // fallback to ai locate\n context: pageContext,\n })\n ).element\n : undefined;\n const aiLocateHitFlag = !!elementFromAiLocate;\n\n const element =\n elementFromXpath || // highest priority\n elementFromCache || // second priority\n elementFromPlan || // third priority\n elementFromAiLocate;\n\n // update cache\n let currentXpaths: string[] | undefined;\n if (\n element &&\n this.taskCache &&\n !cacheHitFlag &&\n param?.cacheable !== false\n ) {\n const elementXpaths = await this.getElementXpath(\n pageContext,\n element,\n );\n if (elementXpaths?.length) {\n currentXpaths = elementXpaths;\n this.taskCache.updateOrAppendCacheRecord(\n {\n type: 'locate',\n prompt: cachePrompt,\n xpaths: elementXpaths,\n },\n locateCacheRecord,\n );\n } else {\n debug(\n 'no xpaths found, will not update cache',\n cachePrompt,\n elementXpaths,\n );\n }\n }\n if (!element) {\n throw new Error(`Element not found: ${param.prompt}`);\n }\n\n let hitBy: ExecutionTaskHitBy | undefined;\n\n if (userExpectedPathHitFlag) {\n hitBy = {\n from: 'User expected path',\n context: {\n xpath: param.xpath,\n },\n };\n } else if (cacheHitFlag) {\n hitBy = {\n from: 'Cache',\n context: {\n xpathsFromCache: xpaths,\n xpathsToSave: currentXpaths,\n },\n };\n } else if (planHitFlag) {\n hitBy = {\n from: 'Planning',\n context: {\n id: elementFromPlan?.id,\n bbox: elementFromPlan?.bbox,\n },\n };\n } else if (aiLocateHitFlag) {\n hitBy = {\n from: 'AI model',\n context: {\n prompt: param.prompt,\n },\n };\n }\n\n return {\n output: {\n element,\n },\n pageContext,\n hitBy,\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 shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('assert');\n task.pageContext = pageContext;\n\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before Insight',\n };\n task.recorder = [recordItem];\n\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 = new Error(assertion.thought);\n }\n\n return {\n output: assertion,\n pageContext,\n log: {\n dump: insightDump,\n },\n usage: assertion.usage,\n };\n },\n };\n tasks.push(taskAssert);\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 === '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 === '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 === '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 {\n const planType = plan.type;\n const task: ExecutionTaskActionApply = {\n type: 'Action',\n subType: planType,\n thought: plan.thought,\n param: plan.param,\n executor: async (param, context) => {\n debug(\n 'executing action',\n planType,\n param,\n `context.element.center: ${context.element?.center}`,\n );\n const actionSpace = await this.page.actionSpace();\n const action = actionSpace.find(\n (action) => action.name === planType,\n );\n if (!action) {\n throw new Error(`Action type '${planType}' not found`);\n }\n const actionFn = action.call.bind(this.page);\n return await actionFn(context, param);\n },\n };\n tasks.push(task);\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 async setupPlanningContext(executorContext: 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 ExecutionTaskPlanning).pageContext = pageContext;\n\n return {\n pageContext,\n };\n }\n\n async loadYamlFlowAsPlanning(userInstruction: string, yamlString: string) {\n const taskExecutor = new Executor(taskTitleStr('Action', userInstruction), {\n onTaskStart: this.onTaskStartCallback,\n });\n\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n subType: 'LoadYaml',\n locate: null,\n param: {\n userInstruction,\n },\n executor: async (param, executorContext) => {\n await this.setupPlanningContext(executorContext);\n return {\n output: {\n actions: [],\n more_actions_needed_by_instruction: false,\n log: '',\n yamlString,\n },\n cache: {\n hit: true,\n },\n };\n },\n };\n\n await taskExecutor.append(task);\n await taskExecutor.flush();\n\n return {\n executor: taskExecutor,\n };\n }\n\n private planningTaskFromPrompt(\n userInstruction: string,\n log?: string,\n actionContext?: string,\n ) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n subType: 'Plan',\n locate: null,\n param: {\n userInstruction,\n log,\n },\n executor: async (param, executorContext) => {\n const startTime = Date.now();\n const { pageContext } =\n await this.setupPlanningContext(executorContext);\n\n assert(\n this.page.actionSpace,\n 'actionSpace for device is not implemented',\n );\n const actionSpace = await this.page.actionSpace();\n debug(\n 'actionSpace for page is:',\n actionSpace.map((action) => action.name).join(', '),\n );\n assert(Array.isArray(actionSpace), 'actionSpace must be an array');\n if (actionSpace.length === 0) {\n console.warn(\n `ActionSpace for ${this.page.pageType} is empty. This may lead to unexpected behavior.`,\n );\n }\n\n const planResult = await plan(param.userInstruction, {\n context: pageContext,\n log: param.log,\n actionContext,\n pageType: this.page.pageType as PageType,\n actionSpace,\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 executorContext.task.log = {\n ...(executorContext.task.log || {}),\n rawResponse,\n };\n executorContext.task.usage = usage;\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 is prompt created by ai, always a string\n thought: planningAction.locate.prompt as string,\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 - startTime);\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 return {\n output: {\n actions: finalActions,\n more_actions_needed_by_instruction,\n log,\n yamlFlow: planResult.yamlFlow,\n },\n cache: {\n hit: false,\n },\n pageContext,\n };\n },\n };\n\n return task;\n }\n\n private planningTaskToGoal(userInstruction: string) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n subType: 'Plan',\n locate: null,\n param: {\n userInstruction,\n },\n executor: async (param, executorContext) => {\n const { pageContext } =\n await this.setupPlanningContext(executorContext);\n\n const imagePayload = await resizeImageForUiTars(\n pageContext.screenshotBase64,\n pageContext.size,\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 planResult: {\n actions: PlanningAction<any>[];\n action_summary: string;\n usage?: AIUsageInfo;\n yamlFlow?: MidsceneYamlFlowItem[];\n rawResponse?: string;\n } = await vlmPlanning({\n userInstruction: param.userInstruction,\n conversationHistory: this.conversationHistory,\n size: pageContext.size,\n });\n\n const { actions, action_summary, usage } = planResult;\n executorContext.task.log = {\n ...(executorContext.task.log || {}),\n rawResponse: planResult.rawResponse,\n };\n executorContext.task.usage = usage;\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 yamlFlow: planResult.yamlFlow,\n },\n cache: {\n hit: false,\n },\n };\n },\n };\n\n return task;\n }\n\n async runPlans(\n title: string,\n plans: PlanningAction[],\n opts?: {\n cacheable?: boolean;\n },\n ): Promise<ExecutionResult> {\n const taskExecutor = new Executor(title, {\n onTaskStart: this.onTaskStartCallback,\n });\n const { tasks } = await this.convertPlanToExecutable(plans, opts);\n await taskExecutor.append(tasks);\n const result = await taskExecutor.flush();\n const { output } = result!;\n return {\n output,\n executor: taskExecutor,\n };\n }\n\n async action(\n userPrompt: string,\n actionContext?: string,\n opts?: {\n cacheable?: boolean;\n },\n ): Promise<\n ExecutionResult<\n | {\n yamlFlow?: MidsceneYamlFlowItem[]; // for cache use\n }\n | undefined\n >\n > {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n\n let planningTask: ExecutionTaskPlanningApply | null =\n this.planningTaskFromPrompt(userPrompt, undefined, actionContext);\n let replanCount = 0;\n const logList: string[] = [];\n\n const yamlFlow: MidsceneYamlFlowItem[] = [];\n const replanningCycleLimit =\n getAIConfigInNumber(MIDSCENE_REPLANNING_CYCLE_LIMIT) ||\n defaultReplanningCycleLimit;\n while (planningTask) {\n if (replanCount > replanningCycleLimit) {\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 result = await taskExecutor.flush();\n const planResult: PlanningAIResponse = result?.output;\n if (taskExecutor.isInErrorState()) {\n return {\n output: planResult,\n executor: taskExecutor,\n };\n }\n\n const plans = planResult.actions || [];\n yamlFlow.push(...(planResult.yamlFlow || []));\n\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans, opts);\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 await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: undefined,\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 logList.length > 0 ? `- ${logList.join('\\n- ')}` : undefined,\n actionContext,\n );\n replanCount++;\n }\n\n return {\n output: {\n yamlFlow,\n },\n executor: taskExecutor,\n };\n }\n\n async actionToGoal(\n userPrompt: string,\n opts?: {\n cacheable?: boolean;\n },\n ): Promise<\n ExecutionResult<\n | {\n yamlFlow?: MidsceneYamlFlowItem[]; // for cache use\n }\n | undefined\n >\n > {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n this.conversationHistory = [];\n const isCompleted = false;\n let currentActionNumber = 0;\n const maxActionNumber = 40;\n\n const yamlFlow: MidsceneYamlFlowItem[] = [];\n while (!isCompleted && currentActionNumber < maxActionNumber) {\n currentActionNumber++;\n const planningTask: ExecutionTaskPlanningApply =\n this.planningTaskToGoal(userPrompt);\n await taskExecutor.append(planningTask);\n const result = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n if (!result) {\n throw new Error(\n 'result of taskExecutor.flush() is undefined in function actionToGoal',\n );\n }\n const { output } = result;\n const plans = output.actions;\n yamlFlow.push(...(output.yamlFlow || []));\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans, opts);\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 await taskExecutor.flush();\n\n if (taskExecutor.isInErrorState()) {\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n\n if (plans[0].type === 'Finished') {\n break;\n }\n }\n return {\n output: {\n yamlFlow,\n },\n executor: taskExecutor,\n };\n }\n\n private async createTypeQueryTask<T>(\n type: 'Query' | 'Boolean' | 'Number' | 'String' | 'Assert',\n demand: InsightExtractParam,\n opt?: InsightExtractOption,\n multimodalPrompt?: TMultimodalPrompt,\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 // TODO: display image thumbnail in report\n dataDemand: multimodalPrompt\n ? ({\n demand,\n multimodalPrompt,\n } as never)\n : demand, // for user param presentation in report right sidebar\n },\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\n // Get page context for query operations\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('extract');\n task.pageContext = pageContext;\n\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before Extract',\n };\n task.recorder = [recordItem];\n\n const ifTypeRestricted = type !== 'Query';\n let demandInput = demand;\n if (ifTypeRestricted) {\n const returnType = type === 'Assert' ? 'Boolean' : type;\n demandInput = {\n result: `${returnType}, ${demand}`,\n };\n }\n\n const { data, usage, thought } = await this.insight.extract<any>(\n demandInput,\n opt,\n multimodalPrompt,\n );\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 thought,\n };\n },\n };\n\n await taskExecutor.append(this.prependExecutorWithScreenshot(queryTask));\n const result = await taskExecutor.flush();\n\n if (!result) {\n throw new Error(\n 'result of taskExecutor.flush() is undefined in function createTypeQueryTask',\n );\n }\n\n const { output, thought } = result;\n\n return {\n output,\n thought,\n executor: taskExecutor,\n };\n }\n\n async query(\n demand: InsightExtractParam,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult> {\n return this.createTypeQueryTask('Query', demand, opt);\n }\n\n async boolean(\n prompt: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<boolean>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n return this.createTypeQueryTask<boolean>(\n 'Boolean',\n textPrompt,\n opt,\n multimodalPrompt,\n );\n }\n\n async number(\n prompt: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<number>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n return this.createTypeQueryTask<number>(\n 'Number',\n textPrompt,\n opt,\n multimodalPrompt,\n );\n }\n\n async string(\n prompt: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<string>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n return this.createTypeQueryTask<string>(\n 'String',\n textPrompt,\n opt,\n multimodalPrompt,\n );\n }\n\n async assert(\n assertion: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<boolean>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(assertion);\n return await this.createTypeQueryTask<boolean>(\n 'Assert',\n textPrompt,\n opt,\n multimodalPrompt,\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 result = await taskExecutor.flush();\n\n if (!result) {\n throw new Error(\n 'result of taskExecutor.flush() is undefined in function waitFor',\n );\n }\n\n const { output } = result as { output: InsightAssertionResponse };\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"],"names":["debug","getDebug","defaultReplanningCycleLimit","PageTaskExecutor","timing","base64","item","Date","pageContext","element","_element_attributes","elementId","undefined","xpaths","NodeType","info","elementByPositionWithElementInfo","result","error","taskApply","appendAfterExecution","taskWithScreenshot","param","context","args","recorder","task","shot","Promise","sleep","shot2","plans","opts","tasks","plan","_plan_locate","_plan_locate1","taskFind","taskContext","_this_taskCache","_locateCacheRecord_cacheContent","assert","insightDump","usage","dumpCollector","dump","_dump_taskInfo","shotTime","recordItem","elementFromXpath","userExpectedPathHitFlag","cachePrompt","locateCacheRecord","elementFromCache","matchElementFromCache","cacheHitFlag","elementFromPlan","matchElementFromPlan","planHitFlag","elementFromAiLocate","aiLocateHitFlag","currentXpaths","elementXpaths","Error","hitBy","assertPlan","taskAssert","assertion","_plan_param","taskActionError","taskActionFinished","taskActionSleep","taskParam","taskActionDrag","planType","_context_element","actionSpace","action","actionFn","wrappedTasks","index","executorContext","userInstruction","yamlString","taskExecutor","Executor","taskTitleStr","log","actionContext","startTime","Array","console","planResult","actions","more_actions_needed_by_instruction","rawResponse","stopCollecting","bboxCollected","planParsingError","finalActions","acc","planningAction","JSON","timeNow","timeRemaining","_actions_","imagePayload","resizeImageForUiTars","vlmPlanning","action_summary","title","output","userPrompt","planningTask","replanCount","logList","yamlFlow","replanningCycleLimit","getAIConfigInNumber","MIDSCENE_REPLANNING_CYCLE_LIMIT","errorMsg","executables","isCompleted","currentActionNumber","maxActionNumber","type","demand","opt","multimodalPrompt","queryTask","ifTypeRestricted","demandInput","returnType","data","thought","outputResult","prompt","textPrompt","parsePrompt","conversationHistory","userImgItems","firstUserImgIndex","errorPlan","description","timeoutMs","checkIntervalMs","overallStartTime","errorThought","assertTasks","now","sleepPlan","sleepTasks","page","insight"],"mappings":"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"}
1
+ {"version":3,"file":"common/tasks.mjs","sources":["webpack://@midscene/web/./src/common/tasks.ts"],"sourcesContent":["import type { WebPage } from '@/common/page';\nimport type { PuppeteerWebPage } from '@/puppeteer';\nimport {\n type AIUsageInfo,\n type BaseElement,\n type DumpSubscriber,\n type ExecutionRecorderItem,\n type ExecutionTaskActionApply,\n type ExecutionTaskApply,\n type ExecutionTaskHitBy,\n type ExecutionTaskInsightLocateApply,\n type ExecutionTaskInsightQueryApply,\n type ExecutionTaskPlanning,\n type ExecutionTaskPlanningApply,\n type ExecutionTaskProgressOptions,\n Executor,\n type ExecutorContext,\n type Insight,\n type InsightAssertionResponse,\n type InsightDump,\n type InsightExtractOption,\n type InsightExtractParam,\n type LocateResultElement,\n type MidsceneYamlFlowItem,\n type PageType,\n type PlanningAIResponse,\n type PlanningAction,\n type PlanningActionParamAssert,\n type PlanningActionParamError,\n type PlanningActionParamSleep,\n type PlanningActionParamWaitFor,\n type TMultimodalPrompt,\n type TUserPrompt,\n type UIContext,\n plan,\n} from '@midscene/core';\nimport {\n type ChatCompletionMessageParam,\n elementByPositionWithElementInfo,\n resizeImageForUiTars,\n vlmPlanning,\n} from '@midscene/core/ai-model';\nimport { sleep } from '@midscene/core/utils';\nimport { NodeType } from '@midscene/shared/constants';\nimport {\n MIDSCENE_REPLANNING_CYCLE_LIMIT,\n getAIConfigInNumber,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { WebElementInfo, WebUIContext } from '../web-element';\nimport type { TaskCache } from './task-cache';\nimport { taskTitleStr } from './ui-utils';\nimport {\n matchElementFromCache,\n matchElementFromPlan,\n parsePrompt,\n} from './utils';\n\ninterface ExecutionResult<OutputType = any> {\n output: OutputType;\n thought?: string;\n executor: Executor;\n}\n\nconst debug = getDebug('device-task-executor');\nconst defaultReplanningCycleLimit = 10;\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 taskCache?: TaskCache;\n onTaskStart?: ExecutionTaskProgressOptions['onTaskStart'];\n },\n ) {\n this.page = page;\n this.insight = insight;\n this.taskCache = opts.taskCache;\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 async getElementXpath(\n pageContext: UIContext<BaseElement>,\n element: LocateResultElement,\n ): Promise<string[] | undefined> {\n let elementId = element?.id;\n if (element?.isOrderSensitive !== undefined) {\n const xpaths = await this.page.getXpathsByPoint(\n {\n left: element.center[0],\n top: element.center[1],\n },\n element?.isOrderSensitive,\n );\n\n return xpaths;\n }\n\n // find the nearest xpath for the element\n if (element?.attributes?.nodeType === NodeType.POSITION) {\n await this.insight.contextRetrieverFn('locate');\n const info = elementByPositionWithElementInfo(\n pageContext.tree,\n {\n x: element.center[0],\n y: element.center[1],\n },\n {\n requireStrictDistance: false,\n filterPositionElements: true,\n },\n );\n if (info?.id) {\n elementId = info.id;\n } else {\n debug(\n 'no element id found for position node, will not update cache',\n element,\n );\n }\n }\n\n if (!elementId) {\n return undefined;\n }\n try {\n const result = await this.page.getXpathsById(elementId);\n return result;\n } catch (error) {\n debug('getXpathsById error: ', error);\n }\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 public async convertPlanToExecutable(\n plans: PlanningAction[],\n opts?: {\n cacheable?: boolean;\n },\n ) {\n const tasks: ExecutionTaskApply[] = [];\n for (const plan of plans) {\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 continue;\n }\n const taskFind: ExecutionTaskInsightLocateApply = {\n type: 'Insight',\n subType: 'Locate',\n param: plan.locate\n ? {\n ...plan.locate,\n cacheable: opts?.cacheable,\n }\n : 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\n // Get context through contextRetrieverFn which handles frozen context\n const pageContext = await this.insight.contextRetrieverFn('locate');\n task.pageContext = pageContext;\n\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before Insight',\n };\n task.recorder = [recordItem];\n\n // try matching xpath\n const elementFromXpath = param.xpath\n ? await this.page.getElementInfoByXpath(param.xpath)\n : undefined;\n const userExpectedPathHitFlag = !!elementFromXpath;\n\n // try matching cache\n const cachePrompt = param.prompt;\n const locateCacheRecord =\n this.taskCache?.matchLocateCache(cachePrompt);\n const xpaths = locateCacheRecord?.cacheContent?.xpaths;\n const elementFromCache = userExpectedPathHitFlag\n ? null\n : await matchElementFromCache(\n this,\n xpaths,\n cachePrompt,\n param.cacheable,\n );\n const cacheHitFlag = !!elementFromCache;\n\n // try matching plan\n const elementFromPlan =\n !userExpectedPathHitFlag && !cacheHitFlag\n ? matchElementFromPlan(param, pageContext.tree)\n : undefined;\n const planHitFlag = !!elementFromPlan;\n\n // try ai locate\n const elementFromAiLocate =\n !userExpectedPathHitFlag && !cacheHitFlag && !planHitFlag\n ? (\n await this.insight.locate(param, {\n // fallback to ai locate\n context: pageContext,\n })\n ).element\n : undefined;\n const aiLocateHitFlag = !!elementFromAiLocate;\n\n const element =\n elementFromXpath || // highest priority\n elementFromCache || // second priority\n elementFromPlan || // third priority\n elementFromAiLocate;\n\n // update cache\n let currentXpaths: string[] | undefined;\n if (\n element &&\n this.taskCache &&\n !cacheHitFlag &&\n param?.cacheable !== false\n ) {\n const elementXpaths = await this.getElementXpath(\n pageContext,\n element,\n );\n if (elementXpaths?.length) {\n currentXpaths = elementXpaths;\n this.taskCache.updateOrAppendCacheRecord(\n {\n type: 'locate',\n prompt: cachePrompt,\n xpaths: elementXpaths,\n },\n locateCacheRecord,\n );\n } else {\n debug(\n 'no xpaths found, will not update cache',\n cachePrompt,\n elementXpaths,\n );\n }\n }\n if (!element) {\n throw new Error(`Element not found: ${param.prompt}`);\n }\n\n let hitBy: ExecutionTaskHitBy | undefined;\n\n if (userExpectedPathHitFlag) {\n hitBy = {\n from: 'User expected path',\n context: {\n xpath: param.xpath,\n },\n };\n } else if (cacheHitFlag) {\n hitBy = {\n from: 'Cache',\n context: {\n xpathsFromCache: xpaths,\n xpathsToSave: currentXpaths,\n },\n };\n } else if (planHitFlag) {\n hitBy = {\n from: 'Planning',\n context: {\n id: elementFromPlan?.id,\n bbox: elementFromPlan?.bbox,\n },\n };\n } else if (aiLocateHitFlag) {\n hitBy = {\n from: 'AI model',\n context: {\n prompt: param.prompt,\n },\n };\n }\n\n return {\n output: {\n element,\n },\n pageContext,\n hitBy,\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 shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('assert');\n task.pageContext = pageContext;\n\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before Insight',\n };\n task.recorder = [recordItem];\n\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 = new Error(assertion.thought);\n }\n\n return {\n output: assertion,\n pageContext,\n log: {\n dump: insightDump,\n },\n usage: assertion.usage,\n };\n },\n };\n tasks.push(taskAssert);\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 === '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 === '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 === '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 {\n const planType = plan.type;\n const task: ExecutionTaskActionApply = {\n type: 'Action',\n subType: planType,\n thought: plan.thought,\n param: plan.param,\n executor: async (param, context) => {\n debug(\n 'executing action',\n planType,\n param,\n `context.element.center: ${context.element?.center}`,\n );\n const actionSpace = await this.page.actionSpace();\n const action = actionSpace.find(\n (action) => action.name === planType,\n );\n if (!action) {\n throw new Error(`Action type '${planType}' not found`);\n }\n const actionFn = action.call.bind(this.page);\n return await actionFn(context, param);\n },\n };\n tasks.push(task);\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 async setupPlanningContext(executorContext: 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 ExecutionTaskPlanning).pageContext = pageContext;\n\n return {\n pageContext,\n };\n }\n\n async loadYamlFlowAsPlanning(userInstruction: string, yamlString: string) {\n const taskExecutor = new Executor(taskTitleStr('Action', userInstruction), {\n onTaskStart: this.onTaskStartCallback,\n });\n\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n subType: 'LoadYaml',\n locate: null,\n param: {\n userInstruction,\n },\n executor: async (param, executorContext) => {\n await this.setupPlanningContext(executorContext);\n return {\n output: {\n actions: [],\n more_actions_needed_by_instruction: false,\n log: '',\n yamlString,\n },\n cache: {\n hit: true,\n },\n };\n },\n };\n\n await taskExecutor.append(task);\n await taskExecutor.flush();\n\n return {\n executor: taskExecutor,\n };\n }\n\n private planningTaskFromPrompt(\n userInstruction: string,\n log?: string,\n actionContext?: string,\n ) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n subType: 'Plan',\n locate: null,\n param: {\n userInstruction,\n log,\n },\n executor: async (param, executorContext) => {\n const startTime = Date.now();\n const { pageContext } =\n await this.setupPlanningContext(executorContext);\n\n assert(\n this.page.actionSpace,\n 'actionSpace for device is not implemented',\n );\n const actionSpace = await this.page.actionSpace();\n debug(\n 'actionSpace for page is:',\n actionSpace.map((action) => action.name).join(', '),\n );\n assert(Array.isArray(actionSpace), 'actionSpace must be an array');\n if (actionSpace.length === 0) {\n console.warn(\n `ActionSpace for ${this.page.pageType} is empty. This may lead to unexpected behavior.`,\n );\n }\n\n const planResult = await plan(param.userInstruction, {\n context: pageContext,\n log: param.log,\n actionContext,\n pageType: this.page.pageType as PageType,\n actionSpace,\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 executorContext.task.log = {\n ...(executorContext.task.log || {}),\n rawResponse,\n };\n executorContext.task.usage = usage;\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 is prompt created by ai, always a string\n thought: planningAction.locate.prompt as string,\n });\n } else {\n const actionType = planningAction.type;\n const action = actionSpace.find(\n (action) => action.name === actionType,\n );\n if (action && action?.location === 'required') {\n planParsingError = `Location is required for action: ${actionType}, but not provided by planning`;\n stopCollecting = true;\n return acc;\n }\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 - startTime);\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 return {\n output: {\n actions: finalActions,\n more_actions_needed_by_instruction,\n log,\n yamlFlow: planResult.yamlFlow,\n },\n cache: {\n hit: false,\n },\n pageContext,\n };\n },\n };\n\n return task;\n }\n\n private planningTaskToGoal(userInstruction: string) {\n const task: ExecutionTaskPlanningApply = {\n type: 'Planning',\n subType: 'Plan',\n locate: null,\n param: {\n userInstruction,\n },\n executor: async (param, executorContext) => {\n const { pageContext } =\n await this.setupPlanningContext(executorContext);\n\n const imagePayload = await resizeImageForUiTars(\n pageContext.screenshotBase64,\n pageContext.size,\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 planResult: {\n actions: PlanningAction<any>[];\n action_summary: string;\n usage?: AIUsageInfo;\n yamlFlow?: MidsceneYamlFlowItem[];\n rawResponse?: string;\n } = await vlmPlanning({\n userInstruction: param.userInstruction,\n conversationHistory: this.conversationHistory,\n size: pageContext.size,\n });\n\n const { actions, action_summary, usage } = planResult;\n executorContext.task.log = {\n ...(executorContext.task.log || {}),\n rawResponse: planResult.rawResponse,\n };\n executorContext.task.usage = usage;\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 yamlFlow: planResult.yamlFlow,\n },\n cache: {\n hit: false,\n },\n };\n },\n };\n\n return task;\n }\n\n async runPlans(\n title: string,\n plans: PlanningAction[],\n opts?: {\n cacheable?: boolean;\n },\n ): Promise<ExecutionResult> {\n const taskExecutor = new Executor(title, {\n onTaskStart: this.onTaskStartCallback,\n });\n const { tasks } = await this.convertPlanToExecutable(plans, opts);\n await taskExecutor.append(tasks);\n const result = await taskExecutor.flush();\n const { output } = result!;\n return {\n output,\n executor: taskExecutor,\n };\n }\n\n async action(\n userPrompt: string,\n actionContext?: string,\n opts?: {\n cacheable?: boolean;\n },\n ): Promise<\n ExecutionResult<\n | {\n yamlFlow?: MidsceneYamlFlowItem[]; // for cache use\n }\n | undefined\n >\n > {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n\n let planningTask: ExecutionTaskPlanningApply | null =\n this.planningTaskFromPrompt(userPrompt, undefined, actionContext);\n let replanCount = 0;\n const logList: string[] = [];\n\n const yamlFlow: MidsceneYamlFlowItem[] = [];\n const replanningCycleLimit =\n getAIConfigInNumber(MIDSCENE_REPLANNING_CYCLE_LIMIT) ||\n defaultReplanningCycleLimit;\n while (planningTask) {\n if (replanCount > replanningCycleLimit) {\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 result = await taskExecutor.flush();\n const planResult: PlanningAIResponse = result?.output;\n if (taskExecutor.isInErrorState()) {\n return {\n output: planResult,\n executor: taskExecutor,\n };\n }\n\n const plans = planResult.actions || [];\n yamlFlow.push(...(planResult.yamlFlow || []));\n\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans, opts);\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 await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: undefined,\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 logList.length > 0 ? `- ${logList.join('\\n- ')}` : undefined,\n actionContext,\n );\n replanCount++;\n }\n\n return {\n output: {\n yamlFlow,\n },\n executor: taskExecutor,\n };\n }\n\n async actionToGoal(\n userPrompt: string,\n opts?: {\n cacheable?: boolean;\n },\n ): Promise<\n ExecutionResult<\n | {\n yamlFlow?: MidsceneYamlFlowItem[]; // for cache use\n }\n | undefined\n >\n > {\n const taskExecutor = new Executor(taskTitleStr('Action', userPrompt), {\n onTaskStart: this.onTaskStartCallback,\n });\n this.conversationHistory = [];\n const isCompleted = false;\n let currentActionNumber = 0;\n const maxActionNumber = 40;\n\n const yamlFlow: MidsceneYamlFlowItem[] = [];\n while (!isCompleted && currentActionNumber < maxActionNumber) {\n currentActionNumber++;\n const planningTask: ExecutionTaskPlanningApply =\n this.planningTaskToGoal(userPrompt);\n await taskExecutor.append(planningTask);\n const result = await taskExecutor.flush();\n if (taskExecutor.isInErrorState()) {\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n if (!result) {\n throw new Error(\n 'result of taskExecutor.flush() is undefined in function actionToGoal',\n );\n }\n const { output } = result;\n const plans = output.actions;\n yamlFlow.push(...(output.yamlFlow || []));\n let executables: Awaited<ReturnType<typeof this.convertPlanToExecutable>>;\n try {\n executables = await this.convertPlanToExecutable(plans, opts);\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 await taskExecutor.flush();\n\n if (taskExecutor.isInErrorState()) {\n return {\n output: undefined,\n executor: taskExecutor,\n };\n }\n\n if (plans[0].type === 'Finished') {\n break;\n }\n }\n return {\n output: {\n yamlFlow,\n },\n executor: taskExecutor,\n };\n }\n\n private async createTypeQueryTask<T>(\n type: 'Query' | 'Boolean' | 'Number' | 'String' | 'Assert',\n demand: InsightExtractParam,\n opt?: InsightExtractOption,\n multimodalPrompt?: TMultimodalPrompt,\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 // TODO: display image thumbnail in report\n dataDemand: multimodalPrompt\n ? ({\n demand,\n multimodalPrompt,\n } as never)\n : demand, // for user param presentation in report right sidebar\n },\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\n // Get page context for query operations\n const shotTime = Date.now();\n const pageContext = await this.insight.contextRetrieverFn('extract');\n task.pageContext = pageContext;\n\n const recordItem: ExecutionRecorderItem = {\n type: 'screenshot',\n ts: shotTime,\n screenshot: pageContext.screenshotBase64,\n timing: 'before Extract',\n };\n task.recorder = [recordItem];\n\n const ifTypeRestricted = type !== 'Query';\n let demandInput = demand;\n if (ifTypeRestricted) {\n const returnType = type === 'Assert' ? 'Boolean' : type;\n demandInput = {\n result: `${returnType}, ${demand}`,\n };\n }\n\n const { data, usage, thought } = await this.insight.extract<any>(\n demandInput,\n opt,\n multimodalPrompt,\n );\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 thought,\n };\n },\n };\n\n await taskExecutor.append(this.prependExecutorWithScreenshot(queryTask));\n const result = await taskExecutor.flush();\n\n if (!result) {\n throw new Error(\n 'result of taskExecutor.flush() is undefined in function createTypeQueryTask',\n );\n }\n\n const { output, thought } = result;\n\n return {\n output,\n thought,\n executor: taskExecutor,\n };\n }\n\n async query(\n demand: InsightExtractParam,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult> {\n return this.createTypeQueryTask('Query', demand, opt);\n }\n\n async boolean(\n prompt: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<boolean>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n return this.createTypeQueryTask<boolean>(\n 'Boolean',\n textPrompt,\n opt,\n multimodalPrompt,\n );\n }\n\n async number(\n prompt: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<number>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n return this.createTypeQueryTask<number>(\n 'Number',\n textPrompt,\n opt,\n multimodalPrompt,\n );\n }\n\n async string(\n prompt: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<string>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n return this.createTypeQueryTask<string>(\n 'String',\n textPrompt,\n opt,\n multimodalPrompt,\n );\n }\n\n async assert(\n assertion: TUserPrompt,\n opt?: InsightExtractOption,\n ): Promise<ExecutionResult<boolean>> {\n const { textPrompt, multimodalPrompt } = parsePrompt(assertion);\n return await this.createTypeQueryTask<boolean>(\n 'Assert',\n textPrompt,\n opt,\n multimodalPrompt,\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 result = await taskExecutor.flush();\n\n if (!result) {\n throw new Error(\n 'result of taskExecutor.flush() is undefined in function waitFor',\n );\n }\n\n const { output } = result as { output: InsightAssertionResponse };\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"],"names":["debug","getDebug","defaultReplanningCycleLimit","PageTaskExecutor","timing","base64","item","Date","pageContext","element","_element_attributes","elementId","undefined","xpaths","NodeType","info","elementByPositionWithElementInfo","result","error","taskApply","appendAfterExecution","taskWithScreenshot","param","context","args","recorder","task","shot","Promise","sleep","shot2","plans","opts","tasks","plan","_plan_locate","_plan_locate1","taskFind","taskContext","_this_taskCache","_locateCacheRecord_cacheContent","assert","insightDump","usage","dumpCollector","dump","_dump_taskInfo","shotTime","recordItem","elementFromXpath","userExpectedPathHitFlag","cachePrompt","locateCacheRecord","elementFromCache","matchElementFromCache","cacheHitFlag","elementFromPlan","matchElementFromPlan","planHitFlag","elementFromAiLocate","aiLocateHitFlag","currentXpaths","elementXpaths","Error","hitBy","assertPlan","taskAssert","assertion","_plan_param","taskActionError","taskActionFinished","taskActionSleep","taskParam","taskActionDrag","planType","_context_element","actionSpace","action","actionFn","wrappedTasks","index","executorContext","userInstruction","yamlString","taskExecutor","Executor","taskTitleStr","log","actionContext","startTime","Array","console","planResult","actions","more_actions_needed_by_instruction","rawResponse","stopCollecting","bboxCollected","planParsingError","finalActions","acc","planningAction","actionType","timeNow","timeRemaining","_actions_","imagePayload","resizeImageForUiTars","vlmPlanning","action_summary","title","output","userPrompt","planningTask","replanCount","logList","yamlFlow","replanningCycleLimit","getAIConfigInNumber","MIDSCENE_REPLANNING_CYCLE_LIMIT","errorMsg","executables","JSON","isCompleted","currentActionNumber","maxActionNumber","type","demand","opt","multimodalPrompt","queryTask","ifTypeRestricted","demandInput","returnType","data","thought","outputResult","prompt","textPrompt","parsePrompt","conversationHistory","userImgItems","firstUserImgIndex","errorPlan","description","timeoutMs","checkIntervalMs","overallStartTime","errorThought","assertTasks","now","sleepPlan","sleepTasks","page","insight"],"mappings":"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"}
@@ -187,7 +187,7 @@ function trimContextByViewport(execution) {
187
187
  }) : execution.tasks
188
188
  };
189
189
  }
190
- const getMidsceneVersion = ()=>"0.26.6";
190
+ const getMidsceneVersion = ()=>"0.26.7-beta-20250815153024.0";
191
191
  const parsePrompt = (prompt)=>{
192
192
  if ('string' == typeof prompt) return {
193
193
  textPrompt: prompt,
@@ -206,6 +206,7 @@ const commonWebActionsForWebPage = (page)=>[
206
206
  name: 'Tap',
207
207
  description: 'Tap the element',
208
208
  location: 'required',
209
+ interfaceAlias: 'aiTap',
209
210
  call: async (context)=>{
210
211
  const { element } = context;
211
212
  assert(element, 'Element not found, cannot tap');
@@ -230,6 +231,7 @@ const commonWebActionsForWebPage = (page)=>[
230
231
  name: 'Hover',
231
232
  description: 'Move the mouse to the element',
232
233
  location: 'required',
234
+ interfaceAlias: 'aiHover',
233
235
  call: async (context)=>{
234
236
  const { element } = context;
235
237
  assert(element, 'Element not found, cannot hover');
@@ -243,6 +245,7 @@ const commonWebActionsForWebPage = (page)=>[
243
245
  paramDescription: '`value` is the final that should be filled in the input box. No matter what modifications are required, just provide the final value to replace the existing input value. Giving a blank string means clear the input field.',
244
246
  location: 'required',
245
247
  whatToLocate: 'The input field to be filled',
248
+ interfaceAlias: 'aiInput',
246
249
  call: async (context, param)=>{
247
250
  const { element } = context;
248
251
  if (element) {
@@ -258,6 +261,7 @@ const commonWebActionsForWebPage = (page)=>[
258
261
  paramSchema: '{ value: string }',
259
262
  paramDescription: 'The key to be pressed',
260
263
  location: false,
264
+ interfaceAlias: 'aiKeyboardPress',
261
265
  call: async (context, param)=>{
262
266
  const keys = getKeyCommands(param.value);
263
267
  await page.keyboard.press(keys);
@@ -270,6 +274,7 @@ const commonWebActionsForWebPage = (page)=>[
270
274
  paramDescription: 'The direction to scroll, the scroll type, and the distance to scroll. The distance is the number of pixels to scroll. If not specified, use `down` direction, `once` scroll type, and `null` distance.',
271
275
  location: 'optional',
272
276
  whatToLocate: 'The element to be scrolled',
277
+ interfaceAlias: 'aiScroll',
273
278
  call: async (context, param)=>{
274
279
  const { element } = context;
275
280
  const startingPoint = element ? {
@@ -1 +1 @@
1
- {"version":3,"file":"common/utils.mjs","sources":["webpack://@midscene/web/./src/common/utils.ts"],"sourcesContent":["import type { StaticPage } from '@/playground';\nimport type {\n BaseElement,\n DeviceAction,\n ElementTreeNode,\n ExecutionDump,\n ExecutionTask,\n ExecutorContext,\n PlanningLocateParam,\n PlaywrightParserOpt,\n ScrollParam,\n TMultimodalPrompt,\n TUserPrompt,\n UIContext,\n} from '@midscene/core';\nimport { elementByPositionWithElementInfo } from '@midscene/core/ai-model';\nimport { sleep, uploadTestInfoToServer } from '@midscene/core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n traverseTree,\n} from '@midscene/shared/extractor';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport { type DebugFunction, getDebug } 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 type { AbstractPage } from '../page';\nimport { WebElementInfo, type WebUIContext } from '../web-element';\nimport type { WebPage } from './page';\nimport { debug as cacheDebug } from './task-cache';\nimport type { PageTaskExecutor } from './tasks';\nimport { getKeyCommands } from './ui-utils';\n\nconst debug = getDebug('tool:profile');\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\n debug('Getting page URL');\n const url = await page.url();\n debug('URL end');\n\n debug('Uploading test info to server');\n uploadTestInfoToServer({ testUrl: url });\n debug('UploadTestInfoToServer end');\n\n let screenshotBase64: string;\n let tree: ElementTreeNode<ElementInfo>;\n\n debug('Starting parallel operations: screenshot and element tree');\n await Promise.all([\n page.screenshotBase64().then((base64) => {\n screenshotBase64 = base64;\n debug('ScreenshotBase64 end');\n }),\n page.getElementsNodeTree().then(async (treeRoot) => {\n tree = treeRoot;\n debug('GetElementsNodeTree end');\n }),\n ]);\n debug('ParseContextFromWebPage end');\n debug('Traversing element tree');\n const webTree = traverseTree(tree!, (elementInfo) => {\n const { rect, id, content, attributes, indexId, isVisible } = elementInfo;\n return new WebElementInfo({\n rect,\n id,\n content,\n attributes,\n indexId,\n isVisible,\n });\n });\n debug('TraverseTree end');\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const size = await page.size();\n\n debug(`size: ${size.width}x${size.height} dpr: ${size.dpr}`);\n\n if (size.dpr && size.dpr > 1) {\n debug('Resizing screenshot for high DPR display');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n debug('ResizeImgBase64 end');\n }\n\n return {\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\n url,\n };\n}\n\nexport function getReportFileName(tag = 'web') {\n const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\n}\n\nexport function printReportMsg(filepath: string) {\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED =\n 'NOT_IMPLEMENTED_AS_DESIGNED';\n\nexport function replaceIllegalPathCharsAndSpace(str: string) {\n // Only replace characters that are illegal in filenames, but preserve path separators\n return str.replace(/[:*?\"<>| ]/g, '-');\n}\n\nexport function forceClosePopup(\n page: PuppeteerPage | PlaywrightPage,\n debug: DebugFunction,\n) {\n page.on('popup', async (popup) => {\n if (!popup) {\n console.warn('got a popup event, but the popup is not ready yet, skip');\n return;\n }\n const url = await (popup as PuppeteerPage).url();\n console.log(`Popup opened: ${url}`);\n if (!(popup as PuppeteerPage).isClosed()) {\n try {\n await (popup as PuppeteerPage).close(); // Close the newly opened TAB\n } catch (error) {\n debug(`failed to close popup ${url}, error: ${error}`);\n }\n } else {\n debug(`popup is already closed, skip close ${url}`);\n }\n\n if (!page.isClosed()) {\n try {\n await page.goto(url);\n } catch (error) {\n debug(`failed to goto ${url}, error: ${error}`);\n }\n } else {\n debug(`page is already closed, skip goto ${url}`);\n }\n });\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n\nexport async function matchElementFromCache(\n taskExecutor: PageTaskExecutor,\n xpaths: string[] | undefined,\n cachePrompt: TUserPrompt,\n cacheable: boolean | undefined,\n) {\n try {\n if (\n xpaths?.length &&\n taskExecutor.taskCache?.isCacheResultUsed &&\n cacheable !== false\n ) {\n // hit cache, use new id\n for (let i = 0; i < xpaths.length; i++) {\n const element = await taskExecutor.page.getElementInfoByXpath(\n xpaths[i],\n );\n\n if (element?.id) {\n cacheDebug('cache hit, prompt: %s', cachePrompt);\n cacheDebug(\n 'found a new element with same xpath, xpath: %s, id: %s',\n xpaths[i],\n element?.id,\n );\n return element;\n }\n }\n }\n } catch (error) {\n cacheDebug('get element info by xpath error: ', error);\n }\n}\n\nexport function trimContextByViewport(execution: ExecutionDump) {\n function filterVisibleTree(\n node: ElementTreeNode<BaseElement>,\n ): ElementTreeNode<BaseElement> | null {\n if (!node) return null;\n\n // recursively process all children\n const filteredChildren = Array.isArray(node.children)\n ? (node.children\n .map(filterVisibleTree)\n .filter((child) => child !== null) as ElementTreeNode<BaseElement>[])\n : [];\n\n // if the current node is visible, keep it and the filtered children\n if (node.node && node.node.isVisible === true) {\n return {\n ...node,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible, but has visible children, create an empty node to include these children\n if (filteredChildren.length > 0) {\n return {\n node: null,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible and has no visible children, return null\n return null;\n }\n\n return {\n ...execution,\n tasks: Array.isArray(execution.tasks)\n ? execution.tasks.map((task: ExecutionTask) => {\n const newTask = { ...task };\n if (task.pageContext?.tree) {\n newTask.pageContext = {\n ...task.pageContext,\n tree: filterVisibleTree(task.pageContext.tree) || {\n node: null,\n children: [],\n },\n };\n }\n return newTask;\n })\n : execution.tasks,\n };\n}\n\ndeclare const __VERSION__: string | undefined;\n\nexport const getMidsceneVersion = (): string => {\n if (typeof __VERSION__ !== 'undefined') {\n return __VERSION__;\n } else if (\n process.env.__VERSION__ &&\n process.env.__VERSION__ !== 'undefined'\n ) {\n return process.env.__VERSION__;\n }\n throw new Error('__VERSION__ inject failed during build');\n};\n\nexport const parsePrompt = (\n prompt: TUserPrompt,\n): {\n textPrompt: string;\n multimodalPrompt?: TMultimodalPrompt;\n} => {\n if (typeof prompt === 'string') {\n return {\n textPrompt: prompt,\n multimodalPrompt: undefined,\n };\n }\n return {\n textPrompt: prompt.prompt,\n multimodalPrompt: prompt.images\n ? {\n images: prompt.images,\n convertHttpImage2Base64: !!prompt.convertHttpImage2Base64,\n }\n : undefined,\n };\n};\n\nexport const commonWebActionsForWebPage = <T extends AbstractPage>(\n page: T,\n): DeviceAction[] => [\n {\n name: 'Tap',\n description: 'Tap the element',\n location: 'required',\n call: async (context) => {\n const { element } = context;\n assert(element, 'Element not found, cannot tap');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n },\n },\n {\n name: 'RightClick',\n description: 'Right click the element',\n location: 'required',\n call: async (context) => {\n const { element } = context;\n assert(element, 'Element not found, cannot right click');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'right',\n });\n },\n },\n {\n name: 'Hover',\n description: 'Move the mouse to the element',\n location: 'required',\n call: async (context) => {\n const { element } = context;\n assert(element, 'Element not found, cannot hover');\n await page.mouse.move(element.center[0], element.center[1]);\n },\n },\n {\n name: 'Input',\n description: 'Replace the input field with a new value',\n paramSchema: '{ value: string }',\n paramDescription:\n '`value` is the final that should be filled in the input box. No matter what modifications are required, just provide the final value to replace the existing input value. Giving a blank string means clear the input field.',\n location: 'required',\n whatToLocate: 'The input field to be filled',\n call: async (context, param) => {\n const { element } = context;\n if (element) {\n await page.clearInput(element as unknown as ElementInfo);\n\n if (!param || !param.value) {\n return;\n }\n }\n\n // Note: there is another implementation in AndroidDevicePage, which is more complex\n await page.keyboard.type(param.value);\n },\n } as DeviceAction<{ value: string }>,\n {\n name: 'KeyboardPress',\n description: 'Press a key',\n paramSchema: '{ value: string }',\n paramDescription: 'The key to be pressed',\n location: false,\n call: async (context, param) => {\n const keys = getKeyCommands(param.value);\n await page.keyboard.press(keys as any); // TODO: fix this type error\n },\n } as DeviceAction<{ value: string }>,\n {\n name: 'Scroll',\n description: 'Scroll the page or an element',\n paramSchema:\n '{ direction: \"down\"(default) | \"up\" | \"right\" | \"left\", scrollType: \"once\" (default) | \"untilBottom\" | \"untilTop\" | \"untilRight\" | \"untilLeft\", distance: number | null }',\n paramDescription:\n 'The direction to scroll, the scroll type, and the distance to scroll. The distance is the number of pixels to scroll. If not specified, use `down` direction, `once` scroll type, and `null` distance.',\n location: 'optional',\n whatToLocate: 'The element to be scrolled',\n call: async (context, param) => {\n const { element } = context;\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = param?.scrollType;\n if (scrollToEventName === 'untilTop') {\n await page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'untilBottom') {\n await page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'untilRight') {\n await page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'untilLeft') {\n await page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'once' || !scrollToEventName) {\n if (param?.direction === 'down' || !param || !param.direction) {\n await page.scrollDown(param?.distance || undefined, startingPoint);\n } else if (param.direction === 'up') {\n await page.scrollUp(param.distance || undefined, startingPoint);\n } else if (param.direction === 'left') {\n await page.scrollLeft(param.distance || undefined, startingPoint);\n } else if (param.direction === 'right') {\n await page.scrollRight(param.distance || undefined, startingPoint);\n } else {\n throw new Error(`Unknown scroll direction: ${param.direction}`);\n }\n // until mouse event is done\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(\n param,\n )}`,\n );\n }\n },\n } as DeviceAction<ScrollParam>,\n];\n"],"names":["debug","getDebug","parseContextFromWebPage","page","_opt","assert","url","uploadTestInfoToServer","screenshotBase64","tree","Promise","base64","treeRoot","webTree","traverseTree","elementInfo","rect","id","content","attributes","indexId","isVisible","WebElementInfo","size","resizeImgBase64","getReportFileName","tag","reportTagName","getAIConfig","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","logMsg","getCurrentExecutionFile","trace","error","Error","stackTrace","pkgDir","process","stackLines","line","match","targetFileName","testFileIndex","Map","generateCacheId","fileName","taskFile","console","currentIndex","undefined","ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED","replaceIllegalPathCharsAndSpace","str","forceClosePopup","popup","matchElementFromPlan","planLocateParam","getNodeFromCacheList","centerPosition","Math","element","elementByPositionWithElementInfo","generateElementByPosition","matchElementFromCache","taskExecutor","xpaths","cachePrompt","cacheable","_taskExecutor_taskCache","i","cacheDebug","trimContextByViewport","execution","filterVisibleTree","node","filteredChildren","Array","child","task","_task_pageContext","newTask","getMidsceneVersion","__VERSION__","parsePrompt","prompt","commonWebActionsForWebPage","context","param","keys","getKeyCommands","startingPoint","scrollToEventName","JSON","sleep"],"mappings":"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"}
1
+ {"version":3,"file":"common/utils.mjs","sources":["webpack://@midscene/web/./src/common/utils.ts"],"sourcesContent":["import type { StaticPage } from '@/playground';\nimport type {\n BaseElement,\n DeviceAction,\n ElementTreeNode,\n ExecutionDump,\n ExecutionTask,\n ExecutorContext,\n PlanningLocateParam,\n PlaywrightParserOpt,\n ScrollParam,\n TMultimodalPrompt,\n TUserPrompt,\n UIContext,\n} from '@midscene/core';\nimport { elementByPositionWithElementInfo } from '@midscene/core/ai-model';\nimport { sleep, uploadTestInfoToServer } from '@midscene/core/utils';\nimport { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n traverseTree,\n} from '@midscene/shared/extractor';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport { type DebugFunction, getDebug } 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 type { AbstractPage } from '../page';\nimport { WebElementInfo, type WebUIContext } from '../web-element';\nimport type { WebPage } from './page';\nimport { debug as cacheDebug } from './task-cache';\nimport type { PageTaskExecutor } from './tasks';\nimport { getKeyCommands } from './ui-utils';\n\nconst debug = getDebug('tool:profile');\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\n debug('Getting page URL');\n const url = await page.url();\n debug('URL end');\n\n debug('Uploading test info to server');\n uploadTestInfoToServer({ testUrl: url });\n debug('UploadTestInfoToServer end');\n\n let screenshotBase64: string;\n let tree: ElementTreeNode<ElementInfo>;\n\n debug('Starting parallel operations: screenshot and element tree');\n await Promise.all([\n page.screenshotBase64().then((base64) => {\n screenshotBase64 = base64;\n debug('ScreenshotBase64 end');\n }),\n page.getElementsNodeTree().then(async (treeRoot) => {\n tree = treeRoot;\n debug('GetElementsNodeTree end');\n }),\n ]);\n debug('ParseContextFromWebPage end');\n debug('Traversing element tree');\n const webTree = traverseTree(tree!, (elementInfo) => {\n const { rect, id, content, attributes, indexId, isVisible } = elementInfo;\n return new WebElementInfo({\n rect,\n id,\n content,\n attributes,\n indexId,\n isVisible,\n });\n });\n debug('TraverseTree end');\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const size = await page.size();\n\n debug(`size: ${size.width}x${size.height} dpr: ${size.dpr}`);\n\n if (size.dpr && size.dpr > 1) {\n debug('Resizing screenshot for high DPR display');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n debug('ResizeImgBase64 end');\n }\n\n return {\n tree: webTree,\n size,\n screenshotBase64: screenshotBase64!,\n url,\n };\n}\n\nexport function getReportFileName(tag = 'web') {\n const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\n}\n\nexport function printReportMsg(filepath: string) {\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED =\n 'NOT_IMPLEMENTED_AS_DESIGNED';\n\nexport function replaceIllegalPathCharsAndSpace(str: string) {\n // Only replace characters that are illegal in filenames, but preserve path separators\n return str.replace(/[:*?\"<>| ]/g, '-');\n}\n\nexport function forceClosePopup(\n page: PuppeteerPage | PlaywrightPage,\n debug: DebugFunction,\n) {\n page.on('popup', async (popup) => {\n if (!popup) {\n console.warn('got a popup event, but the popup is not ready yet, skip');\n return;\n }\n const url = await (popup as PuppeteerPage).url();\n console.log(`Popup opened: ${url}`);\n if (!(popup as PuppeteerPage).isClosed()) {\n try {\n await (popup as PuppeteerPage).close(); // Close the newly opened TAB\n } catch (error) {\n debug(`failed to close popup ${url}, error: ${error}`);\n }\n } else {\n debug(`popup is already closed, skip close ${url}`);\n }\n\n if (!page.isClosed()) {\n try {\n await page.goto(url);\n } catch (error) {\n debug(`failed to goto ${url}, error: ${error}`);\n }\n } else {\n debug(`page is already closed, skip goto ${url}`);\n }\n });\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n\nexport async function matchElementFromCache(\n taskExecutor: PageTaskExecutor,\n xpaths: string[] | undefined,\n cachePrompt: TUserPrompt,\n cacheable: boolean | undefined,\n) {\n try {\n if (\n xpaths?.length &&\n taskExecutor.taskCache?.isCacheResultUsed &&\n cacheable !== false\n ) {\n // hit cache, use new id\n for (let i = 0; i < xpaths.length; i++) {\n const element = await taskExecutor.page.getElementInfoByXpath(\n xpaths[i],\n );\n\n if (element?.id) {\n cacheDebug('cache hit, prompt: %s', cachePrompt);\n cacheDebug(\n 'found a new element with same xpath, xpath: %s, id: %s',\n xpaths[i],\n element?.id,\n );\n return element;\n }\n }\n }\n } catch (error) {\n cacheDebug('get element info by xpath error: ', error);\n }\n}\n\nexport function trimContextByViewport(execution: ExecutionDump) {\n function filterVisibleTree(\n node: ElementTreeNode<BaseElement>,\n ): ElementTreeNode<BaseElement> | null {\n if (!node) return null;\n\n // recursively process all children\n const filteredChildren = Array.isArray(node.children)\n ? (node.children\n .map(filterVisibleTree)\n .filter((child) => child !== null) as ElementTreeNode<BaseElement>[])\n : [];\n\n // if the current node is visible, keep it and the filtered children\n if (node.node && node.node.isVisible === true) {\n return {\n ...node,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible, but has visible children, create an empty node to include these children\n if (filteredChildren.length > 0) {\n return {\n node: null,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible and has no visible children, return null\n return null;\n }\n\n return {\n ...execution,\n tasks: Array.isArray(execution.tasks)\n ? execution.tasks.map((task: ExecutionTask) => {\n const newTask = { ...task };\n if (task.pageContext?.tree) {\n newTask.pageContext = {\n ...task.pageContext,\n tree: filterVisibleTree(task.pageContext.tree) || {\n node: null,\n children: [],\n },\n };\n }\n return newTask;\n })\n : execution.tasks,\n };\n}\n\ndeclare const __VERSION__: string | undefined;\n\nexport const getMidsceneVersion = (): string => {\n if (typeof __VERSION__ !== 'undefined') {\n return __VERSION__;\n } else if (\n process.env.__VERSION__ &&\n process.env.__VERSION__ !== 'undefined'\n ) {\n return process.env.__VERSION__;\n }\n throw new Error('__VERSION__ inject failed during build');\n};\n\nexport const parsePrompt = (\n prompt: TUserPrompt,\n): {\n textPrompt: string;\n multimodalPrompt?: TMultimodalPrompt;\n} => {\n if (typeof prompt === 'string') {\n return {\n textPrompt: prompt,\n multimodalPrompt: undefined,\n };\n }\n return {\n textPrompt: prompt.prompt,\n multimodalPrompt: prompt.images\n ? {\n images: prompt.images,\n convertHttpImage2Base64: !!prompt.convertHttpImage2Base64,\n }\n : undefined,\n };\n};\n\nexport const commonWebActionsForWebPage = <T extends AbstractPage>(\n page: T,\n): DeviceAction[] => [\n {\n name: 'Tap',\n description: 'Tap the element',\n location: 'required',\n interfaceAlias: 'aiTap',\n call: async (context) => {\n const { element } = context;\n assert(element, 'Element not found, cannot tap');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n },\n },\n {\n name: 'RightClick',\n description: 'Right click the element',\n location: 'required',\n call: async (context) => {\n const { element } = context;\n assert(element, 'Element not found, cannot right click');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'right',\n });\n },\n },\n {\n name: 'Hover',\n description: 'Move the mouse to the element',\n location: 'required',\n interfaceAlias: 'aiHover',\n call: async (context) => {\n const { element } = context;\n assert(element, 'Element not found, cannot hover');\n await page.mouse.move(element.center[0], element.center[1]);\n },\n },\n {\n name: 'Input',\n description: 'Replace the input field with a new value',\n paramSchema: '{ value: string }',\n paramDescription:\n '`value` is the final that should be filled in the input box. No matter what modifications are required, just provide the final value to replace the existing input value. Giving a blank string means clear the input field.',\n location: 'required',\n whatToLocate: 'The input field to be filled',\n interfaceAlias: 'aiInput',\n call: async (context, param) => {\n const { element } = context;\n if (element) {\n await page.clearInput(element as unknown as ElementInfo);\n\n if (!param || !param.value) {\n return;\n }\n }\n\n // Note: there is another implementation in AndroidDevicePage, which is more complex\n await page.keyboard.type(param.value);\n },\n } as DeviceAction<{ value: string }>,\n {\n name: 'KeyboardPress',\n description: 'Press a key',\n paramSchema: '{ value: string }',\n paramDescription: 'The key to be pressed',\n location: false,\n interfaceAlias: 'aiKeyboardPress',\n call: async (context, param) => {\n const keys = getKeyCommands(param.value);\n await page.keyboard.press(keys as any); // TODO: fix this type error\n },\n } as DeviceAction<{ value: string }>,\n {\n name: 'Scroll',\n description: 'Scroll the page or an element',\n paramSchema:\n '{ direction: \"down\"(default) | \"up\" | \"right\" | \"left\", scrollType: \"once\" (default) | \"untilBottom\" | \"untilTop\" | \"untilRight\" | \"untilLeft\", distance: number | null }',\n paramDescription:\n 'The direction to scroll, the scroll type, and the distance to scroll. The distance is the number of pixels to scroll. If not specified, use `down` direction, `once` scroll type, and `null` distance.',\n location: 'optional',\n whatToLocate: 'The element to be scrolled',\n interfaceAlias: 'aiScroll',\n call: async (context, param) => {\n const { element } = context;\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = param?.scrollType;\n if (scrollToEventName === 'untilTop') {\n await page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'untilBottom') {\n await page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'untilRight') {\n await page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'untilLeft') {\n await page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'once' || !scrollToEventName) {\n if (param?.direction === 'down' || !param || !param.direction) {\n await page.scrollDown(param?.distance || undefined, startingPoint);\n } else if (param.direction === 'up') {\n await page.scrollUp(param.distance || undefined, startingPoint);\n } else if (param.direction === 'left') {\n await page.scrollLeft(param.distance || undefined, startingPoint);\n } else if (param.direction === 'right') {\n await page.scrollRight(param.distance || undefined, startingPoint);\n } else {\n throw new Error(`Unknown scroll direction: ${param.direction}`);\n }\n // until mouse event is done\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(\n param,\n )}`,\n );\n }\n },\n } as DeviceAction<ScrollParam>,\n];\n"],"names":["debug","getDebug","parseContextFromWebPage","page","_opt","assert","url","uploadTestInfoToServer","screenshotBase64","tree","Promise","base64","treeRoot","webTree","traverseTree","elementInfo","rect","id","content","attributes","indexId","isVisible","WebElementInfo","size","resizeImgBase64","getReportFileName","tag","reportTagName","getAIConfig","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","logMsg","getCurrentExecutionFile","trace","error","Error","stackTrace","pkgDir","process","stackLines","line","match","targetFileName","testFileIndex","Map","generateCacheId","fileName","taskFile","console","currentIndex","undefined","ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED","replaceIllegalPathCharsAndSpace","str","forceClosePopup","popup","matchElementFromPlan","planLocateParam","getNodeFromCacheList","centerPosition","Math","element","elementByPositionWithElementInfo","generateElementByPosition","matchElementFromCache","taskExecutor","xpaths","cachePrompt","cacheable","_taskExecutor_taskCache","i","cacheDebug","trimContextByViewport","execution","filterVisibleTree","node","filteredChildren","Array","child","task","_task_pageContext","newTask","getMidsceneVersion","__VERSION__","parsePrompt","prompt","commonWebActionsForWebPage","context","param","keys","getKeyCommands","startingPoint","scrollToEventName","JSON","sleep"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
2
  import { basename, dirname, join, resolve as external_node_path_resolve } from "node:path";
3
3
  import { assert, ifInBrowser, ifInWorker } from "@midscene/shared/utils";
4
+ import { actionSpaceTypePrefix } from "@midscene/core/ai-model";
4
5
  import { getMidsceneRunSubDir } from "@midscene/shared/common";
5
6
  function _define_property(obj, key, value) {
6
7
  if (key in obj) Object.defineProperty(obj, key, {
@@ -155,24 +156,62 @@ class ScriptPlayer {
155
156
  if ('string' == typeof ms) msNumber = Number.parseInt(ms, 10);
156
157
  assert(msNumber && msNumber > 0, `ms for sleep must be greater than 0, but got ${ms}`);
157
158
  await new Promise((resolve)=>setTimeout(resolve, msNumber));
158
- } else if ('aiTap' in flowItem) {
159
- const tapTask = flowItem;
160
- await agent.aiTap(tapTask.aiTap, tapTask);
161
- } else if ('aiRightClick' in flowItem) {
162
- const rightClickTask = flowItem;
163
- await agent.aiRightClick(rightClickTask.aiRightClick, rightClickTask);
164
- } else if ('aiHover' in flowItem) {
165
- const hoverTask = flowItem;
166
- await agent.aiHover(hoverTask.aiHover, hoverTask);
167
159
  } else if ('aiInput' in flowItem) {
168
160
  const inputTask = flowItem;
169
- await agent.aiInput(inputTask.aiInput, inputTask.locate, inputTask);
161
+ if (inputTask.locate) {
162
+ const value = inputTask.aiInput;
163
+ const locatePrompt = inputTask.locate;
164
+ await agent.aiInput(value, locatePrompt, inputTask);
165
+ } else {
166
+ const locatePrompt = inputTask.aiInput;
167
+ const value = inputTask.value;
168
+ if (locatePrompt) await agent.aiInput(locatePrompt, {
169
+ ...inputTask,
170
+ value: value
171
+ });
172
+ else throw new Error('aiInput requires either locatePrompt or value and locate');
173
+ }
170
174
  } else if ('aiKeyboardPress' in flowItem) {
171
175
  const keyboardPressTask = flowItem;
172
- await agent.aiKeyboardPress(keyboardPressTask.aiKeyboardPress, keyboardPressTask.locate, keyboardPressTask);
176
+ if (keyboardPressTask.locate) {
177
+ const keyName = keyboardPressTask.aiKeyboardPress;
178
+ const locatePrompt = keyboardPressTask.locate;
179
+ await agent.aiKeyboardPress(keyName, locatePrompt, keyboardPressTask);
180
+ } else if (keyboardPressTask.key) {
181
+ const locatePrompt = keyboardPressTask.aiKeyboardPress;
182
+ const keyName = keyboardPressTask.key;
183
+ if (locatePrompt) await agent.aiKeyboardPress(locatePrompt, {
184
+ ...keyboardPressTask,
185
+ keyName: keyName
186
+ });
187
+ else throw new Error('aiKeyboardPress in new format requires locatePrompt');
188
+ } else {
189
+ const keyName = keyboardPressTask.aiKeyboardPress;
190
+ await agent.aiKeyboardPress(keyName, void 0, keyboardPressTask);
191
+ }
173
192
  } else if ('aiScroll' in flowItem) {
174
193
  const scrollTask = flowItem;
175
- await agent.aiScroll(scrollTask, scrollTask.locate, scrollTask);
194
+ if (scrollTask.locate) {
195
+ const locatePrompt = scrollTask.locate;
196
+ const scrollParam = {
197
+ direction: scrollTask.direction,
198
+ scrollType: scrollTask.scrollType,
199
+ distance: scrollTask.distance
200
+ };
201
+ await agent.aiScroll(scrollParam, locatePrompt, scrollTask);
202
+ } else {
203
+ const locatePrompt = scrollTask.aiScroll;
204
+ const scrollParam = {
205
+ direction: scrollTask.direction,
206
+ scrollType: scrollTask.scrollType,
207
+ distance: scrollTask.distance
208
+ };
209
+ if (locatePrompt) await agent.aiScroll(locatePrompt, {
210
+ ...scrollTask,
211
+ ...scrollParam
212
+ });
213
+ else await agent.aiScroll(scrollParam, void 0, scrollTask);
214
+ }
176
215
  } else if ("javascript" in flowItem) {
177
216
  const evaluateJavaScriptTask = flowItem;
178
217
  const result = await agent.evaluateJavaScript(evaluateJavaScriptTask.javascript);
@@ -182,7 +221,27 @@ class ScriptPlayer {
182
221
  await agent.logScreenshot(logScreenshotTask.logScreenshot, {
183
222
  content: logScreenshotTask.content || ''
184
223
  });
185
- } else throw new Error(`unknown flowItem: ${JSON.stringify(flowItem)}`);
224
+ } else {
225
+ const actionSpace = this.actionSpace;
226
+ let locatePrompt;
227
+ const matchedAction = actionSpace.find((action)=>{
228
+ const actionInterfaceAlias = action.interfaceAlias;
229
+ if (actionInterfaceAlias && Object.prototype.hasOwnProperty.call(flowItem, actionInterfaceAlias)) {
230
+ locatePrompt = flowItem[actionInterfaceAlias];
231
+ return true;
232
+ }
233
+ const keyOfActionInActionSpace = `${actionSpaceTypePrefix}${action.name}`;
234
+ if (Object.prototype.hasOwnProperty.call(flowItem, keyOfActionInActionSpace)) {
235
+ locatePrompt = flowItem[keyOfActionInActionSpace];
236
+ return true;
237
+ }
238
+ return false;
239
+ });
240
+ if (matchedAction) {
241
+ const { [matchedAction.interfaceAlias]: _, [actionSpaceTypePrefix + matchedAction.name]: __, ...restParams } = flowItem;
242
+ await agent.callActionInActionSpace(matchedAction.name, locatePrompt, restParams);
243
+ } else throw new Error(`unknown flowItem: ${JSON.stringify(flowItem)}`);
244
+ }
186
245
  }
187
246
  this.reportFile = agent.reportFile;
188
247
  await this.flushUnstableLogContent();
@@ -197,6 +256,7 @@ class ScriptPlayer {
197
256
  let freeFn = [];
198
257
  try {
199
258
  const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(platform);
259
+ this.actionSpace = await newAgent.getActionSpace();
200
260
  agent = newAgent;
201
261
  const originalOnTaskStartTip = agent.onTaskStartTip;
202
262
  agent.onTaskStartTip = (tip)=>{
@@ -263,6 +323,7 @@ class ScriptPlayer {
263
323
  _define_property(this, "pageAgent", void 0);
264
324
  _define_property(this, "agentStatusTip", void 0);
265
325
  _define_property(this, "target", void 0);
326
+ _define_property(this, "actionSpace", void 0);
266
327
  _define_property(this, "scriptPath", void 0);
267
328
  this.script = script;
268
329
  this.setupAgent = setupAgent;
@@ -271,6 +332,7 @@ class ScriptPlayer {
271
332
  this.status = 'init';
272
333
  this.unnamedResultIndex = 0;
273
334
  this.pageAgent = null;
335
+ this.actionSpace = [];
274
336
  this.scriptPath = scriptPath;
275
337
  this.result = {};
276
338
  this.target = script.target || script.web || script.android;