@midscene/core 1.0.1-beta-20251030070226.0 → 1.0.1-beta-20251104075048.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 (50) hide show
  1. package/dist/es/agent/agent.mjs +70 -45
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/execution-session.mjs.map +1 -1
  4. package/dist/es/agent/task-builder.mjs +8 -7
  5. package/dist/es/agent/task-builder.mjs.map +1 -1
  6. package/dist/es/agent/tasks.mjs +30 -29
  7. package/dist/es/agent/tasks.mjs.map +1 -1
  8. package/dist/es/agent/ui-utils.mjs +6 -7
  9. package/dist/es/agent/ui-utils.mjs.map +1 -1
  10. package/dist/es/agent/utils.mjs +1 -1
  11. package/dist/es/ai-model/prompt/llm-planning.mjs +84 -66
  12. package/dist/es/ai-model/prompt/llm-planning.mjs.map +1 -1
  13. package/dist/es/device/index.mjs.map +1 -1
  14. package/dist/es/service/index.mjs +1 -1
  15. package/dist/es/service/index.mjs.map +1 -1
  16. package/dist/es/task-runner.mjs +42 -7
  17. package/dist/es/task-runner.mjs.map +1 -1
  18. package/dist/es/types.mjs.map +1 -1
  19. package/dist/es/utils.mjs +2 -2
  20. package/dist/es/yaml/player.mjs +67 -16
  21. package/dist/es/yaml/player.mjs.map +1 -1
  22. package/dist/lib/agent/agent.js +69 -44
  23. package/dist/lib/agent/agent.js.map +1 -1
  24. package/dist/lib/agent/execution-session.js.map +1 -1
  25. package/dist/lib/agent/task-builder.js +8 -7
  26. package/dist/lib/agent/task-builder.js.map +1 -1
  27. package/dist/lib/agent/tasks.js +32 -28
  28. package/dist/lib/agent/tasks.js.map +1 -1
  29. package/dist/lib/agent/ui-utils.js +6 -7
  30. package/dist/lib/agent/ui-utils.js.map +1 -1
  31. package/dist/lib/agent/utils.js +1 -1
  32. package/dist/lib/ai-model/prompt/llm-planning.js +84 -66
  33. package/dist/lib/ai-model/prompt/llm-planning.js.map +1 -1
  34. package/dist/lib/device/index.js.map +1 -1
  35. package/dist/lib/service/index.js +1 -1
  36. package/dist/lib/service/index.js.map +1 -1
  37. package/dist/lib/task-runner.js +44 -6
  38. package/dist/lib/task-runner.js.map +1 -1
  39. package/dist/lib/types.js.map +1 -1
  40. package/dist/lib/utils.js +2 -2
  41. package/dist/lib/yaml/player.js +67 -16
  42. package/dist/lib/yaml/player.js.map +1 -1
  43. package/dist/types/agent/agent.d.ts +6 -3
  44. package/dist/types/agent/execution-session.d.ts +7 -4
  45. package/dist/types/agent/tasks.d.ts +7 -0
  46. package/dist/types/device/index.d.ts +3 -3
  47. package/dist/types/task-runner.d.ts +15 -3
  48. package/dist/types/types.d.ts +24 -6
  49. package/dist/types/yaml.d.ts +1 -2
  50. package/package.json +2 -2
@@ -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 { z } from "zod";
4
5
  import { getMidsceneRunSubDir } from "@midscene/shared/common";
5
6
  import { getDebug } from "@midscene/shared/logger";
6
7
  import { buildDetailedLocateParam, buildDetailedLocateParamAndRestParams } from "./utils.mjs";
@@ -15,6 +16,34 @@ function _define_property(obj, key, value) {
15
16
  return obj;
16
17
  }
17
18
  const debug = getDebug('yaml-player');
19
+ const isStringParamSchema = (schema)=>{
20
+ if (!schema) return false;
21
+ const schemaDef = null == schema ? void 0 : schema._def;
22
+ if (!(null == schemaDef ? void 0 : schemaDef.typeName)) return false;
23
+ switch(schemaDef.typeName){
24
+ case z.ZodFirstPartyTypeKind.ZodString:
25
+ case z.ZodFirstPartyTypeKind.ZodEnum:
26
+ case z.ZodFirstPartyTypeKind.ZodNativeEnum:
27
+ return true;
28
+ case z.ZodFirstPartyTypeKind.ZodLiteral:
29
+ return 'string' == typeof schemaDef.value;
30
+ case z.ZodFirstPartyTypeKind.ZodOptional:
31
+ case z.ZodFirstPartyTypeKind.ZodNullable:
32
+ case z.ZodFirstPartyTypeKind.ZodDefault:
33
+ return isStringParamSchema(schemaDef.innerType);
34
+ case z.ZodFirstPartyTypeKind.ZodEffects:
35
+ return isStringParamSchema(schemaDef.schema);
36
+ case z.ZodFirstPartyTypeKind.ZodPipeline:
37
+ return isStringParamSchema(schemaDef.out);
38
+ case z.ZodFirstPartyTypeKind.ZodUnion:
39
+ {
40
+ const options = schemaDef.options;
41
+ return Array.isArray(options) ? options.every((option)=>isStringParamSchema(option)) : false;
42
+ }
43
+ default:
44
+ return false;
45
+ }
46
+ };
18
47
  class ScriptPlayer {
19
48
  setResult(key, value) {
20
49
  const keyToUse = key || this.unnamedResultIndex++;
@@ -222,34 +251,56 @@ class ScriptPlayer {
222
251
  } else {
223
252
  const actionSpace = this.actionSpace;
224
253
  let locatePromptShortcut;
254
+ let actionParamForMatchedAction;
225
255
  const matchedAction = actionSpace.find((action)=>{
226
256
  const actionInterfaceAlias = action.interfaceAlias;
227
257
  if (actionInterfaceAlias && Object.prototype.hasOwnProperty.call(flowItem, actionInterfaceAlias)) {
228
- locatePromptShortcut = flowItem[actionInterfaceAlias];
258
+ actionParamForMatchedAction = flowItem[actionInterfaceAlias];
259
+ if ('string' == typeof actionParamForMatchedAction) locatePromptShortcut = actionParamForMatchedAction;
229
260
  return true;
230
261
  }
231
262
  const keyOfActionInActionSpace = action.name;
232
263
  if (Object.prototype.hasOwnProperty.call(flowItem, keyOfActionInActionSpace)) {
233
- locatePromptShortcut = flowItem[keyOfActionInActionSpace];
264
+ actionParamForMatchedAction = flowItem[keyOfActionInActionSpace];
265
+ if ('string' == typeof actionParamForMatchedAction) locatePromptShortcut = actionParamForMatchedAction;
234
266
  return true;
235
267
  }
236
268
  return false;
237
269
  });
238
270
  assert(matchedAction, `unknown flowItem in yaml: ${JSON.stringify(flowItem)}`);
239
- const flowItemForProcessing = locatePromptShortcut ? {
240
- ...flowItem,
241
- prompt: locatePromptShortcut
242
- } : flowItem;
243
- const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePromptShortcut || '', flowItemForProcessing, [
244
- matchedAction.name,
245
- matchedAction.interfaceAlias || '_never_mind_'
246
- ]);
247
- const flowParams = {
248
- ...restParams,
249
- locate: locateParam
250
- };
251
- debug(`matchedAction: ${matchedAction.name}`, `flowParams: ${JSON.stringify(flowParams, null, 2)}`);
252
- await agent.callActionInActionSpace(matchedAction.name, flowParams);
271
+ const schemaIsStringParam = isStringParamSchema(matchedAction.paramSchema);
272
+ let stringParamToCall;
273
+ if ('string' == typeof actionParamForMatchedAction && schemaIsStringParam) if (matchedAction.paramSchema) {
274
+ const parseResult = matchedAction.paramSchema.safeParse(actionParamForMatchedAction);
275
+ if (parseResult.success && 'string' == typeof parseResult.data) stringParamToCall = parseResult.data;
276
+ else if (!parseResult.success) {
277
+ debug(`parse failed for action ${matchedAction.name} with string param`, parseResult.error);
278
+ stringParamToCall = actionParamForMatchedAction;
279
+ }
280
+ } else stringParamToCall = actionParamForMatchedAction;
281
+ if (void 0 !== stringParamToCall) {
282
+ debug(`matchedAction: ${matchedAction.name}`, `flowParams: ${JSON.stringify(stringParamToCall)}`);
283
+ const result = await agent.callActionInActionSpace(matchedAction.name, stringParamToCall);
284
+ const resultName = flowItem.name;
285
+ if (void 0 !== result) this.setResult(resultName, result);
286
+ } else {
287
+ const sourceForParams = locatePromptShortcut && 'string' == typeof actionParamForMatchedAction ? {
288
+ ...flowItem,
289
+ prompt: locatePromptShortcut
290
+ } : 'object' == typeof actionParamForMatchedAction && null !== actionParamForMatchedAction ? actionParamForMatchedAction : flowItem;
291
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePromptShortcut || '', sourceForParams, [
292
+ matchedAction.name,
293
+ matchedAction.interfaceAlias || '_never_mind_'
294
+ ]);
295
+ const flowParams = {
296
+ ...restParams,
297
+ locate: locateParam
298
+ };
299
+ debug(`matchedAction: ${matchedAction.name}`, `flowParams: ${JSON.stringify(flowParams, null, 2)}`);
300
+ const result = await agent.callActionInActionSpace(matchedAction.name, flowParams);
301
+ const resultName = flowItem.name;
302
+ if (void 0 !== result) this.setResult(resultName, result);
303
+ }
253
304
  }
