@midscene/core 1.10.4-beta-20260710032704.0 → 1.10.4-beta-20260710115744.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 (53) hide show
  1. package/dist/es/agent/agent.mjs +24 -22
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/prompt-context.mjs +12 -1
  4. package/dist/es/agent/prompt-context.mjs.map +1 -1
  5. package/dist/es/agent/task-builder.mjs +11 -2
  6. package/dist/es/agent/task-builder.mjs.map +1 -1
  7. package/dist/es/agent/tasks.mjs +3 -0
  8. package/dist/es/agent/tasks.mjs.map +1 -1
  9. package/dist/es/agent/ui-utils.mjs +1 -0
  10. package/dist/es/agent/ui-utils.mjs.map +1 -1
  11. package/dist/es/agent/utils.mjs +1 -1
  12. package/dist/es/ai-model/inspect.mjs +1 -1
  13. package/dist/es/ai-model/inspect.mjs.map +1 -1
  14. package/dist/es/ai-model/prompt/extraction.mjs +4 -2
  15. package/dist/es/ai-model/prompt/extraction.mjs.map +1 -1
  16. package/dist/es/ai-model/service-caller/json.mjs +3 -47
  17. package/dist/es/ai-model/service-caller/json.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/builder.mjs +1 -1
  21. package/dist/es/yaml/builder.mjs.map +1 -1
  22. package/dist/es/yaml/utils.mjs +44 -2
  23. package/dist/es/yaml/utils.mjs.map +1 -1
  24. package/dist/lib/agent/agent.js +23 -21
  25. package/dist/lib/agent/agent.js.map +1 -1
  26. package/dist/lib/agent/prompt-context.js +14 -0
  27. package/dist/lib/agent/prompt-context.js.map +1 -1
  28. package/dist/lib/agent/task-builder.js +11 -2
  29. package/dist/lib/agent/task-builder.js.map +1 -1
  30. package/dist/lib/agent/tasks.js +3 -0
  31. package/dist/lib/agent/tasks.js.map +1 -1
  32. package/dist/lib/agent/ui-utils.js +1 -0
  33. package/dist/lib/agent/ui-utils.js.map +1 -1
  34. package/dist/lib/agent/utils.js +1 -1
  35. package/dist/lib/ai-model/inspect.js +1 -1
  36. package/dist/lib/ai-model/inspect.js.map +1 -1
  37. package/dist/lib/ai-model/prompt/extraction.js +4 -2
  38. package/dist/lib/ai-model/prompt/extraction.js.map +1 -1
  39. package/dist/lib/ai-model/service-caller/json.js +3 -47
  40. package/dist/lib/ai-model/service-caller/json.js.map +1 -1
  41. package/dist/lib/types.js.map +1 -1
  42. package/dist/lib/utils.js +2 -2
  43. package/dist/lib/yaml/builder.js +1 -1
  44. package/dist/lib/yaml/builder.js.map +1 -1
  45. package/dist/lib/yaml/utils.js +47 -2
  46. package/dist/lib/yaml/utils.js.map +1 -1
  47. package/dist/types/agent/agent.d.ts +1 -1
  48. package/dist/types/agent/prompt-context.d.ts +1 -0
  49. package/dist/types/ai-model/prompt/extraction.d.ts +1 -1
  50. package/dist/types/types.d.ts +1 -0
  51. package/dist/types/yaml/utils.d.ts +11 -1
  52. package/dist/types/yaml.d.ts +17 -1
  53. package/package.json +2 -2
@@ -6,7 +6,7 @@ import service from "../service/index.mjs";
6
6
  import { ExecutionDump, ReportActionDump } from "../types.mjs";
7
7
  import { ReportGenerator, assertReportGenerationOptions } from "../report-generator.mjs";
8
8
  import { getVersion, processCacheConfig, reportHTMLContent } from "../utils.mjs";
9
- import { ScriptPlayer, buildDetailedLocateParam, parseYamlScript } from "../yaml/index.mjs";
9
+ import { ScriptPlayer, buildDetailedLocateParam, buildDetailedLocateParamAndRestParams, parseYamlScript } from "../yaml/index.mjs";
10
10
  import { readFile } from "node:fs/promises";
11
11
  import { basename } from "node:path";
12
12
  import { MIDSCENE_REPLANNING_CYCLE_LIMIT, ModelConfigManager, globalConfigManager, globalModelConfigManager } from "@midscene/shared/env";
@@ -114,7 +114,7 @@ class Agent {
114
114
  openFrameSource: async ()=>await this.interface.openFrameSource?.() ?? void 0,
115
115
  screenshot: ()=>this.interface.screenshotBase64(),
116
116
  captureRepresentative: ()=>this.getUIContext('assert'),
117
- runAssert: (assertion, uiContext, msg, assertOpt)=>this.aiAssertWithContext(assertion, uiContext, msg, assertOpt),
117
+ runAssert: (assertion, uiContext, msg, assertOpt)=>this.aiAssertWithUIContext(assertion, uiContext, msg, assertOpt),
118
118
  runBoolean: (prompt, uiContext, boolOpt)=>this.aiBooleanWithContext(prompt, uiContext, boolOpt),
119
119
  onStopped: ()=>{
120
120
  this.activeObserver = null;
@@ -287,13 +287,13 @@ class Agent {
287
287
  }
288
288
  assert('string' == typeof value || 'number' == typeof value, 'input value must be a string or number, use empty string if you want to clear the input');
289
289
  assert(locatePrompt, 'missing locate prompt for input');
290
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
290
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt, opt);
291
291
  const stringValue = 'number' == typeof value ? String(value) : value;
292
292
  const mode = opt?.mode === 'append' ? 'typeOnly' : opt?.mode;
293
293
  await this.callActionInActionSpace('Input', {
294
- ...opt || {},
294
+ ...restParams,
295
295
  value: stringValue,
296
- locate: detailedLocateParam,
296
+ locate: locateParam,
297
297
  mode
298
298
  });
299
299
  }
@@ -313,10 +313,10 @@ class Agent {
313
313
  };
314
314
  }
315
315
  assert(opt?.keyName, 'missing keyName for keyboard press');
316
- const detailedLocateParam = locatePrompt ? buildDetailedLocateParam(locatePrompt, opt) : void 0;
316
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', opt);
317
317
  await this.callActionInActionSpace('KeyboardPress', {
318
- ...opt || {},
319
- locate: detailedLocateParam
318
+ ...restParams,
319
+ locate: locateParam
320
320
  });
321
321
  }
322
322
  async aiScroll(locatePromptOrScrollParam, locatePromptOrOpt, optOrUndefined) {
@@ -345,25 +345,25 @@ class Agent {
345
345
  scrollType: normalizedScrollType
346
346
  };
347
347
  }
348
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt || '', opt);
348
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', opt);
349
349
  await this.callActionInActionSpace('Scroll', {
350
- ...opt || {},
351
- locate: detailedLocateParam
350
+ ...restParams,
351
+ locate: locateParam
352
352
  });
353
353
  }
354
354
  async aiPinch(locatePrompt, opt) {
355
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt || '', opt);
355
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt || '', opt);
356
356
  await this.callActionInActionSpace('Pinch', {
357
- ...opt,
358
- locate: detailedLocateParam
357
+ ...restParams,
358
+ locate: locateParam
359
359
  });
360
360
  }
361
361
  async aiLongPress(locatePrompt, opt) {
362
362
  assert(locatePrompt, 'missing locate prompt for long press');
363
- const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);
363
+ const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(locatePrompt, opt);
364
364
  await this.callActionInActionSpace('LongPress', {
365
- ...opt || {},
366
- locate: detailedLocateParam
365
+ ...restParams,
366
+ locate: locateParam
367
367
  });
368
368
  }
369
369
  async aiClearInput(locatePrompt, opt) {
@@ -511,16 +511,18 @@ class Agent {
511
511
  };
512
512
  }
513
513
  async aiAssert(assertion, msg, opt) {
514
- return this.aiAssertWithContext(assertion, void 0, msg, opt);
514
+ return this.aiAssertWithUIContext(assertion, void 0, msg, opt);
515
515
  }