254
305
  }
255
306
  this.reportFile = agent.reportFile;
@@ -1 +1 @@
1
- {"version":3,"file":"yaml/player.mjs","sources":["webpack://@midscene/core/./src/yaml/player.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { assert, ifInBrowser, ifInWorker } from '@midscene/shared/utils';\n\n// previous defined yaml flow, as a helper\ninterface MidsceneYamlFlowItemAIInput extends LocateOption {\n // previous version\n // aiInput: string; // value to input\n // locate: TUserPrompt; // where to input\n aiInput: TUserPrompt | undefined; // where to input\n value: string | number; // value to input\n}\n\ninterface MidsceneYamlFlowItemAIKeyboardPress extends LocateOption {\n // previous version\n // aiKeyboardPress: string;\n // locate?: TUserPrompt; // where to press, optional\n aiKeyboardPress: TUserPrompt | undefined; // where to press\n keyName: string; // key to press\n}\n\ninterface MidsceneYamlFlowItemAIScroll extends LocateOption, ScrollParam {\n // previous version\n // aiScroll: null;\n // locate?: TUserPrompt; // which area to scroll, optional\n aiScroll: TUserPrompt | undefined; // which area to scroll\n}\n\nimport type { Agent } from '@/agent/agent';\nimport type { TUserPrompt } from '@/ai-model/common';\nimport type {\n DeviceAction,\n FreeFn,\n LocateOption,\n MidsceneYamlFlowItemAIAction,\n MidsceneYamlFlowItemAIAsk,\n MidsceneYamlFlowItemAIAssert,\n MidsceneYamlFlowItemAIBoolean,\n MidsceneYamlFlowItemAILocate,\n MidsceneYamlFlowItemAINumber,\n MidsceneYamlFlowItemAIQuery,\n MidsceneYamlFlowItemAIString,\n MidsceneYamlFlowItemAIWaitFor,\n MidsceneYamlFlowItemEvaluateJavaScript,\n MidsceneYamlFlowItemLogScreenshot,\n MidsceneYamlFlowItemSleep,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n ScrollParam,\n} from '@/types';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport { getDebug } from '@midscene/shared/logger';\nimport {\n buildDetailedLocateParam,\n buildDetailedLocateParamAndRestParams,\n} from './utils';\n\nconst debug = getDebug('yaml-player');\nexport class ScriptPlayer<T extends MidsceneYamlScriptEnv> {\n public currentTaskIndex?: number;\n public taskStatusList: ScriptPlayerTaskStatus[] = [];\n public status: ScriptPlayerStatusValue = 'init';\n public reportFile?: string | null;\n public result: Record<string, any>;\n private unnamedResultIndex = 0;\n public output?: string | null;\n public unstableLogContent?: string | null;\n public errorInSetup?: Error;\n private interfaceAgent: Agent | null = null;\n public agentStatusTip?: string;\n public target?: MidsceneYamlScriptEnv;\n private actionSpace: DeviceAction[] = [];\n private scriptPath?: string;\n constructor(\n private script: MidsceneYamlScript,\n private setupAgent: (platform: T) => Promise<{\n agent: Agent;\n freeFn: FreeFn[];\n }>,\n public onTaskStatusChange?: (taskStatus: ScriptPlayerTaskStatus) => void,\n scriptPath?: string,\n ) {\n this.scriptPath = scriptPath;\n this.result = {};\n this.target =\n script.target ||\n script.web ||\n script.android ||\n script.ios ||\n script.config;\n\n if (ifInBrowser || ifInWorker) {\n this.output = undefined;\n debug('output is undefined in browser or worker');\n } else if (this.target?.output) {\n this.output = resolve(process.cwd(), this.target.output);\n debug('setting output by config.output', this.output);\n } else {\n const scriptName = this.scriptPath\n ? basename(this.scriptPath, '.yaml').replace(/\\.(ya?ml)$/i, '')\n : 'script';\n this.output = join(\n getMidsceneRunSubDir('output'),\n `${scriptName}-${Date.now()}.json`,\n );\n debug('setting output by script path', this.output);\n }\n\n if (ifInBrowser || ifInWorker) {\n this.unstableLogContent = undefined;\n } else if (typeof this.target?.unstableLogContent === 'string') {\n this.unstableLogContent = resolve(\n process.cwd(),\n this.target.unstableLogContent,\n );\n } else if (this.target?.unstableLogContent === true) {\n this.unstableLogContent = join(\n getMidsceneRunSubDir('output'),\n 'unstableLogContent.json',\n );\n }\n\n this.taskStatusList = (script.tasks || []).map((task, taskIndex) => ({\n ...task,\n index: taskIndex,\n status: 'init',\n totalSteps: task.flow?.length || 0,\n }));\n }\n\n private setResult(key: string | undefined, value: any) {\n const keyToUse = key || this.unnamedResultIndex++;\n if (this.result[keyToUse]) {\n console.warn(`result key ${keyToUse} already exists, will overwrite`);\n }\n this.result[keyToUse] = value;\n\n return this.flushResult();\n }\n\n private setPlayerStatus(status: ScriptPlayerStatusValue, error?: Error) {\n this.status = status;\n this.errorInSetup = error;\n }\n\n private notifyCurrentTaskStatusChange(taskIndex?: number) {\n const taskIndexToNotify =\n typeof taskIndex === 'number' ? taskIndex : this.currentTaskIndex;\n\n if (typeof taskIndexToNotify !== 'number') {\n return;\n }\n\n const taskStatus = this.taskStatusList[taskIndexToNotify];\n if (this.onTaskStatusChange) {\n this.onTaskStatusChange(taskStatus);\n }\n }\n\n private async setTaskStatus(\n index: number,\n statusValue: ScriptPlayerStatusValue,\n error?: Error,\n ) {\n this.taskStatusList[index].status = statusValue;\n if (error) {\n this.taskStatusList[index].error = error;\n }\n\n this.notifyCurrentTaskStatusChange(index);\n }\n\n private setTaskIndex(taskIndex: number) {\n this.currentTaskIndex = taskIndex;\n }\n\n private flushResult() {\n if (this.output) {\n const output = resolve(process.cwd(), this.output);\n const outputDir = dirname(output);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(output, JSON.stringify(this.result || {}, undefined, 2));\n }\n }\n\n private flushUnstableLogContent() {\n if (this.unstableLogContent) {\n const content = this.interfaceAgent?._unstableLogContent();\n const filePath = resolve(process.cwd(), this.unstableLogContent);\n const outputDir = dirname(filePath);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(filePath, JSON.stringify(content, null, 2));\n }\n }\n\n async playTask(taskStatus: ScriptPlayerTaskStatus, agent: Agent) {\n const { flow } = taskStatus;\n assert(flow, 'missing flow in task');\n\n for (const flowItemIndex in flow) {\n const currentStep = Number.parseInt(flowItemIndex, 10);\n taskStatus.currentStep = currentStep;\n const flowItem = flow[flowItemIndex];\n debug(\n `playing step ${flowItemIndex}, flowItem=${JSON.stringify(flowItem)}`,\n );\n if (\n 'aiAct' in (flowItem as MidsceneYamlFlowItemAIAction) ||\n 'aiAction' in (flowItem as MidsceneYamlFlowItemAIAction) ||\n 'ai' in (flowItem as MidsceneYamlFlowItemAIAction)\n ) {\n const actionTask = flowItem as MidsceneYamlFlowItemAIAction;\n const prompt = actionTask.aiAct || actionTask.aiAction || actionTask.ai;\n assert(prompt, 'missing prompt for ai (aiAct)');\n await agent.aiAct(prompt, {\n cacheable: actionTask.cacheable,\n });\n } else if ('aiAssert' in (flowItem as MidsceneYamlFlowItemAIAssert)) {\n const assertTask = flowItem as MidsceneYamlFlowItemAIAssert;\n const prompt = assertTask.aiAssert;\n const msg = assertTask.errorMessage;\n assert(prompt, 'missing prompt for aiAssert');\n const { pass, thought, message } =\n (await agent.aiAssert(prompt, msg, {\n keepRawResponse: true,\n })) || {};\n\n this.setResult(assertTask.name, {\n pass,\n thought,\n message,\n });\n\n if (!pass) {\n throw new Error(message);\n }\n } else if ('aiQuery' in (flowItem as MidsceneYamlFlowItemAIQuery)) {\n const queryTask = flowItem as MidsceneYamlFlowItemAIQuery;\n const prompt = queryTask.aiQuery;\n const options = {\n domIncluded: queryTask.domIncluded,\n screenshotIncluded: queryTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiQuery');\n const queryResult = await agent.aiQuery(prompt, options);\n this.setResult(queryTask.name, queryResult);\n } else if ('aiNumber' in (flowItem as MidsceneYamlFlowItemAINumber)) {\n const numberTask = flowItem as MidsceneYamlFlowItemAINumber;\n const prompt = numberTask.aiNumber;\n const options = {\n domIncluded: numberTask.domIncluded,\n screenshotIncluded: numberTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiNumber');\n const numberResult = await agent.aiNumber(prompt, options);\n this.setResult(numberTask.name, numberResult);\n } else if ('aiString' in (flowItem as MidsceneYamlFlowItemAIString)) {\n const stringTask = flowItem as MidsceneYamlFlowItemAIString;\n const prompt = stringTask.aiString;\n const options = {\n domIncluded: stringTask.domIncluded,\n screenshotIncluded: stringTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiString');\n const stringResult = await agent.aiString(prompt, options);\n this.setResult(stringTask.name, stringResult);\n } else if ('aiBoolean' in (flowItem as MidsceneYamlFlowItemAIBoolean)) {\n const booleanTask = flowItem as MidsceneYamlFlowItemAIBoolean;\n const prompt = booleanTask.aiBoolean;\n const options = {\n domIncluded: booleanTask.domIncluded,\n screenshotIncluded: booleanTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiBoolean');\n const booleanResult = await agent.aiBoolean(prompt, options);\n this.setResult(booleanTask.name, booleanResult);\n } else if ('aiAsk' in (flowItem as MidsceneYamlFlowItemAIAsk)) {\n const askTask = flowItem as MidsceneYamlFlowItemAIAsk;\n const prompt = askTask.aiAsk;\n assert(prompt, 'missing prompt for aiAsk');\n const askResult = await agent.aiAsk(prompt);\n this.setResult(askTask.name, askResult);\n } else if ('aiLocate' in (flowItem as MidsceneYamlFlowItemAILocate)) {\n const locateTask = flowItem as MidsceneYamlFlowItemAILocate;\n const prompt = locateTask.aiLocate;\n assert(prompt, 'missing prompt for aiLocate');\n const locateResult = await agent.aiLocate(prompt, locateTask);\n this.setResult(locateTask.name, locateResult);\n } else if ('aiWaitFor' in (flowItem as MidsceneYamlFlowItemAIWaitFor)) {\n const waitForTask = flowItem as MidsceneYamlFlowItemAIWaitFor;\n const prompt = waitForTask.aiWaitFor;\n assert(prompt, 'missing prompt for aiWaitFor');\n const timeout = waitForTask.timeout;\n await agent.aiWaitFor(prompt, { timeoutMs: timeout });\n } else if ('sleep' in (flowItem as MidsceneYamlFlowItemSleep)) {\n const sleepTask = flowItem as MidsceneYamlFlowItemSleep;\n const ms = sleepTask.sleep;\n let msNumber = ms;\n if (typeof ms === 'string') {\n msNumber = Number.parseInt(ms, 10);\n }\n assert(\n msNumber && msNumber > 0,\n `ms for sleep must be greater than 0, but got ${ms}`,\n );\n await new Promise((resolve) => setTimeout(resolve, msNumber));\n } else if (\n 'javascript' in (flowItem as MidsceneYamlFlowItemEvaluateJavaScript)\n ) {\n const evaluateJavaScriptTask =\n flowItem as MidsceneYamlFlowItemEvaluateJavaScript;\n\n const result = await agent.evaluateJavaScript(\n evaluateJavaScriptTask.javascript,\n );\n this.setResult(evaluateJavaScriptTask.name, result);\n } else if (\n 'logScreenshot' in (flowItem as MidsceneYamlFlowItemLogScreenshot) ||\n 'recordToReport' in (flowItem as MidsceneYamlFlowItemLogScreenshot)\n ) {\n const recordTask = flowItem as MidsceneYamlFlowItemLogScreenshot;\n const title =\n recordTask.recordToReport ?? recordTask.logScreenshot ?? 'untitled';\n const content = recordTask.content || '';\n await agent.recordToReport(title, { content });\n } else if ('aiInput' in (flowItem as MidsceneYamlFlowItemAIInput)) {\n // may be input empty string ''\n const {\n aiInput,\n value: rawValue,\n ...inputTask\n } = flowItem as MidsceneYamlFlowItemAIInput;\n\n // Compatibility with previous version:\n // Old format: { aiInput: string (value), locate: TUserPrompt }\n // New format - 1: { aiInput: TUserPrompt, value: string | number }\n // New format - 2: { aiInput: undefined, locate: TUserPrompt, value: string | number }\n let locatePrompt: TUserPrompt | undefined;\n let value: string | number | undefined;\n if ((inputTask as any).locate) {\n // Old format - aiInput is the value, locate is the prompt\n // Keep backward compatibility: empty string is treated as no value\n value = (aiInput as string | number) || rawValue;\n locatePrompt = (inputTask as any).locate;\n } else {\n // New format - aiInput is the prompt, value is the value\n locatePrompt = aiInput || '';\n value = rawValue;\n }\n\n // Convert value to string for Input action\n await agent.callActionInActionSpace('Input', {\n ...inputTask,\n ...(value !== undefined ? { value: String(value) } : {}),\n ...(locatePrompt\n ? { locate: buildDetailedLocateParam(locatePrompt, inputTask) }\n : {}),\n });\n } else if (\n 'aiKeyboardPress' in (flowItem as MidsceneYamlFlowItemAIKeyboardPress)\n ) {\n const { aiKeyboardPress, ...keyboardPressTask } =\n flowItem as MidsceneYamlFlowItemAIKeyboardPress;\n\n // Compatibility with previous version:\n // Old format: { aiKeyboardPress: string (key), locate?: TUserPrompt }\n // New format - 1: { aiKeyboardPress: TUserPrompt, keyName: string }\n // New format - 2: { aiKeyboardPress: , locate?: TUserPrompt, keyName: string }\n let locatePrompt: TUserPrompt | undefined;\n let keyName: string | undefined;\n if ((keyboardPressTask as any).locate) {\n // Old format - aiKeyboardPress is the key, locate is the prompt\n keyName = aiKeyboardPress as string;\n locatePrompt = (keyboardPressTask as any).locate;\n } else if (keyboardPressTask.keyName) {\n // New format - aiKeyboardPress is the prompt, key is the key\n keyName = keyboardPressTask.keyName;\n locatePrompt = aiKeyboardPress;\n } else {\n keyName = aiKeyboardPress as string;\n }\n\n await agent.callActionInActionSpace('KeyboardPress', {\n ...keyboardPressTask,\n ...(keyName ? { keyName } : {}),\n ...(locatePrompt\n ? {\n locate: buildDetailedLocateParam(\n locatePrompt,\n keyboardPressTask,\n ),\n }\n : {}),\n });\n } else if ('aiScroll' in (flowItem as MidsceneYamlFlowItemAIScroll)) {\n const { aiScroll, ...scrollTask } =\n flowItem as MidsceneYamlFlowItemAIScroll;\n\n // Compatibility with previous version:\n // Old format: { aiScroll: null, locate?: TUserPrompt, direction, scrollType, distance? }\n // New format - 1: { aiScroll: TUserPrompt, direction, scrollType, distance? }\n // New format - 2: { aiScroll: undefined, locate: TUserPrompt, direction, scrollType, distance? }\n let locatePrompt: TUserPrompt | undefined;\n if ((scrollTask as any).locate) {\n // Old format - locate is the prompt, aiScroll is null/ignored\n locatePrompt = (scrollTask as any).locate;\n } else {\n // New format - aiScroll is the prompt, or no prompt for global scroll\n locatePrompt = aiScroll;\n }\n\n await agent.callActionInActionSpace('Scroll', {\n ...scrollTask,\n ...(locatePrompt\n ? { locate: buildDetailedLocateParam(locatePrompt, scrollTask) }\n : {}),\n });\n } else {\n // generic action, find the action in actionSpace\n\n /* for aiTap, aiRightClick, the parameters are a flattened data for the 'locate', these are all valid data\n\n - aiTap: 'search input box'\n - aiTap: 'search input box'\n deepThink: true\n cacheable: false\n - aiTap:\n prompt: 'search input box'\n - aiTap:\n prompt: 'search input box'\n deepThink: true\n cacheable: false\n */\n\n const actionSpace = this.actionSpace;\n let locatePromptShortcut: string | undefined;\n const matchedAction = actionSpace.find((action) => {\n const actionInterfaceAlias = action.interfaceAlias;\n if (\n actionInterfaceAlias &&\n Object.prototype.hasOwnProperty.call(flowItem, actionInterfaceAlias)\n ) {\n locatePromptShortcut = flowItem[\n actionInterfaceAlias as keyof typeof flowItem\n ] as string;\n return true;\n }\n\n const keyOfActionInActionSpace = action.name;\n if (\n Object.prototype.hasOwnProperty.call(\n flowItem,\n keyOfActionInActionSpace,\n )\n ) {\n locatePromptShortcut = flowItem[\n keyOfActionInActionSpace as keyof typeof flowItem\n ] as string;\n return true;\n }\n\n return false;\n });\n\n assert(\n matchedAction,\n `unknown flowItem in yaml: ${JSON.stringify(flowItem)}`,\n );\n\n // Create a new object instead of mutating the original flowItem\n // This prevents issues when the same YAML script is executed multiple times\n const flowItemForProcessing = locatePromptShortcut\n ? { ...flowItem, prompt: locatePromptShortcut }\n : flowItem;\n\n const { locateParam, restParams } =\n buildDetailedLocateParamAndRestParams(\n locatePromptShortcut || '',\n flowItemForProcessing as LocateOption,\n [\n matchedAction.name,\n matchedAction.interfaceAlias || '_never_mind_',\n ],\n );\n\n const flowParams = {\n ...restParams,\n locate: locateParam,\n };\n\n debug(\n `matchedAction: ${matchedAction.name}`,\n `flowParams: ${JSON.stringify(flowParams, null, 2)}`,\n );\n await agent.callActionInActionSpace(matchedAction.name, flowParams);\n }\n }\n this.reportFile = agent.reportFile;\n await this.flushUnstableLogContent();\n }\n\n async run() {\n const { target, web, android, ios, tasks } = this.script;\n const webEnv = web || target;\n const androidEnv = android;\n const iosEnv = ios;\n const platform = webEnv || androidEnv || iosEnv;\n\n this.setPlayerStatus('running');\n\n let agent: Agent | null = null;\n let freeFn: FreeFn[] = [];\n try {\n const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(\n platform as T,\n );\n this.actionSpace = await newAgent.getActionSpace();\n agent = newAgent;\n const originalOnTaskStartTip = agent.onTaskStartTip;\n agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') {\n this.agentStatusTip = tip;\n }\n originalOnTaskStartTip?.(tip);\n };\n freeFn = [\n ...(newFreeFn || []),\n {\n name: 'restore-agent-onTaskStartTip',\n fn: () => {\n if (agent) {\n agent.onTaskStartTip = originalOnTaskStartTip;\n }\n },\n },\n ];\n } catch (e) {\n this.setPlayerStatus('error', e as Error);\n return;\n }\n this.interfaceAgent = agent;\n\n let taskIndex = 0;\n this.setPlayerStatus('running');\n let errorFlag = false;\n while (taskIndex < tasks.length) {\n const taskStatus = this.taskStatusList[taskIndex];\n this.setTaskStatus(taskIndex, 'running' as any);\n this.setTaskIndex(taskIndex);\n\n try {\n await this.playTask(taskStatus, this.interfaceAgent);\n this.setTaskStatus(taskIndex, 'done' as any);\n } catch (e) {\n this.setTaskStatus(taskIndex, 'error' as any, e as Error);\n\n if (taskStatus.continueOnError) {\n // nothing more to do\n } else {\n this.reportFile = agent.reportFile;\n errorFlag = true;\n break;\n }\n }\n this.reportFile = agent?.reportFile;\n taskIndex++;\n }\n\n if (errorFlag) {\n this.setPlayerStatus('error');\n } else {\n this.setPlayerStatus('done');\n }\n this.agentStatusTip = '';\n\n // free the resources\n for (const fn of freeFn) {\n try {\n // console.log('freeing', fn.name);\n await fn.fn();\n // console.log('freed', fn.name);\n } catch (e) {\n // console.error('error freeing', fn.name, e);\n }\n }\n }\n}\n"],"names":["debug","getDebug","ScriptPlayer","key","value","keyToUse","console","status","error","taskIndex","taskIndexToNotify","taskStatus","index","statusValue","output","resolve","process","outputDir","dirname","existsSync","mkdirSync","writeFileSync","JSON","undefined","_this_interfaceAgent","content","filePath","agent","flow","assert","flowItemIndex","currentStep","Number","flowItem","actionTask","prompt","assertTask","msg","pass","thought","message","Error","queryTask","options","queryResult","numberTask","numberResult","stringTask","stringResult","booleanTask","booleanResult","askTask","askResult","locateTask","locateResult","waitForTask","timeout","sleepTask","ms","msNumber","Promise","setTimeout","evaluateJavaScriptTask","result","recordTask","title","aiInput","rawValue","inputTask","locatePrompt","String","buildDetailedLocateParam","aiKeyboardPress","keyboardPressTask","keyName","aiScroll","scrollTask","actionSpace","locatePromptShortcut","matchedAction","action","actionInterfaceAlias","Object","keyOfActionInActionSpace","flowItemForProcessing","locateParam","restParams","buildDetailedLocateParamAndRestParams","flowParams","target","web","android","ios","tasks","webEnv","androidEnv","iosEnv","platform","freeFn","newAgent","newFreeFn","originalOnTaskStartTip","tip","e","errorFlag","fn","script","setupAgent","onTaskStatusChange","scriptPath","_this_target","_this_target1","_this_target2","ifInBrowser","ifInWorker","scriptName","basename","join","getMidsceneRunSubDir","Date","task","_task_flow"],"mappings":"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"}
1
+ {"version":3,"file":"yaml/player.mjs","sources":["webpack://@midscene/core/./src/yaml/player.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { assert, ifInBrowser, ifInWorker } from '@midscene/shared/utils';\nimport { type ZodTypeAny, z } from 'zod';\n\n// previous defined yaml flow, as a helper\ninterface MidsceneYamlFlowItemAIInput extends LocateOption {\n // previous version\n // aiInput: string; // value to input\n // locate: TUserPrompt; // where to input\n aiInput: TUserPrompt | undefined; // where to input\n value: string | number; // value to input\n}\n\ninterface MidsceneYamlFlowItemAIKeyboardPress extends LocateOption {\n // previous version\n // aiKeyboardPress: string;\n // locate?: TUserPrompt; // where to press, optional\n aiKeyboardPress: TUserPrompt | undefined; // where to press\n keyName: string; // key to press\n}\n\ninterface MidsceneYamlFlowItemAIScroll extends LocateOption, ScrollParam {\n // previous version\n // aiScroll: null;\n // locate?: TUserPrompt; // which area to scroll, optional\n aiScroll: TUserPrompt | undefined; // which area to scroll\n}\n\nimport type { Agent } from '@/agent/agent';\nimport type { TUserPrompt } from '@/ai-model/common';\nimport type {\n DeviceAction,\n FreeFn,\n LocateOption,\n MidsceneYamlFlowItemAIAction,\n MidsceneYamlFlowItemAIAsk,\n MidsceneYamlFlowItemAIAssert,\n MidsceneYamlFlowItemAIBoolean,\n MidsceneYamlFlowItemAILocate,\n MidsceneYamlFlowItemAINumber,\n MidsceneYamlFlowItemAIQuery,\n MidsceneYamlFlowItemAIString,\n MidsceneYamlFlowItemAIWaitFor,\n MidsceneYamlFlowItemEvaluateJavaScript,\n MidsceneYamlFlowItemLogScreenshot,\n MidsceneYamlFlowItemSleep,\n MidsceneYamlScript,\n MidsceneYamlScriptEnv,\n ScriptPlayerStatusValue,\n ScriptPlayerTaskStatus,\n ScrollParam,\n} from '@/types';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport { getDebug } from '@midscene/shared/logger';\nimport {\n buildDetailedLocateParam,\n buildDetailedLocateParamAndRestParams,\n} from './utils';\n\nconst debug = getDebug('yaml-player');\n\nconst isStringParamSchema = (schema?: ZodTypeAny): boolean => {\n if (!schema) {\n return false;\n }\n\n const schemaDef = (schema as any)?._def;\n if (!schemaDef?.typeName) {\n return false;\n }\n\n switch (schemaDef.typeName) {\n case z.ZodFirstPartyTypeKind.ZodString:\n case z.ZodFirstPartyTypeKind.ZodEnum:\n case z.ZodFirstPartyTypeKind.ZodNativeEnum:\n return true;\n case z.ZodFirstPartyTypeKind.ZodLiteral:\n return typeof schemaDef.value === 'string';\n case z.ZodFirstPartyTypeKind.ZodOptional:\n case z.ZodFirstPartyTypeKind.ZodNullable:\n case z.ZodFirstPartyTypeKind.ZodDefault:\n return isStringParamSchema(schemaDef.innerType);\n case z.ZodFirstPartyTypeKind.ZodEffects:\n return isStringParamSchema(schemaDef.schema);\n case z.ZodFirstPartyTypeKind.ZodPipeline:\n return isStringParamSchema(schemaDef.out);\n case z.ZodFirstPartyTypeKind.ZodUnion: {\n const options = schemaDef.options as ZodTypeAny[] | undefined;\n return Array.isArray(options)\n ? options.every((option) => isStringParamSchema(option))\n : false;\n }\n default:\n return false;\n }\n};\nexport class ScriptPlayer<T extends MidsceneYamlScriptEnv> {\n public currentTaskIndex?: number;\n public taskStatusList: ScriptPlayerTaskStatus[] = [];\n public status: ScriptPlayerStatusValue = 'init';\n public reportFile?: string | null;\n public result: Record<string, any>;\n private unnamedResultIndex = 0;\n public output?: string | null;\n public unstableLogContent?: string | null;\n public errorInSetup?: Error;\n private interfaceAgent: Agent | null = null;\n public agentStatusTip?: string;\n public target?: MidsceneYamlScriptEnv;\n private actionSpace: DeviceAction[] = [];\n private scriptPath?: string;\n constructor(\n private script: MidsceneYamlScript,\n private setupAgent: (platform: T) => Promise<{\n agent: Agent;\n freeFn: FreeFn[];\n }>,\n public onTaskStatusChange?: (taskStatus: ScriptPlayerTaskStatus) => void,\n scriptPath?: string,\n ) {\n this.scriptPath = scriptPath;\n this.result = {};\n this.target =\n script.target ||\n script.web ||\n script.android ||\n script.ios ||\n script.config;\n\n if (ifInBrowser || ifInWorker) {\n this.output = undefined;\n debug('output is undefined in browser or worker');\n } else if (this.target?.output) {\n this.output = resolve(process.cwd(), this.target.output);\n debug('setting output by config.output', this.output);\n } else {\n const scriptName = this.scriptPath\n ? basename(this.scriptPath, '.yaml').replace(/\\.(ya?ml)$/i, '')\n : 'script';\n this.output = join(\n getMidsceneRunSubDir('output'),\n `${scriptName}-${Date.now()}.json`,\n );\n debug('setting output by script path', this.output);\n }\n\n if (ifInBrowser || ifInWorker) {\n this.unstableLogContent = undefined;\n } else if (typeof this.target?.unstableLogContent === 'string') {\n this.unstableLogContent = resolve(\n process.cwd(),\n this.target.unstableLogContent,\n );\n } else if (this.target?.unstableLogContent === true) {\n this.unstableLogContent = join(\n getMidsceneRunSubDir('output'),\n 'unstableLogContent.json',\n );\n }\n\n this.taskStatusList = (script.tasks || []).map((task, taskIndex) => ({\n ...task,\n index: taskIndex,\n status: 'init',\n totalSteps: task.flow?.length || 0,\n }));\n }\n\n private setResult(key: string | undefined, value: any) {\n const keyToUse = key || this.unnamedResultIndex++;\n if (this.result[keyToUse]) {\n console.warn(`result key ${keyToUse} already exists, will overwrite`);\n }\n this.result[keyToUse] = value;\n\n return this.flushResult();\n }\n\n private setPlayerStatus(status: ScriptPlayerStatusValue, error?: Error) {\n this.status = status;\n this.errorInSetup = error;\n }\n\n private notifyCurrentTaskStatusChange(taskIndex?: number) {\n const taskIndexToNotify =\n typeof taskIndex === 'number' ? taskIndex : this.currentTaskIndex;\n\n if (typeof taskIndexToNotify !== 'number') {\n return;\n }\n\n const taskStatus = this.taskStatusList[taskIndexToNotify];\n if (this.onTaskStatusChange) {\n this.onTaskStatusChange(taskStatus);\n }\n }\n\n private async setTaskStatus(\n index: number,\n statusValue: ScriptPlayerStatusValue,\n error?: Error,\n ) {\n this.taskStatusList[index].status = statusValue;\n if (error) {\n this.taskStatusList[index].error = error;\n }\n\n this.notifyCurrentTaskStatusChange(index);\n }\n\n private setTaskIndex(taskIndex: number) {\n this.currentTaskIndex = taskIndex;\n }\n\n private flushResult() {\n if (this.output) {\n const output = resolve(process.cwd(), this.output);\n const outputDir = dirname(output);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(output, JSON.stringify(this.result || {}, undefined, 2));\n }\n }\n\n private flushUnstableLogContent() {\n if (this.unstableLogContent) {\n const content = this.interfaceAgent?._unstableLogContent();\n const filePath = resolve(process.cwd(), this.unstableLogContent);\n const outputDir = dirname(filePath);\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(filePath, JSON.stringify(content, null, 2));\n }\n }\n\n async playTask(taskStatus: ScriptPlayerTaskStatus, agent: Agent) {\n const { flow } = taskStatus;\n assert(flow, 'missing flow in task');\n\n for (const flowItemIndex in flow) {\n const currentStep = Number.parseInt(flowItemIndex, 10);\n taskStatus.currentStep = currentStep;\n const flowItem = flow[flowItemIndex];\n debug(\n `playing step ${flowItemIndex}, flowItem=${JSON.stringify(flowItem)}`,\n );\n if (\n 'aiAct' in (flowItem as MidsceneYamlFlowItemAIAction) ||\n 'aiAction' in (flowItem as MidsceneYamlFlowItemAIAction) ||\n 'ai' in (flowItem as MidsceneYamlFlowItemAIAction)\n ) {\n const actionTask = flowItem as MidsceneYamlFlowItemAIAction;\n const prompt = actionTask.aiAct || actionTask.aiAction || actionTask.ai;\n assert(prompt, 'missing prompt for ai (aiAct)');\n await agent.aiAct(prompt, {\n cacheable: actionTask.cacheable,\n });\n } else if ('aiAssert' in (flowItem as MidsceneYamlFlowItemAIAssert)) {\n const assertTask = flowItem as MidsceneYamlFlowItemAIAssert;\n const prompt = assertTask.aiAssert;\n const msg = assertTask.errorMessage;\n assert(prompt, 'missing prompt for aiAssert');\n const { pass, thought, message } =\n (await agent.aiAssert(prompt, msg, {\n keepRawResponse: true,\n })) || {};\n\n this.setResult(assertTask.name, {\n pass,\n thought,\n message,\n });\n\n if (!pass) {\n throw new Error(message);\n }\n } else if ('aiQuery' in (flowItem as MidsceneYamlFlowItemAIQuery)) {\n const queryTask = flowItem as MidsceneYamlFlowItemAIQuery;\n const prompt = queryTask.aiQuery;\n const options = {\n domIncluded: queryTask.domIncluded,\n screenshotIncluded: queryTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiQuery');\n const queryResult = await agent.aiQuery(prompt, options);\n this.setResult(queryTask.name, queryResult);\n } else if ('aiNumber' in (flowItem as MidsceneYamlFlowItemAINumber)) {\n const numberTask = flowItem as MidsceneYamlFlowItemAINumber;\n const prompt = numberTask.aiNumber;\n const options = {\n domIncluded: numberTask.domIncluded,\n screenshotIncluded: numberTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiNumber');\n const numberResult = await agent.aiNumber(prompt, options);\n this.setResult(numberTask.name, numberResult);\n } else if ('aiString' in (flowItem as MidsceneYamlFlowItemAIString)) {\n const stringTask = flowItem as MidsceneYamlFlowItemAIString;\n const prompt = stringTask.aiString;\n const options = {\n domIncluded: stringTask.domIncluded,\n screenshotIncluded: stringTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiString');\n const stringResult = await agent.aiString(prompt, options);\n this.setResult(stringTask.name, stringResult);\n } else if ('aiBoolean' in (flowItem as MidsceneYamlFlowItemAIBoolean)) {\n const booleanTask = flowItem as MidsceneYamlFlowItemAIBoolean;\n const prompt = booleanTask.aiBoolean;\n const options = {\n domIncluded: booleanTask.domIncluded,\n screenshotIncluded: booleanTask.screenshotIncluded,\n };\n assert(prompt, 'missing prompt for aiBoolean');\n const booleanResult = await agent.aiBoolean(prompt, options);\n this.setResult(booleanTask.name, booleanResult);\n } else if ('aiAsk' in (flowItem as MidsceneYamlFlowItemAIAsk)) {\n const askTask = flowItem as MidsceneYamlFlowItemAIAsk;\n const prompt = askTask.aiAsk;\n assert(prompt, 'missing prompt for aiAsk');\n const askResult = await agent.aiAsk(prompt);\n this.setResult(askTask.name, askResult);\n } else if ('aiLocate' in (flowItem as MidsceneYamlFlowItemAILocate)) {\n const locateTask = flowItem as MidsceneYamlFlowItemAILocate;\n const prompt = locateTask.aiLocate;\n assert(prompt, 'missing prompt for aiLocate');\n const locateResult = await agent.aiLocate(prompt, locateTask);\n this.setResult(locateTask.name, locateResult);\n } else if ('aiWaitFor' in (flowItem as MidsceneYamlFlowItemAIWaitFor)) {\n const waitForTask = flowItem as MidsceneYamlFlowItemAIWaitFor;\n const prompt = waitForTask.aiWaitFor;\n assert(prompt, 'missing prompt for aiWaitFor');\n const timeout = waitForTask.timeout;\n await agent.aiWaitFor(prompt, { timeoutMs: timeout });\n } else if ('sleep' in (flowItem as MidsceneYamlFlowItemSleep)) {\n const sleepTask = flowItem as MidsceneYamlFlowItemSleep;\n const ms = sleepTask.sleep;\n let msNumber = ms;\n if (typeof ms === 'string') {\n msNumber = Number.parseInt(ms, 10);\n }\n assert(\n msNumber && msNumber > 0,\n `ms for sleep must be greater than 0, but got ${ms}`,\n );\n await new Promise((resolve) => setTimeout(resolve, msNumber));\n } else if (\n 'javascript' in (flowItem as MidsceneYamlFlowItemEvaluateJavaScript)\n ) {\n const evaluateJavaScriptTask =\n flowItem as MidsceneYamlFlowItemEvaluateJavaScript;\n\n const result = await agent.evaluateJavaScript(\n evaluateJavaScriptTask.javascript,\n );\n this.setResult(evaluateJavaScriptTask.name, result);\n } else if (\n 'logScreenshot' in (flowItem as MidsceneYamlFlowItemLogScreenshot) ||\n 'recordToReport' in (flowItem as MidsceneYamlFlowItemLogScreenshot)\n ) {\n const recordTask = flowItem as MidsceneYamlFlowItemLogScreenshot;\n const title =\n recordTask.recordToReport ?? recordTask.logScreenshot ?? 'untitled';\n const content = recordTask.content || '';\n await agent.recordToReport(title, { content });\n } else if ('aiInput' in (flowItem as MidsceneYamlFlowItemAIInput)) {\n // may be input empty string ''\n const {\n aiInput,\n value: rawValue,\n ...inputTask\n } = flowItem as MidsceneYamlFlowItemAIInput;\n\n // Compatibility with previous version:\n // Old format: { aiInput: string (value), locate: TUserPrompt }\n // New format - 1: { aiInput: TUserPrompt, value: string | number }\n // New format - 2: { aiInput: undefined, locate: TUserPrompt, value: string | number }\n let locatePrompt: TUserPrompt | undefined;\n let value: string | number | undefined;\n if ((inputTask as any).locate) {\n // Old format - aiInput is the value, locate is the prompt\n // Keep backward compatibility: empty string is treated as no value\n value = (aiInput as string | number) || rawValue;\n locatePrompt = (inputTask as any).locate;\n } else {\n // New format - aiInput is the prompt, value is the value\n locatePrompt = aiInput || '';\n value = rawValue;\n }\n\n // Convert value to string for Input action\n await agent.callActionInActionSpace('Input', {\n ...inputTask,\n ...(value !== undefined ? { value: String(value) } : {}),\n ...(locatePrompt\n ? { locate: buildDetailedLocateParam(locatePrompt, inputTask) }\n : {}),\n });\n } else if (\n 'aiKeyboardPress' in (flowItem as MidsceneYamlFlowItemAIKeyboardPress)\n ) {\n const { aiKeyboardPress, ...keyboardPressTask } =\n flowItem as MidsceneYamlFlowItemAIKeyboardPress;\n\n // Compatibility with previous version:\n // Old format: { aiKeyboardPress: string (key), locate?: TUserPrompt }\n // New format - 1: { aiKeyboardPress: TUserPrompt, keyName: string }\n // New format - 2: { aiKeyboardPress: , locate?: TUserPrompt, keyName: string }\n let locatePrompt: TUserPrompt | undefined;\n let keyName: string | undefined;\n if ((keyboardPressTask as any).locate) {\n // Old format - aiKeyboardPress is the key, locate is the prompt\n keyName = aiKeyboardPress as string;\n locatePrompt = (keyboardPressTask as any).locate;\n } else if (keyboardPressTask.keyName) {\n // New format - aiKeyboardPress is the prompt, key is the key\n keyName = keyboardPressTask.keyName;\n locatePrompt = aiKeyboardPress;\n } else {\n keyName = aiKeyboardPress as string;\n }\n\n await agent.callActionInActionSpace('KeyboardPress', {\n ...keyboardPressTask,\n ...(keyName ? { keyName } : {}),\n ...(locatePrompt\n ? {\n locate: buildDetailedLocateParam(\n locatePrompt,\n keyboardPressTask,\n ),\n }\n : {}),\n });\n } else if ('aiScroll' in (flowItem as MidsceneYamlFlowItemAIScroll)) {\n const { aiScroll, ...scrollTask } =\n flowItem as MidsceneYamlFlowItemAIScroll;\n\n // Compatibility with previous version:\n // Old format: { aiScroll: null, locate?: TUserPrompt, direction, scrollType, distance? }\n // New format - 1: { aiScroll: TUserPrompt, direction, scrollType, distance? }\n // New format - 2: { aiScroll: undefined, locate: TUserPrompt, direction, scrollType, distance? }\n let locatePrompt: TUserPrompt | undefined;\n if ((scrollTask as any).locate) {\n // Old format - locate is the prompt, aiScroll is null/ignored\n locatePrompt = (scrollTask as any).locate;\n } else {\n // New format - aiScroll is the prompt, or no prompt for global scroll\n locatePrompt = aiScroll;\n }\n\n await agent.callActionInActionSpace('Scroll', {\n ...scrollTask,\n ...(locatePrompt\n ? { locate: buildDetailedLocateParam(locatePrompt, scrollTask) }\n : {}),\n });\n } else {\n // generic action, find the action in actionSpace\n\n /* for aiTap, aiRightClick, the parameters are a flattened data for the 'locate', these are all valid data\n\n - aiTap: 'search input box'\n - aiTap: 'search input box'\n deepThink: true\n cacheable: false\n - aiTap:\n prompt: 'search input box'\n - aiTap:\n prompt: 'search input box'\n deepThink: true\n cacheable: false\n */\n\n const actionSpace = this.actionSpace;\n let locatePromptShortcut: string | undefined;\n let actionParamForMatchedAction: unknown;\n const matchedAction = actionSpace.find((action) => {\n const actionInterfaceAlias = action.interfaceAlias;\n if (\n actionInterfaceAlias &&\n Object.prototype.hasOwnProperty.call(flowItem, actionInterfaceAlias)\n ) {\n actionParamForMatchedAction =\n flowItem[actionInterfaceAlias as keyof typeof flowItem];\n if (typeof actionParamForMatchedAction === 'string') {\n locatePromptShortcut = actionParamForMatchedAction;\n }\n return true;\n }\n\n const keyOfActionInActionSpace = action.name;\n if (\n Object.prototype.hasOwnProperty.call(\n flowItem,\n keyOfActionInActionSpace,\n )\n ) {\n actionParamForMatchedAction =\n flowItem[keyOfActionInActionSpace as keyof typeof flowItem];\n if (typeof actionParamForMatchedAction === 'string') {\n locatePromptShortcut = actionParamForMatchedAction;\n }\n return true;\n }\n\n return false;\n });\n\n assert(\n matchedAction,\n `unknown flowItem in yaml: ${JSON.stringify(flowItem)}`,\n );\n\n const schemaIsStringParam = isStringParamSchema(\n matchedAction.paramSchema,\n );\n let stringParamToCall: string | undefined;\n if (\n typeof actionParamForMatchedAction === 'string' &&\n schemaIsStringParam\n ) {\n if (matchedAction.paramSchema) {\n const parseResult = matchedAction.paramSchema.safeParse(\n actionParamForMatchedAction,\n );\n if (parseResult.success && typeof parseResult.data === 'string') {\n stringParamToCall = parseResult.data;\n } else if (!parseResult.success) {\n debug(\n `parse failed for action ${matchedAction.name} with string param`,\n parseResult.error,\n );\n stringParamToCall = actionParamForMatchedAction;\n }\n } else {\n stringParamToCall = actionParamForMatchedAction;\n }\n }\n\n if (stringParamToCall !== undefined) {\n debug(\n `matchedAction: ${matchedAction.name}`,\n `flowParams: ${JSON.stringify(stringParamToCall)}`,\n );\n const result = await agent.callActionInActionSpace(\n matchedAction.name,\n stringParamToCall,\n );\n\n // Store result if there's a name property in flowItem\n const resultName = (flowItem as any).name;\n if (result !== undefined) {\n this.setResult(resultName, result);\n }\n } else {\n // Determine the source for parameter extraction:\n // - If we have a locatePromptShortcut, use the flowItem (for actions like aiTap with prompt)\n // - Otherwise, use actionParamForMatchedAction (for actions like runWdaRequest with structured params)\n const sourceForParams =\n locatePromptShortcut &&\n typeof actionParamForMatchedAction === 'string'\n ? { ...flowItem, prompt: locatePromptShortcut }\n : typeof actionParamForMatchedAction === 'object' &&\n actionParamForMatchedAction !== null\n ? actionParamForMatchedAction\n : flowItem;\n\n const { locateParam, restParams } =\n buildDetailedLocateParamAndRestParams(\n locatePromptShortcut || '',\n sourceForParams as LocateOption,\n [\n matchedAction.name,\n matchedAction.interfaceAlias || '_never_mind_',\n ],\n );\n\n const flowParams = {\n ...restParams,\n locate: locateParam,\n };\n\n debug(\n `matchedAction: ${matchedAction.name}`,\n `flowParams: ${JSON.stringify(flowParams, null, 2)}`,\n );\n const result = await agent.callActionInActionSpace(\n matchedAction.name,\n flowParams,\n );\n\n // Store result if there's a name property in flowItem\n const resultName = (flowItem as any).name;\n if (result !== undefined) {\n this.setResult(resultName, result);\n }\n }\n }\n }\n this.reportFile = agent.reportFile;\n await this.flushUnstableLogContent();\n }\n\n async run() {\n const { target, web, android, ios, tasks } = this.script;\n const webEnv = web || target;\n const androidEnv = android;\n const iosEnv = ios;\n const platform = webEnv || androidEnv || iosEnv;\n\n this.setPlayerStatus('running');\n\n let agent: Agent | null = null;\n let freeFn: FreeFn[] = [];\n try {\n const { agent: newAgent, freeFn: newFreeFn } = await this.setupAgent(\n platform as T,\n );\n this.actionSpace = await newAgent.getActionSpace();\n agent = newAgent;\n const originalOnTaskStartTip = agent.onTaskStartTip;\n agent.onTaskStartTip = (tip) => {\n if (this.status === 'running') {\n this.agentStatusTip = tip;\n }\n originalOnTaskStartTip?.(tip);\n };\n freeFn = [\n ...(newFreeFn || []),\n {\n name: 'restore-agent-onTaskStartTip',\n fn: () => {\n if (agent) {\n agent.onTaskStartTip = originalOnTaskStartTip;\n }\n },\n },\n ];\n } catch (e) {\n this.setPlayerStatus('error', e as Error);\n return;\n }\n this.interfaceAgent = agent;\n\n let taskIndex = 0;\n this.setPlayerStatus('running');\n let errorFlag = false;\n while (taskIndex < tasks.length) {\n const taskStatus = this.taskStatusList[taskIndex];\n this.setTaskStatus(taskIndex, 'running' as any);\n this.setTaskIndex(taskIndex);\n\n try {\n await this.playTask(taskStatus, this.interfaceAgent);\n this.setTaskStatus(taskIndex, 'done' as any);\n } catch (e) {\n this.setTaskStatus(taskIndex, 'error' as any, e as Error);\n\n if (taskStatus.continueOnError) {\n // nothing more to do\n } else {\n this.reportFile = agent.reportFile;\n errorFlag = true;\n break;\n }\n }\n this.reportFile = agent?.reportFile;\n taskIndex++;\n }\n\n if (errorFlag) {\n this.setPlayerStatus('error');\n } else {\n this.setPlayerStatus('done');\n }\n this.agentStatusTip = '';\n\n // free the resources\n for (const fn of freeFn) {\n try {\n // console.log('freeing', fn.name);\n await fn.fn();\n // console.log('freed', fn.name);\n } catch (e) {\n // console.error('error freeing', fn.name, e);\n }\n }\n }\n}\n"],"names":["debug","getDebug","isStringParamSchema","schema","schemaDef","z","options","Array","option","ScriptPlayer","key","value","keyToUse","console","status","error","taskIndex","taskIndexToNotify","taskStatus","index","statusValue","output","resolve","process","outputDir","dirname","existsSync","mkdirSync","writeFileSync","JSON","undefined","_this_interfaceAgent","content","filePath","agent","flow","assert","flowItemIndex","currentStep","Number","flowItem","actionTask","prompt","assertTask","msg","pass","thought","message","Error","queryTask","queryResult","numberTask","numberResult","stringTask","stringResult","booleanTask","booleanResult","askTask","askResult","locateTask","locateResult","waitForTask","timeout","sleepTask","ms","msNumber","Promise","setTimeout","evaluateJavaScriptTask","result","recordTask","title","aiInput","rawValue","inputTask","locatePrompt","String","buildDetailedLocateParam","aiKeyboardPress","keyboardPressTask","keyName","aiScroll","scrollTask","actionSpace","locatePromptShortcut","actionParamForMatchedAction","matchedAction","action","actionInterfaceAlias","Object","keyOfActionInActionSpace","schemaIsStringParam","stringParamToCall","parseResult","resultName","sourceForParams","locateParam","restParams","buildDetailedLocateParamAndRestParams","flowParams","target","web","android","ios","tasks","webEnv","androidEnv","iosEnv","platform","freeFn","newAgent","newFreeFn","originalOnTaskStartTip","tip","e","errorFlag","fn","script","setupAgent","onTaskStatusChange","scriptPath","_this_target","_this_target1","_this_target2","ifInBrowser","ifInWorker","scriptName","basename","join","getMidsceneRunSubDir","Date","task","_task_flow"],"mappings":"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"}
@@ -159,10 +159,21 @@ class Agent {
159
159
  executions: [],
160
160
  modelBriefs: []
161
161
  };
162
+ this.executionDumpIndexByRunner = new WeakMap();
162
163
  return this.dump;
163
164
  }
164
- appendExecutionDump(execution) {
165
+ appendExecutionDump(execution, runner) {
165
166
  const currentDump = this.dump;
167
+ if (runner) {
168
+ const existingIndex = this.executionDumpIndexByRunner.get(runner);
169
+ if (void 0 !== existingIndex) {
170
+ currentDump.executions[existingIndex] = execution;
171
+ return;
172
+ }
173
+ currentDump.executions.push(execution);
174
+ this.executionDumpIndexByRunner.set(runner, currentDump.executions.length - 1);
175
+ return;
176
+ }
166
177
  currentDump.executions.push(execution);
167
178
  }
168
179
  dumpDataString() {
@@ -191,9 +202,8 @@ class Agent {
191
202
  const tip = param ? `${(0, external_ui_utils_js_namespaceObject.typeStr)(task)} - ${param}` : (0, external_ui_utils_js_namespaceObject.typeStr)(task);
192
203
  if (this.onTaskStartTip) await this.onTaskStartTip(tip);
193
204
  }
194
- async afterTaskRunning(runner, doNotThrowError = false) {
205
+ async handleRunnerAfterFlush(runner) {
195
206
  const executionDump = runner.dump();
196
- if (this.opts.aiActionContext) executionDump.aiActionContext = this.opts.aiActionContext;
197
207
  this.appendExecutionDump(executionDump);
198
208
  try {
199
209
  if (this.onDumpUpdate) this.onDumpUpdate(this.dumpDataString());
@@ -201,12 +211,9 @@ class Agent {
201
211
  console.error('Error in onDumpUpdate', error);
202
212
  }
203
213
  this.writeOutActionDumps();
204
- if (runner.isInErrorState() && !doNotThrowError) {
205
- const errorTask = runner.latestErrorTask();
206
- throw new Error(`${null == errorTask ? void 0 : errorTask.errorMessage}\n${null == errorTask ? void 0 : errorTask.errorStack}`, {
207
- cause: null == errorTask ? void 0 : errorTask.error
208
- });
209
- }
214
+ }
215
+ wrapActionInActionSpace(name) {
216
+ return async (param)=>await this.callActionInActionSpace(name, param);
210
217
  }
211
218
  async callActionInActionSpace(type, opt) {
212
219
  debug('callActionInActionSpace', type, ',', opt);
@@ -222,7 +229,6 @@ class Agent {
222
229
  const title = (0, external_ui_utils_js_namespaceObject.taskTitleStr)(type, (0, external_ui_utils_js_namespaceObject.locateParamStr)((null == opt ? void 0 : opt.locate) || {}));
223
230
  const modelConfig = this.modelConfigManager.getModelConfig('grounding');
224
231
  const { output, runner } = await this.taskExecutor.runPlans(title, plans, modelConfig);
225
- await this.afterTaskRunning(runner);
226
232
  return output;
227
233
  }
228
234
  async aiTap(locatePrompt, opt) {
@@ -331,13 +337,12 @@ class Agent {
331
337
  const matchedCache = isVlmUiTars || false === cacheable ? void 0 : null == (_this_taskCache = this.taskCache) ? void 0 : _this_taskCache.matchPlanCache(taskPrompt);
332
338
  if (matchedCache && (null == (_this_taskCache1 = this.taskCache) ? void 0 : _this_taskCache1.isCacheResultUsed)) {
333
339
  var _matchedCache_cacheContent, _matchedCache_cacheContent1;
334
- const { runner } = await this.taskExecutor.loadYamlFlowAsPlanning(taskPrompt, null == (_matchedCache_cacheContent = matchedCache.cacheContent) ? void 0 : _matchedCache_cacheContent.yamlWorkflow);
335
- await this.afterTaskRunning(runner);
340
+ await this.taskExecutor.loadYamlFlowAsPlanning(taskPrompt, null == (_matchedCache_cacheContent = matchedCache.cacheContent) ? void 0 : _matchedCache_cacheContent.yamlWorkflow);
336
341
  debug('matched cache, will call .runYaml to run the action');
337
342
  const yaml = null == (_matchedCache_cacheContent1 = matchedCache.cacheContent) ? void 0 : _matchedCache_cacheContent1.yamlWorkflow;
338
343
  return this.runYaml(yaml);
339
344
  }
340
- const { output, runner } = await this.taskExecutor.action(taskPrompt, modelConfig, this.opts.aiActionContext, cacheable);
345
+ const { output } = await this.taskExecutor.action(taskPrompt, modelConfig, this.opts.aiActionContext, cacheable);
341
346
  if (this.taskCache && (null == output ? void 0 : output.yamlFlow) && false !== cacheable) {
342
347
  const yamlContent = {
343
348
  tasks: [
@@ -354,7 +359,6 @@ class Agent {
354
359
  yamlWorkflow: yamlFlowStr
355
360
  }, matchedCache);
356
361
  }
357
- await this.afterTaskRunning(runner);
358
362
  return output;
359
363
  }
360
364
  async aiAction(taskPrompt, opt) {
@@ -362,29 +366,25 @@ class Agent {
362
366
  }
363
367
  async aiQuery(demand, opt = defaultServiceExtractOption) {
364
368
  const modelConfig = this.modelConfigManager.getModelConfig('VQA');
365
- const { output, runner } = await this.taskExecutor.createTypeQueryExecution('Query', demand, modelConfig, opt);
366
- await this.afterTaskRunning(runner);
369
+ const { output } = await this.taskExecutor.createTypeQueryExecution('Query', demand, modelConfig, opt);
367
370
  return output;
368
371
  }
369
372
  async aiBoolean(prompt, opt = defaultServiceExtractOption) {
370
373
  const modelConfig = this.modelConfigManager.getModelConfig('VQA');
371
374
  const { textPrompt, multimodalPrompt } = (0, external_utils_js_namespaceObject_1.parsePrompt)(prompt);
372
- const { output, runner } = await this.taskExecutor.createTypeQueryExecution('Boolean', textPrompt, modelConfig, opt, multimodalPrompt);
373
- await this.afterTaskRunning(runner);
375
+ const { output } = await this.taskExecutor.createTypeQueryExecution('Boolean', textPrompt, modelConfig, opt, multimodalPrompt);
374
376
  return output;
375
377
  }
376
378
  async aiNumber(prompt, opt = defaultServiceExtractOption) {
377
379
  const modelConfig = this.modelConfigManager.getModelConfig('VQA');
378
380
  const { textPrompt, multimodalPrompt } = (0, external_utils_js_namespaceObject_1.parsePrompt)(prompt);
379
- const { output, runner } = await this.taskExecutor.createTypeQueryExecution('Number', textPrompt, modelConfig, opt, multimodalPrompt);
380
- await this.afterTaskRunning(runner);
381
+ const { output } = await this.taskExecutor.createTypeQueryExecution('Number', textPrompt, modelConfig, opt, multimodalPrompt);
381
382
  return output;
382
383
  }
383
384
  async aiString(prompt, opt = defaultServiceExtractOption) {
384
385
  const modelConfig = this.modelConfigManager.getModelConfig('VQA');
385
386
  const { textPrompt, multimodalPrompt } = (0, external_utils_js_namespaceObject_1.parsePrompt)(prompt);
386
- const { output, runner } = await this.taskExecutor.createTypeQueryExecution('String', textPrompt, modelConfig, opt, multimodalPrompt);
387
- await this.afterTaskRunning(runner);
387
+ const { output } = await this.taskExecutor.createTypeQueryExecution('String', textPrompt, modelConfig, opt, multimodalPrompt);
388
388
  return output;
389
389
  }
390
390
  async aiAsk(prompt, opt = defaultServiceExtractOption) {
@@ -442,8 +442,7 @@ class Agent {
442
442
  locatePlan
443
443
  ];
444
444
  const modelConfig = this.modelConfigManager.getModelConfig('grounding');
445
- const { runner, output } = await this.taskExecutor.runPlans((0, external_ui_utils_js_namespaceObject.taskTitleStr)('Locate', (0, external_ui_utils_js_namespaceObject.locateParamStr)(locateParam)), plans, modelConfig);
446
- await this.afterTaskRunning(runner);
445
+ const { output } = await this.taskExecutor.runPlans((0, external_ui_utils_js_namespaceObject.taskTitleStr)('Locate', (0, external_ui_utils_js_namespaceObject.locateParamStr)(locateParam)), plans, modelConfig);
447
446
  const { element } = output;
448
447
  const dprValue = await this.interface.size().dpr;
449
448
  const dprEntry = dprValue ? {
@@ -456,35 +455,49 @@ class Agent {
456
455
  };
457
456
  }
458
457
  async aiAssert(assertion, msg, opt) {
459
- var _runner_latestErrorTask;
460
458
  const modelConfig = this.modelConfigManager.getModelConfig('VQA');
461
459
  const serviceOpt = {
462
460
  domIncluded: (null == opt ? void 0 : opt.domIncluded) ?? defaultServiceExtractOption.domIncluded,
463
- screenshotIncluded: (null == opt ? void 0 : opt.screenshotIncluded) ?? defaultServiceExtractOption.screenshotIncluded,
464
- doNotThrowError: null == opt ? void 0 : opt.doNotThrowError
461
+ screenshotIncluded: (null == opt ? void 0 : opt.screenshotIncluded) ?? defaultServiceExtractOption.screenshotIncluded
465
462
  };
466
463
  const { textPrompt, multimodalPrompt } = (0, external_utils_js_namespaceObject_1.parsePrompt)(assertion);
467
- const { output, runner, thought } = await this.taskExecutor.createTypeQueryExecution('Assert', textPrompt, modelConfig, serviceOpt, multimodalPrompt);
468
- await this.afterTaskRunning(runner, true);
469
- const message = output ? void 0 : `Assertion failed: ${msg || ('string' == typeof assertion ? assertion : assertion.prompt)}\nReason: ${thought || (null == (_runner_latestErrorTask = runner.latestErrorTask()) ? void 0 : _runner_latestErrorTask.error) || '(no_reason)'}`;
470
- if (null == opt ? void 0 : opt.keepRawResponse) return {
471
- pass: output,
472
- thought,
473
- message
474
- };
475
- if (!output) throw new Error(message);
464
+ const assertionText = 'string' == typeof assertion ? assertion : assertion.prompt;
465
+ try {
466
+ const { output, thought } = await this.taskExecutor.createTypeQueryExecution('Assert', textPrompt, modelConfig, serviceOpt, multimodalPrompt);
467
+ const pass = Boolean(output);
468
+ const message = pass ? void 0 : `Assertion failed: ${msg || assertionText}\nReason: ${thought || '(no_reason)'}`;
469
+ if (null == opt ? void 0 : opt.keepRawResponse) return {
470
+ pass,
471
+ thought,
472
+ message
473
+ };
474
+ if (!pass) throw new Error(message);
475
+ } catch (error) {
476
+ if (error instanceof external_tasks_js_namespaceObject.TaskExecutionError) {
477
+ const errorTask = error.errorTask;
478
+ const thought = null == errorTask ? void 0 : errorTask.thought;
479
+ const rawError = null == errorTask ? void 0 : errorTask.error;
480
+ const rawMessage = (null == errorTask ? void 0 : errorTask.errorMessage) || (rawError instanceof Error ? rawError.message : rawError ? String(rawError) : void 0);
481
+ const reason = thought || rawMessage || '(no_reason)';
482
+ const message = `Assertion failed: ${msg || assertionText}\nReason: ${reason}`;
483
+ if (null == opt ? void 0 : opt.keepRawResponse) return {
484
+ pass: false,
485
+ thought,
486
+ message
487
+ };
488
+ throw new Error(message, {
489
+ cause: rawError ?? error
490
+ });
491
+ }
492
+ throw error;
493
+ }
476
494
  }
477
495
  async aiWaitFor(assertion, opt) {
478
496
  const modelConfig = this.modelConfigManager.getModelConfig('VQA');
479
- const { runner } = await this.taskExecutor.waitFor(assertion, {
497
+ await this.taskExecutor.waitFor(assertion, {
480
498
  timeoutMs: (null == opt ? void 0 : opt.timeoutMs) || 15000,
481
499
  checkIntervalMs: (null == opt ? void 0 : opt.checkIntervalMs) || 3000
482
500
  }, modelConfig);
483
- await this.afterTaskRunning(runner, true);
484
- if (runner.isInErrorState()) {
485
- const errorTask = runner.latestErrorTask();
486
- throw new Error(`${null == errorTask ? void 0 : errorTask.error}\n${null == errorTask ? void 0 : errorTask.errorStack}`);
487
- }
488
501
  }
489
502
  async ai(taskPrompt, type = 'action') {
490
503
  if ('action' === type) return this.aiAct(taskPrompt);
@@ -557,7 +570,6 @@ class Agent {
557
570
  task
558
571
  ]
559
572
  };
560
- if (this.opts.aiActionContext) executionDump.aiActionContext = this.opts.aiActionContext;
561
573
  this.appendExecutionDump(executionDump);
562
574
  try {
563
575
  var _this_onDumpUpdate, _this;
@@ -650,6 +662,7 @@ class Agent {
650
662
  _define_property(this, "hasWarnedNonVLModel", false);
651
663
  _define_property(this, "screenshotScale", void 0);
652
664
  _define_property(this, "screenshotScalePromise", void 0);
665
+ _define_property(this, "executionDumpIndexByRunner", new WeakMap());
653
666
  this.interface = interfaceInstance;
654
667
  this.opts = Object.assign({
655
668
  generateReport: true,
@@ -669,7 +682,19 @@ class Agent {
669
682
  this.taskExecutor = new external_tasks_js_namespaceObject.TaskExecutor(this.interface, this.service, {
670
683
  taskCache: this.taskCache,
671
684
  onTaskStart: this.callbackOnTaskStartTip.bind(this),
672
- replanningCycleLimit: this.opts.replanningCycleLimit
685
+ replanningCycleLimit: this.opts.replanningCycleLimit,
686
+ hooks: {
687
+ onTaskUpdate: (runner)=>{
688
+ const executionDump = runner.dump();
689
+ this.appendExecutionDump(executionDump, runner);
690
+ try {
691
+ if (this.onDumpUpdate) this.onDumpUpdate(this.dumpDataString());
692
+ } catch (error) {
693
+ console.error('Error in onDumpUpdate', error);
694
+ }
695
+ this.writeOutActionDumps();
696
+ }
697
+ }
673
698
  });
674
699
  this.dump = this.resetDump();
675
700
  this.reportFileName = (null == opts ? void 0 : opts.reportFileName) || (0, external_utils_js_namespaceObject_1.getReportFileName)((null == opts ? void 0 : opts.testId) || this.interface.interfaceType || 'web');