516
- async aiAssertWithContext(assertion, uiContext, msg, opt) {
516
+ async aiAssertWithUIContext(assertion, uiContext, msg, opt) {
517
517
  const modelRuntime = this.resolveModelRuntime('insight');
518
518
  const serviceOpt = {
519
519
  domIncluded: opt?.domIncluded ?? defaultServiceExtractOption.domIncluded,
520
- screenshotIncluded: opt?.screenshotIncluded ?? defaultServiceExtractOption.screenshotIncluded
520
+ screenshotIncluded: opt?.screenshotIncluded ?? defaultServiceExtractOption.screenshotIncluded,
521
+ ...opt?.context !== void 0 ? {
522
+ context: opt.context
523
+ } : {}
521
524
  };
522
- const assertionWithContext = buildPromptWithContext(assertion, opt?.context);
523
- const { textPrompt, multimodalPrompt } = parsePrompt(assertionWithContext);
525
+ const { textPrompt, multimodalPrompt } = parsePrompt(assertion);
524
526
  const assertionText = 'string' == typeof assertion ? assertion : assertion.prompt;
525
527
  const executionOptions = {
526
528
  abortSignal: opt?.abortSignal,
@@ -1 +1 @@
1
- {"version":3,"file":"agent/agent.mjs","sources":["../../../src/agent/agent.ts"],"sourcesContent":["import { type ModelRuntime, getModelRuntime } from '@/ai-model/models';\nimport { INTERNAL_CALL_ID_FIELD } from '@/ai-model/service-caller';\nimport yaml from 'js-yaml';\nimport type { TUserPrompt } from '../ai-model/index';\nimport { ScreenshotItem } from '../screenshot-item';\nimport Service from '../service/index';\n// Import types and values directly from their source files to avoid circular dependency\n// DO NOT import from '../index' as it creates a circular dependency:\n// index.ts -> agent/index.ts -> agent/agent.ts -> index.ts\nimport {\n type AIUsageInfo,\n type ActionParam,\n type ActionReturn,\n type AgentAssertOpt,\n type AgentOpt,\n type AgentProgressListener,\n type AgentWaitForOpt,\n type DeepThinkOption,\n type DeviceAction,\n ExecutionDump,\n type ExecutionRecorderItem,\n type ExecutionTask,\n type ExecutionTaskLog,\n type LocateOption,\n type LocateResultElement,\n type OnTaskStartTip,\n type PlanningAction,\n type RecordToReportOptions,\n type RecordToReportScreenshot,\n ReportActionDump,\n type ReportMeta,\n type ScrollParam,\n type ServiceAction,\n type ServiceExtractOption,\n type ServiceExtractParam,\n type TestStatus,\n type UIContext,\n} from '../types';\nimport type { MidsceneYamlScript } from '../yaml';\n\nimport type { IReportGenerator } from '@/report-generator';\nimport {\n ReportGenerator,\n assertReportGenerationOptions,\n} from '@/report-generator';\nimport { getVersion, processCacheConfig, reportHTMLContent } from '@/utils';\nimport {\n ScriptPlayer,\n buildDetailedLocateParam,\n parseYamlScript,\n} from '../yaml/index';\n\nimport { readFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\nimport type { AbstractInterface } from '@/device';\nimport type { TaskRunner } from '@/task-runner';\nimport {\n type IModelConfig,\n MIDSCENE_REPLANNING_CYCLE_LIMIT,\n ModelConfigManager,\n type TIntent,\n globalConfigManager,\n globalModelConfigManager,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport { defineActionSleep } from '../device';\nimport { validateAgentCacheInput } from './cache-config';\nimport { MetricsCollector, type MidsceneUsageMetrics } from './metrics';\nimport { AgentProgressBus } from './progress';\nimport { buildPromptWithContext } from './prompt-context';\nimport { normalizeRecordToReportScreenshot } from './record-to-report';\nimport {\n type RunGherkinScenarioOptions,\n runGherkinScenario,\n} from './run-gherkin-scenario';\nimport { markdownToAiActPrompt } from './run-markdown';\nimport { TaskCache } from './task-cache';\nimport {\n TaskExecutionError,\n TaskExecutor,\n locatePlanForLocate,\n withFileChooser,\n} from './tasks';\nimport { UIObserver, type UIObserverOption } from './ui-observer';\nimport {\n type TaskTitleType,\n locateParamStr,\n paramStr,\n taskTitleStr,\n typeStr,\n} from './ui-utils';\nimport {\n commonContextParser,\n getReportFileName,\n normalizeFilePaths,\n normalizeScrollType,\n parsePrompt,\n} from './utils';\n\nconst debug = getDebug('agent');\nconst warn = getDebug('agent', { console: true });\n\nconst defaultServiceExtractOption: ServiceExtractOption = {\n domIncluded: false,\n screenshotIncluded: true,\n};\n\nexport type AiActOptions = {\n cacheable?: boolean;\n fileChooserAccept?: string | string[];\n deepThink?: DeepThinkOption;\n deepLocate?: boolean;\n abortSignal?: AbortSignal;\n context?: string;\n};\n\ntype AiActInternalOptions = AiActOptions & {\n _internalReportDisplay?: {\n type?: TaskTitleType;\n prompt?: string;\n };\n};\n\n/**\n * Shared input option type for aiInput(), used consistently across\n * overload signatures and the implementation so fields don't drift.\n */\ntype AgentInputOption = LocateOption & {\n autoDismissKeyboard?: boolean;\n keyboardTypeDelay?: number;\n mode?: 'replace' | 'clear' | 'typeOnly' | 'append';\n};\n\nexport class Agent<\n InterfaceType extends AbstractInterface = AbstractInterface,\n> {\n interface: InterfaceType;\n\n service: Service;\n\n dump: ReportActionDump;\n\n reportFile?: string | null;\n\n reportFileName?: string;\n\n taskExecutor: TaskExecutor;\n\n opts: AgentOpt;\n\n /**\n * If true, the agent will not perform any actions\n */\n dryMode = false;\n\n onTaskStartTip?: OnTaskStartTip;\n\n taskCache?: TaskCache;\n\n private readonly metricsCollector = new MetricsCollector();\n\n // Monotonic counter for generating unique dedup keys when a usage has no\n // request_id (e.g. estimated streaming usage).\n private usageCallCounter = 0;\n\n // Usage values already folded into `metricsCollector`, keyed by\n // `${taskId}:${field}` so re-emitted snapshots never double-count.\n private readonly countedUsageKeys = new Set<string>();\n\n private dumpUpdateListeners: Array<\n (dump: string, executionDump?: ExecutionDump) => void\n > = [];\n\n // Generic progress bus: every producer (aiAct today, more later) broadcasts\n // through here. Consumers narrow by `event.scope`.\n private readonly progressBus = new AgentProgressBus();\n\n get onDumpUpdate():\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined {\n return this.dumpUpdateListeners[0];\n }\n\n set onDumpUpdate(callback:\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined) {\n // Clear existing listeners\n this.dumpUpdateListeners = [];\n // Add callback to array if provided\n if (callback) {\n this.dumpUpdateListeners.push(callback);\n }\n }\n\n destroyed = false;\n\n modelConfigManager: ModelConfigManager;\n\n /**\n * Frozen page context for consistent AI operations\n */\n private frozenUIContext?: UIContext;\n\n /**\n * Currently active UIObserver (from startObserving). Only one observer may\n * be active at a time since frame sources are device-level singletons.\n */\n private activeObserver: UIObserver | null = null;\n\n private get aiActContext(): string | undefined {\n return this.opts.aiActContext ?? this.opts.aiActionContext;\n }\n\n private executionDumpIndexByRunner = new WeakMap<TaskRunner, number>();\n\n private fullActionSpace: DeviceAction[];\n\n private reportGenerator: IReportGenerator;\n\n // @deprecated use .interface instead\n get page() {\n return this.interface;\n }\n\n /**\n * Fails fast for non-web interfaces when the model family is missing.\n *\n * Early Midscene web usage allowed running without `modelFamily` and falling\n * back to a default bbox parser. Non-web users do not have that compatibility\n * path, so this check helps surface configuration problems before spending a\n * model call.\n *\n * Web flows validate missing locate model family at workflow boundaries:\n * `Service.locate` throws when aiTap/aiType fallback to the default model for\n * direct locate, and generic planning throws when aiAct asks a planning model\n * to return inline locate coordinates. Those checks are intentionally placed\n * where Midscene knows which model role should provide coordinate parsing.\n */\n private assertModelFamilyForNonWebContext() {\n if (\n this.interface.interfaceType !== 'puppeteer' &&\n this.interface.interfaceType !== 'playwright' &&\n this.interface.interfaceType !== 'static' &&\n this.interface.interfaceType !== 'chrome-extension-proxy' &&\n this.interface.interfaceType !== 'page-over-chrome-extension-bridge'\n ) {\n this.modelConfigManager.throwErrorIfNonVLModel();\n }\n }\n\n private resolveReplanningCycleLimit(planningModel: ModelRuntime): number {\n return (\n this.opts.replanningCycleLimit ??\n globalConfigManager.getEnvConfigValueAsNumber(\n MIDSCENE_REPLANNING_CYCLE_LIMIT,\n ) ??\n planningModel.adapter.planning.defaultReplanningCycleLimit\n );\n }\n\n private resolveModelRuntime(intent: TIntent): ModelRuntime {\n const runtime = getModelRuntime(\n this.modelConfigManager.getModelConfig(intent),\n );\n return {\n ...runtime,\n onUsage: (usage) => {\n this.usageCallCounter += 1;\n // buildUsageInfo leaves intent undefined; fill it from the model\n // config slot so metrics.byIntent has a meaningful category.\n const enriched = usage.intent\n ? usage\n : { ...usage, intent: usage.slot };\n this.consumeUsage(\n enriched,\n `callai:${usage.request_id ?? this.usageCallCounter}`,\n );\n },\n };\n }\n\n constructor(interfaceInstance: InterfaceType, opts?: AgentOpt) {\n this.interface = interfaceInstance;\n\n this.opts = Object.assign(\n {\n generateReport: true,\n persistExecutionDump: false,\n autoPrintReportMsg: true,\n groupName: 'Midscene Report',\n groupDescription: '',\n },\n opts || {},\n );\n assertReportGenerationOptions(this.opts);\n\n const resolvedAiActContext =\n this.opts.aiActContext ?? this.opts.aiActionContext;\n if (resolvedAiActContext !== undefined) {\n this.opts.aiActContext = resolvedAiActContext;\n this.opts.aiActionContext ??= resolvedAiActContext;\n }\n\n if (\n opts?.modelConfig &&\n (typeof opts?.modelConfig !== 'object' || Array.isArray(opts.modelConfig))\n ) {\n throw new Error(\n `opts.modelConfig must be a plain object map of env keys to values, but got ${typeof opts?.modelConfig}`,\n );\n }\n // Create ModelConfigManager if modelConfig or createOpenAIClient is provided\n // Otherwise, use the global config manager\n const hasCustomConfig = opts?.modelConfig || opts?.createOpenAIClient;\n this.modelConfigManager = hasCustomConfig\n ? new ModelConfigManager(opts?.modelConfig, opts?.createOpenAIClient)\n : globalModelConfigManager;\n\n this.onTaskStartTip = this.opts.onTaskStartTip;\n\n this.service = new Service(async () => {\n return this.getUIContext();\n });\n\n // Process cache configuration\n const cacheConfigObj = this.processCacheConfig(opts || {});\n if (cacheConfigObj) {\n this.taskCache = new TaskCache(\n cacheConfigObj.id,\n cacheConfigObj.enabled,\n undefined, // cacheFilePath\n {\n readOnly: cacheConfigObj.readOnly,\n writeOnly: cacheConfigObj.writeOnly,\n cacheDir: cacheConfigObj.cacheDir,\n },\n );\n }\n\n const baseActionSpace = this.interface.actionSpace();\n this.fullActionSpace = [...baseActionSpace, defineActionSleep()];\n\n this.taskExecutor = new TaskExecutor(this.interface, this.service, {\n taskCache: this.taskCache,\n onTaskStart: this.callbackOnTaskStartTip.bind(this),\n replanningCycleLimit: this.opts.replanningCycleLimit,\n waitAfterAction: this.opts.waitAfterAction,\n useDeviceTime: this.opts.useDeviceTime,\n actionSpace: this.fullActionSpace,\n hooks: {\n onSnapshotChange: async (runner) => {\n const executionDump = runner.dump();\n this.appendExecutionDump(executionDump, runner);\n this.collectUsageMetrics(executionDump);\n\n // Persist report updates before notifying listeners so screenshot\n // payloads can be released from memory and serialized as references.\n this.writeOutActionDumps(executionDump);\n await this.reportGenerator.flush();\n\n // Call all registered dump update listeners\n const dumpString = this.dumpDataString();\n for (const listener of this.dumpUpdateListeners) {\n try {\n listener(dumpString, executionDump);\n } catch (error) {\n console.error('Error in onDumpUpdate listener', error);\n }\n }\n },\n onProgress: this.progressBus.publish,\n },\n });\n this.dump = this.resetDump();\n this.reportFileName =\n opts?.reportFileName ??\n // Keep deprecated testId behavior for generated report names until it is\n // fully removed from the public API.\n getReportFileName(opts?.testId || this.interface.interfaceType || 'web');\n\n this.reportGenerator = ReportGenerator.create(this.reportFileName!, {\n generateReport: this.opts.generateReport,\n persistExecutionDump: this.opts.persistExecutionDump,\n outputFormat: this.opts.outputFormat,\n autoPrintReportMsg: this.opts.autoPrintReportMsg,\n reuseExistingReport:\n this.opts.reportAttributes?.['data-group-id'] === this.reportFileName,\n });\n }\n\n async getActionSpace(): Promise<DeviceAction[]> {\n return this.fullActionSpace;\n }\n\n private static readonly CONTEXT_RETRY_MAX = 3;\n private static readonly CONTEXT_RETRY_DELAY_MS = 1500;\n\n /**\n * Override in subclasses to indicate which errors are transient and should\n * trigger an automatic retry when building the UI context.\n * Returns `false` by default (no retry).\n */\n protected isRetryableContextError(_error: unknown): boolean {\n return false;\n }\n\n async getUIContext(action?: ServiceAction): Promise<UIContext> {\n // Some non-web flows, such as Android, need an Agent instance before they\n // can call device methods via ADB, so defer missing modelFamily errors\n // until UI context is actually requested.\n this.assertModelFamilyForNonWebContext();\n\n // If page context is frozen, return the frozen context for all actions\n if (this.frozenUIContext) {\n debug('Using frozen page context for action:', action);\n return this.frozenUIContext;\n }\n\n const maxRetries = Agent.CONTEXT_RETRY_MAX;\n for (let attempt = 0; ; attempt++) {\n try {\n return await commonContextParser(this.interface, {\n uploadServerUrl: this.modelConfigManager.getUploadTestServerUrl(),\n screenshotShrinkFactor: this.opts.screenshotShrinkFactor,\n });\n } catch (error) {\n if (attempt < maxRetries && this.isRetryableContextError(error)) {\n debug(\n `retryable context error (attempt ${attempt + 1}/${maxRetries}), retrying in ${Agent.CONTEXT_RETRY_DELAY_MS}ms: ${error}`,\n );\n await new Promise((resolve) =>\n setTimeout(resolve, Agent.CONTEXT_RETRY_DELAY_MS),\n );\n continue;\n }\n throw error;\n }\n }\n }\n\n async _snapshotContext(): Promise<UIContext> {\n return await this.getUIContext('locate');\n }\n\n /**\n * Start observing the screen in the background so a later assertion can\n * judge everything that happened while other agent calls ran — including\n * transient UI (toasts, banners, transitions) that appears mid-action:\n *\n * ```ts\n * const observer = await agent.startObserving();\n * await agent.aiAct('submit the form');\n * await observer.stop();\n * await observer.aiAssert('a success toast appeared during the process');\n * ```\n *\n * Frames come from the device's continuous frame source when available\n * (scrcpy on Android, WDA MJPEG on iOS — both opt-in; CDP screencast on\n * web) and fall back to plain screenshots otherwise. Sampling is capped at\n * 5fps, the buffer is bounded and self-thinning, decoding is deferred to\n * the end, and all buffered frames (up to `maxFrames`) are sent to\n * the model at assert time. To control token cost for long windows,\n * increase `intervalMs` or decrease `maxFrames`.\n * Awaiting `startObserving()` guarantees one baseline frame is captured\n * before your next action.\n */\n async startObserving(opt?: UIObserverOption): Promise<UIObserver> {\n // A frozen context pins perception to a single snapshot; observing a\n // window of frames contradicts that. Fail fast instead of silently\n // producing an all-identical sequence.\n assert(\n !this.frozenUIContext,\n 'startObserving() cannot be used while the UI context is frozen (call unfreezePageContext() first)',\n );\n // Frame sources are device-level singletons — two concurrent observers\n // would conflict (scrcpy stream, WDA MJPEG port, CDP screencast).\n assert(\n !this.activeObserver,\n 'An observation window is already active on this agent. ' +\n 'Stop the existing observer first (await observer.stop()) before starting a new one.',\n );\n const observer = new UIObserver(\n {\n openFrameSource: async () =>\n (await this.interface.openFrameSource?.()) ?? undefined,\n // Fallback single-frame capture. Deliberately bypasses getUIContext so\n // the observation loop never pollutes the TaskRunner context cache.\n screenshot: () => this.interface.screenshotBase64(),\n captureRepresentative: () => this.getUIContext('assert'),\n runAssert: (assertion, uiContext, msg, assertOpt) =>\n this.aiAssertWithContext(assertion, uiContext, msg, assertOpt),\n runBoolean: (prompt, uiContext, boolOpt) =>\n this.aiBooleanWithContext(prompt, uiContext, boolOpt),\n onStopped: () => {\n this.activeObserver = null;\n },\n screenshotShrinkFactor: this.opts.screenshotShrinkFactor,\n },\n opt,\n );\n // Mark as active BEFORE the async start() so concurrent calls hit the\n // assert guard above. If start() throws, clear the reference below.\n this.activeObserver = observer;\n try {\n await observer.start();\n } catch (error) {\n this.activeObserver = null;\n throw error;\n }\n return observer;\n }\n\n /**\n * @deprecated Use {@link setAIActContext} instead.\n */\n async setAIActionContext(prompt: string) {\n await this.setAIActContext(prompt);\n }\n\n async setAIActContext(prompt: string) {\n if (this.aiActContext) {\n console.warn(\n 'aiActContext is already set, and it is called again, will override the previous setting',\n );\n }\n this.opts.aiActContext = prompt;\n this.opts.aiActionContext = prompt;\n }\n\n resetDump() {\n this.dump = new ReportActionDump({\n sdkVersion: getVersion(),\n groupName: this.opts.groupName!,\n groupDescription: this.opts.groupDescription,\n executions: [],\n modelBriefs: [],\n deviceType: this.interface.interfaceType,\n });\n this.executionDumpIndexByRunner = new WeakMap<TaskRunner, number>();\n\n return this.dump;\n }\n\n appendExecutionDump(execution: ExecutionDump, runner?: TaskRunner) {\n const currentDump = this.dump;\n if (runner) {\n const existingIndex = this.executionDumpIndexByRunner.get(runner);\n if (existingIndex !== undefined) {\n currentDump.executions[existingIndex] = execution;\n return;\n }\n currentDump.executions.push(execution);\n this.executionDumpIndexByRunner.set(\n runner,\n currentDump.executions.length - 1,\n );\n return;\n }\n currentDump.executions.push(execution);\n }\n\n /**\n * Fold any not-yet-counted task usage from an execution dump into the\n * instance metrics. Snapshots are re-emitted as tasks progress, so each\n * usage value is keyed by `${taskId}:${field}` and counted at most once.\n */\n private collectUsageMetrics(execution: ExecutionDump) {\n for (const task of execution.tasks) {\n this.consumeUsage(task.usage, `${task.taskId}:usage`);\n this.consumeUsage(task.searchAreaUsage, `${task.taskId}:searchAreaUsage`);\n }\n }\n\n private consumeUsage(usage: AIUsageInfo | undefined, key: string) {\n if (!usage) {\n return;\n }\n // Dedup key priority:\n // 1. request_id — provider-issued, stable across onUsage and task dump paths\n // 2. INTERNAL_CALL_ID_FIELD — callAI-generated internal id, covers\n // providers that don't return a request_id\n // 3. caller-provided key (taskId:field or callai:counter)\n let dedupKey: string;\n if (usage.request_id) {\n dedupKey = `req:${usage.request_id}`;\n } else if ((usage as any)[INTERNAL_CALL_ID_FIELD]) {\n dedupKey = `int:${(usage as any)[INTERNAL_CALL_ID_FIELD]}`;\n } else {\n dedupKey = key;\n }\n if (this.countedUsageKeys.has(dedupKey)) {\n return;\n }\n this.countedUsageKeys.add(dedupKey);\n this.metricsCollector.add(usage);\n if (this.opts.onLLMUsage) {\n try {\n this.opts.onLLMUsage(usage);\n } catch (error) {\n warn(`onLLMUsage listener threw, ignoring: ${error}`);\n }\n }\n }\n\n /**\n * Aggregated LLM usage accumulated by this agent since it was created.\n */\n get metrics(): MidsceneUsageMetrics {\n return this.metricsCollector.snapshot();\n }\n\n dumpDataString(opt?: { inlineScreenshots?: boolean }) {\n // update dump info\n this.dump.groupName = this.opts.groupName!;\n this.dump.groupDescription = this.opts.groupDescription;\n // In browser environment, use inline screenshots since file system is not available\n if (ifInBrowser || opt?.inlineScreenshots) {\n return this.dump.serializeWithInlineScreenshots();\n }\n return this.dump.serialize();\n }\n\n reportHTMLString(opt?: { inlineScreenshots?: boolean }) {\n // dumpDataString() handles browser environment with inline screenshots\n return reportHTMLContent(this.dumpDataString(opt));\n }\n\n private lastExecutionDump?: ExecutionDump;\n\n writeOutActionDumps(executionDump?: ExecutionDump) {\n const exec = executionDump || this.lastExecutionDump;\n if (exec) {\n this.lastExecutionDump = exec;\n this.reportGenerator.onExecutionUpdate(\n exec,\n this.getReportMeta(),\n this.opts.reportAttributes,\n );\n }\n this.reportFile = this.reportGenerator.getReportPath();\n }\n\n private getReportMeta(): ReportMeta {\n return {\n groupName: this.dump.groupName,\n groupDescription: this.dump.groupDescription,\n sdkVersion: this.dump.sdkVersion,\n modelBriefs: this.dump.modelBriefs,\n deviceType: this.dump.deviceType,\n };\n }\n\n private async callbackOnTaskStartTip(task: ExecutionTask) {\n const param = paramStr(task);\n const tip = param ? `${typeStr(task)} - ${param}` : typeStr(task);\n\n if (this.onTaskStartTip) {\n await this.onTaskStartTip(tip);\n }\n }\n\n wrapActionInActionSpace<T extends DeviceAction>(\n name: string,\n ): (param: ActionParam<T>) => Promise<ActionReturn<T>> {\n return async (param: ActionParam<T>) => {\n return await this.callActionInActionSpace<ActionReturn<T>>(name, param);\n };\n }\n\n async callActionInActionSpace<T = any>(\n type: string,\n opt?: T, // and all other action params\n ) {\n debug('callActionInActionSpace', type, ',', opt);\n\n const actionPlan: PlanningAction<T> = {\n type: type as any,\n param: (opt as any) || {},\n thought: '',\n };\n debug('actionPlan', actionPlan); // , ', in which the locateParam is', locateParam);\n\n const plans: PlanningAction[] = [actionPlan].filter(\n Boolean,\n ) as PlanningAction[];\n\n const title = taskTitleStr(\n type as any,\n locateParamStr((opt as any)?.locate || {}),\n );\n\n // assume all operation in action space is related to locating\n const defaultModel = this.resolveModelRuntime('default');\n const planningModel = this.resolveModelRuntime('planning');\n\n const { output } = await this.taskExecutor.runPlans(\n title,\n plans,\n planningModel,\n defaultModel,\n );\n return output;\n }\n\n async aiTap(\n locatePrompt: TUserPrompt,\n opt?: LocateOption & { fileChooserAccept?: string | string[] },\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for tap');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n const fileChooserAccept = opt?.fileChooserAccept\n ? this.normalizeFileInput(opt.fileChooserAccept)\n : undefined;\n\n await withFileChooser(this.interface, fileChooserAccept, async () => {\n await this.callActionInActionSpace('Tap', {\n locate: detailedLocateParam,\n });\n });\n }\n\n async aiRightClick(\n locatePrompt: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for right click');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('RightClick', {\n locate: detailedLocateParam,\n });\n }\n\n async aiDoubleClick(\n locatePrompt: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for double click');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('DoubleClick', {\n locate: detailedLocateParam,\n });\n }\n\n async aiHover(locatePrompt: TUserPrompt, opt?: LocateOption): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for hover');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('Hover', {\n locate: detailedLocateParam,\n });\n }\n\n // New signature, always use locatePrompt as the first param\n async aiInput(\n locatePrompt: TUserPrompt,\n opt: AgentInputOption & { value: string | number },\n ): Promise<void>;\n\n // Legacy signature - deprecated\n /**\n * @deprecated Use aiInput(locatePrompt, opt) instead where opt contains the value\n */\n async aiInput(\n value: string | number,\n locatePrompt: TUserPrompt,\n opt?: AgentInputOption,\n ): Promise<void>;\n\n // Implementation\n async aiInput(\n locatePromptOrValue: TUserPrompt | string | number,\n locatePromptOrOpt:\n | TUserPrompt\n | (AgentInputOption & { value: string | number })\n | undefined,\n optOrUndefined?: AgentInputOption,\n ) {\n let value: string | number;\n let locatePrompt: TUserPrompt;\n let opt: (AgentInputOption & { value: string | number }) | undefined;\n\n // Check if using new signature (first param is locatePrompt, second has value)\n if (\n typeof locatePromptOrOpt === 'object' &&\n locatePromptOrOpt !== null &&\n 'value' in locatePromptOrOpt\n ) {\n // New signature: aiInput(locatePrompt, opt)\n locatePrompt = locatePromptOrValue as TUserPrompt;\n const optWithValue = locatePromptOrOpt as AgentInputOption & {\n value: string | number;\n };\n value = optWithValue.value;\n opt = optWithValue;\n } else {\n // Legacy signature: aiInput(value, locatePrompt, opt)\n value = locatePromptOrValue as string | number;\n locatePrompt = locatePromptOrOpt as TUserPrompt;\n opt = {\n ...optOrUndefined,\n value,\n };\n }\n\n assert(\n typeof value === 'string' || typeof value === 'number',\n 'input value must be a string or number, use empty string if you want to clear the input',\n );\n assert(locatePrompt, 'missing locate prompt for input');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n // Convert value to string to ensure consistency\n const stringValue = typeof value === 'number' ? String(value) : value;\n\n // backward compat: convert deprecated 'append' to 'typeOnly'\n const mode = opt?.mode === 'append' ? 'typeOnly' : opt?.mode;\n\n await this.callActionInActionSpace('Input', {\n ...(opt || {}),\n value: stringValue,\n locate: detailedLocateParam,\n mode,\n });\n }\n\n // New signature\n async aiKeyboardPress(\n locatePrompt: TUserPrompt,\n opt: LocateOption & { keyName: string },\n ): Promise<void>;\n\n // Legacy signature - deprecated\n /**\n * @deprecated Use aiKeyboardPress(locatePrompt, opt) instead where opt contains the keyName\n */\n async aiKeyboardPress(\n keyName: string,\n locatePrompt?: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void>;\n\n // Implementation\n async aiKeyboardPress(\n locatePromptOrKeyName: TUserPrompt | string,\n locatePromptOrOpt:\n | TUserPrompt\n | (LocateOption & { keyName: string })\n | undefined,\n optOrUndefined?: LocateOption,\n ) {\n let keyName: string;\n let locatePrompt: TUserPrompt | undefined;\n let opt: (LocateOption & { keyName: string }) | undefined;\n\n // Check if using new signature (first param is locatePrompt, second has keyName)\n if (\n typeof locatePromptOrOpt === 'object' &&\n locatePromptOrOpt !== null &&\n 'keyName' in locatePromptOrOpt\n ) {\n // New signature: aiKeyboardPress(locatePrompt, opt)\n locatePrompt = locatePromptOrKeyName as TUserPrompt;\n opt = locatePromptOrOpt as LocateOption & {\n keyName: string;\n };\n } else {\n // Legacy signature: aiKeyboardPress(keyName, locatePrompt, opt)\n keyName = locatePromptOrKeyName as string;\n locatePrompt = locatePromptOrOpt as TUserPrompt | undefined;\n opt = {\n ...(optOrUndefined || {}),\n keyName,\n };\n }\n\n assert(opt?.keyName, 'missing keyName for keyboard press');\n\n const detailedLocateParam = locatePrompt\n ? buildDetailedLocateParam(locatePrompt, opt)\n : undefined;\n\n await this.callActionInActionSpace('KeyboardPress', {\n ...(opt || {}),\n locate: detailedLocateParam,\n });\n }\n\n // New signature\n async aiScroll(\n locatePrompt: TUserPrompt | undefined,\n opt: LocateOption & ScrollParam,\n ): Promise<void>;\n\n // Legacy signature - deprecated\n /**\n * @deprecated Use aiScroll(locatePrompt, opt) instead where opt contains the scroll parameters\n */\n async aiScroll(\n scrollParam: ScrollParam,\n locatePrompt?: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void>;\n\n // Implementation\n async aiScroll(\n locatePromptOrScrollParam: TUserPrompt | ScrollParam | undefined,\n locatePromptOrOpt: TUserPrompt | (LocateOption & ScrollParam) | undefined,\n optOrUndefined?: LocateOption,\n ) {\n let scrollParam: ScrollParam;\n let locatePrompt: TUserPrompt | undefined;\n let opt: LocateOption | undefined;\n\n const isLocatePromptLike = (value: unknown): value is TUserPrompt => {\n if (\n typeof value === 'string' ||\n typeof value === 'undefined' ||\n value === null\n ) {\n return true;\n }\n\n return typeof value === 'object' && value !== null && 'prompt' in value;\n };\n\n // Check if using new signature (first param is locatePrompt, second is options)\n if (\n isLocatePromptLike(locatePromptOrScrollParam) &&\n typeof locatePromptOrOpt === 'object' &&\n locatePromptOrOpt !== null\n ) {\n // New signature: aiScroll(locatePrompt, opt)\n locatePrompt = locatePromptOrScrollParam as TUserPrompt;\n opt = locatePromptOrOpt as LocateOption & ScrollParam;\n } else {\n // Legacy signature: aiScroll(scrollParam, locatePrompt, opt)\n scrollParam = locatePromptOrScrollParam as ScrollParam;\n locatePrompt = locatePromptOrOpt as TUserPrompt | undefined;\n opt = {\n ...(optOrUndefined || {}),\n ...(scrollParam || {}),\n };\n }\n\n if (opt) {\n const normalizedScrollType = normalizeScrollType(\n (opt as ScrollParam).scrollType,\n );\n\n if (normalizedScrollType !== (opt as ScrollParam).scrollType) {\n (opt as ScrollParam) = {\n ...(opt || {}),\n scrollType: normalizedScrollType as ScrollParam['scrollType'],\n };\n }\n }\n\n const detailedLocateParam = buildDetailedLocateParam(\n locatePrompt || '',\n opt,\n );\n\n await this.callActionInActionSpace('Scroll', {\n ...(opt || {}),\n locate: detailedLocateParam,\n });\n }\n\n async aiPinch(\n locatePrompt: TUserPrompt | undefined,\n opt: LocateOption & {\n direction: 'in' | 'out';\n distance?: number;\n duration?: number;\n },\n ): Promise<void> {\n const detailedLocateParam = buildDetailedLocateParam(\n locatePrompt || '',\n opt,\n );\n\n await this.callActionInActionSpace('Pinch', {\n ...opt,\n locate: detailedLocateParam,\n });\n }\n\n async aiLongPress(\n locatePrompt: TUserPrompt,\n opt?: LocateOption & { duration?: number },\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for long press');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('LongPress', {\n ...(opt || {}),\n locate: detailedLocateParam,\n });\n }\n\n async aiClearInput(\n locatePrompt: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for clear input');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('ClearInput', {\n locate: detailedLocateParam,\n });\n }\n\n async aiAct(\n taskPrompt: TUserPrompt,\n opt?: AiActOptions,\n ): Promise<string | undefined> {\n const internalReportDisplay = (opt as AiActInternalOptions | undefined)\n ?._internalReportDisplay;\n const taskPromptText =\n typeof taskPrompt === 'string' ? taskPrompt : taskPrompt.prompt;\n const reportPrompt = internalReportDisplay?.prompt || taskPromptText;\n const fileChooserAccept = opt?.fileChooserAccept\n ? this.normalizeFileInput(opt.fileChooserAccept)\n : undefined;\n\n const abortSignal = opt?.abortSignal;\n if (abortSignal?.aborted) {\n throw new Error(\n `aiAct aborted: ${abortSignal.reason || 'signal already aborted'}`,\n );\n }\n\n const runAiAct = async () => {\n const planningModel = this.resolveModelRuntime('planning');\n const defaultModel = this.resolveModelRuntime('default');\n const aiActContext =\n opt?.context !== undefined ? opt.context : this.aiActContext;\n const cachePrompt = buildPromptWithContext(taskPrompt, aiActContext);\n // Controls the aiAct planning mode, such as sub-goal prompts and locate result strategy.\n let deepThink = opt?.deepThink === true;\n if (deepThink && planningModel.adapter.planning.kind === 'custom') {\n warn(\n `The \"deepThink\" option is not supported for aiAct with custom planning adapters (modelFamily: ${planningModel.config.modelFamily ?? 'unknown'}). It will be ignored.`,\n );\n deepThink = false;\n }\n\n let deepLocate = opt?.deepLocate;\n if (\n deepLocate &&\n !planningModel.adapter.planning.supportsActionDeepLocate\n ) {\n warn(\n `The \"deepLocate\" option is not supported for aiAct with the current planning adapter (modelFamily: ${planningModel.config.modelFamily ?? 'unknown'}). It will be ignored.`,\n );\n deepLocate = false;\n }\n\n const noIndividualLocateModel = planningModel.config.slot === 'default';\n\n const includeLocateInPlanning = !deepThink && noIndividualLocateModel;\n\n debug('setting includeLocateInPlanning to', includeLocateInPlanning, {\n deepThink,\n noIndividualLocateModel,\n });\n\n const cacheable = opt?.cacheable;\n const replanningCycleLimit =\n this.resolveReplanningCycleLimit(planningModel);\n const planCacheEnabled = planningModel.adapter.planning.cacheEnabled;\n const matchedCache =\n !planCacheEnabled || cacheable === false\n ? undefined\n : this.taskCache?.matchPlanCache(cachePrompt);\n let cachedYamlFailed = false;\n if (\n matchedCache?.cacheUsable &&\n this.taskCache?.isCacheResultUsed &&\n matchedCache.cacheContent?.yamlWorkflow?.trim()\n ) {\n const yaml = matchedCache.cacheContent.yamlWorkflow;\n try {\n // log into report file\n await this.taskExecutor.loadYamlFlowAsPlanning(\n taskPrompt,\n yaml,\n internalReportDisplay,\n );\n\n debug('matched cache, will call .runYaml to run the action');\n await this.runYaml(yaml);\n return;\n } catch (error) {\n cachedYamlFailed = true;\n warn(\n `cached aiAct plan failed, will replan and disable the stale cache: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n // If cache matched but is not executable, fall through to normal execution\n const imagesIncludeCount: number = deepThink ? 2 : 1;\n const { output: actionOutput } = await this.taskExecutor.action(\n taskPrompt,\n planningModel,\n defaultModel,\n includeLocateInPlanning,\n aiActContext,\n cacheable,\n replanningCycleLimit,\n imagesIncludeCount,\n deepThink,\n fileChooserAccept,\n deepLocate,\n abortSignal,\n internalReportDisplay,\n );\n\n // update cache\n if (this.taskCache && cacheable !== false) {\n const yamlFlow = cachedYamlFailed ? [] : actionOutput?.yamlFlow;\n\n if (!cachedYamlFailed && !yamlFlow?.length) {\n return actionOutput?.output;\n }\n\n const yamlFlowToCache = yamlFlow ?? [];\n const yamlContent: MidsceneYamlScript = {\n tasks: [\n {\n name: reportPrompt,\n flow: yamlFlowToCache,\n },\n ],\n };\n const yamlFlowStr = yaml.dump(yamlContent);\n this.taskCache.updateOrAppendCacheRecord(\n {\n type: 'plan',\n prompt: cachePrompt,\n yamlWorkflow: yamlFlowStr,\n },\n matchedCache,\n );\n }\n\n return actionOutput?.output;\n };\n\n return await runAiAct();\n }\n\n async runMarkdown(\n markdownPath: string,\n opt?: AiActOptions,\n ): Promise<string | undefined> {\n const markdown = await readFile(markdownPath, 'utf-8');\n const { prompt } = await markdownToAiActPrompt(markdown, markdownPath);\n return this.aiAct(prompt, {\n ...opt,\n _internalReportDisplay: {\n type: 'Markdown',\n prompt: basename(markdownPath),\n },\n } as AiActOptions);\n }\n\n async runGherkinScenario(\n scenarioText: string,\n opt?: RunGherkinScenarioOptions,\n ): Promise<void> {\n return runGherkinScenario(this, scenarioText, opt);\n }\n\n /**\n * @deprecated Use {@link Agent.aiAct} instead.\n */\n async aiAction(taskPrompt: TUserPrompt, opt?: AiActOptions) {\n return this.aiAct(taskPrompt, opt);\n }\n\n async aiQuery<ReturnType = any>(\n demand: ServiceExtractParam,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<ReturnType> {\n const modelRuntime = this.resolveModelRuntime('insight');\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'Query',\n demand,\n modelRuntime,\n opt,\n );\n return output as ReturnType;\n }\n\n async aiBoolean(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<boolean> {\n return this.aiBooleanWithContext(prompt, undefined, opt);\n }\n\n private async aiBooleanWithContext(\n prompt: TUserPrompt,\n uiContext?: UIContext,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<boolean> {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'Boolean',\n textPrompt,\n modelRuntime,\n opt,\n multimodalPrompt,\n uiContext ? { uiContext } : undefined,\n );\n return output as boolean;\n }\n\n async aiNumber(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<number> {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'Number',\n textPrompt,\n modelRuntime,\n opt,\n multimodalPrompt,\n );\n return output as number;\n }\n\n async aiString(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<string> {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'String',\n textPrompt,\n modelRuntime,\n opt,\n multimodalPrompt,\n );\n return output as string;\n }\n\n async aiAsk(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<string> {\n return this.aiString(prompt, opt);\n }\n\n /**\n * Locate an element and return both its center point and an approximate rect.\n *\n * - In most locate flows, `rect` represents the matched element boundary.\n * - Some models only support point grounding instead of boundary grounding.\n * In those cases (for example, AutoGLM), `rect` falls back to a small 8x8\n * box centered on the located point.\n *\n * Because `rect` may vary with the underlying model capability, avoid relying\n * on it too heavily for strict boundary semantics. If you need a stable click\n * target, prefer `center`.\n */\n async aiLocate(prompt: TUserPrompt, opt?: LocateOption) {\n const locateParam = buildDetailedLocateParam(prompt, opt);\n assert(locateParam, 'cannot get locate param for aiLocate');\n const locatePlan = locatePlanForLocate(locateParam);\n const plans = [locatePlan];\n const defaultModel = this.resolveModelRuntime('default');\n const planningModel = this.resolveModelRuntime('planning');\n\n const { output } = await this.taskExecutor.runPlans(\n taskTitleStr('Locate', locateParamStr(locateParam)),\n plans,\n planningModel,\n defaultModel,\n opt?.uiContext ? { uiContext: opt.uiContext } : undefined,\n );\n\n const { element } = output;\n\n return {\n rect: element?.rect,\n center: element?.center,\n dpr: element?.dpr,\n } as Pick<LocateResultElement, 'rect' | 'center'>;\n }\n\n async aiAssert(\n assertion: TUserPrompt,\n msg?: string,\n opt?: AgentAssertOpt & ServiceExtractOption,\n ) {\n return this.aiAssertWithContext(assertion, undefined, msg, opt);\n }\n\n private async aiAssertWithContext(\n assertion: TUserPrompt,\n uiContext?: UIContext,\n msg?: string,\n opt?: AgentAssertOpt & ServiceExtractOption,\n ) {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const serviceOpt: ServiceExtractOption = {\n domIncluded: opt?.domIncluded ?? defaultServiceExtractOption.domIncluded,\n screenshotIncluded:\n opt?.screenshotIncluded ??\n defaultServiceExtractOption.screenshotIncluded,\n };\n\n const assertionWithContext = buildPromptWithContext(\n assertion,\n opt?.context,\n );\n const { textPrompt, multimodalPrompt } = parsePrompt(assertionWithContext);\n const assertionText =\n typeof assertion === 'string' ? assertion : assertion.prompt;\n\n const executionOptions = {\n abortSignal: opt?.abortSignal,\n ...(uiContext ? { uiContext } : {}),\n };\n\n try {\n const { output, thought } =\n await this.taskExecutor.createTypeQueryExecution<boolean>(\n 'Assert',\n textPrompt,\n modelRuntime,\n serviceOpt,\n multimodalPrompt,\n executionOptions,\n );\n\n const pass = Boolean(output);\n const message = pass\n ? undefined\n : `Assertion failed: ${msg || assertionText}\\nReason: ${thought || '(no_reason)'}`;\n\n if (opt?.keepRawResponse) {\n return {\n pass,\n thought,\n message,\n };\n }\n\n if (!pass) {\n throw new Error(message);\n }\n } catch (error) {\n if (error instanceof TaskExecutionError) {\n const errorTask = error.errorTask;\n const thought = errorTask?.thought;\n const rawError = errorTask?.error;\n const rawMessage =\n errorTask?.errorMessage ||\n (rawError instanceof Error\n ? rawError.message\n : rawError\n ? String(rawError)\n : undefined);\n const reason = thought || rawMessage || '(no_reason)';\n const message = `Assertion failed: ${msg || assertionText}\\nReason: ${reason}`;\n\n if (opt?.keepRawResponse) {\n return {\n pass: false,\n thought,\n message,\n };\n }\n\n throw new Error(message, {\n cause: rawError ?? error,\n });\n }\n\n throw error;\n }\n }\n\n async aiWaitFor(assertion: TUserPrompt, opt?: AgentWaitForOpt) {\n const modelRuntime = this.resolveModelRuntime('insight');\n await this.taskExecutor.waitFor(\n assertion,\n {\n ...opt,\n timeoutMs: opt?.timeoutMs || 15 * 1000,\n checkIntervalMs: opt?.checkIntervalMs || 3 * 1000,\n },\n modelRuntime,\n );\n }\n\n async ai(...args: Parameters<typeof this.aiAct>) {\n return this.aiAct(...args);\n }\n\n async runYaml(yamlScriptContent: string): Promise<{\n result: Record<string, any>;\n }> {\n const script = parseYamlScript(yamlScriptContent, 'yaml');\n const player = new ScriptPlayer(script, async () => {\n return { agent: this, freeFn: [] };\n });\n await player.run();\n\n if (player.status === 'error') {\n const errors = player.taskStatusList\n .filter((task) => task.status === 'error')\n .map((task) => {\n return `task - ${task.name}: ${task.error?.message}`;\n })\n .join('\\n');\n throw new Error(`Error(s) occurred in running yaml script:\\n${errors}`);\n }\n\n return {\n result: player.result,\n };\n }\n\n async evaluateJavaScript(script: string) {\n assert(\n this.interface.evaluateJavaScript,\n 'evaluateJavaScript is not supported in current agent',\n );\n return this.interface.evaluateJavaScript(script);\n }\n\n /**\n * Add a dump update listener\n * @param listener Listener function\n * @returns A remove function that can be called to remove this listener\n */\n addDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): () => void {\n this.dumpUpdateListeners.push(listener);\n\n // Return remove function\n return () => {\n this.removeDumpUpdateListener(listener);\n };\n }\n\n /**\n * Remove a dump update listener\n * @param listener The listener function to remove\n */\n removeDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n const index = this.dumpUpdateListeners.indexOf(listener);\n if (index > -1) {\n this.dumpUpdateListeners.splice(index, 1);\n }\n }\n\n /**\n * Clear all dump update listeners\n */\n clearDumpUpdateListeners(): void {\n this.dumpUpdateListeners = [];\n }\n\n /**\n * Subscribe to the generic agent progress bus. The listener receives every\n * progress event regardless of producer; narrow by `event.scope` to handle a\n * specific producer (e.g. `'aiAct'`).\n * @param listener Listener function\n * @returns A remove function that can be called to remove this listener\n */\n addProgressListener(listener: AgentProgressListener): () => void {\n return this.progressBus.subscribe(listener);\n }\n\n /**\n * Remove a progress listener added via {@link addProgressListener}.\n */\n removeProgressListener(listener: AgentProgressListener): void {\n this.progressBus.unsubscribe(listener);\n }\n\n /**\n * Clear all generic progress listeners.\n */\n clearProgressListeners(): void {\n this.progressBus.clear();\n }\n\n private notifyDumpUpdateListeners(executionDump?: ExecutionDump) {\n const dumpString = this.dumpDataString();\n for (const listener of this.dumpUpdateListeners) {\n try {\n listener(dumpString, executionDump);\n } catch (error) {\n console.error('Error in onDumpUpdate listener', error);\n }\n }\n }\n\n async destroy() {\n // Early return if already destroyed\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n\n // Stop any active observer before tearing down the interface. The observer\n // may hold a frame source subscription that needs explicit cleanup.\n if (this.activeObserver) {\n try {\n await this.activeObserver.stop();\n } catch (error) {\n debug(`error stopping active observer during destroy: ${error}`);\n }\n // onStopped callback should have cleared this, but ensure it's null\n this.activeObserver = null;\n }\n\n let interfaceDestroyError: unknown;\n try {\n await this.interface.destroy?.();\n } catch (error) {\n interfaceDestroyError = error;\n }\n\n // Wait for all queued write operations to complete\n await this.reportGenerator.flush();\n\n const finalPath = await this.reportGenerator.finalize();\n this.reportFile = finalPath;\n\n this.resetDump(); // reset dump to release memory\n\n if (interfaceDestroyError) {\n throw interfaceDestroyError;\n }\n }\n\n async recordToReport(title?: string, opt?: RecordToReportOptions) {\n const now = Date.now();\n const screenshots = opt?.screenshots;\n const screenshotBase64 = opt?.screenshotBase64;\n const hasScreenshots = screenshots !== undefined;\n const hasScreenshotBase64 = screenshotBase64 !== undefined;\n if (hasScreenshots && !Array.isArray(screenshots)) {\n throw new Error('recordToReport: screenshots must be an array');\n }\n if (hasScreenshotBase64 && typeof screenshotBase64 !== 'string') {\n throw new Error('recordToReport: screenshotBase64 must be a string');\n }\n if (hasScreenshots && hasScreenshotBase64) {\n throw new Error(\n 'recordToReport: provide only one of screenshots or screenshotBase64',\n );\n }\n if (opt && 'subType' in opt) {\n throw new Error('recordToReport: subType is not supported');\n }\n const customScreenshots = hasScreenshots ? screenshots : undefined;\n if (customScreenshots && customScreenshots.length === 0) {\n throw new Error('recordToReport: screenshots cannot be empty');\n }\n const screenshotInputs: RecordToReportScreenshot[] =\n customScreenshots ??\n (hasScreenshotBase64\n ? [{ base64: screenshotBase64 }]\n : [{ base64: await this.interface.screenshotBase64() }]);\n\n // 1. build recorder\n const recorder: ExecutionRecorderItem[] = screenshotInputs.map(\n (screenshotInput, index) => {\n const normalizedScreenshotInput = normalizeRecordToReportScreenshot(\n screenshotInput,\n index,\n );\n const ts = now + index;\n return {\n type: 'screenshot',\n ts,\n screenshot: ScreenshotItem.create(\n normalizedScreenshotInput.base64,\n ts,\n ),\n description: normalizedScreenshotInput.description,\n };\n },\n );\n // 2. build ExecutionTaskLog\n const task: ExecutionTaskLog = {\n taskId: uuid(),\n type: 'Log',\n subType: 'Screenshot',\n status: 'finished',\n recorder,\n timing: {\n start: now,\n end: now,\n cost: 0,\n },\n param: {\n content: opt?.content || '',\n },\n executor: async () => {},\n };\n // 3. build ExecutionDump\n const executionDump = new ExecutionDump({\n id: uuid(),\n logTime: now,\n name: `Log - ${title || 'untitled'}`,\n description: opt?.content || '',\n tasks: [task],\n });\n // 4. append to execution dump\n this.appendExecutionDump(executionDump);\n\n this.writeOutActionDumps(executionDump);\n await this.reportGenerator.flush();\n\n // Call all registered dump update listeners\n this.notifyDumpUpdateListeners(executionDump);\n }\n\n async recordErrorToReport(\n title: string,\n opt: {\n error: Error;\n content?: string;\n screenshotBase64?: string;\n },\n ) {\n const now = Date.now();\n const recorder: ExecutionRecorderItem[] = [];\n const base64 =\n opt.screenshotBase64 ?? (await this.interface.screenshotBase64());\n if (base64) {\n recorder.push({\n type: 'screenshot',\n ts: now,\n screenshot: ScreenshotItem.create(base64, now),\n });\n }\n\n const task: ExecutionTaskLog = {\n taskId: uuid(),\n type: 'Log',\n subType: 'Error',\n status: 'failed',\n recorder,\n timing: {\n start: now,\n end: now,\n cost: 0,\n },\n param: {\n content: opt.content || '',\n },\n error: opt.error,\n errorMessage: opt.error.message,\n errorStack: opt.error.stack,\n executor: async () => {},\n };\n\n const executionDump = new ExecutionDump({\n id: uuid(),\n logTime: now,\n name: title,\n description: opt.content || opt.error.message,\n tasks: [task],\n });\n\n this.appendExecutionDump(executionDump);\n this.writeOutActionDumps(executionDump);\n await this.reportGenerator.flush();\n this.notifyDumpUpdateListeners(executionDump);\n }\n\n /**\n * @deprecated Use {@link Agent.recordToReport} instead.\n */\n async logScreenshot(\n title?: string,\n opt?: {\n content: string;\n },\n ) {\n await this.recordToReport(title, opt);\n }\n\n _unstableLogContent() {\n const { groupName, groupDescription, executions } = this.dump;\n return {\n groupName,\n groupDescription,\n executions: executions || [],\n };\n }\n\n /**\n * Freezes the current page context to be reused in subsequent AI operations\n * This avoids recalculating page context for each operation\n */\n async freezePageContext(): Promise<void> {\n debug('Freezing page context');\n const context = await this._snapshotContext();\n // Mark the context as frozen\n context._isFrozen = true;\n this.frozenUIContext = context;\n debug('Page context frozen successfully');\n }\n\n /**\n * Unfreezes the page context, allowing AI operations to calculate context dynamically\n */\n async unfreezePageContext(): Promise<void> {\n debug('Unfreezing page context');\n this.frozenUIContext = undefined;\n debug('Page context unfrozen successfully');\n }\n\n /**\n * Process cache configuration and return normalized cache settings\n */\n private processCacheConfig(opts: AgentOpt): {\n id: string;\n enabled: boolean;\n readOnly: boolean;\n writeOnly: boolean;\n cacheDir?: string;\n } | null {\n validateAgentCacheInput(opts.cache);\n\n // Use the unified utils function to process cache configuration\n const cacheConfig = processCacheConfig(\n opts.cache,\n opts.cacheId || 'default',\n );\n\n if (!cacheConfig) {\n return null;\n }\n\n // Handle cache configuration object\n if (typeof cacheConfig === 'object' && cacheConfig !== null) {\n const id = cacheConfig.id;\n const strategyValue = cacheConfig.strategy ?? 'read-write';\n const isReadOnly = strategyValue === 'read-only';\n const isWriteOnly = strategyValue === 'write-only';\n\n return {\n id,\n enabled: !isWriteOnly,\n readOnly: isReadOnly,\n writeOnly: isWriteOnly,\n cacheDir: cacheConfig.cacheDir?.trim(),\n };\n }\n\n return null;\n }\n\n private normalizeFileInput(files: string | string[]): string[] {\n const filesArray = Array.isArray(files) ? files : [files];\n return normalizeFilePaths(filesArray);\n }\n\n /**\n * Manually flush cache to file\n * @param options - Optional configuration\n * @param options.cleanUnused - If true, removes unused cache records before flushing\n */\n async flushCache(options?: { cleanUnused?: boolean }): Promise<void> {\n if (!this.taskCache) {\n throw new Error('Cache is not configured');\n }\n\n this.taskCache.flushCacheToFile(options);\n }\n}\n\nexport const createAgent = (\n interfaceInstance: AbstractInterface,\n opts?: AgentOpt,\n) => {\n return new Agent(interfaceInstance, opts);\n};\n"],"names":["debug","getDebug","warn","defaultServiceExtractOption","Agent","callback","planningModel","globalConfigManager","MIDSCENE_REPLANNING_CYCLE_LIMIT","intent","runtime","getModelRuntime","usage","enriched","_error","action","maxRetries","attempt","commonContextParser","error","Promise","resolve","setTimeout","opt","assert","observer","UIObserver","undefined","assertion","uiContext","msg","assertOpt","prompt","boolOpt","console","ReportActionDump","getVersion","WeakMap","execution","runner","currentDump","existingIndex","task","key","dedupKey","INTERNAL_CALL_ID_FIELD","ifInBrowser","reportHTMLContent","executionDump","exec","param","paramStr","tip","typeStr","name","type","actionPlan","plans","Boolean","title","taskTitleStr","locateParamStr","defaultModel","output","locatePrompt","detailedLocateParam","buildDetailedLocateParam","fileChooserAccept","withFileChooser","locatePromptOrValue","locatePromptOrOpt","optOrUndefined","value","optWithValue","stringValue","String","mode","locatePromptOrKeyName","keyName","locatePromptOrScrollParam","scrollParam","isLocatePromptLike","normalizedScrollType","normalizeScrollType","taskPrompt","internalReportDisplay","taskPromptText","reportPrompt","abortSignal","Error","runAiAct","aiActContext","cachePrompt","buildPromptWithContext","deepThink","deepLocate","noIndividualLocateModel","includeLocateInPlanning","cacheable","replanningCycleLimit","planCacheEnabled","matchedCache","cachedYamlFailed","yaml","imagesIncludeCount","actionOutput","yamlFlow","yamlFlowToCache","yamlContent","yamlFlowStr","markdownPath","markdown","readFile","markdownToAiActPrompt","basename","scenarioText","runGherkinScenario","demand","modelRuntime","textPrompt","multimodalPrompt","parsePrompt","locateParam","locatePlan","locatePlanForLocate","element","serviceOpt","assertionWithContext","assertionText","executionOptions","thought","pass","message","TaskExecutionError","errorTask","rawError","rawMessage","reason","args","yamlScriptContent","script","parseYamlScript","player","ScriptPlayer","errors","listener","index","dumpString","interfaceDestroyError","finalPath","now","Date","screenshots","screenshotBase64","hasScreenshots","hasScreenshotBase64","Array","customScreenshots","screenshotInputs","recorder","screenshotInput","normalizedScreenshotInput","normalizeRecordToReportScreenshot","ts","ScreenshotItem","uuid","ExecutionDump","base64","groupName","groupDescription","executions","context","opts","validateAgentCacheInput","cacheConfig","processCacheConfig","id","strategyValue","isReadOnly","isWriteOnly","files","filesArray","normalizeFilePaths","options","interfaceInstance","MetricsCollector","Set","AgentProgressBus","Object","assertReportGenerationOptions","resolvedAiActContext","hasCustomConfig","ModelConfigManager","globalModelConfigManager","Service","cacheConfigObj","TaskCache","baseActionSpace","defineActionSleep","TaskExecutor","getReportFileName","ReportGenerator","createAgent"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoGA,MAAMA,QAAQC,SAAS;AACvB,MAAMC,OAAOD,SAAS,SAAS;IAAE,SAAS;AAAK;AAE/C,MAAME,8BAAoD;IACxD,aAAa;IACb,oBAAoB;AACtB;AA4BO,MAAMC;IA4CX,IAAI,eAEU;QACZ,OAAO,IAAI,CAAC,mBAAmB,CAAC,EAAE;IACpC;IAEA,IAAI,aAAaC,QAEJ,EAAE;QAEb,IAAI,CAAC,mBAAmB,GAAG,EAAE;QAE7B,IAAIA,UACF,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAACA;IAElC;IAiBA,IAAY,eAAmC;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe;IAC5D;IASA,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,SAAS;IACvB;IAgBQ,oCAAoC;QAC1C,IACE,AAAiC,gBAAjC,IAAI,CAAC,SAAS,CAAC,aAAa,IAC5B,AAAiC,iBAAjC,IAAI,CAAC,SAAS,CAAC,aAAa,IAC5B,AAAiC,aAAjC,IAAI,CAAC,SAAS,CAAC,aAAa,IAC5B,AAAiC,6BAAjC,IAAI,CAAC,SAAS,CAAC,aAAa,IAC5B,AAAiC,wCAAjC,IAAI,CAAC,SAAS,CAAC,aAAa,EAE5B,IAAI,CAAC,kBAAkB,CAAC,sBAAsB;IAElD;IAEQ,4BAA4BC,aAA2B,EAAU;QACvE,OACE,IAAI,CAAC,IAAI,CAAC,oBAAoB,IAC9BC,oBAAoB,yBAAyB,CAC3CC,oCAEFF,cAAc,OAAO,CAAC,QAAQ,CAAC,2BAA2B;IAE9D;IAEQ,oBAAoBG,MAAe,EAAgB;QACzD,MAAMC,UAAUC,gBACd,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAACF;QAEzC,OAAO;YACL,GAAGC,OAAO;YACV,SAAS,CAACE;gBACR,IAAI,CAAC,gBAAgB,IAAI;gBAGzB,MAAMC,WAAWD,MAAM,MAAM,GACzBA,QACA;oBAAE,GAAGA,KAAK;oBAAE,QAAQA,MAAM,IAAI;gBAAC;gBACnC,IAAI,CAAC,YAAY,CACfC,UACA,CAAC,OAAO,EAAED,MAAM,UAAU,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAEzD;QACF;IACF;IA+GA,MAAM,iBAA0C;QAC9C,OAAO,IAAI,CAAC,eAAe;IAC7B;IAUU,wBAAwBE,MAAe,EAAW;QAC1D,OAAO;IACT;IAEA,MAAM,aAAaC,MAAsB,EAAsB;QAI7D,IAAI,CAAC,iCAAiC;QAGtC,IAAI,IAAI,CAAC,eAAe,EAAE;YACxBf,MAAM,yCAAyCe;YAC/C,OAAO,IAAI,CAAC,eAAe;QAC7B;QAEA,MAAMC,aAAaZ,MAAM,iBAAiB;QAC1C,IAAK,IAAIa,UAAU,IAAKA,UACtB,IAAI;YACF,OAAO,MAAMC,oBAAoB,IAAI,CAAC,SAAS,EAAE;gBAC/C,iBAAiB,IAAI,CAAC,kBAAkB,CAAC,sBAAsB;gBAC/D,wBAAwB,IAAI,CAAC,IAAI,CAAC,sBAAsB;YAC1D;QACF,EAAE,OAAOC,OAAO;YACd,IAAIF,UAAUD,cAAc,IAAI,CAAC,uBAAuB,CAACG,QAAQ;gBAC/DnB,MACE,CAAC,iCAAiC,EAAEiB,UAAU,EAAE,CAAC,EAAED,WAAW,eAAe,EAAEZ,MAAM,sBAAsB,CAAC,IAAI,EAAEe,OAAO;gBAE3H,MAAM,IAAIC,QAAQ,CAACC,UACjBC,WAAWD,SAASjB,MAAM,sBAAsB;gBAElD;YACF;YACA,MAAMe;QACR;IAEJ;IAEA,MAAM,mBAAuC;QAC3C,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC;IACjC;IAwBA,MAAM,eAAeI,GAAsB,EAAuB;QAIhEC,OACE,CAAC,IAAI,CAAC,eAAe,EACrB;QAIFA,OACE,CAAC,IAAI,CAAC,cAAc,EACpB;QAGF,MAAMC,WAAW,IAAIC,WACnB;YACE,iBAAiB,UACd,MAAM,IAAI,CAAC,SAAS,CAAC,eAAe,QAASC;YAGhD,YAAY,IAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB;YACjD,uBAAuB,IAAM,IAAI,CAAC,YAAY,CAAC;YAC/C,WAAW,CAACC,WAAWC,WAAWC,KAAKC,YACrC,IAAI,CAAC,mBAAmB,CAACH,WAAWC,WAAWC,KAAKC;YACtD,YAAY,CAACC,QAAQH,WAAWI,UAC9B,IAAI,CAAC,oBAAoB,CAACD,QAAQH,WAAWI;YAC/C,WAAW;gBACT,IAAI,CAAC,cAAc,GAAG;YACxB;YACA,wBAAwB,IAAI,CAAC,IAAI,CAAC,sBAAsB;QAC1D,GACAV;QAIF,IAAI,CAAC,cAAc,GAAGE;QACtB,IAAI;YACF,MAAMA,SAAS,KAAK;QACtB,EAAE,OAAON,OAAO;YACd,IAAI,CAAC,cAAc,GAAG;YACtB,MAAMA;QACR;QACA,OAAOM;IACT;IAKA,MAAM,mBAAmBO,MAAc,EAAE;QACvC,MAAM,IAAI,CAAC,eAAe,CAACA;IAC7B;IAEA,MAAM,gBAAgBA,MAAc,EAAE;QACpC,IAAI,IAAI,CAAC,YAAY,EACnBE,QAAQ,IAAI,CACV;QAGJ,IAAI,CAAC,IAAI,CAAC,YAAY,GAAGF;QACzB,IAAI,CAAC,IAAI,CAAC,eAAe,GAAGA;IAC9B;IAEA,YAAY;QACV,IAAI,CAAC,IAAI,GAAG,IAAIG,iBAAiB;YAC/B,YAAYC;YACZ,WAAW,IAAI,CAAC,IAAI,CAAC,SAAS;YAC9B,kBAAkB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAC5C,YAAY,EAAE;YACd,aAAa,EAAE;YACf,YAAY,IAAI,CAAC,SAAS,CAAC,aAAa;QAC1C;QACA,IAAI,CAAC,0BAA0B,GAAG,IAAIC;QAEtC,OAAO,IAAI,CAAC,IAAI;IAClB;IAEA,oBAAoBC,SAAwB,EAAEC,MAAmB,EAAE;QACjE,MAAMC,cAAc,IAAI,CAAC,IAAI;QAC7B,IAAID,QAAQ;YACV,MAAME,gBAAgB,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAACF;YAC1D,IAAIE,AAAkBd,WAAlBc,eAA6B;gBAC/BD,YAAY,UAAU,CAACC,cAAc,GAAGH;gBACxC;YACF;YACAE,YAAY,UAAU,CAAC,IAAI,CAACF;YAC5B,IAAI,CAAC,0BAA0B,CAAC,GAAG,CACjCC,QACAC,YAAY,UAAU,CAAC,MAAM,GAAG;YAElC;QACF;QACAA,YAAY,UAAU,CAAC,IAAI,CAACF;IAC9B;IAOQ,oBAAoBA,SAAwB,EAAE;QACpD,KAAK,MAAMI,QAAQJ,UAAU,KAAK,CAAE;YAClC,IAAI,CAAC,YAAY,CAACI,KAAK,KAAK,EAAE,GAAGA,KAAK,MAAM,CAAC,MAAM,CAAC;YACpD,IAAI,CAAC,YAAY,CAACA,KAAK,eAAe,EAAE,GAAGA,KAAK,MAAM,CAAC,gBAAgB,CAAC;QAC1E;IACF;IAEQ,aAAa9B,KAA8B,EAAE+B,GAAW,EAAE;QAChE,IAAI,CAAC/B,OACH;QAOF,IAAIgC;QAEFA,WADEhC,MAAM,UAAU,GACP,CAAC,IAAI,EAAEA,MAAM,UAAU,EAAE,GAC1BA,KAAa,CAACiC,uBAAuB,GACpC,CAAC,IAAI,EAAGjC,KAAa,CAACiC,uBAAuB,EAAE,GAE/CF;QAEb,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACC,WAC5B;QAEF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACA;QAC1B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAChC;QAC1B,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EACtB,IAAI;YACF,IAAI,CAAC,IAAI,CAAC,UAAU,CAACA;QACvB,EAAE,OAAOO,OAAO;YACdjB,KAAK,CAAC,qCAAqC,EAAEiB,OAAO;QACtD;IAEJ;IAKA,IAAI,UAAgC;QAClC,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ;IACvC;IAEA,eAAeI,GAAqC,EAAE;QAEpD,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS;QACzC,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB;QAEvD,IAAIuB,eAAevB,KAAK,mBACtB,OAAO,IAAI,CAAC,IAAI,CAAC,8BAA8B;QAEjD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS;IAC5B;IAEA,iBAAiBA,GAAqC,EAAE;QAEtD,OAAOwB,kBAAkB,IAAI,CAAC,cAAc,CAACxB;IAC/C;IAIA,oBAAoByB,aAA6B,EAAE;QACjD,MAAMC,OAAOD,iBAAiB,IAAI,CAAC,iBAAiB;QACpD,IAAIC,MAAM;YACR,IAAI,CAAC,iBAAiB,GAAGA;YACzB,IAAI,CAAC,eAAe,CAAC,iBAAiB,CACpCA,MACA,IAAI,CAAC,aAAa,IAClB,IAAI,CAAC,IAAI,CAAC,gBAAgB;QAE9B;QACA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa;IACtD;IAEQ,gBAA4B;QAClC,OAAO;YACL,WAAW,IAAI,CAAC,IAAI,CAAC,SAAS;YAC9B,kBAAkB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAC5C,YAAY,IAAI,CAAC,IAAI,CAAC,UAAU;YAChC,aAAa,IAAI,CAAC,IAAI,CAAC,WAAW;YAClC,YAAY,IAAI,CAAC,IAAI,CAAC,UAAU;QAClC;IACF;IAEA,MAAc,uBAAuBP,IAAmB,EAAE;QACxD,MAAMQ,QAAQC,SAAST;QACvB,MAAMU,MAAMF,QAAQ,GAAGG,QAAQX,MAAM,GAAG,EAAEQ,OAAO,GAAGG,QAAQX;QAE5D,IAAI,IAAI,CAAC,cAAc,EACrB,MAAM,IAAI,CAAC,cAAc,CAACU;IAE9B;IAEA,wBACEE,IAAY,EACyC;QACrD,OAAO,OAAOJ,QACL,MAAM,IAAI,CAAC,uBAAuB,CAAkBI,MAAMJ;IAErE;IAEA,MAAM,wBACJK,IAAY,EACZhC,GAAO,EACP;QACAvB,MAAM,2BAA2BuD,MAAM,KAAKhC;QAE5C,MAAMiC,aAAgC;YACpC,MAAMD;YACN,OAAQhC,OAAe,CAAC;YACxB,SAAS;QACX;QACAvB,MAAM,cAAcwD;QAEpB,MAAMC,QAA0B;YAACD;SAAW,CAAC,MAAM,CACjDE;QAGF,MAAMC,QAAQC,aACZL,MACAM,eAAgBtC,KAAa,UAAU,CAAC;QAI1C,MAAMuC,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAC9C,MAAMxD,gBAAgB,IAAI,CAAC,mBAAmB,CAAC;QAE/C,MAAM,EAAEyD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CACjDJ,OACAF,OACAnD,eACAwD;QAEF,OAAOC;IACT;IAEA,MAAM,MACJC,YAAyB,EACzBzC,GAA8D,EAC/C;QACfC,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAEnE,MAAM4C,oBAAoB5C,KAAK,oBAC3B,IAAI,CAAC,kBAAkB,CAACA,IAAI,iBAAiB,IAC7CI;QAEJ,MAAMyC,gBAAgB,IAAI,CAAC,SAAS,EAAED,mBAAmB;YACvD,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO;gBACxC,QAAQF;YACV;QACF;IACF;IAEA,MAAM,aACJD,YAAyB,EACzBzC,GAAkB,EACH;QACfC,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAEnE,MAAM,IAAI,CAAC,uBAAuB,CAAC,cAAc;YAC/C,QAAQ0C;QACV;IACF;IAEA,MAAM,cACJD,YAAyB,EACzBzC,GAAkB,EACH;QACfC,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAEnE,MAAM,IAAI,CAAC,uBAAuB,CAAC,eAAe;YAChD,QAAQ0C;QACV;IACF;IAEA,MAAM,QAAQD,YAAyB,EAAEzC,GAAkB,EAAiB;QAC1EC,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAEnE,MAAM,IAAI,CAAC,uBAAuB,CAAC,SAAS;YAC1C,QAAQ0C;QACV;IACF;IAmBA,MAAM,QACJI,mBAAkD,EAClDC,iBAGa,EACbC,cAAiC,EACjC;QACA,IAAIC;QACJ,IAAIR;QACJ,IAAIzC;QAGJ,IACE,AAA6B,YAA7B,OAAO+C,qBACPA,AAAsB,SAAtBA,qBACA,WAAWA,mBACX;YAEAN,eAAeK;YACf,MAAMI,eAAeH;YAGrBE,QAAQC,aAAa,KAAK;YAC1BlD,MAAMkD;QACR,OAAO;YAELD,QAAQH;YACRL,eAAeM;YACf/C,MAAM;gBACJ,GAAGgD,cAAc;gBACjBC;YACF;QACF;QAEAhD,OACE,AAAiB,YAAjB,OAAOgD,SAAsB,AAAiB,YAAjB,OAAOA,OACpC;QAEFhD,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAGnE,MAAMmD,cAAc,AAAiB,YAAjB,OAAOF,QAAqBG,OAAOH,SAASA;QAGhE,MAAMI,OAAOrD,KAAK,SAAS,WAAW,aAAaA,KAAK;QAExD,MAAM,IAAI,CAAC,uBAAuB,CAAC,SAAS;YAC1C,GAAIA,OAAO,CAAC,CAAC;YACb,OAAOmD;YACP,QAAQT;YACRW;QACF;IACF;IAmBA,MAAM,gBACJC,qBAA2C,EAC3CP,iBAGa,EACbC,cAA6B,EAC7B;QACA,IAAIO;QACJ,IAAId;QACJ,IAAIzC;QAGJ,IACE,AAA6B,YAA7B,OAAO+C,qBACPA,AAAsB,SAAtBA,qBACA,aAAaA,mBACb;YAEAN,eAAea;YACftD,MAAM+C;QAGR,OAAO;YAELQ,UAAUD;YACVb,eAAeM;YACf/C,MAAM;gBACJ,GAAIgD,kBAAkB,CAAC,CAAC;gBACxBO;YACF;QACF;QAEAtD,OAAOD,KAAK,SAAS;QAErB,MAAM0C,sBAAsBD,eACxBE,yBAAyBF,cAAczC,OACvCI;QAEJ,MAAM,IAAI,CAAC,uBAAuB,CAAC,iBAAiB;YAClD,GAAIJ,OAAO,CAAC,CAAC;YACb,QAAQ0C;QACV;IACF;IAmBA,MAAM,SACJc,yBAAgE,EAChET,iBAAyE,EACzEC,cAA6B,EAC7B;QACA,IAAIS;QACJ,IAAIhB;QACJ,IAAIzC;QAEJ,MAAM0D,qBAAqB,CAACT;YAC1B,IACE,AAAiB,YAAjB,OAAOA,SAEPA,QADOA,OAGP,OAAO;YAGT,OAAO,AAAiB,YAAjB,OAAOA,SAAsBA,AAAU,SAAVA,SAAkB,YAAYA;QACpE;QAGA,IACES,mBAAmBF,8BACnB,AAA6B,YAA7B,OAAOT,qBACPA,AAAsB,SAAtBA,mBACA;YAEAN,eAAee;YACfxD,MAAM+C;QACR,OAAO;YAELU,cAAcD;YACdf,eAAeM;YACf/C,MAAM;gBACJ,GAAIgD,kBAAkB,CAAC,CAAC;gBACxB,GAAIS,eAAe,CAAC,CAAC;YACvB;QACF;QAEA,IAAIzD,KAAK;YACP,MAAM2D,uBAAuBC,oBAC1B5D,IAAoB,UAAU;YAGjC,IAAI2D,yBAA0B3D,IAAoB,UAAU,EACzDA,MAAsB;gBACrB,GAAIA,OAAO,CAAC,CAAC;gBACb,YAAY2D;YACd;QAEJ;QAEA,MAAMjB,sBAAsBC,yBAC1BF,gBAAgB,IAChBzC;QAGF,MAAM,IAAI,CAAC,uBAAuB,CAAC,UAAU;YAC3C,GAAIA,OAAO,CAAC,CAAC;YACb,QAAQ0C;QACV;IACF;IAEA,MAAM,QACJD,YAAqC,EACrCzC,GAIC,EACc;QACf,MAAM0C,sBAAsBC,yBAC1BF,gBAAgB,IAChBzC;QAGF,MAAM,IAAI,CAAC,uBAAuB,CAAC,SAAS;YAC1C,GAAGA,GAAG;YACN,QAAQ0C;QACV;IACF;IAEA,MAAM,YACJD,YAAyB,EACzBzC,GAA0C,EAC3B;QACfC,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAEnE,MAAM,IAAI,CAAC,uBAAuB,CAAC,aAAa;YAC9C,GAAIA,OAAO,CAAC,CAAC;YACb,QAAQ0C;QACV;IACF;IAEA,MAAM,aACJD,YAAyB,EACzBzC,GAAkB,EACH;QACfC,OAAOwC,cAAc;QAErB,MAAMC,sBAAsBC,yBAAyBF,cAAczC;QAEnE,MAAM,IAAI,CAAC,uBAAuB,CAAC,cAAc;YAC/C,QAAQ0C;QACV;IACF;IAEA,MAAM,MACJmB,UAAuB,EACvB7D,GAAkB,EACW;QAC7B,MAAM8D,wBAAyB9D,KAC3B;QACJ,MAAM+D,iBACJ,AAAsB,YAAtB,OAAOF,aAA0BA,aAAaA,WAAW,MAAM;QACjE,MAAMG,eAAeF,uBAAuB,UAAUC;QACtD,MAAMnB,oBAAoB5C,KAAK,oBAC3B,IAAI,CAAC,kBAAkB,CAACA,IAAI,iBAAiB,IAC7CI;QAEJ,MAAM6D,cAAcjE,KAAK;QACzB,IAAIiE,aAAa,SACf,MAAM,IAAIC,MACR,CAAC,eAAe,EAAED,YAAY,MAAM,IAAI,0BAA0B;QAItE,MAAME,WAAW;YACf,MAAMpF,gBAAgB,IAAI,CAAC,mBAAmB,CAAC;YAC/C,MAAMwD,eAAe,IAAI,CAAC,mBAAmB,CAAC;YAC9C,MAAM6B,eACJpE,KAAK,YAAYI,SAAYJ,IAAI,OAAO,GAAG,IAAI,CAAC,YAAY;YAC9D,MAAMqE,cAAcC,uBAAuBT,YAAYO;YAEvD,IAAIG,YAAYvE,KAAK,cAAc;YACnC,IAAIuE,aAAaxF,AAAwC,aAAxCA,cAAc,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAe;gBACjEJ,KACE,CAAC,8FAA8F,EAAEI,cAAc,MAAM,CAAC,WAAW,IAAI,UAAU,sBAAsB,CAAC;gBAExKwF,YAAY;YACd;YAEA,IAAIC,aAAaxE,KAAK;YACtB,IACEwE,cACA,CAACzF,cAAc,OAAO,CAAC,QAAQ,CAAC,wBAAwB,EACxD;gBACAJ,KACE,CAAC,mGAAmG,EAAEI,cAAc,MAAM,CAAC,WAAW,IAAI,UAAU,sBAAsB,CAAC;gBAE7KyF,aAAa;YACf;YAEA,MAAMC,0BAA0B1F,AAA8B,cAA9BA,cAAc,MAAM,CAAC,IAAI;YAEzD,MAAM2F,0BAA0B,CAACH,aAAaE;YAE9ChG,MAAM,sCAAsCiG,yBAAyB;gBACnEH;gBACAE;YACF;YAEA,MAAME,YAAY3E,KAAK;YACvB,MAAM4E,uBACJ,IAAI,CAAC,2BAA2B,CAAC7F;YACnC,MAAM8F,mBAAmB9F,cAAc,OAAO,CAAC,QAAQ,CAAC,YAAY;YACpE,MAAM+F,eACJ,AAACD,oBAAoBF,AAAc,UAAdA,YAEjB,IAAI,CAAC,SAAS,EAAE,eAAeN,eAD/BjE;YAEN,IAAI2E,mBAAmB;YACvB,IACED,cAAc,eACd,IAAI,CAAC,SAAS,EAAE,qBAChBA,aAAa,YAAY,EAAE,cAAc,QACzC;gBACA,MAAME,OAAOF,aAAa,YAAY,CAAC,YAAY;gBACnD,IAAI;oBAEF,MAAM,IAAI,CAAC,YAAY,CAAC,sBAAsB,CAC5CjB,YACAmB,MACAlB;oBAGFrF,MAAM;oBACN,MAAM,IAAI,CAAC,OAAO,CAACuG;oBACnB;gBACF,EAAE,OAAOpF,OAAO;oBACdmF,mBAAmB;oBACnBpG,KACE,CAAC,mEAAmE,EAClEiB,iBAAiBsE,QAAQtE,MAAM,OAAO,GAAGwD,OAAOxD,QAChD;gBAEN;YACF;YAGA,MAAMqF,qBAA6BV,YAAY,IAAI;YACnD,MAAM,EAAE,QAAQW,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAC7DrB,YACA9E,eACAwD,cACAmC,yBACAN,cACAO,WACAC,sBACAK,oBACAV,WACA3B,mBACA4B,YACAP,aACAH;YAIF,IAAI,IAAI,CAAC,SAAS,IAAIa,AAAc,UAAdA,WAAqB;gBACzC,MAAMQ,WAAWJ,mBAAmB,EAAE,GAAGG,cAAc;gBAEvD,IAAI,CAACH,oBAAoB,CAACI,UAAU,QAClC,OAAOD,cAAc;gBAGvB,MAAME,kBAAkBD,YAAY,EAAE;gBACtC,MAAME,cAAkC;oBACtC,OAAO;wBACL;4BACE,MAAMrB;4BACN,MAAMoB;wBACR;qBACD;gBACH;gBACA,MAAME,cAAcN,QAAAA,IAAS,CAACK;gBAC9B,IAAI,CAAC,SAAS,CAAC,yBAAyB,CACtC;oBACE,MAAM;oBACN,QAAQhB;oBACR,cAAciB;gBAChB,GACAR;YAEJ;YAEA,OAAOI,cAAc;QACvB;QAEA,OAAO,MAAMf;IACf;IAEA,MAAM,YACJoB,YAAoB,EACpBvF,GAAkB,EACW;QAC7B,MAAMwF,WAAW,MAAMC,SAASF,cAAc;QAC9C,MAAM,EAAE9E,MAAM,EAAE,GAAG,MAAMiF,sBAAsBF,UAAUD;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC9E,QAAQ;YACxB,GAAGT,GAAG;YACN,wBAAwB;gBACtB,MAAM;gBACN,QAAQ2F,SAASJ;YACnB;QACF;IACF;IAEA,MAAM,mBACJK,YAAoB,EACpB5F,GAA+B,EAChB;QACf,OAAO6F,mBAAmB,IAAI,EAAED,cAAc5F;IAChD;IAKA,MAAM,SAAS6D,UAAuB,EAAE7D,GAAkB,EAAE;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC6D,YAAY7D;IAChC;IAEA,MAAM,QACJ8F,MAA2B,EAC3B9F,MAA4BpB,2BAA2B,EAClC;QACrB,MAAMmH,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAC9C,MAAM,EAAEvD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,wBAAwB,CACjE,SACAsD,QACAC,cACA/F;QAEF,OAAOwC;IACT;IAEA,MAAM,UACJ/B,MAAmB,EACnBT,MAA4BpB,2BAA2B,EACrC;QAClB,OAAO,IAAI,CAAC,oBAAoB,CAAC6B,QAAQL,QAAWJ;IACtD;IAEA,MAAc,qBACZS,MAAmB,EACnBH,SAAqB,EACrBN,MAA4BpB,2BAA2B,EACrC;QAClB,MAAMmH,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAE9C,MAAM,EAAEC,UAAU,EAAEC,gBAAgB,EAAE,GAAGC,YAAYzF;QACrD,MAAM,EAAE+B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,wBAAwB,CACjE,WACAwD,YACAD,cACA/F,KACAiG,kBACA3F,YAAY;YAAEA;QAAU,IAAIF;QAE9B,OAAOoC;IACT;IAEA,MAAM,SACJ/B,MAAmB,EACnBT,MAA4BpB,2BAA2B,EACtC;QACjB,MAAMmH,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAE9C,MAAM,EAAEC,UAAU,EAAEC,gBAAgB,EAAE,GAAGC,YAAYzF;QACrD,MAAM,EAAE+B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,wBAAwB,CACjE,UACAwD,YACAD,cACA/F,KACAiG;QAEF,OAAOzD;IACT;IAEA,MAAM,SACJ/B,MAAmB,EACnBT,MAA4BpB,2BAA2B,EACtC;QACjB,MAAMmH,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAE9C,MAAM,EAAEC,UAAU,EAAEC,gBAAgB,EAAE,GAAGC,YAAYzF;QACrD,MAAM,EAAE+B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,wBAAwB,CACjE,UACAwD,YACAD,cACA/F,KACAiG;QAEF,OAAOzD;IACT;IAEA,MAAM,MACJ/B,MAAmB,EACnBT,MAA4BpB,2BAA2B,EACtC;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC6B,QAAQT;IAC/B;IAcA,MAAM,SAASS,MAAmB,EAAET,GAAkB,EAAE;QACtD,MAAMmG,cAAcxD,yBAAyBlC,QAAQT;QACrDC,OAAOkG,aAAa;QACpB,MAAMC,aAAaC,oBAAoBF;QACvC,MAAMjE,QAAQ;YAACkE;SAAW;QAC1B,MAAM7D,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAC9C,MAAMxD,gBAAgB,IAAI,CAAC,mBAAmB,CAAC;QAE/C,MAAM,EAAEyD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CACjDH,aAAa,UAAUC,eAAe6D,eACtCjE,OACAnD,eACAwD,cACAvC,KAAK,YAAY;YAAE,WAAWA,IAAI,SAAS;QAAC,IAAII;QAGlD,MAAM,EAAEkG,OAAO,EAAE,GAAG9D;QAEpB,OAAO;YACL,MAAM8D,SAAS;YACf,QAAQA,SAAS;YACjB,KAAKA,SAAS;QAChB;IACF;IAEA,MAAM,SACJjG,SAAsB,EACtBE,GAAY,EACZP,GAA2C,EAC3C;QACA,OAAO,IAAI,CAAC,mBAAmB,CAACK,WAAWD,QAAWG,KAAKP;IAC7D;IAEA,MAAc,oBACZK,SAAsB,EACtBC,SAAqB,EACrBC,GAAY,EACZP,GAA2C,EAC3C;QACA,MAAM+F,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAE9C,MAAMQ,aAAmC;YACvC,aAAavG,KAAK,eAAepB,4BAA4B,WAAW;YACxE,oBACEoB,KAAK,sBACLpB,4BAA4B,kBAAkB;QAClD;QAEA,MAAM4H,uBAAuBlC,uBAC3BjE,WACAL,KAAK;QAEP,MAAM,EAAEgG,UAAU,EAAEC,gBAAgB,EAAE,GAAGC,YAAYM;QACrD,MAAMC,gBACJ,AAAqB,YAArB,OAAOpG,YAAyBA,YAAYA,UAAU,MAAM;QAE9D,MAAMqG,mBAAmB;YACvB,aAAa1G,KAAK;YAClB,GAAIM,YAAY;gBAAEA;YAAU,IAAI,CAAC,CAAC;QACpC;QAEA,IAAI;YACF,MAAM,EAAEkC,MAAM,EAAEmE,OAAO,EAAE,GACvB,MAAM,IAAI,CAAC,YAAY,CAAC,wBAAwB,CAC9C,UACAX,YACAD,cACAQ,YACAN,kBACAS;YAGJ,MAAME,OAAOzE,QAAQK;YACrB,MAAMqE,UAAUD,OACZxG,SACA,CAAC,kBAAkB,EAAEG,OAAOkG,cAAc,UAAU,EAAEE,WAAW,eAAe;YAEpF,IAAI3G,KAAK,iBACP,OAAO;gBACL4G;gBACAD;gBACAE;YACF;YAGF,IAAI,CAACD,MACH,MAAM,IAAI1C,MAAM2C;QAEpB,EAAE,OAAOjH,OAAO;YACd,IAAIA,iBAAiBkH,oBAAoB;gBACvC,MAAMC,YAAYnH,MAAM,SAAS;gBACjC,MAAM+G,UAAUI,WAAW;gBAC3B,MAAMC,WAAWD,WAAW;gBAC5B,MAAME,aACJF,WAAW,gBACVC,CAAAA,oBAAoB9C,QACjB8C,SAAS,OAAO,GAChBA,WACE5D,OAAO4D,YACP5G,MAAQ;gBAChB,MAAM8G,SAASP,WAAWM,cAAc;gBACxC,MAAMJ,UAAU,CAAC,kBAAkB,EAAEtG,OAAOkG,cAAc,UAAU,EAAES,QAAQ;gBAE9E,IAAIlH,KAAK,iBACP,OAAO;oBACL,MAAM;oBACN2G;oBACAE;gBACF;gBAGF,MAAM,IAAI3C,MAAM2C,SAAS;oBACvB,OAAOG,YAAYpH;gBACrB;YACF;YAEA,MAAMA;QACR;IACF;IAEA,MAAM,UAAUS,SAAsB,EAAEL,GAAqB,EAAE;QAC7D,MAAM+F,eAAe,IAAI,CAAC,mBAAmB,CAAC;QAC9C,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAC7B1F,WACA;YACE,GAAGL,GAAG;YACN,WAAWA,KAAK,aAAa;YAC7B,iBAAiBA,KAAK,mBAAmB;QAC3C,GACA+F;IAEJ;IAEA,MAAM,GAAG,GAAGoB,IAAmC,EAAE;QAC/C,OAAO,IAAI,CAAC,KAAK,IAAIA;IACvB;IAEA,MAAM,QAAQC,iBAAyB,EAEpC;QACD,MAAMC,SAASC,gBAAgBF,mBAAmB;QAClD,MAAMG,SAAS,IAAIC,aAAaH,QAAQ,UAC/B;gBAAE,OAAO,IAAI;gBAAE,QAAQ,EAAE;YAAC;QAEnC,MAAME,OAAO,GAAG;QAEhB,IAAIA,AAAkB,YAAlBA,OAAO,MAAM,EAAc;YAC7B,MAAME,SAASF,OAAO,cAAc,CACjC,MAAM,CAAC,CAACpG,OAASA,AAAgB,YAAhBA,KAAK,MAAM,EAC5B,GAAG,CAAC,CAACA,OACG,CAAC,OAAO,EAAEA,KAAK,IAAI,CAAC,EAAE,EAAEA,KAAK,KAAK,EAAE,SAAS,EAErD,IAAI,CAAC;YACR,MAAM,IAAI+C,MAAM,CAAC,2CAA2C,EAAEuD,QAAQ;QACxE;QAEA,OAAO;YACL,QAAQF,OAAO,MAAM;QACvB;IACF;IAEA,MAAM,mBAAmBF,MAAc,EAAE;QACvCpH,OACE,IAAI,CAAC,SAAS,CAAC,kBAAkB,EACjC;QAEF,OAAO,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAACoH;IAC3C;IAOA,sBACEK,QAA+D,EACnD;QACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAACA;QAG9B,OAAO;YACL,IAAI,CAAC,wBAAwB,CAACA;QAChC;IACF;IAMA,yBACEA,QAA+D,EACzD;QACN,MAAMC,QAAQ,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAACD;QAC/C,IAAIC,QAAQ,IACV,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAACA,OAAO;IAE3C;IAKA,2BAAiC;QAC/B,IAAI,CAAC,mBAAmB,GAAG,EAAE;IAC/B;IASA,oBAAoBD,QAA+B,EAAc;QAC/D,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAACA;IACpC;IAKA,uBAAuBA,QAA+B,EAAQ;QAC5D,IAAI,CAAC,WAAW,CAAC,WAAW,CAACA;IAC/B;IAKA,yBAA+B;QAC7B,IAAI,CAAC,WAAW,CAAC,KAAK;IACxB;IAEQ,0BAA0BjG,aAA6B,EAAE;QAC/D,MAAMmG,aAAa,IAAI,CAAC,cAAc;QACtC,KAAK,MAAMF,YAAY,IAAI,CAAC,mBAAmB,CAC7C,IAAI;YACFA,SAASE,YAAYnG;QACvB,EAAE,OAAO7B,OAAO;YACde,QAAQ,KAAK,CAAC,kCAAkCf;QAClD;IAEJ;IAEA,MAAM,UAAU;QAEd,IAAI,IAAI,CAAC,SAAS,EAChB;QAGF,IAAI,CAAC,SAAS,GAAG;QAIjB,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,IAAI;gBACF,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI;YAChC,EAAE,OAAOA,OAAO;gBACdnB,MAAM,CAAC,+CAA+C,EAAEmB,OAAO;YACjE;YAEA,IAAI,CAAC,cAAc,GAAG;QACxB;QAEA,IAAIiI;QACJ,IAAI;YACF,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO;QAC9B,EAAE,OAAOjI,OAAO;YACdiI,wBAAwBjI;QAC1B;QAGA,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK;QAEhC,MAAMkI,YAAY,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ;QACrD,IAAI,CAAC,UAAU,GAAGA;QAElB,IAAI,CAAC,SAAS;QAEd,IAAID,uBACF,MAAMA;IAEV;IAEA,MAAM,eAAezF,KAAc,EAAEpC,GAA2B,EAAE;QAChE,MAAM+H,MAAMC,KAAK,GAAG;QACpB,MAAMC,cAAcjI,KAAK;QACzB,MAAMkI,mBAAmBlI,KAAK;QAC9B,MAAMmI,iBAAiBF,AAAgB7H,WAAhB6H;QACvB,MAAMG,sBAAsBF,AAAqB9H,WAArB8H;QAC5B,IAAIC,kBAAkB,CAACE,MAAM,OAAO,CAACJ,cACnC,MAAM,IAAI/D,MAAM;QAElB,IAAIkE,uBAAuB,AAA4B,YAA5B,OAAOF,kBAChC,MAAM,IAAIhE,MAAM;QAElB,IAAIiE,kBAAkBC,qBACpB,MAAM,IAAIlE,MACR;QAGJ,IAAIlE,OAAO,aAAaA,KACtB,MAAM,IAAIkE,MAAM;QAElB,MAAMoE,oBAAoBH,iBAAiBF,cAAc7H;QACzD,IAAIkI,qBAAqBA,AAA6B,MAA7BA,kBAAkB,MAAM,EAC/C,MAAM,IAAIpE,MAAM;QAElB,MAAMqE,mBACJD,qBACCF,CAAAA,sBACG;YAAC;gBAAE,QAAQF;YAAiB;SAAE,GAC9B;YAAC;gBAAE,QAAQ,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB;YAAG;SAAC,A;QAG1D,MAAMM,WAAoCD,iBAAiB,GAAG,CAC5D,CAACE,iBAAiBd;YAChB,MAAMe,4BAA4BC,kCAChCF,iBACAd;YAEF,MAAMiB,KAAKb,MAAMJ;YACjB,OAAO;gBACL,MAAM;gBACNiB;gBACA,YAAYC,eAAe,MAAM,CAC/BH,0BAA0B,MAAM,EAChCE;gBAEF,aAAaF,0BAA0B,WAAW;YACpD;QACF;QAGF,MAAMvH,OAAyB;YAC7B,QAAQ2H;YACR,MAAM;YACN,SAAS;YACT,QAAQ;YACRN;YACA,QAAQ;gBACN,OAAOT;gBACP,KAAKA;gBACL,MAAM;YACR;YACA,OAAO;gBACL,SAAS/H,KAAK,WAAW;YAC3B;YACA,UAAU,WAAa;QACzB;QAEA,MAAMyB,gBAAgB,IAAIsH,cAAc;YACtC,IAAID;YACJ,SAASf;YACT,MAAM,CAAC,MAAM,EAAE3F,SAAS,YAAY;YACpC,aAAapC,KAAK,WAAW;YAC7B,OAAO;gBAACmB;aAAK;QACf;QAEA,IAAI,CAAC,mBAAmB,CAACM;QAEzB,IAAI,CAAC,mBAAmB,CAACA;QACzB,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK;QAGhC,IAAI,CAAC,yBAAyB,CAACA;IACjC;IAEA,MAAM,oBACJW,KAAa,EACbpC,GAIC,EACD;QACA,MAAM+H,MAAMC,KAAK,GAAG;QACpB,MAAMQ,WAAoC,EAAE;QAC5C,MAAMQ,SACJhJ,IAAI,gBAAgB,IAAK,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB;QAChE,IAAIgJ,QACFR,SAAS,IAAI,CAAC;YACZ,MAAM;YACN,IAAIT;YACJ,YAAYc,eAAe,MAAM,CAACG,QAAQjB;QAC5C;QAGF,MAAM5G,OAAyB;YAC7B,QAAQ2H;YACR,MAAM;YACN,SAAS;YACT,QAAQ;YACRN;YACA,QAAQ;gBACN,OAAOT;gBACP,KAAKA;gBACL,MAAM;YACR;YACA,OAAO;gBACL,SAAS/H,IAAI,OAAO,IAAI;YAC1B;YACA,OAAOA,IAAI,KAAK;YAChB,cAAcA,IAAI,KAAK,CAAC,OAAO;YAC/B,YAAYA,IAAI,KAAK,CAAC,KAAK;YAC3B,UAAU,WAAa;QACzB;QAEA,MAAMyB,gBAAgB,IAAIsH,cAAc;YACtC,IAAID;YACJ,SAASf;YACT,MAAM3F;YACN,aAAapC,IAAI,OAAO,IAAIA,IAAI,KAAK,CAAC,OAAO;YAC7C,OAAO;gBAACmB;aAAK;QACf;QAEA,IAAI,CAAC,mBAAmB,CAACM;QACzB,IAAI,CAAC,mBAAmB,CAACA;QACzB,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK;QAChC,IAAI,CAAC,yBAAyB,CAACA;IACjC;IAKA,MAAM,cACJW,KAAc,EACdpC,GAEC,EACD;QACA,MAAM,IAAI,CAAC,cAAc,CAACoC,OAAOpC;IACnC;IAEA,sBAAsB;QACpB,MAAM,EAAEiJ,SAAS,EAAEC,gBAAgB,EAAEC,UAAU,EAAE,GAAG,IAAI,CAAC,IAAI;QAC7D,OAAO;YACLF;YACAC;YACA,YAAYC,cAAc,EAAE;QAC9B;IACF;IAMA,MAAM,oBAAmC;QACvC1K,MAAM;QACN,MAAM2K,UAAU,MAAM,IAAI,CAAC,gBAAgB;QAE3CA,QAAQ,SAAS,GAAG;QACpB,IAAI,CAAC,eAAe,GAAGA;QACvB3K,MAAM;IACR;IAKA,MAAM,sBAAqC;QACzCA,MAAM;QACN,IAAI,CAAC,eAAe,GAAG2B;QACvB3B,MAAM;IACR;IAKQ,mBAAmB4K,IAAc,EAMhC;QACPC,wBAAwBD,KAAK,KAAK;QAGlC,MAAME,cAAcC,mBAClBH,KAAK,KAAK,EACVA,KAAK,OAAO,IAAI;QAGlB,IAAI,CAACE,aACH,OAAO;QAIT,IAAI,AAAuB,YAAvB,OAAOA,eAA4BA,AAAgB,SAAhBA,aAAsB;YAC3D,MAAME,KAAKF,YAAY,EAAE;YACzB,MAAMG,gBAAgBH,YAAY,QAAQ,IAAI;YAC9C,MAAMI,aAAaD,AAAkB,gBAAlBA;YACnB,MAAME,cAAcF,AAAkB,iBAAlBA;YAEpB,OAAO;gBACLD;gBACA,SAAS,CAACG;gBACV,UAAUD;gBACV,WAAWC;gBACX,UAAUL,YAAY,QAAQ,EAAE;YAClC;QACF;QAEA,OAAO;IACT;IAEQ,mBAAmBM,KAAwB,EAAY;QAC7D,MAAMC,aAAazB,MAAM,OAAO,CAACwB,SAASA,QAAQ;YAACA;SAAM;QACzD,OAAOE,mBAAmBD;IAC5B;IAOA,MAAM,WAAWE,OAAmC,EAAiB;QACnE,IAAI,CAAC,IAAI,CAAC,SAAS,EACjB,MAAM,IAAI9F,MAAM;QAGlB,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC8F;IAClC;IAr/CA,YAAYC,iBAAgC,EAAEZ,IAAe,CAAE;QAjJ/D;QAEA;QAEA;QAEA;QAEA;QAEA;QAEA;QAKA,kCAAU;QAEV;QAEA;QAEA,uBAAiB,oBAAmB,IAAIa;QAIxC,uBAAQ,oBAAmB;QAI3B,uBAAiB,oBAAmB,IAAIC;QAExC,uBAAQ,uBAEJ,EAAE;QAIN,uBAAiB,eAAc,IAAIC;QAmBnC,oCAAY;QAEZ;QAKA,uBAAQ,mBAAR;QAMA,uBAAQ,kBAAoC;QAM5C,uBAAQ,8BAA6B,IAAItJ;QAEzC,uBAAQ,mBAAR;QAEA,uBAAQ,mBAAR;QA0ZA,uBAAQ,qBAAR;QAzVE,IAAI,CAAC,SAAS,GAAGmJ;QAEjB,IAAI,CAAC,IAAI,GAAGI,OAAO,MAAM,CACvB;YACE,gBAAgB;YAChB,sBAAsB;YACtB,oBAAoB;YACpB,WAAW;YACX,kBAAkB;QACpB,GACAhB,QAAQ,CAAC;QAEXiB,8BAA8B,IAAI,CAAC,IAAI;QAEvC,MAAMC,uBACJ,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe;QACrD,IAAIA,AAAyBnK,WAAzBmK,sBAAoC;YACtC,IAAI,CAAC,IAAI,CAAC,YAAY,GAAGA;YACzB,IAAI,CAAC,IAAI,CAAC,eAAe,KAAKA;QAChC;QAEA,IACElB,MAAM,eACL,CAA6B,YAA7B,OAAOA,MAAM,eAA4BhB,MAAM,OAAO,CAACgB,KAAK,WAAW,IAExE,MAAM,IAAInF,MACR,CAAC,2EAA2E,EAAE,OAAOmF,MAAM,aAAa;QAK5G,MAAMmB,kBAAkBnB,MAAM,eAAeA,MAAM;QACnD,IAAI,CAAC,kBAAkB,GAAGmB,kBACtB,IAAIC,mBAAmBpB,MAAM,aAAaA,MAAM,sBAChDqB;QAEJ,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc;QAE9C,IAAI,CAAC,OAAO,GAAG,IAAIC,QAAQ,UAClB,IAAI,CAAC,YAAY;QAI1B,MAAMC,iBAAiB,IAAI,CAAC,kBAAkB,CAACvB,QAAQ,CAAC;QACxD,IAAIuB,gBACF,IAAI,CAAC,SAAS,GAAG,IAAIC,UACnBD,eAAe,EAAE,EACjBA,eAAe,OAAO,EACtBxK,QACA;YACE,UAAUwK,eAAe,QAAQ;YACjC,WAAWA,eAAe,SAAS;YACnC,UAAUA,eAAe,QAAQ;QACnC;QAIJ,MAAME,kBAAkB,IAAI,CAAC,SAAS,CAAC,WAAW;QAClD,IAAI,CAAC,eAAe,GAAG;eAAIA;YAAiBC;SAAoB;QAEhE,IAAI,CAAC,YAAY,GAAG,IAAIC,aAAa,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE;YACjE,WAAW,IAAI,CAAC,SAAS;YACzB,aAAa,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI;YAClD,sBAAsB,IAAI,CAAC,IAAI,CAAC,oBAAoB;YACpD,iBAAiB,IAAI,CAAC,IAAI,CAAC,eAAe;YAC1C,eAAe,IAAI,CAAC,IAAI,CAAC,aAAa;YACtC,aAAa,IAAI,CAAC,eAAe;YACjC,OAAO;gBACL,kBAAkB,OAAOhK;oBACvB,MAAMS,gBAAgBT,OAAO,IAAI;oBACjC,IAAI,CAAC,mBAAmB,CAACS,eAAeT;oBACxC,IAAI,CAAC,mBAAmB,CAACS;oBAIzB,IAAI,CAAC,mBAAmB,CAACA;oBACzB,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK;oBAGhC,MAAMmG,aAAa,IAAI,CAAC,cAAc;oBACtC,KAAK,MAAMF,YAAY,IAAI,CAAC,mBAAmB,CAC7C,IAAI;wBACFA,SAASE,YAAYnG;oBACvB,EAAE,OAAO7B,OAAO;wBACde,QAAQ,KAAK,CAAC,kCAAkCf;oBAClD;gBAEJ;gBACA,YAAY,IAAI,CAAC,WAAW,CAAC,OAAO;YACtC;QACF;QACA,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS;QAC1B,IAAI,CAAC,cAAc,GACjByJ,MAAM,kBAGN4B,kBAAkB5B,MAAM,UAAU,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI;QAEpE,IAAI,CAAC,eAAe,GAAG6B,gBAAgB,MAAM,CAAC,IAAI,CAAC,cAAc,EAAG;YAClE,gBAAgB,IAAI,CAAC,IAAI,CAAC,cAAc;YACxC,sBAAsB,IAAI,CAAC,IAAI,CAAC,oBAAoB;YACpD,cAAc,IAAI,CAAC,IAAI,CAAC,YAAY;YACpC,oBAAoB,IAAI,CAAC,IAAI,CAAC,kBAAkB;YAChD,qBACE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,gBAAgB,KAAK,IAAI,CAAC,cAAc;QACzE;IACF;AA24CF;AAr4CE,iBArQWrM,OAqQa,qBAAoB;AAC5C,iBAtQWA,OAsQa,0BAAyB;AAs4C5C,MAAMsM,cAAc,CACzBlB,mBACAZ,OAEO,IAAIxK,MAAMoL,mBAAmBZ"}
1
+ {"version":3,"file":"agent/agent.mjs","sources":["../../../src/agent/agent.ts"],"sourcesContent":["import { type ModelRuntime, getModelRuntime } from '@/ai-model/models';\nimport { INTERNAL_CALL_ID_FIELD } from '@/ai-model/service-caller';\nimport yaml from 'js-yaml';\nimport type { TUserPrompt } from '../ai-model/index';\nimport { ScreenshotItem } from '../screenshot-item';\nimport Service from '../service/index';\n// Import types and values directly from their source files to avoid circular dependency\n// DO NOT import from '../index' as it creates a circular dependency:\n// index.ts -> agent/index.ts -> agent/agent.ts -> index.ts\nimport {\n type AIUsageInfo,\n type ActionParam,\n type ActionReturn,\n type AgentAssertOpt,\n type AgentOpt,\n type AgentProgressListener,\n type AgentWaitForOpt,\n type DeepThinkOption,\n type DeviceAction,\n ExecutionDump,\n type ExecutionRecorderItem,\n type ExecutionTask,\n type ExecutionTaskLog,\n type LocateOption,\n type LocateResultElement,\n type OnTaskStartTip,\n type PlanningAction,\n type RecordToReportOptions,\n type RecordToReportScreenshot,\n ReportActionDump,\n type ReportMeta,\n type ScrollParam,\n type ServiceAction,\n type ServiceExtractOption,\n type ServiceExtractParam,\n type TestStatus,\n type UIContext,\n} from '../types';\nimport type { MidsceneYamlScript } from '../yaml';\n\nimport type { IReportGenerator } from '@/report-generator';\nimport {\n ReportGenerator,\n assertReportGenerationOptions,\n} from '@/report-generator';\nimport { getVersion, processCacheConfig, reportHTMLContent } from '@/utils';\nimport {\n ScriptPlayer,\n buildDetailedLocateParam,\n buildDetailedLocateParamAndRestParams,\n parseYamlScript,\n} from '../yaml/index';\n\nimport { readFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\nimport type { AbstractInterface } from '@/device';\nimport type { TaskRunner } from '@/task-runner';\nimport {\n type IModelConfig,\n MIDSCENE_REPLANNING_CYCLE_LIMIT,\n ModelConfigManager,\n type TIntent,\n globalConfigManager,\n globalModelConfigManager,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport { defineActionSleep } from '../device';\nimport { validateAgentCacheInput } from './cache-config';\nimport { MetricsCollector, type MidsceneUsageMetrics } from './metrics';\nimport { AgentProgressBus } from './progress';\nimport { buildPromptWithContext } from './prompt-context';\nimport { normalizeRecordToReportScreenshot } from './record-to-report';\nimport {\n type RunGherkinScenarioOptions,\n runGherkinScenario,\n} from './run-gherkin-scenario';\nimport { markdownToAiActPrompt } from './run-markdown';\nimport { TaskCache } from './task-cache';\nimport {\n TaskExecutionError,\n TaskExecutor,\n locatePlanForLocate,\n withFileChooser,\n} from './tasks';\nimport { UIObserver, type UIObserverOption } from './ui-observer';\nimport {\n type TaskTitleType,\n locateParamStr,\n paramStr,\n taskTitleStr,\n typeStr,\n} from './ui-utils';\nimport {\n commonContextParser,\n getReportFileName,\n normalizeFilePaths,\n normalizeScrollType,\n parsePrompt,\n} from './utils';\n\nconst debug = getDebug('agent');\nconst warn = getDebug('agent', { console: true });\n\nconst defaultServiceExtractOption: ServiceExtractOption = {\n domIncluded: false,\n screenshotIncluded: true,\n};\n\nexport type AiActOptions = {\n cacheable?: boolean;\n fileChooserAccept?: string | string[];\n deepThink?: DeepThinkOption;\n deepLocate?: boolean;\n abortSignal?: AbortSignal;\n context?: string;\n};\n\ntype AiActInternalOptions = AiActOptions & {\n _internalReportDisplay?: {\n type?: TaskTitleType;\n prompt?: string;\n };\n};\n\n/**\n * Shared input option type for aiInput(), used consistently across\n * overload signatures and the implementation so fields don't drift.\n */\ntype AgentInputOption = LocateOption & {\n autoDismissKeyboard?: boolean;\n keyboardTypeDelay?: number;\n mode?: 'replace' | 'clear' | 'typeOnly' | 'append';\n};\n\nexport class Agent<\n InterfaceType extends AbstractInterface = AbstractInterface,\n> {\n interface: InterfaceType;\n\n service: Service;\n\n dump: ReportActionDump;\n\n reportFile?: string | null;\n\n reportFileName?: string;\n\n taskExecutor: TaskExecutor;\n\n opts: AgentOpt;\n\n /**\n * If true, the agent will not perform any actions\n */\n dryMode = false;\n\n onTaskStartTip?: OnTaskStartTip;\n\n taskCache?: TaskCache;\n\n private readonly metricsCollector = new MetricsCollector();\n\n // Monotonic counter for generating unique dedup keys when a usage has no\n // request_id (e.g. estimated streaming usage).\n private usageCallCounter = 0;\n\n // Usage values already folded into `metricsCollector`, keyed by\n // `${taskId}:${field}` so re-emitted snapshots never double-count.\n private readonly countedUsageKeys = new Set<string>();\n\n private dumpUpdateListeners: Array<\n (dump: string, executionDump?: ExecutionDump) => void\n > = [];\n\n // Generic progress bus: every producer (aiAct today, more later) broadcasts\n // through here. Consumers narrow by `event.scope`.\n private readonly progressBus = new AgentProgressBus();\n\n get onDumpUpdate():\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined {\n return this.dumpUpdateListeners[0];\n }\n\n set onDumpUpdate(callback:\n | ((dump: string, executionDump?: ExecutionDump) => void)\n | undefined) {\n // Clear existing listeners\n this.dumpUpdateListeners = [];\n // Add callback to array if provided\n if (callback) {\n this.dumpUpdateListeners.push(callback);\n }\n }\n\n destroyed = false;\n\n modelConfigManager: ModelConfigManager;\n\n /**\n * Frozen page context for consistent AI operations\n */\n private frozenUIContext?: UIContext;\n\n /**\n * Currently active UIObserver (from startObserving). Only one observer may\n * be active at a time since frame sources are device-level singletons.\n */\n private activeObserver: UIObserver | null = null;\n\n private get aiActContext(): string | undefined {\n return this.opts.aiActContext ?? this.opts.aiActionContext;\n }\n\n private executionDumpIndexByRunner = new WeakMap<TaskRunner, number>();\n\n private fullActionSpace: DeviceAction[];\n\n private reportGenerator: IReportGenerator;\n\n // @deprecated use .interface instead\n get page() {\n return this.interface;\n }\n\n /**\n * Fails fast for non-web interfaces when the model family is missing.\n *\n * Early Midscene web usage allowed running without `modelFamily` and falling\n * back to a default bbox parser. Non-web users do not have that compatibility\n * path, so this check helps surface configuration problems before spending a\n * model call.\n *\n * Web flows validate missing locate model family at workflow boundaries:\n * `Service.locate` throws when aiTap/aiType fallback to the default model for\n * direct locate, and generic planning throws when aiAct asks a planning model\n * to return inline locate coordinates. Those checks are intentionally placed\n * where Midscene knows which model role should provide coordinate parsing.\n */\n private assertModelFamilyForNonWebContext() {\n if (\n this.interface.interfaceType !== 'puppeteer' &&\n this.interface.interfaceType !== 'playwright' &&\n this.interface.interfaceType !== 'static' &&\n this.interface.interfaceType !== 'chrome-extension-proxy' &&\n this.interface.interfaceType !== 'page-over-chrome-extension-bridge'\n ) {\n this.modelConfigManager.throwErrorIfNonVLModel();\n }\n }\n\n private resolveReplanningCycleLimit(planningModel: ModelRuntime): number {\n return (\n this.opts.replanningCycleLimit ??\n globalConfigManager.getEnvConfigValueAsNumber(\n MIDSCENE_REPLANNING_CYCLE_LIMIT,\n ) ??\n planningModel.adapter.planning.defaultReplanningCycleLimit\n );\n }\n\n private resolveModelRuntime(intent: TIntent): ModelRuntime {\n const runtime = getModelRuntime(\n this.modelConfigManager.getModelConfig(intent),\n );\n return {\n ...runtime,\n onUsage: (usage) => {\n this.usageCallCounter += 1;\n // buildUsageInfo leaves intent undefined; fill it from the model\n // config slot so metrics.byIntent has a meaningful category.\n const enriched = usage.intent\n ? usage\n : { ...usage, intent: usage.slot };\n this.consumeUsage(\n enriched,\n `callai:${usage.request_id ?? this.usageCallCounter}`,\n );\n },\n };\n }\n\n constructor(interfaceInstance: InterfaceType, opts?: AgentOpt) {\n this.interface = interfaceInstance;\n\n this.opts = Object.assign(\n {\n generateReport: true,\n persistExecutionDump: false,\n autoPrintReportMsg: true,\n groupName: 'Midscene Report',\n groupDescription: '',\n },\n opts || {},\n );\n assertReportGenerationOptions(this.opts);\n\n const resolvedAiActContext =\n this.opts.aiActContext ?? this.opts.aiActionContext;\n if (resolvedAiActContext !== undefined) {\n this.opts.aiActContext = resolvedAiActContext;\n this.opts.aiActionContext ??= resolvedAiActContext;\n }\n\n if (\n opts?.modelConfig &&\n (typeof opts?.modelConfig !== 'object' || Array.isArray(opts.modelConfig))\n ) {\n throw new Error(\n `opts.modelConfig must be a plain object map of env keys to values, but got ${typeof opts?.modelConfig}`,\n );\n }\n // Create ModelConfigManager if modelConfig or createOpenAIClient is provided\n // Otherwise, use the global config manager\n const hasCustomConfig = opts?.modelConfig || opts?.createOpenAIClient;\n this.modelConfigManager = hasCustomConfig\n ? new ModelConfigManager(opts?.modelConfig, opts?.createOpenAIClient)\n : globalModelConfigManager;\n\n this.onTaskStartTip = this.opts.onTaskStartTip;\n\n this.service = new Service(async () => {\n return this.getUIContext();\n });\n\n // Process cache configuration\n const cacheConfigObj = this.processCacheConfig(opts || {});\n if (cacheConfigObj) {\n this.taskCache = new TaskCache(\n cacheConfigObj.id,\n cacheConfigObj.enabled,\n undefined, // cacheFilePath\n {\n readOnly: cacheConfigObj.readOnly,\n writeOnly: cacheConfigObj.writeOnly,\n cacheDir: cacheConfigObj.cacheDir,\n },\n );\n }\n\n const baseActionSpace = this.interface.actionSpace();\n this.fullActionSpace = [...baseActionSpace, defineActionSleep()];\n\n this.taskExecutor = new TaskExecutor(this.interface, this.service, {\n taskCache: this.taskCache,\n onTaskStart: this.callbackOnTaskStartTip.bind(this),\n replanningCycleLimit: this.opts.replanningCycleLimit,\n waitAfterAction: this.opts.waitAfterAction,\n useDeviceTime: this.opts.useDeviceTime,\n actionSpace: this.fullActionSpace,\n hooks: {\n onSnapshotChange: async (runner) => {\n const executionDump = runner.dump();\n this.appendExecutionDump(executionDump, runner);\n this.collectUsageMetrics(executionDump);\n\n // Persist report updates before notifying listeners so screenshot\n // payloads can be released from memory and serialized as references.\n this.writeOutActionDumps(executionDump);\n await this.reportGenerator.flush();\n\n // Call all registered dump update listeners\n const dumpString = this.dumpDataString();\n for (const listener of this.dumpUpdateListeners) {\n try {\n listener(dumpString, executionDump);\n } catch (error) {\n console.error('Error in onDumpUpdate listener', error);\n }\n }\n },\n onProgress: this.progressBus.publish,\n },\n });\n this.dump = this.resetDump();\n this.reportFileName =\n opts?.reportFileName ??\n // Keep deprecated testId behavior for generated report names until it is\n // fully removed from the public API.\n getReportFileName(opts?.testId || this.interface.interfaceType || 'web');\n\n this.reportGenerator = ReportGenerator.create(this.reportFileName!, {\n generateReport: this.opts.generateReport,\n persistExecutionDump: this.opts.persistExecutionDump,\n outputFormat: this.opts.outputFormat,\n autoPrintReportMsg: this.opts.autoPrintReportMsg,\n reuseExistingReport:\n this.opts.reportAttributes?.['data-group-id'] === this.reportFileName,\n });\n }\n\n async getActionSpace(): Promise<DeviceAction[]> {\n return this.fullActionSpace;\n }\n\n private static readonly CONTEXT_RETRY_MAX = 3;\n private static readonly CONTEXT_RETRY_DELAY_MS = 1500;\n\n /**\n * Override in subclasses to indicate which errors are transient and should\n * trigger an automatic retry when building the UI context.\n * Returns `false` by default (no retry).\n */\n protected isRetryableContextError(_error: unknown): boolean {\n return false;\n }\n\n async getUIContext(action?: ServiceAction): Promise<UIContext> {\n // Some non-web flows, such as Android, need an Agent instance before they\n // can call device methods via ADB, so defer missing modelFamily errors\n // until UI context is actually requested.\n this.assertModelFamilyForNonWebContext();\n\n // If page context is frozen, return the frozen context for all actions\n if (this.frozenUIContext) {\n debug('Using frozen page context for action:', action);\n return this.frozenUIContext;\n }\n\n const maxRetries = Agent.CONTEXT_RETRY_MAX;\n for (let attempt = 0; ; attempt++) {\n try {\n return await commonContextParser(this.interface, {\n uploadServerUrl: this.modelConfigManager.getUploadTestServerUrl(),\n screenshotShrinkFactor: this.opts.screenshotShrinkFactor,\n });\n } catch (error) {\n if (attempt < maxRetries && this.isRetryableContextError(error)) {\n debug(\n `retryable context error (attempt ${attempt + 1}/${maxRetries}), retrying in ${Agent.CONTEXT_RETRY_DELAY_MS}ms: ${error}`,\n );\n await new Promise((resolve) =>\n setTimeout(resolve, Agent.CONTEXT_RETRY_DELAY_MS),\n );\n continue;\n }\n throw error;\n }\n }\n }\n\n async _snapshotContext(): Promise<UIContext> {\n return await this.getUIContext('locate');\n }\n\n /**\n * Start observing the screen in the background so a later assertion can\n * judge everything that happened while other agent calls ran — including\n * transient UI (toasts, banners, transitions) that appears mid-action:\n *\n * ```ts\n * const observer = await agent.startObserving();\n * await agent.aiAct('submit the form');\n * await observer.stop();\n * await observer.aiAssert('a success toast appeared during the process');\n * ```\n *\n * Frames come from the device's continuous frame source when available\n * (scrcpy on Android, WDA MJPEG on iOS — both opt-in; CDP screencast on\n * web) and fall back to plain screenshots otherwise. Sampling is capped at\n * 5fps, the buffer is bounded and self-thinning, decoding is deferred to\n * the end, and all buffered frames (up to `maxFrames`) are sent to\n * the model at assert time. To control token cost for long windows,\n * increase `intervalMs` or decrease `maxFrames`.\n * Awaiting `startObserving()` guarantees one baseline frame is captured\n * before your next action.\n */\n async startObserving(opt?: UIObserverOption): Promise<UIObserver> {\n // A frozen context pins perception to a single snapshot; observing a\n // window of frames contradicts that. Fail fast instead of silently\n // producing an all-identical sequence.\n assert(\n !this.frozenUIContext,\n 'startObserving() cannot be used while the UI context is frozen (call unfreezePageContext() first)',\n );\n // Frame sources are device-level singletons — two concurrent observers\n // would conflict (scrcpy stream, WDA MJPEG port, CDP screencast).\n assert(\n !this.activeObserver,\n 'An observation window is already active on this agent. ' +\n 'Stop the existing observer first (await observer.stop()) before starting a new one.',\n );\n const observer = new UIObserver(\n {\n openFrameSource: async () =>\n (await this.interface.openFrameSource?.()) ?? undefined,\n // Fallback single-frame capture. Deliberately bypasses getUIContext so\n // the observation loop never pollutes the TaskRunner context cache.\n screenshot: () => this.interface.screenshotBase64(),\n captureRepresentative: () => this.getUIContext('assert'),\n runAssert: (assertion, uiContext, msg, assertOpt) =>\n this.aiAssertWithUIContext(assertion, uiContext, msg, assertOpt),\n runBoolean: (prompt, uiContext, boolOpt) =>\n this.aiBooleanWithContext(prompt, uiContext, boolOpt),\n onStopped: () => {\n this.activeObserver = null;\n },\n screenshotShrinkFactor: this.opts.screenshotShrinkFactor,\n },\n opt,\n );\n // Mark as active BEFORE the async start() so concurrent calls hit the\n // assert guard above. If start() throws, clear the reference below.\n this.activeObserver = observer;\n try {\n await observer.start();\n } catch (error) {\n this.activeObserver = null;\n throw error;\n }\n return observer;\n }\n\n /**\n * @deprecated Use {@link setAIActContext} instead.\n */\n async setAIActionContext(prompt: string) {\n await this.setAIActContext(prompt);\n }\n\n async setAIActContext(prompt: string) {\n if (this.aiActContext) {\n console.warn(\n 'aiActContext is already set, and it is called again, will override the previous setting',\n );\n }\n this.opts.aiActContext = prompt;\n this.opts.aiActionContext = prompt;\n }\n\n resetDump() {\n this.dump = new ReportActionDump({\n sdkVersion: getVersion(),\n groupName: this.opts.groupName!,\n groupDescription: this.opts.groupDescription,\n executions: [],\n modelBriefs: [],\n deviceType: this.interface.interfaceType,\n });\n this.executionDumpIndexByRunner = new WeakMap<TaskRunner, number>();\n\n return this.dump;\n }\n\n appendExecutionDump(execution: ExecutionDump, runner?: TaskRunner) {\n const currentDump = this.dump;\n if (runner) {\n const existingIndex = this.executionDumpIndexByRunner.get(runner);\n if (existingIndex !== undefined) {\n currentDump.executions[existingIndex] = execution;\n return;\n }\n currentDump.executions.push(execution);\n this.executionDumpIndexByRunner.set(\n runner,\n currentDump.executions.length - 1,\n );\n return;\n }\n currentDump.executions.push(execution);\n }\n\n /**\n * Fold any not-yet-counted task usage from an execution dump into the\n * instance metrics. Snapshots are re-emitted as tasks progress, so each\n * usage value is keyed by `${taskId}:${field}` and counted at most once.\n */\n private collectUsageMetrics(execution: ExecutionDump) {\n for (const task of execution.tasks) {\n this.consumeUsage(task.usage, `${task.taskId}:usage`);\n this.consumeUsage(task.searchAreaUsage, `${task.taskId}:searchAreaUsage`);\n }\n }\n\n private consumeUsage(usage: AIUsageInfo | undefined, key: string) {\n if (!usage) {\n return;\n }\n // Dedup key priority:\n // 1. request_id — provider-issued, stable across onUsage and task dump paths\n // 2. INTERNAL_CALL_ID_FIELD — callAI-generated internal id, covers\n // providers that don't return a request_id\n // 3. caller-provided key (taskId:field or callai:counter)\n let dedupKey: string;\n if (usage.request_id) {\n dedupKey = `req:${usage.request_id}`;\n } else if ((usage as any)[INTERNAL_CALL_ID_FIELD]) {\n dedupKey = `int:${(usage as any)[INTERNAL_CALL_ID_FIELD]}`;\n } else {\n dedupKey = key;\n }\n if (this.countedUsageKeys.has(dedupKey)) {\n return;\n }\n this.countedUsageKeys.add(dedupKey);\n this.metricsCollector.add(usage);\n if (this.opts.onLLMUsage) {\n try {\n this.opts.onLLMUsage(usage);\n } catch (error) {\n warn(`onLLMUsage listener threw, ignoring: ${error}`);\n }\n }\n }\n\n /**\n * Aggregated LLM usage accumulated by this agent since it was created.\n */\n get metrics(): MidsceneUsageMetrics {\n return this.metricsCollector.snapshot();\n }\n\n dumpDataString(opt?: { inlineScreenshots?: boolean }) {\n // update dump info\n this.dump.groupName = this.opts.groupName!;\n this.dump.groupDescription = this.opts.groupDescription;\n // In browser environment, use inline screenshots since file system is not available\n if (ifInBrowser || opt?.inlineScreenshots) {\n return this.dump.serializeWithInlineScreenshots();\n }\n return this.dump.serialize();\n }\n\n reportHTMLString(opt?: { inlineScreenshots?: boolean }) {\n // dumpDataString() handles browser environment with inline screenshots\n return reportHTMLContent(this.dumpDataString(opt));\n }\n\n private lastExecutionDump?: ExecutionDump;\n\n writeOutActionDumps(executionDump?: ExecutionDump) {\n const exec = executionDump || this.lastExecutionDump;\n if (exec) {\n this.lastExecutionDump = exec;\n this.reportGenerator.onExecutionUpdate(\n exec,\n this.getReportMeta(),\n this.opts.reportAttributes,\n );\n }\n this.reportFile = this.reportGenerator.getReportPath();\n }\n\n private getReportMeta(): ReportMeta {\n return {\n groupName: this.dump.groupName,\n groupDescription: this.dump.groupDescription,\n sdkVersion: this.dump.sdkVersion,\n modelBriefs: this.dump.modelBriefs,\n deviceType: this.dump.deviceType,\n };\n }\n\n private async callbackOnTaskStartTip(task: ExecutionTask) {\n const param = paramStr(task);\n const tip = param ? `${typeStr(task)} - ${param}` : typeStr(task);\n\n if (this.onTaskStartTip) {\n await this.onTaskStartTip(tip);\n }\n }\n\n wrapActionInActionSpace<T extends DeviceAction>(\n name: string,\n ): (param: ActionParam<T>) => Promise<ActionReturn<T>> {\n return async (param: ActionParam<T>) => {\n return await this.callActionInActionSpace<ActionReturn<T>>(name, param);\n };\n }\n\n async callActionInActionSpace<T = any>(\n type: string,\n opt?: T, // and all other action params\n ) {\n debug('callActionInActionSpace', type, ',', opt);\n\n const actionPlan: PlanningAction<T> = {\n type: type as any,\n param: (opt as any) || {},\n thought: '',\n };\n debug('actionPlan', actionPlan); // , ', in which the locateParam is', locateParam);\n\n const plans: PlanningAction[] = [actionPlan].filter(\n Boolean,\n ) as PlanningAction[];\n\n const title = taskTitleStr(\n type as any,\n locateParamStr((opt as any)?.locate || {}),\n );\n\n // assume all operation in action space is related to locating\n const defaultModel = this.resolveModelRuntime('default');\n const planningModel = this.resolveModelRuntime('planning');\n\n const { output } = await this.taskExecutor.runPlans(\n title,\n plans,\n planningModel,\n defaultModel,\n );\n return output;\n }\n\n async aiTap(\n locatePrompt: TUserPrompt,\n opt?: LocateOption & { fileChooserAccept?: string | string[] },\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for tap');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n const fileChooserAccept = opt?.fileChooserAccept\n ? this.normalizeFileInput(opt.fileChooserAccept)\n : undefined;\n\n await withFileChooser(this.interface, fileChooserAccept, async () => {\n await this.callActionInActionSpace('Tap', {\n locate: detailedLocateParam,\n });\n });\n }\n\n async aiRightClick(\n locatePrompt: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for right click');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('RightClick', {\n locate: detailedLocateParam,\n });\n }\n\n async aiDoubleClick(\n locatePrompt: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for double click');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('DoubleClick', {\n locate: detailedLocateParam,\n });\n }\n\n async aiHover(locatePrompt: TUserPrompt, opt?: LocateOption): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for hover');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('Hover', {\n locate: detailedLocateParam,\n });\n }\n\n // New signature, always use locatePrompt as the first param\n async aiInput(\n locatePrompt: TUserPrompt,\n opt: AgentInputOption & { value: string | number },\n ): Promise<void>;\n\n // Legacy signature - deprecated\n /**\n * @deprecated Use aiInput(locatePrompt, opt) instead where opt contains the value\n */\n async aiInput(\n value: string | number,\n locatePrompt: TUserPrompt,\n opt?: AgentInputOption,\n ): Promise<void>;\n\n // Implementation\n async aiInput(\n locatePromptOrValue: TUserPrompt | string | number,\n locatePromptOrOpt:\n | TUserPrompt\n | (AgentInputOption & { value: string | number })\n | undefined,\n optOrUndefined?: AgentInputOption,\n ) {\n let value: string | number;\n let locatePrompt: TUserPrompt;\n let opt: (AgentInputOption & { value: string | number }) | undefined;\n\n // Check if using new signature (first param is locatePrompt, second has value)\n if (\n typeof locatePromptOrOpt === 'object' &&\n locatePromptOrOpt !== null &&\n 'value' in locatePromptOrOpt\n ) {\n // New signature: aiInput(locatePrompt, opt)\n locatePrompt = locatePromptOrValue as TUserPrompt;\n const optWithValue = locatePromptOrOpt as AgentInputOption & {\n value: string | number;\n };\n value = optWithValue.value;\n opt = optWithValue;\n } else {\n // Legacy signature: aiInput(value, locatePrompt, opt)\n value = locatePromptOrValue as string | number;\n locatePrompt = locatePromptOrOpt as TUserPrompt;\n opt = {\n ...optOrUndefined,\n value,\n };\n }\n\n assert(\n typeof value === 'string' || typeof value === 'number',\n 'input value must be a string or number, use empty string if you want to clear the input',\n );\n assert(locatePrompt, 'missing locate prompt for input');\n\n const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(\n locatePrompt,\n opt,\n );\n\n // Convert value to string to ensure consistency\n const stringValue = typeof value === 'number' ? String(value) : value;\n\n // backward compat: convert deprecated 'append' to 'typeOnly'\n const mode = opt?.mode === 'append' ? 'typeOnly' : opt?.mode;\n\n await this.callActionInActionSpace('Input', {\n ...restParams,\n value: stringValue,\n locate: locateParam,\n mode,\n });\n }\n\n // New signature\n async aiKeyboardPress(\n locatePrompt: TUserPrompt,\n opt: LocateOption & { keyName: string },\n ): Promise<void>;\n\n // Legacy signature - deprecated\n /**\n * @deprecated Use aiKeyboardPress(locatePrompt, opt) instead where opt contains the keyName\n */\n async aiKeyboardPress(\n keyName: string,\n locatePrompt?: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void>;\n\n // Implementation\n async aiKeyboardPress(\n locatePromptOrKeyName: TUserPrompt | string,\n locatePromptOrOpt:\n | TUserPrompt\n | (LocateOption & { keyName: string })\n | undefined,\n optOrUndefined?: LocateOption,\n ) {\n let keyName: string;\n let locatePrompt: TUserPrompt | undefined;\n let opt: (LocateOption & { keyName: string }) | undefined;\n\n // Check if using new signature (first param is locatePrompt, second has keyName)\n if (\n typeof locatePromptOrOpt === 'object' &&\n locatePromptOrOpt !== null &&\n 'keyName' in locatePromptOrOpt\n ) {\n // New signature: aiKeyboardPress(locatePrompt, opt)\n locatePrompt = locatePromptOrKeyName as TUserPrompt;\n opt = locatePromptOrOpt as LocateOption & {\n keyName: string;\n };\n } else {\n // Legacy signature: aiKeyboardPress(keyName, locatePrompt, opt)\n keyName = locatePromptOrKeyName as string;\n locatePrompt = locatePromptOrOpt as TUserPrompt | undefined;\n opt = {\n ...(optOrUndefined || {}),\n keyName,\n };\n }\n\n assert(opt?.keyName, 'missing keyName for keyboard press');\n\n const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(\n locatePrompt || '',\n opt,\n );\n\n await this.callActionInActionSpace('KeyboardPress', {\n ...restParams,\n locate: locateParam,\n });\n }\n\n // New signature\n async aiScroll(\n locatePrompt: TUserPrompt | undefined,\n opt: LocateOption & ScrollParam,\n ): Promise<void>;\n\n // Legacy signature - deprecated\n /**\n * @deprecated Use aiScroll(locatePrompt, opt) instead where opt contains the scroll parameters\n */\n async aiScroll(\n scrollParam: ScrollParam,\n locatePrompt?: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void>;\n\n // Implementation\n async aiScroll(\n locatePromptOrScrollParam: TUserPrompt | ScrollParam | undefined,\n locatePromptOrOpt: TUserPrompt | (LocateOption & ScrollParam) | undefined,\n optOrUndefined?: LocateOption,\n ) {\n let scrollParam: ScrollParam;\n let locatePrompt: TUserPrompt | undefined;\n let opt: LocateOption | undefined;\n\n const isLocatePromptLike = (value: unknown): value is TUserPrompt => {\n if (\n typeof value === 'string' ||\n typeof value === 'undefined' ||\n value === null\n ) {\n return true;\n }\n\n return typeof value === 'object' && value !== null && 'prompt' in value;\n };\n\n // Check if using new signature (first param is locatePrompt, second is options)\n if (\n isLocatePromptLike(locatePromptOrScrollParam) &&\n typeof locatePromptOrOpt === 'object' &&\n locatePromptOrOpt !== null\n ) {\n // New signature: aiScroll(locatePrompt, opt)\n locatePrompt = locatePromptOrScrollParam as TUserPrompt;\n opt = locatePromptOrOpt as LocateOption & ScrollParam;\n } else {\n // Legacy signature: aiScroll(scrollParam, locatePrompt, opt)\n scrollParam = locatePromptOrScrollParam as ScrollParam;\n locatePrompt = locatePromptOrOpt as TUserPrompt | undefined;\n opt = {\n ...(optOrUndefined || {}),\n ...(scrollParam || {}),\n };\n }\n\n if (opt) {\n const normalizedScrollType = normalizeScrollType(\n (opt as ScrollParam).scrollType,\n );\n\n if (normalizedScrollType !== (opt as ScrollParam).scrollType) {\n (opt as ScrollParam) = {\n ...(opt || {}),\n scrollType: normalizedScrollType as ScrollParam['scrollType'],\n };\n }\n }\n\n const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(\n locatePrompt || '',\n opt,\n );\n\n await this.callActionInActionSpace('Scroll', {\n ...restParams,\n locate: locateParam,\n });\n }\n\n async aiPinch(\n locatePrompt: TUserPrompt | undefined,\n opt: LocateOption & {\n direction: 'in' | 'out';\n distance?: number;\n duration?: number;\n },\n ): Promise<void> {\n const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(\n locatePrompt || '',\n opt,\n );\n\n await this.callActionInActionSpace('Pinch', {\n ...restParams,\n locate: locateParam,\n });\n }\n\n async aiLongPress(\n locatePrompt: TUserPrompt,\n opt?: LocateOption & { duration?: number },\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for long press');\n\n const { locateParam, restParams } = buildDetailedLocateParamAndRestParams(\n locatePrompt,\n opt,\n );\n\n await this.callActionInActionSpace('LongPress', {\n ...restParams,\n locate: locateParam,\n });\n }\n\n async aiClearInput(\n locatePrompt: TUserPrompt,\n opt?: LocateOption,\n ): Promise<void> {\n assert(locatePrompt, 'missing locate prompt for clear input');\n\n const detailedLocateParam = buildDetailedLocateParam(locatePrompt, opt);\n\n await this.callActionInActionSpace('ClearInput', {\n locate: detailedLocateParam,\n });\n }\n\n async aiAct(\n taskPrompt: TUserPrompt,\n opt?: AiActOptions,\n ): Promise<string | undefined> {\n const internalReportDisplay = (opt as AiActInternalOptions | undefined)\n ?._internalReportDisplay;\n const taskPromptText =\n typeof taskPrompt === 'string' ? taskPrompt : taskPrompt.prompt;\n const reportPrompt = internalReportDisplay?.prompt || taskPromptText;\n const fileChooserAccept = opt?.fileChooserAccept\n ? this.normalizeFileInput(opt.fileChooserAccept)\n : undefined;\n\n const abortSignal = opt?.abortSignal;\n if (abortSignal?.aborted) {\n throw new Error(\n `aiAct aborted: ${abortSignal.reason || 'signal already aborted'}`,\n );\n }\n\n const runAiAct = async () => {\n const planningModel = this.resolveModelRuntime('planning');\n const defaultModel = this.resolveModelRuntime('default');\n const aiActContext =\n opt?.context !== undefined ? opt.context : this.aiActContext;\n const cachePrompt = buildPromptWithContext(taskPrompt, aiActContext);\n // Controls the aiAct planning mode, such as sub-goal prompts and locate result strategy.\n let deepThink = opt?.deepThink === true;\n if (deepThink && planningModel.adapter.planning.kind === 'custom') {\n warn(\n `The \"deepThink\" option is not supported for aiAct with custom planning adapters (modelFamily: ${planningModel.config.modelFamily ?? 'unknown'}). It will be ignored.`,\n );\n deepThink = false;\n }\n\n let deepLocate = opt?.deepLocate;\n if (\n deepLocate &&\n !planningModel.adapter.planning.supportsActionDeepLocate\n ) {\n warn(\n `The \"deepLocate\" option is not supported for aiAct with the current planning adapter (modelFamily: ${planningModel.config.modelFamily ?? 'unknown'}). It will be ignored.`,\n );\n deepLocate = false;\n }\n\n const noIndividualLocateModel = planningModel.config.slot === 'default';\n\n const includeLocateInPlanning = !deepThink && noIndividualLocateModel;\n\n debug('setting includeLocateInPlanning to', includeLocateInPlanning, {\n deepThink,\n noIndividualLocateModel,\n });\n\n const cacheable = opt?.cacheable;\n const replanningCycleLimit =\n this.resolveReplanningCycleLimit(planningModel);\n const planCacheEnabled = planningModel.adapter.planning.cacheEnabled;\n const matchedCache =\n !planCacheEnabled || cacheable === false\n ? undefined\n : this.taskCache?.matchPlanCache(cachePrompt);\n let cachedYamlFailed = false;\n if (\n matchedCache?.cacheUsable &&\n this.taskCache?.isCacheResultUsed &&\n matchedCache.cacheContent?.yamlWorkflow?.trim()\n ) {\n const yaml = matchedCache.cacheContent.yamlWorkflow;\n try {\n // log into report file\n await this.taskExecutor.loadYamlFlowAsPlanning(\n taskPrompt,\n yaml,\n internalReportDisplay,\n );\n\n debug('matched cache, will call .runYaml to run the action');\n await this.runYaml(yaml);\n return;\n } catch (error) {\n cachedYamlFailed = true;\n warn(\n `cached aiAct plan failed, will replan and disable the stale cache: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n\n // If cache matched but is not executable, fall through to normal execution\n const imagesIncludeCount: number = deepThink ? 2 : 1;\n const { output: actionOutput } = await this.taskExecutor.action(\n taskPrompt,\n planningModel,\n defaultModel,\n includeLocateInPlanning,\n aiActContext,\n cacheable,\n replanningCycleLimit,\n imagesIncludeCount,\n deepThink,\n fileChooserAccept,\n deepLocate,\n abortSignal,\n internalReportDisplay,\n );\n\n // update cache\n if (this.taskCache && cacheable !== false) {\n const yamlFlow = cachedYamlFailed ? [] : actionOutput?.yamlFlow;\n\n if (!cachedYamlFailed && !yamlFlow?.length) {\n return actionOutput?.output;\n }\n\n const yamlFlowToCache = yamlFlow ?? [];\n const yamlContent: MidsceneYamlScript = {\n tasks: [\n {\n name: reportPrompt,\n flow: yamlFlowToCache,\n },\n ],\n };\n const yamlFlowStr = yaml.dump(yamlContent);\n this.taskCache.updateOrAppendCacheRecord(\n {\n type: 'plan',\n prompt: cachePrompt,\n yamlWorkflow: yamlFlowStr,\n },\n matchedCache,\n );\n }\n\n return actionOutput?.output;\n };\n\n return await runAiAct();\n }\n\n async runMarkdown(\n markdownPath: string,\n opt?: AiActOptions,\n ): Promise<string | undefined> {\n const markdown = await readFile(markdownPath, 'utf-8');\n const { prompt } = await markdownToAiActPrompt(markdown, markdownPath);\n return this.aiAct(prompt, {\n ...opt,\n _internalReportDisplay: {\n type: 'Markdown',\n prompt: basename(markdownPath),\n },\n } as AiActOptions);\n }\n\n async runGherkinScenario(\n scenarioText: string,\n opt?: RunGherkinScenarioOptions,\n ): Promise<void> {\n return runGherkinScenario(this, scenarioText, opt);\n }\n\n /**\n * @deprecated Use {@link Agent.aiAct} instead.\n */\n async aiAction(taskPrompt: TUserPrompt, opt?: AiActOptions) {\n return this.aiAct(taskPrompt, opt);\n }\n\n async aiQuery<ReturnType = any>(\n demand: ServiceExtractParam,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<ReturnType> {\n const modelRuntime = this.resolveModelRuntime('insight');\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'Query',\n demand,\n modelRuntime,\n opt,\n );\n return output as ReturnType;\n }\n\n async aiBoolean(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<boolean> {\n return this.aiBooleanWithContext(prompt, undefined, opt);\n }\n\n private async aiBooleanWithContext(\n prompt: TUserPrompt,\n uiContext?: UIContext,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<boolean> {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'Boolean',\n textPrompt,\n modelRuntime,\n opt,\n multimodalPrompt,\n uiContext ? { uiContext } : undefined,\n );\n return output as boolean;\n }\n\n async aiNumber(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<number> {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'Number',\n textPrompt,\n modelRuntime,\n opt,\n multimodalPrompt,\n );\n return output as number;\n }\n\n async aiString(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<string> {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const { textPrompt, multimodalPrompt } = parsePrompt(prompt);\n const { output } = await this.taskExecutor.createTypeQueryExecution(\n 'String',\n textPrompt,\n modelRuntime,\n opt,\n multimodalPrompt,\n );\n return output as string;\n }\n\n async aiAsk(\n prompt: TUserPrompt,\n opt: ServiceExtractOption = defaultServiceExtractOption,\n ): Promise<string> {\n return this.aiString(prompt, opt);\n }\n\n /**\n * Locate an element and return both its center point and an approximate rect.\n *\n * - In most locate flows, `rect` represents the matched element boundary.\n * - Some models only support point grounding instead of boundary grounding.\n * In those cases (for example, AutoGLM), `rect` falls back to a small 8x8\n * box centered on the located point.\n *\n * Because `rect` may vary with the underlying model capability, avoid relying\n * on it too heavily for strict boundary semantics. If you need a stable click\n * target, prefer `center`.\n */\n async aiLocate(prompt: TUserPrompt, opt?: LocateOption) {\n const locateParam = buildDetailedLocateParam(prompt, opt);\n assert(locateParam, 'cannot get locate param for aiLocate');\n const locatePlan = locatePlanForLocate(locateParam);\n const plans = [locatePlan];\n const defaultModel = this.resolveModelRuntime('default');\n const planningModel = this.resolveModelRuntime('planning');\n\n const { output } = await this.taskExecutor.runPlans(\n taskTitleStr('Locate', locateParamStr(locateParam)),\n plans,\n planningModel,\n defaultModel,\n opt?.uiContext ? { uiContext: opt.uiContext } : undefined,\n );\n\n const { element } = output;\n\n return {\n rect: element?.rect,\n center: element?.center,\n dpr: element?.dpr,\n } as Pick<LocateResultElement, 'rect' | 'center'>;\n }\n\n async aiAssert(\n assertion: TUserPrompt,\n msg?: string,\n opt?: AgentAssertOpt & ServiceExtractOption,\n ) {\n return this.aiAssertWithUIContext(assertion, undefined, msg, opt);\n }\n\n private async aiAssertWithUIContext(\n assertion: TUserPrompt,\n uiContext?: UIContext,\n msg?: string,\n opt?: AgentAssertOpt & ServiceExtractOption,\n ) {\n const modelRuntime = this.resolveModelRuntime('insight');\n\n const serviceOpt: ServiceExtractOption = {\n domIncluded: opt?.domIncluded ?? defaultServiceExtractOption.domIncluded,\n screenshotIncluded:\n opt?.screenshotIncluded ??\n defaultServiceExtractOption.screenshotIncluded,\n ...(opt?.context !== undefined ? { context: opt.context } : {}),\n };\n\n const { textPrompt, multimodalPrompt } = parsePrompt(assertion);\n const assertionText =\n typeof assertion === 'string' ? assertion : assertion.prompt;\n\n const executionOptions = {\n abortSignal: opt?.abortSignal,\n ...(uiContext ? { uiContext } : {}),\n };\n\n try {\n const { output, thought } =\n await this.taskExecutor.createTypeQueryExecution<boolean>(\n 'Assert',\n textPrompt,\n modelRuntime,\n serviceOpt,\n multimodalPrompt,\n executionOptions,\n );\n\n const pass = Boolean(output);\n const message = pass\n ? undefined\n : `Assertion failed: ${msg || assertionText}\\nReason: ${thought || '(no_reason)'}`;\n\n if (opt?.keepRawResponse) {\n return {\n pass,\n thought,\n message,\n };\n }\n\n if (!pass) {\n throw new Error(message);\n }\n } catch (error) {\n if (error instanceof TaskExecutionError) {\n const errorTask = error.errorTask;\n const thought = errorTask?.thought;\n const rawError = errorTask?.error;\n const rawMessage =\n errorTask?.errorMessage ||\n (rawError instanceof Error\n ? rawError.message\n : rawError\n ? String(rawError)\n : undefined);\n const reason = thought || rawMessage || '(no_reason)';\n const message = `Assertion failed: ${msg || assertionText}\\nReason: ${reason}`;\n\n if (opt?.keepRawResponse) {\n return {\n pass: false,\n thought,\n message,\n };\n }\n\n throw new Error(message, {\n cause: rawError ?? error,\n });\n }\n\n throw error;\n }\n }\n\n async aiWaitFor(assertion: TUserPrompt, opt?: AgentWaitForOpt) {\n const modelRuntime = this.resolveModelRuntime('insight');\n await this.taskExecutor.waitFor(\n assertion,\n {\n ...opt,\n timeoutMs: opt?.timeoutMs || 15 * 1000,\n checkIntervalMs: opt?.checkIntervalMs || 3 * 1000,\n },\n modelRuntime,\n );\n }\n\n async ai(...args: Parameters<typeof this.aiAct>) {\n return this.aiAct(...args);\n }\n\n async runYaml(yamlScriptContent: string): Promise<{\n result: Record<string, any>;\n }> {\n const script = parseYamlScript(yamlScriptContent, 'yaml');\n const player = new ScriptPlayer(script, async () => {\n return { agent: this, freeFn: [] };\n });\n await player.run();\n\n if (player.status === 'error') {\n const errors = player.taskStatusList\n .filter((task) => task.status === 'error')\n .map((task) => {\n return `task - ${task.name}: ${task.error?.message}`;\n })\n .join('\\n');\n throw new Error(`Error(s) occurred in running yaml script:\\n${errors}`);\n }\n\n return {\n result: player.result,\n };\n }\n\n async evaluateJavaScript(script: string) {\n assert(\n this.interface.evaluateJavaScript,\n 'evaluateJavaScript is not supported in current agent',\n );\n return this.interface.evaluateJavaScript(script);\n }\n\n /**\n * Add a dump update listener\n * @param listener Listener function\n * @returns A remove function that can be called to remove this listener\n */\n addDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): () => void {\n this.dumpUpdateListeners.push(listener);\n\n // Return remove function\n return () => {\n this.removeDumpUpdateListener(listener);\n };\n }\n\n /**\n * Remove a dump update listener\n * @param listener The listener function to remove\n */\n removeDumpUpdateListener(\n listener: (dump: string, executionDump?: ExecutionDump) => void,\n ): void {\n const index = this.dumpUpdateListeners.indexOf(listener);\n if (index > -1) {\n this.dumpUpdateListeners.splice(index, 1);\n }\n }\n\n /**\n * Clear all dump update listeners\n */\n clearDumpUpdateListeners(): void {\n this.dumpUpdateListeners = [];\n }\n\n /**\n * Subscribe to the generic agent progress bus. The listener receives every\n * progress event regardless of producer; narrow by `event.scope` to handle a\n * specific producer (e.g. `'aiAct'`).\n * @param listener Listener function\n * @returns A remove function that can be called to remove this listener\n */\n addProgressListener(listener: AgentProgressListener): () => void {\n return this.progressBus.subscribe(listener);\n }\n\n /**\n * Remove a progress listener added via {@link addProgressListener}.\n */\n removeProgressListener(listener: AgentProgressListener): void {\n this.progressBus.unsubscribe(listener);\n }\n\n /**\n * Clear all generic progress listeners.\n */\n clearProgressListeners(): void {\n this.progressBus.clear();\n }\n\n private notifyDumpUpdateListeners(executionDump?: ExecutionDump) {\n const dumpString = this.dumpDataString();\n for (const listener of this.dumpUpdateListeners) {\n try {\n listener(dumpString, executionDump);\n } catch (error) {\n console.error('Error in onDumpUpdate listener', error);\n }\n }\n }\n\n async destroy() {\n // Early return if already destroyed\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n\n // Stop any active observer before tearing down the interface. The observer\n // may hold a frame source subscription that needs explicit cleanup.\n if (this.activeObserver) {\n try {\n await this.activeObserver.stop();\n } catch (error) {\n debug(`error stopping active observer during destroy: ${error}`);\n }\n // onStopped callback should have cleared this, but ensure it's null\n this.activeObserver = null;\n }\n\n let interfaceDestroyError: unknown;\n try {\n await this.interface.destroy?.();\n } catch (error) {\n interfaceDestroyError = error;\n }\n\n // Wait for all queued write operations to complete\n await this.reportGenerator.flush();\n\n const finalPath = await this.reportGenerator.finalize();\n this.reportFile = finalPath;\n\n this.resetDump(); // reset dump to release memory\n\n if (interfaceDestroyError) {\n throw interfaceDestroyError;\n }\n }\n\n async recordToReport(title?: string, opt?: RecordToReportOptions) {\n const now = Date.now();\n const screenshots = opt?.screenshots;\n const screenshotBase64 = opt?.screenshotBase64;\n const hasScreenshots = screenshots !== undefined;\n const hasScreenshotBase64 = screenshotBase64 !== undefined;\n if (hasScreenshots && !Array.isArray(screenshots)) {\n throw new Error('recordToReport: screenshots must be an array');\n }\n if (hasScreenshotBase64 && typeof screenshotBase64 !== 'string') {\n throw new Error('recordToReport: screenshotBase64 must be a string');\n }\n if (hasScreenshots && hasScreenshotBase64) {\n throw new Error(\n 'recordToReport: provide only one of screenshots or screenshotBase64',\n );\n }\n if (opt && 'subType' in opt) {\n throw new Error('recordToReport: subType is not supported');\n }\n const customScreenshots = hasScreenshots ? screenshots : undefined;\n if (customScreenshots && customScreenshots.length === 0) {\n throw new Error('recordToReport: screenshots cannot be empty');\n }\n const screenshotInputs: RecordToReportScreenshot[] =\n customScreenshots ??\n (hasScreenshotBase64\n ? [{ base64: screenshotBase64 }]\n : [{ base64: await this.interface.screenshotBase64() }]);\n\n // 1. build recorder\n const recorder: ExecutionRecorderItem[] = screenshotInputs.map(\n (screenshotInput, index) => {\n const normalizedScreenshotInput = normalizeRecordToReportScreenshot(\n screenshotInput,\n index,\n );\n const ts = now + index;\n return {\n type: 'screenshot',\n ts,\n screenshot: ScreenshotItem.create(\n normalizedScreenshotInput.base64,\n ts,\n ),\n description: normalizedScreenshotInput.description,\n };\n },\n );\n // 2. build ExecutionTaskLog\n const task: ExecutionTaskLog = {\n taskId: uuid(),\n type: 'Log',\n subType: 'Screenshot',\n status: 'finished',\n recorder,\n timing: {\n start: now,\n end: now,\n cost: 0,\n },\n param: {\n content: opt?.content || '',\n },\n executor: async () => {},\n };\n // 3. build ExecutionDump\n const executionDump = new ExecutionDump({\n id: uuid(),\n logTime: now,\n name: `Log - ${title || 'untitled'}`,\n description: opt?.content || '',\n tasks: [task],\n });\n // 4. append to execution dump\n this.appendExecutionDump(executionDump);\n\n this.writeOutActionDumps(executionDump);\n await this.reportGenerator.flush();\n\n // Call all registered dump update listeners\n this.notifyDumpUpdateListeners(executionDump);\n }\n\n async recordErrorToReport(\n title: string,\n opt: {\n error: Error;\n content?: string;\n screenshotBase64?: string;\n },\n ) {\n const now = Date.now();\n const recorder: ExecutionRecorderItem[] = [];\n const base64 =\n opt.screenshotBase64 ?? (await this.interface.screenshotBase64());\n if (base64) {\n recorder.push({\n type: 'screenshot',\n ts: now,\n screenshot: ScreenshotItem.create(base64, now),\n });\n }\n\n const task: ExecutionTaskLog = {\n taskId: uuid(),\n type: 'Log',\n subType: 'Error',\n status: 'failed',\n recorder,\n timing: {\n start: now,\n end: now,\n cost: 0,\n },\n param: {\n content: opt.content || '',\n },\n error: opt.error,\n errorMessage: opt.error.message,\n errorStack: opt.error.stack,\n executor: async () => {},\n };\n\n const executionDump = new ExecutionDump({\n id: uuid(),\n logTime: now,\n name: title,\n description: opt.content || opt.error.message,\n tasks: [task],\n });\n\n this.appendExecutionDump(executionDump);\n this.writeOutActionDumps(executionDump);\n await this.reportGenerator.flush();\n this.notifyDumpUpdateListeners(executionDump);\n }\n\n /**\n * @deprecated Use {@link Agent.recordToReport} instead.\n */\n async logScreenshot(\n title?: string,\n opt?: {\n content: string;\n },\n ) {\n await this.recordToReport(title, opt);\n }\n\n _unstableLogContent() {\n const { groupName, groupDescription, executions } = this.dump;\n return {\n groupName,\n groupDescription,\n executions: executions || [],\n };\n }\n\n /**\n * Freezes the current page context to be reused in subsequent AI operations\n * This avoids recalculating page context for each operation\n */\n async freezePageContext(): Promise<void> {\n debug('Freezing page context');\n const context = await this._snapshotContext();\n // Mark the context as frozen\n context._isFrozen = true;\n this.frozenUIContext = context;\n debug('Page context frozen successfully');\n }\n\n /**\n * Unfreezes the page context, allowing AI operations to calculate context dynamically\n */\n async unfreezePageContext(): Promise<void> {\n debug('Unfreezing page context');\n this.frozenUIContext = undefined;\n debug('Page context unfrozen successfully');\n }\n\n /**\n * Process cache configuration and return normalized cache settings\n */\n private processCacheConfig(opts: AgentOpt): {\n id: string;\n enabled: boolean;\n readOnly: boolean;\n writeOnly: boolean;\n cacheDir?: string;\n } | null {\n validateAgentCacheInput(opts.cache);\n\n // Use the unified utils function to process cache configuration\n const cacheConfig = processCacheConfig(\n opts.cache,\n opts.cacheId || 'default',\n );\n\n if (!cacheConfig) {\n return null;\n }\n\n // Handle cache configuration object\n if (typeof cacheConfig === 'object' && cacheConfig !== null) {\n const id = cacheConfig.id;\n const strategyValue = cacheConfig.strategy ?? 'read-write';\n const isReadOnly = strategyValue === 'read-only';\n const isWriteOnly = strategyValue === 'write-only';\n\n return {\n id,\n enabled: !isWriteOnly,\n readOnly: isReadOnly,\n writeOnly: isWriteOnly,\n cacheDir: cacheConfig.cacheDir?.trim(),\n };\n }\n\n return null;\n }\n\n private normalizeFileInput(files: string | string[]): string[] {\n const filesArray = Array.isArray(files) ? files : [files];\n return normalizeFilePaths(filesArray);\n }\n\n /**\n * Manually flush cache to file\n * @param options - Optional configuration\n * @param options.cleanUnused - If true, removes unused cache records before flushing\n */\n async flushCache(options?: { cleanUnused?: boolean }): Promise<void> {\n if (!this.taskCache) {\n throw new Error('Cache is not configured');\n }\n\n this.taskCache.flushCacheToFile(options);\n }\n}\n\nexport const createAgent = (\n interfaceInstance: AbstractInterface,\n opts?: AgentOpt,\n) => {\n return new Agent(interfaceInstance, opts);\n};\n"],"names":["debug","getDebug","warn","defaultServiceExtractOption","Agent","callback","planningModel","globalConfigManager","MIDSCENE_REPLANNING_CYCLE_LIMIT","intent","runtime","getModelRuntime","usage","enriched","_error","action","maxRetries","attempt","commonContextParser","error","Promise","resolve","setTimeout","opt","assert","observer","UIObserver","undefined","assertion","uiContext","msg","assertOpt","prompt","boolOpt","console","ReportActionDump","getVersion","WeakMap","execution","runner","currentDump","existingIndex","task","key","dedupKey","INTERNAL_CALL_ID_FIELD","ifInBrowser","reportHTMLContent","executionDump","exec","param","paramStr","tip","typeStr","name","type","actionPlan","plans","Boolean","title","taskTitleStr","locateParamStr","defaultModel","output","locatePrompt","detailedLocateParam","buildDetailedLocateParam","fileChooserAccept","withFileChooser","locatePromptOrValue","locatePromptOrOpt","optOrUndefined","value","optWithValue","locateParam","restParams","buildDetailedLocateParamAndRestParams","stringValue","String","mode","locatePromptOrKeyName","keyName","locatePromptOrScrollParam","scrollParam","isLocatePromptLike","normalizedScrollType","normalizeScrollType","taskPrompt","internalReportDisplay","taskPromptText","reportPrompt","abortSignal","Error","runAiAct","aiActContext","cachePrompt","buildPromptWithContext","deepThink","deepLocate","noIndividualLocateModel","includeLocateInPlanning","cacheable","replanningCycleLimit","planCacheEnabled","matchedCache","cachedYamlFailed","yaml","imagesIncludeCount","actionOutput","yamlFlow","yamlFlowToCache","yamlContent","yamlFlowStr","markdownPath","markdown","readFile","markdownToAiActPrompt","basename","scenarioText","runGherkinScenario","demand","modelRuntime","textPrompt","multimodalPrompt","parsePrompt","locatePlan","locatePlanForLocate","element","serviceOpt","assertionText","executionOptions","thought","pass","message","TaskExecutionError","errorTask","rawError","rawMessage","reason","args","yamlScriptContent","script","parseYamlScript","player","ScriptPlayer","errors","listener","index","dumpString","interfaceDestroyError","finalPath","now","Date","screenshots","screenshotBase64","hasScreenshots","hasScreenshotBase64","Array","customScreenshots","screenshotInputs","recorder","screenshotInput","normalizedScreenshotInput","normalizeRecordToReportScreenshot","ts","ScreenshotItem","uuid","ExecutionDump","base64","groupName","groupDescription","executions","context","opts","validateAgentCacheInput","cacheConfig","processCacheConfig","id","strategyValue","isReadOnly","isWriteOnly","files","filesArray","normalizeFilePaths","options","interfaceInstance","MetricsCollector","Set","AgentProgressBus","Object","assertReportGenerationOptions","resolvedAiActContext","hasCustomConfig","ModelConfigManager","globalModelConfigManager","Service","cacheConfigObj","TaskCache","baseActionSpace","defineActionSleep","TaskExecutor","getReportFileName","ReportGenerator","createAgent"],"mappings":"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"}
@@ -9,6 +9,17 @@ const buildPromptWithContext = (prompt, context)=>{
9
9
  prompt: promptWithContext
10
10
  };
11
11
  };
12
- export { buildPromptWithContext };
12
+ const buildLocatePromptWithContext = (prompt, context)=>{
13
+ const trimmedContext = context?.trim();
14
+ if (!trimmedContext) return prompt;
15
+ const promptText = 'string' == typeof prompt ? prompt : prompt.prompt;
16
+ const promptWithContext = `<CONTEXT>\n${trimmedContext}\n</CONTEXT>\n\n<LOCATE_TARGET>\n${promptText}\n</LOCATE_TARGET>`;
17
+ if ('string' == typeof prompt) return promptWithContext;
18
+ return {
19
+ ...prompt,
20
+ prompt: promptWithContext
21
+ };
22
+ };
23
+ export { buildLocatePromptWithContext, buildPromptWithContext };
13
24
 
14
25
  //# sourceMappingURL=prompt-context.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent/prompt-context.mjs","sources":["../../../src/agent/prompt-context.ts"],"sourcesContent":["import type { TUserPrompt } from '@/ai-model';\n\nexport const buildPromptWithContext = (\n prompt: TUserPrompt,\n context: string | undefined,\n): TUserPrompt => {\n const trimmedContext = context?.trim();\n if (!trimmedContext) {\n return prompt;\n }\n\n const promptText = typeof prompt === 'string' ? prompt : prompt.prompt;\n const promptWithContext = `Context for this request:\\n${trimmedContext}\\n\\n${promptText}`;\n\n if (typeof prompt === 'string') {\n return promptWithContext;\n }\n\n return {\n ...prompt,\n prompt: promptWithContext,\n };\n};\n"],"names":["buildPromptWithContext","prompt","context","trimmedContext","promptText","promptWithContext"],"mappings":"AAEO,MAAMA,yBAAyB,CACpCC,QACAC;IAEA,MAAMC,iBAAiBD,SAAS;IAChC,IAAI,CAACC,gBACH,OAAOF;IAGT,MAAMG,aAAa,AAAkB,YAAlB,OAAOH,SAAsBA,SAASA,OAAO,MAAM;IACtE,MAAMI,oBAAoB,CAAC,2BAA2B,EAAEF,eAAe,IAAI,EAAEC,YAAY;IAEzF,IAAI,AAAkB,YAAlB,OAAOH,QACT,OAAOI;IAGT,OAAO;QACL,GAAGJ,MAAM;QACT,QAAQI;IACV;AACF"}
1
+ {"version":3,"file":"agent/prompt-context.mjs","sources":["../../../src/agent/prompt-context.ts"],"sourcesContent":["import type { TUserPrompt } from '@/ai-model';\n\nexport const buildPromptWithContext = (\n prompt: TUserPrompt,\n context: string | undefined,\n): TUserPrompt => {\n const trimmedContext = context?.trim();\n if (!trimmedContext) {\n return prompt;\n }\n\n const promptText = typeof prompt === 'string' ? prompt : prompt.prompt;\n const promptWithContext = `Context for this request:\\n${trimmedContext}\\n\\n${promptText}`;\n\n if (typeof prompt === 'string') {\n return promptWithContext;\n }\n\n return {\n ...prompt,\n prompt: promptWithContext,\n };\n};\n\nexport const buildLocatePromptWithContext = (\n prompt: TUserPrompt,\n context: string | undefined,\n): TUserPrompt => {\n const trimmedContext = context?.trim();\n if (!trimmedContext) {\n return prompt;\n }\n\n const promptText = typeof prompt === 'string' ? prompt : prompt.prompt;\n const promptWithContext = `<CONTEXT>\\n${trimmedContext}\\n</CONTEXT>\\n\\n<LOCATE_TARGET>\\n${promptText}\\n</LOCATE_TARGET>`;\n\n if (typeof prompt === 'string') {\n return promptWithContext;\n }\n\n return {\n ...prompt,\n prompt: promptWithContext,\n };\n};\n"],"names":["buildPromptWithContext","prompt","context","trimmedContext","promptText","promptWithContext","buildLocatePromptWithContext"],"mappings":"AAEO,MAAMA,yBAAyB,CACpCC,QACAC;IAEA,MAAMC,iBAAiBD,SAAS;IAChC,IAAI,CAACC,gBACH,OAAOF;IAGT,MAAMG,aAAa,AAAkB,YAAlB,OAAOH,SAAsBA,SAASA,OAAO,MAAM;IACtE,MAAMI,oBAAoB,CAAC,2BAA2B,EAAEF,eAAe,IAAI,EAAEC,YAAY;IAEzF,IAAI,AAAkB,YAAlB,OAAOH,QACT,OAAOI;IAGT,OAAO;QACL,GAAGJ,MAAM;QACT,QAAQI;IACV;AACF;AAEO,MAAMC,+BAA+B,CAC1CL,QACAC;IAEA,MAAMC,iBAAiBD,SAAS;IAChC,IAAI,CAACC,gBACH,OAAOF;IAGT,MAAMG,aAAa,AAAkB,YAAlB,OAAOH,SAAsBA,SAASA,OAAO,MAAM;IACtE,MAAMI,oBAAoB,CAAC,WAAW,EAAEF,eAAe,iCAAiC,EAAEC,WAAW,kBAAkB,CAAC;IAExH,IAAI,AAAkB,YAAlB,OAAOH,QACT,OAAOI;IAGT,OAAO;QACL,GAAGJ,MAAM;QACT,QAAQI;IACV;AACF"}
@@ -331,11 +331,20 @@ class TaskBuilder {
331
331
  cacheToSave: currentCacheEntry
332
332
  }
333
333
  };
334
- onResult?.(element);
334
+ const promptDisplay = param.promptDisplay;
335
+ const elementForAction = promptDisplay ? {
336
+ ...element,
337
+ description: promptDisplay
338
+ } : element;
339
+ if (promptDisplay && locateDump?.matchedElement) locateDump.matchedElement = locateDump.matchedElement.map((matchedElement)=>({
340
+ ...matchedElement,
341
+ description: promptDisplay
342
+ }));
343
+ onResult?.(elementForAction);
335
344
  return {
336
345
  output: {
337
346
  element: {
338
- ...element,
347
+ ...elementForAction,
339
348
  dpr: uiContext.deprecatedDpr
340
349
  }
341
350
  },