@midscene/core 1.10.2-beta-20260706032158.0 → 1.10.3

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 (161) hide show
  1. package/dist/es/agent/agent.mjs +40 -1
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/metrics.mjs +81 -0
  4. package/dist/es/agent/metrics.mjs.map +1 -0
  5. package/dist/es/agent/task-builder.mjs +1 -1
  6. package/dist/es/agent/task-builder.mjs.map +1 -1
  7. package/dist/es/agent/utils.mjs +1 -1
  8. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs +9 -3
  9. package/dist/es/ai-model/connectivity/run-connectivity-test.mjs.map +1 -1
  10. package/dist/es/ai-model/inspect.mjs +3 -3
  11. package/dist/es/ai-model/inspect.mjs.map +1 -1
  12. package/dist/es/ai-model/llm-planning.mjs +1 -1
  13. package/dist/es/ai-model/llm-planning.mjs.map +1 -1
  14. package/dist/es/ai-model/model-adapter/resolve.mjs +2 -2
  15. package/dist/es/ai-model/model-adapter/resolve.mjs.map +1 -1
  16. package/dist/es/ai-model/models/default.mjs +2 -1
  17. package/dist/es/ai-model/models/default.mjs.map +1 -1
  18. package/dist/es/ai-model/models/doubao.mjs +38 -60
  19. package/dist/es/ai-model/models/doubao.mjs.map +1 -1
  20. package/dist/es/ai-model/models/gemini.mjs +4 -15
  21. package/dist/es/ai-model/models/gemini.mjs.map +1 -1
  22. package/dist/es/ai-model/models/glm.mjs +4 -0
  23. package/dist/es/ai-model/models/glm.mjs.map +1 -1
  24. package/dist/es/ai-model/models/gpt.mjs +5 -1
  25. package/dist/es/ai-model/models/gpt.mjs.map +1 -1
  26. package/dist/es/ai-model/models/kimi.mjs +4 -0
  27. package/dist/es/ai-model/models/kimi.mjs.map +1 -1
  28. package/dist/es/ai-model/models/mimo.mjs +3 -2
  29. package/dist/es/ai-model/models/mimo.mjs.map +1 -1
  30. package/dist/es/ai-model/models/qwen.mjs.map +1 -1
  31. package/dist/es/ai-model/models/ui-tars/adapter.mjs +2 -41
  32. package/dist/es/ai-model/models/ui-tars/adapter.mjs.map +1 -1
  33. package/dist/es/ai-model/models/utils/intent.mjs +6 -0
  34. package/dist/es/ai-model/models/utils/intent.mjs.map +1 -0
  35. package/dist/es/ai-model/prompt/describe.mjs +31 -34
  36. package/dist/es/ai-model/prompt/describe.mjs.map +1 -1
  37. package/dist/es/ai-model/prompt/extraction.mjs +15 -9
  38. package/dist/es/ai-model/prompt/extraction.mjs.map +1 -1
  39. package/dist/es/ai-model/prompt/llm-planning.mjs +19 -19
  40. package/dist/es/ai-model/prompt/llm-planning.mjs.map +1 -1
  41. package/dist/es/ai-model/prompt/locate-grounding-rules.mjs +7 -3
  42. package/dist/es/ai-model/prompt/locate-grounding-rules.mjs.map +1 -1
  43. package/dist/es/ai-model/prompt/recorder-metadata-generator.mjs +2 -1
  44. package/dist/es/ai-model/prompt/recorder-metadata-generator.mjs.map +1 -1
  45. package/dist/es/ai-model/service-caller/index.mjs +40 -19
  46. package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
  47. package/dist/es/ai-model/service-caller/json.mjs +31 -28
  48. package/dist/es/ai-model/service-caller/json.mjs.map +1 -1
  49. package/dist/es/device/index.mjs +2 -4
  50. package/dist/es/device/index.mjs.map +1 -1
  51. package/dist/es/dump/html-utils.mjs +63 -1
  52. package/dist/es/dump/html-utils.mjs.map +1 -1
  53. package/dist/es/dump/screenshot-restoration.mjs +6 -0
  54. package/dist/es/dump/screenshot-restoration.mjs.map +1 -1
  55. package/dist/es/element-describer.mjs +36 -18
  56. package/dist/es/element-describer.mjs.map +1 -1
  57. package/dist/es/index.mjs +2 -2
  58. package/dist/es/index.mjs.map +1 -1
  59. package/dist/es/report-generator.mjs +28 -1
  60. package/dist/es/report-generator.mjs.map +1 -1
  61. package/dist/es/report-markdown.mjs +300 -35
  62. package/dist/es/report-markdown.mjs.map +1 -1
  63. package/dist/es/report.mjs +29 -1
  64. package/dist/es/report.mjs.map +1 -1
  65. package/dist/es/service/index.mjs +101 -25
  66. package/dist/es/service/index.mjs.map +1 -1
  67. package/dist/es/service/utils.mjs +65 -1
  68. package/dist/es/service/utils.mjs.map +1 -1
  69. package/dist/es/types.mjs.map +1 -1
  70. package/dist/es/utils.mjs +2 -2
  71. package/dist/lib/agent/agent.js +40 -1
  72. package/dist/lib/agent/agent.js.map +1 -1
  73. package/dist/lib/agent/metrics.js +115 -0
  74. package/dist/lib/agent/metrics.js.map +1 -0
  75. package/dist/lib/agent/task-builder.js +1 -1
  76. package/dist/lib/agent/task-builder.js.map +1 -1
  77. package/dist/lib/agent/utils.js +1 -1
  78. package/dist/lib/ai-model/connectivity/run-connectivity-test.js +9 -3
  79. package/dist/lib/ai-model/connectivity/run-connectivity-test.js.map +1 -1
  80. package/dist/lib/ai-model/inspect.js +3 -3
  81. package/dist/lib/ai-model/inspect.js.map +1 -1
  82. package/dist/lib/ai-model/llm-planning.js +1 -1
  83. package/dist/lib/ai-model/llm-planning.js.map +1 -1
  84. package/dist/lib/ai-model/model-adapter/resolve.js +1 -1
  85. package/dist/lib/ai-model/model-adapter/resolve.js.map +1 -1
  86. package/dist/lib/ai-model/models/default.js +2 -1
  87. package/dist/lib/ai-model/models/default.js.map +1 -1
  88. package/dist/lib/ai-model/models/doubao.js +38 -69
  89. package/dist/lib/ai-model/models/doubao.js.map +1 -1
  90. package/dist/lib/ai-model/models/gemini.js +4 -15
  91. package/dist/lib/ai-model/models/gemini.js.map +1 -1
  92. package/dist/lib/ai-model/models/glm.js +4 -0
  93. package/dist/lib/ai-model/models/glm.js.map +1 -1
  94. package/dist/lib/ai-model/models/gpt.js +5 -1
  95. package/dist/lib/ai-model/models/gpt.js.map +1 -1
  96. package/dist/lib/ai-model/models/kimi.js +4 -0
  97. package/dist/lib/ai-model/models/kimi.js.map +1 -1
  98. package/dist/lib/ai-model/models/mimo.js +3 -2
  99. package/dist/lib/ai-model/models/mimo.js.map +1 -1
  100. package/dist/lib/ai-model/models/qwen.js.map +1 -1
  101. package/dist/lib/ai-model/models/ui-tars/adapter.js +1 -40
  102. package/dist/lib/ai-model/models/ui-tars/adapter.js.map +1 -1
  103. package/dist/lib/ai-model/models/utils/intent.js +40 -0
  104. package/dist/lib/ai-model/models/utils/intent.js.map +1 -0
  105. package/dist/lib/ai-model/prompt/describe.js +31 -34
  106. package/dist/lib/ai-model/prompt/describe.js.map +1 -1
  107. package/dist/lib/ai-model/prompt/extraction.js +14 -8
  108. package/dist/lib/ai-model/prompt/extraction.js.map +1 -1
  109. package/dist/lib/ai-model/prompt/llm-planning.js +19 -19
  110. package/dist/lib/ai-model/prompt/llm-planning.js.map +1 -1
  111. package/dist/lib/ai-model/prompt/locate-grounding-rules.js +7 -3
  112. package/dist/lib/ai-model/prompt/locate-grounding-rules.js.map +1 -1
  113. package/dist/lib/ai-model/prompt/recorder-metadata-generator.js +4 -3
  114. package/dist/lib/ai-model/prompt/recorder-metadata-generator.js.map +1 -1
  115. package/dist/lib/ai-model/service-caller/index.js +44 -23
  116. package/dist/lib/ai-model/service-caller/index.js.map +1 -1
  117. package/dist/lib/ai-model/service-caller/json.js +33 -33
  118. package/dist/lib/ai-model/service-caller/json.js.map +1 -1
  119. package/dist/lib/device/index.js +2 -4
  120. package/dist/lib/device/index.js.map +1 -1
  121. package/dist/lib/dump/html-utils.js +65 -0
  122. package/dist/lib/dump/html-utils.js.map +1 -1
  123. package/dist/lib/dump/screenshot-restoration.js +6 -0
  124. package/dist/lib/dump/screenshot-restoration.js.map +1 -1
  125. package/dist/lib/element-describer.js +37 -22
  126. package/dist/lib/element-describer.js.map +1 -1
  127. package/dist/lib/index.js +1 -4
  128. package/dist/lib/index.js.map +1 -1
  129. package/dist/lib/report-generator.js +27 -0
  130. package/dist/lib/report-generator.js.map +1 -1
  131. package/dist/lib/report-markdown.js +300 -35
  132. package/dist/lib/report-markdown.js.map +1 -1
  133. package/dist/lib/report.js +28 -0
  134. package/dist/lib/report.js.map +1 -1
  135. package/dist/lib/service/index.js +99 -23
  136. package/dist/lib/service/index.js.map +1 -1
  137. package/dist/lib/service/utils.js +98 -1
  138. package/dist/lib/service/utils.js.map +1 -1
  139. package/dist/lib/types.js.map +1 -1
  140. package/dist/lib/utils.js +2 -2
  141. package/dist/types/agent/agent.d.ts +15 -2
  142. package/dist/types/agent/index.d.ts +1 -0
  143. package/dist/types/agent/metrics.d.ts +48 -0
  144. package/dist/types/ai-model/model-adapter/types.d.ts +8 -0
  145. package/dist/types/ai-model/models/doubao.d.ts +1 -4
  146. package/dist/types/ai-model/models/gemini.d.ts +1 -1
  147. package/dist/types/ai-model/models/registry.d.ts +1 -1
  148. package/dist/types/ai-model/models/utils/intent.d.ts +2 -0
  149. package/dist/types/ai-model/service-caller/index.d.ts +8 -3
  150. package/dist/types/ai-model/service-caller/json.d.ts +19 -2
  151. package/dist/types/device/device-options.d.ts +0 -28
  152. package/dist/types/device/index.d.ts +0 -5
  153. package/dist/types/dump/html-utils.d.ts +2 -0
  154. package/dist/types/dump/screenshot-restoration.d.ts +1 -1
  155. package/dist/types/element-describer.d.ts +3 -6
  156. package/dist/types/index.d.ts +2 -2
  157. package/dist/types/report-generator.d.ts +6 -0
  158. package/dist/types/service/index.d.ts +1 -1
  159. package/dist/types/service/utils.d.ts +21 -2
  160. package/dist/types/types.d.ts +12 -2
  161. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"device/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/device/index.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { ModelRuntime } from '@/ai-model/models';\nimport { getMidsceneLocationSchema } from '@/common';\nimport type {\n ActionScrollParam,\n DeviceAction,\n ExecutorContext,\n LocateResultElement,\n} from '@/types';\nimport type { ElementNode } from '@midscene/shared/extractor';\nimport { getDebug } from '@midscene/shared/logger';\nimport { _keyDefinitions } from '@midscene/shared/us-keyboard-layout';\nimport { z } from 'zod';\nimport type { ElementCacheFeature, Rect, Size, UIContext } from '../types';\n\nexport interface FileChooserHandler {\n accept(files: string[]): Promise<void>;\n}\n\nexport interface FileChooserRegistration {\n dispose: () => void;\n getError: () => Error | undefined | Promise<Error | undefined>;\n}\n\nexport interface MjpegStreamFrame {\n /** Raw base64-encoded image bytes WITHOUT a `data:image/...;base64,` prefix. */\n data: string;\n contentType?: string;\n}\n\nexport interface MjpegStreamHandle {\n stop(): void | Promise<void>;\n}\n\nexport interface MjpegStreamOptions {\n signal?: AbortSignal;\n onFrame(frame: MjpegStreamFrame): void;\n onError?(error: unknown): void;\n}\n\n/** A point in device-pixel coordinates on the screen. */\nexport interface PointerPoint {\n x: number;\n y: number;\n}\n\nexport interface PointerInputPrimitives {\n tap(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n doubleClick?(p: PointerPoint): Promise<void>;\n rightClick?(p: PointerPoint): Promise<void>;\n hover?(p: PointerPoint): Promise<void>;\n longPress?(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n dragAndDrop?(from: PointerPoint, to: PointerPoint): Promise<void>;\n}\n\nexport interface TouchInputPrimitives {\n swipe(\n start: PointerPoint,\n end: PointerPoint,\n opts?: { duration?: number; repeat?: number },\n ): Promise<void>;\n pinch?(\n center: PointerPoint,\n opts: { startDistance: number; endDistance: number; duration: number },\n ): Promise<void>;\n}\n\nexport interface KeyboardInputPrimitives {\n keyboardPress(keyName: string, opts?: { target?: unknown }): Promise<void>;\n cursorMove?(direction: 'left' | 'right', times?: number): Promise<void>;\n typeText(\n value: string,\n opts?: {\n autoDismissKeyboard?: boolean;\n keyboardDismissStrategy?: 'esc-first' | 'back-first';\n keyboardTypeDelay?: number;\n target?: unknown;\n replace?: boolean;\n focusOnly?: boolean;\n },\n ): Promise<void>;\n clearInput(target?: unknown): Promise<void>;\n}\n\nexport interface ScrollInputPrimitives {\n scroll(param: ActionScrollParam): Promise<void>;\n}\n\nexport interface SystemInputPrimitives {\n backButton?(): Promise<void>;\n homeButton?(): Promise<void>;\n recentAppsButton?(): Promise<void>;\n}\n\nexport interface InputPrimitives {\n pointer?: PointerInputPrimitives;\n keyboard?: KeyboardInputPrimitives;\n touch?: TouchInputPrimitives;\n scroll?: ScrollInputPrimitives;\n system?: SystemInputPrimitives;\n}\n\nexport interface MobileInputPrimitives extends InputPrimitives {\n pointer: PointerInputPrimitives & {\n doubleClick(p: PointerPoint): Promise<void>;\n longPress(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n dragAndDrop(from: PointerPoint, to: PointerPoint): Promise<void>;\n };\n keyboard: KeyboardInputPrimitives;\n touch: TouchInputPrimitives;\n}\n\nexport interface BrowserInputPrimitives extends InputPrimitives {\n pointer: PointerInputPrimitives & {\n doubleClick(p: PointerPoint): Promise<void>;\n rightClick(p: PointerPoint): Promise<void>;\n hover(p: PointerPoint): Promise<void>;\n dragAndDrop(from: PointerPoint, to: PointerPoint): Promise<void>;\n longPress(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n };\n keyboard: KeyboardInputPrimitives;\n scroll: ScrollInputPrimitives;\n touch: TouchInputPrimitives;\n}\n\nexport interface ComputerInputPrimitives extends InputPrimitives {\n pointer: PointerInputPrimitives & {\n doubleClick(p: PointerPoint): Promise<void>;\n rightClick(p: PointerPoint): Promise<void>;\n hover(p: PointerPoint): Promise<void>;\n dragAndDrop(from: PointerPoint, to: PointerPoint): Promise<void>;\n };\n keyboard: KeyboardInputPrimitives;\n scroll: ScrollInputPrimitives;\n}\n\nexport abstract class AbstractInterface {\n abstract interfaceType: string;\n\n abstract screenshotBase64(): Promise<string>;\n abstract size(): Promise<Size>;\n abstract actionSpace(): DeviceAction[];\n\n abstract cacheFeatureForPoint?(\n center: [number, number],\n options?: {\n targetDescription?: string;\n modelRuntime?: ModelRuntime;\n },\n ): Promise<ElementCacheFeature>;\n abstract rectMatchesCacheFeature?(\n feature: ElementCacheFeature,\n ): Promise<Rect>;\n\n abstract destroy?(): Promise<void>;\n\n abstract describe?(): string;\n abstract beforeInvokeAction?(actionName: string, param: any): Promise<void>;\n abstract afterInvokeAction?(actionName: string, param: any): Promise<void>;\n\n // for web only\n registerFileChooserListener?(\n handler: (chooser: FileChooserHandler) => Promise<void>,\n ): Promise<FileChooserRegistration>;\n\n // @deprecated do NOT extend this method\n abstract getElementsNodeTree?: () => Promise<ElementNode>;\n\n // @deprecated do NOT extend this method\n abstract url?: () => string | Promise<string>;\n\n // @deprecated do NOT extend this method\n abstract evaluateJavaScript?<T = any>(script: string): Promise<T>;\n\n /**\n * Get the current device-local time as a formatted string.\n * Prefer this for user-visible time because timestamps alone do not preserve\n * the target device's timezone when formatted on the host machine.\n */\n getDeviceLocalTimeString?(format?: string): Promise<string>;\n\n /** URL of native MJPEG stream for real-time screen preview (e.g. WDA MJPEG server) */\n mjpegStreamUrl?: string;\n\n /**\n * Optional in-process MJPEG frame producer. Implementations can push raw\n * base64 frames here when there is no standalone native MJPEG URL, e.g.\n * Chromium CDP Page.startScreencast for web previews.\n */\n startMjpegStream?(\n options: MjpegStreamOptions,\n ): MjpegStreamHandle | undefined | Promise<MjpegStreamHandle | undefined>;\n\n /**\n * Optional hook used after keyboard-only actions to force a fresh frame on\n * the active MJPEG stream. Implementations should be a no-op when no stream\n * is active.\n */\n flushPendingVisualUpdate?(): Promise<void>;\n\n /**\n * Optional non-blocking variant of `flushPendingVisualUpdate`. Keyboard-\n * heavy preview interactions can schedule a coalesced refresh here without\n * stalling the input hot path.\n */\n schedulePendingVisualUpdate?(): void;\n\n /**\n * Optional navigation state probe for browser-like interfaces, used to drive\n * loading indicators in playground UIs. Returning `undefined` means the\n * interface does not expose this concept.\n */\n navigationState?(): Promise<{ isLoading: boolean }>;\n\n /**\n * Low-level device input surface. Platform implementations expose transport\n * primitives here; higher-level AI actions and manual pointer dispatch should\n * adapt to this instead of duplicating platform gesture logic.\n */\n inputPrimitives?: InputPrimitives;\n}\n\n// Generic function to define actions with proper type inference\n// TRuntime allows specifying a different type for the runtime parameter (after location resolution)\n// TReturn allows specifying the return type of the action\nexport const defineAction = <\n TSchema extends z.ZodType | undefined = undefined,\n TRuntime = TSchema extends z.ZodType ? z.infer<TSchema> : undefined,\n TReturn = any,\n>(\n config: {\n name: string;\n description: string;\n interfaceAlias?: string;\n paramSchema?: TSchema;\n call: (\n param: TRuntime,\n context?: ExecutorContext,\n ) => Promise<TReturn> | TReturn;\n } & Partial<\n Omit<\n DeviceAction<TRuntime, TReturn>,\n 'name' | 'description' | 'interfaceAlias' | 'paramSchema' | 'call'\n >\n >,\n): DeviceAction<TRuntime, TReturn> => {\n return config as any; // Type assertion needed because schema validation type differs from runtime type\n};\n\nfunction pointFromLocate(\n locate: LocateResultElement | undefined,\n missingMessage: string,\n): PointerPoint {\n if (!locate) {\n throw new Error(missingMessage);\n }\n return { x: locate.center[0], y: locate.center[1] };\n}\n\nfunction defineLocatedPointAction<\n TSchema extends z.ZodType,\n TParam extends { locate: LocateResultElement },\n>(config: {\n name: string;\n description: string;\n interfaceAlias?: string;\n paramSchema: TSchema;\n sample: DeviceAction<TParam>['sample'];\n missingLocateMessage: string;\n call: (point: PointerPoint, param: TParam) => Promise<void>;\n}): DeviceAction<TParam> {\n return defineAction<TSchema, TParam>({\n name: config.name,\n description: config.description,\n interfaceAlias: config.interfaceAlias,\n paramSchema: config.paramSchema,\n sample: config.sample,\n call: async (param) => {\n await config.call(\n pointFromLocate(param.locate, config.missingLocateMessage),\n param,\n );\n },\n });\n}\n\n// Tap\nexport const actionTapParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe('The element to be tapped'),\n});\nexport type ActionTapParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionTap = (\n tap: PointerInputPrimitives['tap'],\n): DeviceAction<ActionTapParam> => {\n return defineLocatedPointAction<typeof actionTapParamSchema, ActionTapParam>({\n name: 'Tap',\n description: 'Tap the element',\n interfaceAlias: 'aiTap',\n paramSchema: actionTapParamSchema,\n sample: {\n locate: { prompt: 'the \"Submit\" button' },\n },\n missingLocateMessage: 'Element not found, cannot tap',\n call: async (point) => {\n await tap(point);\n },\n });\n};\n\n// RightClick\nexport const actionRightClickParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be right clicked',\n ),\n});\nexport type ActionRightClickParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionRightClick = (\n rightClick: NonNullable<PointerInputPrimitives['rightClick']>,\n): DeviceAction<ActionRightClickParam> => {\n return defineLocatedPointAction<\n typeof actionRightClickParamSchema,\n ActionRightClickParam\n >({\n name: 'RightClick',\n description: 'Right click the element',\n interfaceAlias: 'aiRightClick',\n paramSchema: actionRightClickParamSchema,\n sample: {\n locate: { prompt: 'the file icon on the desktop' },\n },\n missingLocateMessage: 'Element not found, cannot right click',\n call: async (point) => {\n await rightClick(point);\n },\n });\n};\n\n// DoubleClick\nexport const actionDoubleClickParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be double clicked',\n ),\n});\nexport type ActionDoubleClickParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionDoubleClick = (\n doubleClick: NonNullable<PointerInputPrimitives['doubleClick']>,\n): DeviceAction<ActionDoubleClickParam> => {\n return defineLocatedPointAction<\n typeof actionDoubleClickParamSchema,\n ActionDoubleClickParam\n >({\n name: 'DoubleClick',\n description: 'Double click the element',\n interfaceAlias: 'aiDoubleClick',\n paramSchema: actionDoubleClickParamSchema,\n sample: {\n locate: { prompt: 'the folder icon' },\n },\n missingLocateMessage: 'Element not found, cannot double click',\n call: async (point) => {\n await doubleClick(point);\n },\n });\n};\n\n// Hover\nexport const actionHoverParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe('The element to be hovered'),\n});\nexport type ActionHoverParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionHover = (\n hover: NonNullable<PointerInputPrimitives['hover']>,\n): DeviceAction<ActionHoverParam> => {\n return defineLocatedPointAction<\n typeof actionHoverParamSchema,\n ActionHoverParam\n >({\n name: 'Hover',\n description: 'Move the mouse to the element',\n interfaceAlias: 'aiHover',\n paramSchema: actionHoverParamSchema,\n sample: {\n locate: { prompt: 'the navigation menu item \"Products\"' },\n },\n missingLocateMessage: 'Element not found, cannot hover',\n call: async (point) => {\n await hover(point);\n },\n });\n};\n\n// Input\nconst inputLocateDescription =\n 'the position of the placeholder or text content in the target input field. If there is no content, locate the center of the input field.';\nexport const actionInputParamSchema = z.object({\n value: z\n .union([z.string(), z.number()])\n .transform((val) => String(val))\n .describe(\n 'The text to input. Provide the final content for replace mode, only the inserted characters for typeOnly mode, or an empty string when using clear mode to remove existing text.',\n ),\n locate: getMidsceneLocationSchema()\n .describe(inputLocateDescription)\n .optional(),\n mode: z\n .enum(['replace', 'clear', 'typeOnly'])\n .default('replace')\n .describe(\n 'Input mode: \"replace\" (default) - clear the field and input the value; \"typeOnly\" - type the value directly without clearing the field first, and should be set explicitly for incremental edits after moving the cursor; \"clear\" - clear the field without inputting new text.',\n ),\n autoDismissKeyboard: z\n .boolean()\n .optional()\n .describe(\n 'If true, the keyboard will be dismissed after the input is completed. Do not set it unless the user asks you to do so.',\n ),\n keyboardTypeDelay: z\n .number()\n .optional()\n .describe(\n 'Delay in milliseconds between keystrokes when typing. Passed through from device/user configuration. Do not set it unless the user asks you to do so.',\n ),\n});\nexport type ActionInputParam = {\n value: string;\n locate?: LocateResultElement;\n mode?: 'replace' | 'clear' | 'typeOnly' | 'append';\n autoDismissKeyboard?: boolean;\n keyboardTypeDelay?: number;\n};\n\nexport const defineActionInput = (\n keyboard: KeyboardInputPrimitives,\n): DeviceAction<ActionInputParam> => {\n return defineAction<typeof actionInputParamSchema, ActionInputParam>({\n name: 'Input',\n description: 'Input the value into the element',\n interfaceAlias: 'aiInput',\n paramSchema: actionInputParamSchema,\n sample: {\n value: 'test@example.com',\n locate: { prompt: 'the email input field' },\n },\n call: async (param) => {\n // backward compat: convert deprecated 'append' to 'typeOnly'\n if ((param.mode as string) === 'append') {\n param.mode = 'typeOnly';\n }\n\n if (param.mode === 'clear') {\n await keyboard.clearInput(param.locate);\n return;\n }\n\n if (!param || !param.value) {\n return;\n }\n\n await keyboard.typeText(param.value, {\n target: param.locate,\n replace: param.mode !== 'typeOnly',\n autoDismissKeyboard: param.autoDismissKeyboard,\n keyboardTypeDelay: param.keyboardTypeDelay,\n });\n },\n });\n};\n\n// KeyboardPress\nexport const actionKeyboardPressParamSchema = z.object({\n locate: getMidsceneLocationSchema()\n .describe('The element to be clicked before pressing the key')\n .optional(),\n keyName: z\n .string()\n .describe(\n \"The key to be pressed. Use '+' for key combinations, e.g., 'Control+A', 'Shift+Enter'\",\n ),\n});\nexport type ActionKeyboardPressParam = {\n locate?: LocateResultElement;\n keyName: string;\n};\n\nexport const defineActionKeyboardPress = (\n keyboardPress: KeyboardInputPrimitives['keyboardPress'],\n): DeviceAction<ActionKeyboardPressParam> => {\n return defineAction<\n typeof actionKeyboardPressParamSchema,\n ActionKeyboardPressParam\n >({\n name: 'KeyboardPress',\n description:\n 'Press a key or key combination, like \"Enter\", \"Tab\", \"Escape\", or \"Control+A\", \"Shift+Enter\". Do not use this to type text.',\n interfaceAlias: 'aiKeyboardPress',\n paramSchema: actionKeyboardPressParamSchema,\n sample: {\n keyName: 'Enter',\n },\n call: async (param) => {\n await keyboardPress(param.keyName, {\n target: param.locate,\n });\n },\n });\n};\n\n// Scroll\nexport const actionScrollParamSchema = z.object({\n scrollType: z\n .enum([\n 'singleAction',\n 'scrollToBottom',\n 'scrollToTop',\n 'scrollToRight',\n 'scrollToLeft',\n ])\n .default('singleAction')\n .describe(\n 'The scroll behavior: \"singleAction\" for a single scroll action, \"scrollToBottom\" for scrolling all the way to the bottom by rapidly scrolling 5-10 times (skipping intermediate content until reaching the bottom), \"scrollToTop\" for scrolling all the way to the top by rapidly scrolling 5-10 times (skipping intermediate content until reaching the top), \"scrollToRight\" for scrolling all the way to the right by rapidly scrolling multiple times, \"scrollToLeft\" for scrolling all the way to the left by rapidly scrolling multiple times',\n ),\n direction: z\n .enum(['down', 'up', 'right', 'left'])\n .default('down')\n .describe(\n 'The direction to scroll. Only effective when scrollType is \"singleAction\".',\n ),\n distance: z\n .number()\n .nullable()\n .optional()\n .describe('The distance in pixels to scroll'),\n locate: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'Describe the target element to be scrolled on, like \"the table\" or \"the list\" or \"the content area\" or \"the scrollable area\". Do NOT provide a general intent like \"scroll to find some element\"',\n ),\n});\n\nexport const defineActionScroll = (\n scroll: ScrollInputPrimitives['scroll'],\n): DeviceAction<ActionScrollParam> => {\n return defineAction<typeof actionScrollParamSchema, ActionScrollParam>({\n name: 'Scroll',\n description:\n 'Scroll the page or a scrollable element to browse content. This is the preferred way to scroll on all platforms, including mobile. Supports scrollToBottom/scrollToTop for boundary navigation. Default: direction `down`, scrollType `singleAction`, distance `null`.',\n interfaceAlias: 'aiScroll',\n paramSchema: actionScrollParamSchema,\n sample: {\n direction: 'down',\n scrollType: 'singleAction',\n locate: { prompt: 'the center of the product list area' },\n },\n call: async (param) => {\n await scroll(param);\n },\n });\n};\n\n// DragAndDrop\nexport const actionDragAndDropParamSchema = z.object({\n from: getMidsceneLocationSchema().describe('The position to be dragged'),\n to: getMidsceneLocationSchema().describe('The position to be dropped'),\n});\nexport type ActionDragAndDropParam = {\n from: LocateResultElement;\n to: LocateResultElement;\n};\n\nexport const defineActionDragAndDrop = (\n dragAndDrop: NonNullable<PointerInputPrimitives['dragAndDrop']>,\n): DeviceAction<ActionDragAndDropParam> => {\n return defineAction<\n typeof actionDragAndDropParamSchema,\n ActionDragAndDropParam\n >({\n name: 'DragAndDrop',\n description:\n 'Pick up a specific UI element and move it to a new position (e.g., reorder a card, move a file into a folder, sort list items). The element itself moves with your finger/mouse.',\n interfaceAlias: 'aiDragAndDrop',\n paramSchema: actionDragAndDropParamSchema,\n sample: {\n from: { prompt: 'the \"report.pdf\" file icon' },\n to: { prompt: 'the upload drop zone' },\n },\n call: async (param) => {\n const from = param.from;\n const to = param.to;\n if (!from) {\n throw new Error('missing \"from\" param for drag and drop');\n }\n if (!to) {\n throw new Error('missing \"to\" param for drag and drop');\n }\n await dragAndDrop(\n { x: from.center[0], y: from.center[1] },\n { x: to.center[0], y: to.center[1] },\n );\n },\n });\n};\n\nexport const ActionLongPressParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be long pressed',\n ),\n duration: z\n .number()\n .optional()\n .describe('Long press duration in milliseconds'),\n});\n\nexport type ActionLongPressParam = {\n locate: LocateResultElement;\n duration?: number;\n};\nexport const defineActionLongPress = (\n longPress: NonNullable<PointerInputPrimitives['longPress']>,\n): DeviceAction<ActionLongPressParam> => {\n return defineLocatedPointAction<\n typeof ActionLongPressParamSchema,\n ActionLongPressParam\n >({\n name: 'LongPress',\n description: 'Long press the element',\n interfaceAlias: 'aiLongPress',\n paramSchema: ActionLongPressParamSchema,\n sample: {\n locate: { prompt: 'the message bubble' },\n },\n missingLocateMessage: 'LongPress requires an element to be located',\n call: async (point, param) => {\n await longPress(point, { duration: param.duration });\n },\n });\n};\n\nexport const ActionSwipeParamSchema = z.object({\n start: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'Starting point of the swipe gesture, if not specified, the center of the page will be used',\n ),\n direction: z\n .enum(['up', 'down', 'left', 'right'])\n .optional()\n .describe(\n 'The direction to swipe (required when using distance). The direction means the direction of the finger swipe.',\n ),\n distance: z\n .number()\n .optional()\n .describe('The distance in pixels to swipe (mutually exclusive with end)'),\n end: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'Ending point of the swipe gesture (mutually exclusive with distance)',\n ),\n duration: z\n .number()\n .default(300)\n .describe('Duration of the swipe gesture in milliseconds'),\n repeat: z\n .number()\n .optional()\n .describe(\n 'The number of times to repeat the swipe gesture. 1 for default, 0 for infinite (e.g. endless swipe until the end of the page)',\n ),\n});\n\nexport type ActionSwipeParam = {\n start?: LocateResultElement;\n direction?: 'up' | 'down' | 'left' | 'right';\n distance?: number;\n end?: LocateResultElement;\n duration?: number;\n repeat?: number;\n};\n\nexport function normalizeMobileSwipeParam(\n param: ActionSwipeParam,\n screenSize: { width: number; height: number },\n): {\n startPoint: { x: number; y: number };\n endPoint: { x: number; y: number };\n duration: number;\n repeatCount: number;\n} {\n const { width, height } = screenSize;\n const { start, end } = param;\n\n const startPoint = start\n ? { x: start.center[0], y: start.center[1] }\n : { x: width / 2, y: height / 2 };\n\n let endPoint: { x: number; y: number };\n\n if (end) {\n endPoint = { x: end.center[0], y: end.center[1] };\n } else if (param.distance) {\n const direction = param.direction;\n if (!direction) {\n throw new Error('direction is required for swipe gesture');\n }\n endPoint = {\n x:\n startPoint.x +\n (direction === 'right'\n ? param.distance\n : direction === 'left'\n ? -param.distance\n : 0),\n y:\n startPoint.y +\n (direction === 'down'\n ? param.distance\n : direction === 'up'\n ? -param.distance\n : 0),\n };\n } else {\n throw new Error(\n 'Either end or distance must be specified for swipe gesture',\n );\n }\n\n endPoint.x = Math.max(0, Math.min(endPoint.x, width));\n endPoint.y = Math.max(0, Math.min(endPoint.y, height));\n\n const duration = param.duration ?? 300;\n\n let repeatCount = typeof param.repeat === 'number' ? param.repeat : 1;\n if (repeatCount === 0) {\n repeatCount = 10;\n }\n\n return { startPoint, endPoint, duration, repeatCount };\n}\n\nexport const defineActionSwipe = (config: {\n swipe: TouchInputPrimitives['swipe'];\n size(): Promise<Size>;\n}): DeviceAction<ActionSwipeParam> => {\n return defineAction<typeof ActionSwipeParamSchema, ActionSwipeParam>({\n name: 'Swipe',\n description:\n 'Perform a touch gesture for interactions beyond regular scrolling (e.g., adjust a continuous control such as a slider, flip pages in a carousel, dismiss a notification, swipe-to-delete a list item). For regular content scrolling, use Scroll instead. Use \"distance\" + \"direction\" for relative movement, or \"start\" + \"end\" for precise endpoint movement.',\n paramSchema: ActionSwipeParamSchema,\n sample: {\n start: { prompt: 'center of the notification' },\n end: { prompt: 'upper edge of the screen' },\n },\n call: async (param) => {\n const { startPoint, endPoint, duration, repeatCount } =\n normalizeMobileSwipeParam(param, await config.size());\n for (let i = 0; i < repeatCount; i++) {\n await config.swipe(startPoint, endPoint, { duration });\n }\n },\n });\n};\n\n// ClearInput\nexport const actionClearInputParamSchema = z.object({\n locate: getMidsceneLocationSchema()\n .describe('The input field to be cleared')\n .optional(),\n});\nexport type ActionClearInputParam = {\n locate?: LocateResultElement;\n};\n\nexport const defineActionClearInput = (\n clearInput: KeyboardInputPrimitives['clearInput'],\n): DeviceAction<ActionClearInputParam> => {\n return defineAction<\n typeof actionClearInputParamSchema,\n ActionClearInputParam\n >({\n name: 'ClearInput',\n description: inputLocateDescription,\n interfaceAlias: 'aiClearInput',\n paramSchema: actionClearInputParamSchema,\n sample: {\n locate: { prompt: 'the search input field' },\n },\n call: async (param) => {\n await clearInput(param.locate);\n },\n });\n};\n\n// CursorMove\nexport const actionCursorMoveParamSchema = z.object({\n direction: z\n .enum(['left', 'right'])\n .describe('The direction to move the cursor'),\n times: z\n .number()\n .int()\n .min(1)\n .default(1)\n .describe(\n 'The number of times to move the cursor in the specified direction',\n ),\n});\nexport type ActionCursorMoveParam = {\n direction: 'left' | 'right';\n times?: number;\n};\n\nexport const defineActionCursorMove = (config: {\n keyboard: Pick<KeyboardInputPrimitives, 'keyboardPress' | 'cursorMove'>;\n sleep?(timeMs: number): Promise<void>;\n}): DeviceAction<ActionCursorMoveParam> => {\n return defineAction<\n typeof actionCursorMoveParamSchema,\n ActionCursorMoveParam\n >({\n name: 'CursorMove',\n description:\n 'Move the text cursor (caret) left or right within an input field or text area. Use this to reposition the cursor without selecting text.',\n paramSchema: actionCursorMoveParamSchema,\n sample: {\n direction: 'left',\n times: 3,\n },\n call: async (param) => {\n const times = param.times ?? 1;\n if (config.keyboard.cursorMove) {\n await config.keyboard.cursorMove(param.direction, times);\n return;\n }\n\n const wait =\n config.sleep ??\n ((timeMs: number) =>\n new Promise<void>((resolve) => setTimeout(resolve, timeMs)));\n const arrowKey = param.direction === 'left' ? 'ArrowLeft' : 'ArrowRight';\n for (let i = 0; i < times; i++) {\n await config.keyboard.keyboardPress(arrowKey);\n await wait(100);\n }\n },\n });\n};\n\n// Pinch\nexport const ActionPinchParamSchema = z.object({\n locate: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'The element to pinch on. If not specified, the center of the screen will be used',\n ),\n direction: z\n .enum(['in', 'out'])\n .describe(\n 'Pinch direction. \"in\" = pinch fingers together (zoom out / shrink), \"out\" = spread fingers apart (zoom in / enlarge).',\n ),\n distance: z\n .number()\n .positive()\n .optional()\n .describe(\n 'How far each finger moves in pixels. Defaults to a quarter of the shorter screen dimension.',\n ),\n duration: z\n .number()\n .default(500)\n .optional()\n .describe('Duration of the pinch gesture in milliseconds'),\n});\n\nexport type ActionPinchParam = {\n locate?: LocateResultElement;\n direction: 'in' | 'out';\n distance?: number;\n duration?: number;\n};\n\nexport const defineActionPinch = (config: {\n pinch: TouchInputPrimitives['pinch'];\n size(): Promise<Size>;\n}): DeviceAction<ActionPinchParam> | undefined => {\n if (!config.pinch) {\n return undefined;\n }\n\n return defineAction<typeof ActionPinchParamSchema, ActionPinchParam>({\n name: 'Pinch',\n description:\n 'Perform a two-finger pinch gesture. Use direction \"in\" to pinch fingers together (zoom out), or \"out\" to spread fingers apart (zoom in). Optionally specify distance for how far each finger moves.',\n interfaceAlias: 'aiPinch',\n paramSchema: ActionPinchParamSchema,\n sample: {\n locate: { prompt: 'the map area' },\n direction: 'out',\n distance: 200,\n },\n call: async (param) => {\n const { centerX, centerY, startDistance, endDistance, duration } =\n normalizePinchParam(param, await config.size());\n await config.pinch?.(\n { x: centerX, y: centerY },\n { startDistance, endDistance, duration },\n );\n },\n });\n};\n\nexport function normalizePinchParam(\n param: ActionPinchParam,\n screenSize: { width: number; height: number },\n): {\n centerX: number;\n centerY: number;\n startDistance: number;\n endDistance: number;\n duration: number;\n} {\n const { width, height } = screenSize;\n const element = param.locate;\n const centerX = element\n ? Math.round(element.center[0])\n : Math.round(width / 2);\n const centerY = element\n ? Math.round(element.center[1])\n : Math.round(height / 2);\n const duration = param.duration ?? 500;\n\n const baseDistance = Math.round(Math.min(width, height) / 4);\n const fingerDistance = param.distance ?? baseDistance;\n\n const startDistance = baseDistance;\n const endDistance =\n param.direction === 'out'\n ? baseDistance + fingerDistance\n : Math.max(10, baseDistance - fingerDistance);\n\n return { centerX, centerY, startDistance, endDistance, duration };\n}\n\nexport interface MobileInputActionContext {\n input: MobileInputPrimitives;\n size(): Promise<Size>;\n sleep?(timeMs: number): Promise<void>;\n getDefaultAutoDismissKeyboard?(): boolean | undefined;\n systemActions?: SystemInputActionOptions;\n}\n\nexport interface SystemInputActionConfig {\n name: string;\n description: string;\n interfaceAlias?: string;\n delayBeforeRunner?: number;\n delayAfterRunner?: number;\n}\n\nexport interface SystemInputActionOptions {\n backButton?: SystemInputActionConfig;\n homeButton?: SystemInputActionConfig;\n recentAppsButton?: SystemInputActionConfig;\n}\n\nexport interface InputPrimitiveActionOptions {\n size?: () => Promise<Size>;\n sleep?: (timeMs: number) => Promise<void>;\n includeSwipe?: boolean;\n includePinch?: boolean;\n systemActions?: SystemInputActionOptions;\n}\n\nfunction defineSystemInputAction(\n config: SystemInputActionConfig,\n call: () => Promise<void>,\n): DeviceAction<undefined, void> {\n return defineAction<undefined, undefined, void>({\n name: config.name,\n description: config.description,\n interfaceAlias: config.interfaceAlias,\n delayBeforeRunner: config.delayBeforeRunner,\n delayAfterRunner: config.delayAfterRunner,\n call,\n });\n}\n\nexport function defineActionsFromInputPrimitives(\n input: InputPrimitives,\n options: InputPrimitiveActionOptions = {},\n): DeviceAction<any>[] {\n const actions: Array<DeviceAction<any> | undefined> = [];\n const { pointer, keyboard, scroll, touch, system } = input;\n\n if (pointer) {\n actions.push(defineActionTap(pointer.tap));\n if (pointer.doubleClick) {\n actions.push(defineActionDoubleClick(pointer.doubleClick));\n }\n if (pointer.rightClick) {\n actions.push(defineActionRightClick(pointer.rightClick));\n }\n if (pointer.hover) {\n actions.push(defineActionHover(pointer.hover));\n }\n if (pointer.dragAndDrop) {\n actions.push(defineActionDragAndDrop(pointer.dragAndDrop));\n }\n if (pointer.longPress) {\n actions.push(defineActionLongPress(pointer.longPress));\n }\n }\n\n if (keyboard) {\n actions.push(\n defineActionInput(keyboard),\n defineActionClearInput(keyboard.clearInput),\n defineActionKeyboardPress(keyboard.keyboardPress),\n defineActionCursorMove({ keyboard, sleep: options.sleep }),\n );\n }\n\n if (scroll) {\n actions.push(defineActionScroll(scroll.scroll));\n }\n\n if (touch?.swipe && options.size && options.includeSwipe !== false) {\n actions.push(defineActionSwipe({ swipe: touch.swipe, size: options.size }));\n }\n\n if (touch?.pinch && options.size && options.includePinch !== false) {\n actions.push(defineActionPinch({ pinch: touch.pinch, size: options.size }));\n }\n\n if (system && options.systemActions) {\n const { systemActions } = options;\n if (system.backButton && systemActions.backButton) {\n actions.push(\n defineSystemInputAction(systemActions.backButton, system.backButton),\n );\n }\n if (system.homeButton && systemActions.homeButton) {\n actions.push(\n defineSystemInputAction(systemActions.homeButton, system.homeButton),\n );\n }\n if (system.recentAppsButton && systemActions.recentAppsButton) {\n actions.push(\n defineSystemInputAction(\n systemActions.recentAppsButton,\n system.recentAppsButton,\n ),\n );\n }\n }\n\n return actions.filter((action): action is DeviceAction<any> =>\n Boolean(action),\n );\n}\n\nexport function createDefaultMobileActions(\n context: MobileInputActionContext,\n): DeviceAction<any>[] {\n return defineActionsFromInputPrimitives(context.input, {\n size: context.size,\n sleep: context.sleep,\n systemActions: context.systemActions,\n });\n}\n\n// Sleep\nexport const ActionSleepParamSchema = z.object({\n timeMs: z\n .number()\n .default(1000)\n .optional()\n .describe('Sleep duration in milliseconds, defaults to 1000ms (1 second)'),\n});\n\nexport type ActionSleepParam = {\n timeMs?: number;\n};\n\nexport const defineActionSleep = (): DeviceAction<ActionSleepParam> => {\n return defineAction<typeof ActionSleepParamSchema, ActionSleepParam>({\n name: 'Sleep',\n description:\n 'Wait for a specified duration before continuing. Defaults to 1 second (1000ms) if not specified.',\n paramSchema: ActionSleepParamSchema,\n sample: {\n timeMs: 2000,\n },\n call: async (param) => {\n const duration = param?.timeMs ?? 1000;\n getDebug('device:common-action')(`Sleeping for ${duration}ms`);\n await new Promise((resolve) => setTimeout(resolve, duration));\n },\n });\n};\n\nexport type { DeviceAction } from '../types';\nexport type {\n AndroidDeviceOpt,\n AndroidDeviceInputOpt,\n IOSDeviceOpt,\n IOSDeviceInputOpt,\n HarmonyDeviceOpt,\n HarmonyDeviceInputOpt,\n} from './device-options';\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","AbstractInterface","defineAction","config","pointFromLocate","locate","missingMessage","Error","defineLocatedPointAction","param","actionTapParamSchema","z","getMidsceneLocationSchema","defineActionTap","tap","point","actionRightClickParamSchema","defineActionRightClick","rightClick","actionDoubleClickParamSchema","defineActionDoubleClick","doubleClick","actionHoverParamSchema","defineActionHover","hover","inputLocateDescription","actionInputParamSchema","val","String","defineActionInput","keyboard","actionKeyboardPressParamSchema","defineActionKeyboardPress","keyboardPress","actionScrollParamSchema","defineActionScroll","scroll","actionDragAndDropParamSchema","defineActionDragAndDrop","dragAndDrop","from","to","ActionLongPressParamSchema","defineActionLongPress","longPress","ActionSwipeParamSchema","normalizeMobileSwipeParam","screenSize","width","height","start","end","startPoint","endPoint","direction","Math","duration","repeatCount","defineActionSwipe","i","actionClearInputParamSchema","defineActionClearInput","clearInput","actionCursorMoveParamSchema","defineActionCursorMove","times","wait","timeMs","Promise","resolve","setTimeout","arrowKey","ActionPinchParamSchema","defineActionPinch","centerX","centerY","startDistance","endDistance","normalizePinchParam","element","baseDistance","fingerDistance","defineSystemInputAction","call","defineActionsFromInputPrimitives","input","options","actions","pointer","touch","system","systemActions","action","Boolean","createDefaultMobileActions","context","ActionSleepParamSchema","defineActionSleep","getDebug"],"mappings":"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"}
1
+ {"version":3,"file":"device/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/device/index.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import type { ModelRuntime } from '@/ai-model/models';\nimport { getMidsceneLocationSchema } from '@/common';\nimport type {\n ActionScrollParam,\n DeviceAction,\n ExecutorContext,\n LocateResultElement,\n} from '@/types';\nimport type { ElementNode } from '@midscene/shared/extractor';\nimport { getDebug } from '@midscene/shared/logger';\nimport { _keyDefinitions } from '@midscene/shared/us-keyboard-layout';\nimport { z } from 'zod';\nimport type { ElementCacheFeature, Rect, Size, UIContext } from '../types';\n\nexport interface FileChooserHandler {\n accept(files: string[]): Promise<void>;\n}\n\nexport interface FileChooserRegistration {\n dispose: () => void;\n getError: () => Error | undefined | Promise<Error | undefined>;\n}\n\nexport interface MjpegStreamFrame {\n /** Raw base64-encoded image bytes WITHOUT a `data:image/...;base64,` prefix. */\n data: string;\n contentType?: string;\n}\n\nexport interface MjpegStreamHandle {\n stop(): void | Promise<void>;\n}\n\nexport interface MjpegStreamOptions {\n signal?: AbortSignal;\n onFrame(frame: MjpegStreamFrame): void;\n onError?(error: unknown): void;\n}\n\n/** A point in device-pixel coordinates on the screen. */\nexport interface PointerPoint {\n x: number;\n y: number;\n}\n\nexport interface PointerInputPrimitives {\n tap(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n doubleClick?(p: PointerPoint): Promise<void>;\n rightClick?(p: PointerPoint): Promise<void>;\n hover?(p: PointerPoint): Promise<void>;\n longPress?(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n dragAndDrop?(from: PointerPoint, to: PointerPoint): Promise<void>;\n}\n\nexport interface TouchInputPrimitives {\n swipe(\n start: PointerPoint,\n end: PointerPoint,\n opts?: { duration?: number; repeat?: number },\n ): Promise<void>;\n pinch?(\n center: PointerPoint,\n opts: { startDistance: number; endDistance: number; duration: number },\n ): Promise<void>;\n}\n\nexport interface KeyboardInputPrimitives {\n keyboardPress(keyName: string, opts?: { target?: unknown }): Promise<void>;\n cursorMove?(direction: 'left' | 'right', times?: number): Promise<void>;\n typeText(\n value: string,\n opts?: {\n autoDismissKeyboard?: boolean;\n keyboardDismissStrategy?: 'esc-first' | 'back-first';\n target?: unknown;\n replace?: boolean;\n focusOnly?: boolean;\n },\n ): Promise<void>;\n clearInput(target?: unknown): Promise<void>;\n}\n\nexport interface ScrollInputPrimitives {\n scroll(param: ActionScrollParam): Promise<void>;\n}\n\nexport interface SystemInputPrimitives {\n backButton?(): Promise<void>;\n homeButton?(): Promise<void>;\n recentAppsButton?(): Promise<void>;\n}\n\nexport interface InputPrimitives {\n pointer?: PointerInputPrimitives;\n keyboard?: KeyboardInputPrimitives;\n touch?: TouchInputPrimitives;\n scroll?: ScrollInputPrimitives;\n system?: SystemInputPrimitives;\n}\n\nexport interface MobileInputPrimitives extends InputPrimitives {\n pointer: PointerInputPrimitives & {\n doubleClick(p: PointerPoint): Promise<void>;\n longPress(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n dragAndDrop(from: PointerPoint, to: PointerPoint): Promise<void>;\n };\n keyboard: KeyboardInputPrimitives;\n touch: TouchInputPrimitives;\n}\n\nexport interface BrowserInputPrimitives extends InputPrimitives {\n pointer: PointerInputPrimitives & {\n doubleClick(p: PointerPoint): Promise<void>;\n rightClick(p: PointerPoint): Promise<void>;\n hover(p: PointerPoint): Promise<void>;\n dragAndDrop(from: PointerPoint, to: PointerPoint): Promise<void>;\n longPress(p: PointerPoint, opts?: { duration?: number }): Promise<void>;\n };\n keyboard: KeyboardInputPrimitives;\n scroll: ScrollInputPrimitives;\n touch: TouchInputPrimitives;\n}\n\nexport interface ComputerInputPrimitives extends InputPrimitives {\n pointer: PointerInputPrimitives & {\n doubleClick(p: PointerPoint): Promise<void>;\n rightClick(p: PointerPoint): Promise<void>;\n hover(p: PointerPoint): Promise<void>;\n dragAndDrop(from: PointerPoint, to: PointerPoint): Promise<void>;\n };\n keyboard: KeyboardInputPrimitives;\n scroll: ScrollInputPrimitives;\n}\n\nexport abstract class AbstractInterface {\n abstract interfaceType: string;\n\n abstract screenshotBase64(): Promise<string>;\n abstract size(): Promise<Size>;\n abstract actionSpace(): DeviceAction[];\n\n abstract cacheFeatureForPoint?(\n center: [number, number],\n options?: {\n targetDescription?: string;\n modelRuntime?: ModelRuntime;\n },\n ): Promise<ElementCacheFeature>;\n abstract rectMatchesCacheFeature?(\n feature: ElementCacheFeature,\n ): Promise<Rect>;\n\n abstract destroy?(): Promise<void>;\n\n abstract describe?(): string;\n abstract beforeInvokeAction?(actionName: string, param: any): Promise<void>;\n abstract afterInvokeAction?(actionName: string, param: any): Promise<void>;\n\n // for web only\n registerFileChooserListener?(\n handler: (chooser: FileChooserHandler) => Promise<void>,\n ): Promise<FileChooserRegistration>;\n\n // @deprecated do NOT extend this method\n abstract getElementsNodeTree?: () => Promise<ElementNode>;\n\n // @deprecated do NOT extend this method\n abstract url?: () => string | Promise<string>;\n\n // @deprecated do NOT extend this method\n abstract evaluateJavaScript?<T = any>(script: string): Promise<T>;\n\n /**\n * Get the current device-local time as a formatted string.\n * Prefer this for user-visible time because timestamps alone do not preserve\n * the target device's timezone when formatted on the host machine.\n */\n getDeviceLocalTimeString?(format?: string): Promise<string>;\n\n /** URL of native MJPEG stream for real-time screen preview (e.g. WDA MJPEG server) */\n mjpegStreamUrl?: string;\n\n /**\n * Optional in-process MJPEG frame producer. Implementations can push raw\n * base64 frames here when there is no standalone native MJPEG URL, e.g.\n * Chromium CDP Page.startScreencast for web previews.\n */\n startMjpegStream?(\n options: MjpegStreamOptions,\n ): MjpegStreamHandle | undefined | Promise<MjpegStreamHandle | undefined>;\n\n /**\n * Optional hook used after keyboard-only actions to force a fresh frame on\n * the active MJPEG stream. Implementations should be a no-op when no stream\n * is active.\n */\n flushPendingVisualUpdate?(): Promise<void>;\n\n /**\n * Optional non-blocking variant of `flushPendingVisualUpdate`. Keyboard-\n * heavy preview interactions can schedule a coalesced refresh here without\n * stalling the input hot path.\n */\n schedulePendingVisualUpdate?(): void;\n\n /**\n * Optional navigation state probe for browser-like interfaces, used to drive\n * loading indicators in playground UIs. Returning `undefined` means the\n * interface does not expose this concept.\n */\n navigationState?(): Promise<{ isLoading: boolean }>;\n\n /**\n * Low-level device input surface. Platform implementations expose transport\n * primitives here; higher-level AI actions and manual pointer dispatch should\n * adapt to this instead of duplicating platform gesture logic.\n */\n inputPrimitives?: InputPrimitives;\n}\n\n// Generic function to define actions with proper type inference\n// TRuntime allows specifying a different type for the runtime parameter (after location resolution)\n// TReturn allows specifying the return type of the action\nexport const defineAction = <\n TSchema extends z.ZodType | undefined = undefined,\n TRuntime = TSchema extends z.ZodType ? z.infer<TSchema> : undefined,\n TReturn = any,\n>(\n config: {\n name: string;\n description: string;\n interfaceAlias?: string;\n paramSchema?: TSchema;\n call: (\n param: TRuntime,\n context?: ExecutorContext,\n ) => Promise<TReturn> | TReturn;\n } & Partial<\n Omit<\n DeviceAction<TRuntime, TReturn>,\n 'name' | 'description' | 'interfaceAlias' | 'paramSchema' | 'call'\n >\n >,\n): DeviceAction<TRuntime, TReturn> => {\n return config as any; // Type assertion needed because schema validation type differs from runtime type\n};\n\nfunction pointFromLocate(\n locate: LocateResultElement | undefined,\n missingMessage: string,\n): PointerPoint {\n if (!locate) {\n throw new Error(missingMessage);\n }\n return { x: locate.center[0], y: locate.center[1] };\n}\n\nfunction defineLocatedPointAction<\n TSchema extends z.ZodType,\n TParam extends { locate: LocateResultElement },\n>(config: {\n name: string;\n description: string;\n interfaceAlias?: string;\n paramSchema: TSchema;\n sample: DeviceAction<TParam>['sample'];\n missingLocateMessage: string;\n call: (point: PointerPoint, param: TParam) => Promise<void>;\n}): DeviceAction<TParam> {\n return defineAction<TSchema, TParam>({\n name: config.name,\n description: config.description,\n interfaceAlias: config.interfaceAlias,\n paramSchema: config.paramSchema,\n sample: config.sample,\n call: async (param) => {\n await config.call(\n pointFromLocate(param.locate, config.missingLocateMessage),\n param,\n );\n },\n });\n}\n\n// Tap\nexport const actionTapParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe('The element to be tapped'),\n});\nexport type ActionTapParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionTap = (\n tap: PointerInputPrimitives['tap'],\n): DeviceAction<ActionTapParam> => {\n return defineLocatedPointAction<typeof actionTapParamSchema, ActionTapParam>({\n name: 'Tap',\n description: 'Tap the element',\n interfaceAlias: 'aiTap',\n paramSchema: actionTapParamSchema,\n sample: {\n locate: { prompt: 'the \"Submit\" button' },\n },\n missingLocateMessage: 'Element not found, cannot tap',\n call: async (point) => {\n await tap(point);\n },\n });\n};\n\n// RightClick\nexport const actionRightClickParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be right clicked',\n ),\n});\nexport type ActionRightClickParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionRightClick = (\n rightClick: NonNullable<PointerInputPrimitives['rightClick']>,\n): DeviceAction<ActionRightClickParam> => {\n return defineLocatedPointAction<\n typeof actionRightClickParamSchema,\n ActionRightClickParam\n >({\n name: 'RightClick',\n description: 'Right click the element',\n interfaceAlias: 'aiRightClick',\n paramSchema: actionRightClickParamSchema,\n sample: {\n locate: { prompt: 'the file icon on the desktop' },\n },\n missingLocateMessage: 'Element not found, cannot right click',\n call: async (point) => {\n await rightClick(point);\n },\n });\n};\n\n// DoubleClick\nexport const actionDoubleClickParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be double clicked',\n ),\n});\nexport type ActionDoubleClickParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionDoubleClick = (\n doubleClick: NonNullable<PointerInputPrimitives['doubleClick']>,\n): DeviceAction<ActionDoubleClickParam> => {\n return defineLocatedPointAction<\n typeof actionDoubleClickParamSchema,\n ActionDoubleClickParam\n >({\n name: 'DoubleClick',\n description: 'Double click the element',\n interfaceAlias: 'aiDoubleClick',\n paramSchema: actionDoubleClickParamSchema,\n sample: {\n locate: { prompt: 'the folder icon' },\n },\n missingLocateMessage: 'Element not found, cannot double click',\n call: async (point) => {\n await doubleClick(point);\n },\n });\n};\n\n// Hover\nexport const actionHoverParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe('The element to be hovered'),\n});\nexport type ActionHoverParam = {\n locate: LocateResultElement;\n};\n\nexport const defineActionHover = (\n hover: NonNullable<PointerInputPrimitives['hover']>,\n): DeviceAction<ActionHoverParam> => {\n return defineLocatedPointAction<\n typeof actionHoverParamSchema,\n ActionHoverParam\n >({\n name: 'Hover',\n description: 'Move the mouse to the element',\n interfaceAlias: 'aiHover',\n paramSchema: actionHoverParamSchema,\n sample: {\n locate: { prompt: 'the navigation menu item \"Products\"' },\n },\n missingLocateMessage: 'Element not found, cannot hover',\n call: async (point) => {\n await hover(point);\n },\n });\n};\n\n// Input\nconst inputLocateDescription =\n 'the position of the placeholder or text content in the target input field. If there is no content, locate the center of the input field.';\nexport const actionInputParamSchema = z.object({\n value: z\n .union([z.string(), z.number()])\n .transform((val) => String(val))\n .describe(\n 'The text to input. Provide the final content for replace mode, only the inserted characters for typeOnly mode, or an empty string when using clear mode to remove existing text.',\n ),\n locate: getMidsceneLocationSchema()\n .describe(inputLocateDescription)\n .optional(),\n mode: z\n .enum(['replace', 'clear', 'typeOnly'])\n .default('replace')\n .describe(\n 'Input mode: \"replace\" (default) - clear the field and input the value; \"typeOnly\" - type the value directly without clearing the field first, and should be set explicitly for incremental edits after moving the cursor; \"clear\" - clear the field without inputting new text.',\n ),\n autoDismissKeyboard: z\n .boolean()\n .optional()\n .describe(\n 'If true, the keyboard will be dismissed after the input is completed. Do not set it unless the user asks you to do so.',\n ),\n});\nexport type ActionInputParam = {\n value: string;\n locate?: LocateResultElement;\n mode?: 'replace' | 'clear' | 'typeOnly' | 'append';\n autoDismissKeyboard?: boolean;\n};\n\nexport const defineActionInput = (\n keyboard: KeyboardInputPrimitives,\n): DeviceAction<ActionInputParam> => {\n return defineAction<typeof actionInputParamSchema, ActionInputParam>({\n name: 'Input',\n description: 'Input the value into the element',\n interfaceAlias: 'aiInput',\n paramSchema: actionInputParamSchema,\n sample: {\n value: 'test@example.com',\n locate: { prompt: 'the email input field' },\n },\n call: async (param) => {\n // backward compat: convert deprecated 'append' to 'typeOnly'\n if ((param.mode as string) === 'append') {\n param.mode = 'typeOnly';\n }\n\n if (param.mode === 'clear') {\n await keyboard.clearInput(param.locate);\n return;\n }\n\n if (!param || !param.value) {\n return;\n }\n\n await keyboard.typeText(param.value, {\n target: param.locate,\n replace: param.mode !== 'typeOnly',\n autoDismissKeyboard: param.autoDismissKeyboard,\n });\n },\n });\n};\n\n// KeyboardPress\nexport const actionKeyboardPressParamSchema = z.object({\n locate: getMidsceneLocationSchema()\n .describe('The element to be clicked before pressing the key')\n .optional(),\n keyName: z\n .string()\n .describe(\n \"The key to be pressed. Use '+' for key combinations, e.g., 'Control+A', 'Shift+Enter'\",\n ),\n});\nexport type ActionKeyboardPressParam = {\n locate?: LocateResultElement;\n keyName: string;\n};\n\nexport const defineActionKeyboardPress = (\n keyboardPress: KeyboardInputPrimitives['keyboardPress'],\n): DeviceAction<ActionKeyboardPressParam> => {\n return defineAction<\n typeof actionKeyboardPressParamSchema,\n ActionKeyboardPressParam\n >({\n name: 'KeyboardPress',\n description:\n 'Press a key or key combination, like \"Enter\", \"Tab\", \"Escape\", or \"Control+A\", \"Shift+Enter\". Do not use this to type text.',\n interfaceAlias: 'aiKeyboardPress',\n paramSchema: actionKeyboardPressParamSchema,\n sample: {\n keyName: 'Enter',\n },\n call: async (param) => {\n await keyboardPress(param.keyName, {\n target: param.locate,\n });\n },\n });\n};\n\n// Scroll\nexport const actionScrollParamSchema = z.object({\n scrollType: z\n .enum([\n 'singleAction',\n 'scrollToBottom',\n 'scrollToTop',\n 'scrollToRight',\n 'scrollToLeft',\n ])\n .default('singleAction')\n .describe(\n 'The scroll behavior: \"singleAction\" for a single scroll action, \"scrollToBottom\" for scrolling all the way to the bottom by rapidly scrolling 5-10 times (skipping intermediate content until reaching the bottom), \"scrollToTop\" for scrolling all the way to the top by rapidly scrolling 5-10 times (skipping intermediate content until reaching the top), \"scrollToRight\" for scrolling all the way to the right by rapidly scrolling multiple times, \"scrollToLeft\" for scrolling all the way to the left by rapidly scrolling multiple times',\n ),\n direction: z\n .enum(['down', 'up', 'right', 'left'])\n .default('down')\n .describe(\n 'The direction to scroll. Only effective when scrollType is \"singleAction\".',\n ),\n distance: z\n .number()\n .nullable()\n .optional()\n .describe('The distance in pixels to scroll'),\n locate: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'Describe the target element to be scrolled on, like \"the table\" or \"the list\" or \"the content area\" or \"the scrollable area\". Do NOT provide a general intent like \"scroll to find some element\"',\n ),\n});\n\nexport const defineActionScroll = (\n scroll: ScrollInputPrimitives['scroll'],\n): DeviceAction<ActionScrollParam> => {\n return defineAction<typeof actionScrollParamSchema, ActionScrollParam>({\n name: 'Scroll',\n description:\n 'Scroll the page or a scrollable element to browse content. This is the preferred way to scroll on all platforms, including mobile. Supports scrollToBottom/scrollToTop for boundary navigation. Default: direction `down`, scrollType `singleAction`, distance `null`.',\n interfaceAlias: 'aiScroll',\n paramSchema: actionScrollParamSchema,\n sample: {\n direction: 'down',\n scrollType: 'singleAction',\n locate: { prompt: 'the center of the product list area' },\n },\n call: async (param) => {\n await scroll(param);\n },\n });\n};\n\n// DragAndDrop\nexport const actionDragAndDropParamSchema = z.object({\n from: getMidsceneLocationSchema().describe('The position to be dragged'),\n to: getMidsceneLocationSchema().describe('The position to be dropped'),\n});\nexport type ActionDragAndDropParam = {\n from: LocateResultElement;\n to: LocateResultElement;\n};\n\nexport const defineActionDragAndDrop = (\n dragAndDrop: NonNullable<PointerInputPrimitives['dragAndDrop']>,\n): DeviceAction<ActionDragAndDropParam> => {\n return defineAction<\n typeof actionDragAndDropParamSchema,\n ActionDragAndDropParam\n >({\n name: 'DragAndDrop',\n description:\n 'Pick up a specific UI element and move it to a new position (e.g., reorder a card, move a file into a folder, sort list items). The element itself moves with your finger/mouse.',\n interfaceAlias: 'aiDragAndDrop',\n paramSchema: actionDragAndDropParamSchema,\n sample: {\n from: { prompt: 'the \"report.pdf\" file icon' },\n to: { prompt: 'the upload drop zone' },\n },\n call: async (param) => {\n const from = param.from;\n const to = param.to;\n if (!from) {\n throw new Error('missing \"from\" param for drag and drop');\n }\n if (!to) {\n throw new Error('missing \"to\" param for drag and drop');\n }\n await dragAndDrop(\n { x: from.center[0], y: from.center[1] },\n { x: to.center[0], y: to.center[1] },\n );\n },\n });\n};\n\nexport const ActionLongPressParamSchema = z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be long pressed',\n ),\n duration: z\n .number()\n .optional()\n .describe('Long press duration in milliseconds'),\n});\n\nexport type ActionLongPressParam = {\n locate: LocateResultElement;\n duration?: number;\n};\nexport const defineActionLongPress = (\n longPress: NonNullable<PointerInputPrimitives['longPress']>,\n): DeviceAction<ActionLongPressParam> => {\n return defineLocatedPointAction<\n typeof ActionLongPressParamSchema,\n ActionLongPressParam\n >({\n name: 'LongPress',\n description: 'Long press the element',\n interfaceAlias: 'aiLongPress',\n paramSchema: ActionLongPressParamSchema,\n sample: {\n locate: { prompt: 'the message bubble' },\n },\n missingLocateMessage: 'LongPress requires an element to be located',\n call: async (point, param) => {\n await longPress(point, { duration: param.duration });\n },\n });\n};\n\nexport const ActionSwipeParamSchema = z.object({\n start: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'Starting point of the swipe gesture, if not specified, the center of the page will be used',\n ),\n direction: z\n .enum(['up', 'down', 'left', 'right'])\n .optional()\n .describe(\n 'The direction to swipe (required when using distance). The direction means the direction of the finger swipe.',\n ),\n distance: z\n .number()\n .optional()\n .describe('The distance in pixels to swipe (mutually exclusive with end)'),\n end: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'Ending point of the swipe gesture (mutually exclusive with distance)',\n ),\n duration: z\n .number()\n .default(300)\n .describe('Duration of the swipe gesture in milliseconds'),\n repeat: z\n .number()\n .optional()\n .describe(\n 'The number of times to repeat the swipe gesture. 1 for default, 0 for infinite (e.g. endless swipe until the end of the page)',\n ),\n});\n\nexport type ActionSwipeParam = {\n start?: LocateResultElement;\n direction?: 'up' | 'down' | 'left' | 'right';\n distance?: number;\n end?: LocateResultElement;\n duration?: number;\n repeat?: number;\n};\n\nexport function normalizeMobileSwipeParam(\n param: ActionSwipeParam,\n screenSize: { width: number; height: number },\n): {\n startPoint: { x: number; y: number };\n endPoint: { x: number; y: number };\n duration: number;\n repeatCount: number;\n} {\n const { width, height } = screenSize;\n const { start, end } = param;\n\n const startPoint = start\n ? { x: start.center[0], y: start.center[1] }\n : { x: width / 2, y: height / 2 };\n\n let endPoint: { x: number; y: number };\n\n if (end) {\n endPoint = { x: end.center[0], y: end.center[1] };\n } else if (param.distance) {\n const direction = param.direction;\n if (!direction) {\n throw new Error('direction is required for swipe gesture');\n }\n endPoint = {\n x:\n startPoint.x +\n (direction === 'right'\n ? param.distance\n : direction === 'left'\n ? -param.distance\n : 0),\n y:\n startPoint.y +\n (direction === 'down'\n ? param.distance\n : direction === 'up'\n ? -param.distance\n : 0),\n };\n } else {\n throw new Error(\n 'Either end or distance must be specified for swipe gesture',\n );\n }\n\n endPoint.x = Math.max(0, Math.min(endPoint.x, width));\n endPoint.y = Math.max(0, Math.min(endPoint.y, height));\n\n const duration = param.duration ?? 300;\n\n let repeatCount = typeof param.repeat === 'number' ? param.repeat : 1;\n if (repeatCount === 0) {\n repeatCount = 10;\n }\n\n return { startPoint, endPoint, duration, repeatCount };\n}\n\nexport const defineActionSwipe = (config: {\n swipe: TouchInputPrimitives['swipe'];\n size(): Promise<Size>;\n}): DeviceAction<ActionSwipeParam> => {\n return defineAction<typeof ActionSwipeParamSchema, ActionSwipeParam>({\n name: 'Swipe',\n description:\n 'Perform a touch gesture for interactions beyond regular scrolling (e.g., adjust a continuous control such as a slider, flip pages in a carousel, dismiss a notification, swipe-to-delete a list item). For regular content scrolling, use Scroll instead. Use \"distance\" + \"direction\" for relative movement, or \"start\" + \"end\" for precise endpoint movement.',\n paramSchema: ActionSwipeParamSchema,\n sample: {\n start: { prompt: 'center of the notification' },\n end: { prompt: 'upper edge of the screen' },\n },\n call: async (param) => {\n const { startPoint, endPoint, duration, repeatCount } =\n normalizeMobileSwipeParam(param, await config.size());\n for (let i = 0; i < repeatCount; i++) {\n await config.swipe(startPoint, endPoint, { duration });\n }\n },\n });\n};\n\n// ClearInput\nexport const actionClearInputParamSchema = z.object({\n locate: getMidsceneLocationSchema()\n .describe('The input field to be cleared')\n .optional(),\n});\nexport type ActionClearInputParam = {\n locate?: LocateResultElement;\n};\n\nexport const defineActionClearInput = (\n clearInput: KeyboardInputPrimitives['clearInput'],\n): DeviceAction<ActionClearInputParam> => {\n return defineAction<\n typeof actionClearInputParamSchema,\n ActionClearInputParam\n >({\n name: 'ClearInput',\n description: inputLocateDescription,\n interfaceAlias: 'aiClearInput',\n paramSchema: actionClearInputParamSchema,\n sample: {\n locate: { prompt: 'the search input field' },\n },\n call: async (param) => {\n await clearInput(param.locate);\n },\n });\n};\n\n// CursorMove\nexport const actionCursorMoveParamSchema = z.object({\n direction: z\n .enum(['left', 'right'])\n .describe('The direction to move the cursor'),\n times: z\n .number()\n .int()\n .min(1)\n .default(1)\n .describe(\n 'The number of times to move the cursor in the specified direction',\n ),\n});\nexport type ActionCursorMoveParam = {\n direction: 'left' | 'right';\n times?: number;\n};\n\nexport const defineActionCursorMove = (config: {\n keyboard: Pick<KeyboardInputPrimitives, 'keyboardPress' | 'cursorMove'>;\n sleep?(timeMs: number): Promise<void>;\n}): DeviceAction<ActionCursorMoveParam> => {\n return defineAction<\n typeof actionCursorMoveParamSchema,\n ActionCursorMoveParam\n >({\n name: 'CursorMove',\n description:\n 'Move the text cursor (caret) left or right within an input field or text area. Use this to reposition the cursor without selecting text.',\n paramSchema: actionCursorMoveParamSchema,\n sample: {\n direction: 'left',\n times: 3,\n },\n call: async (param) => {\n const times = param.times ?? 1;\n if (config.keyboard.cursorMove) {\n await config.keyboard.cursorMove(param.direction, times);\n return;\n }\n\n const wait =\n config.sleep ??\n ((timeMs: number) =>\n new Promise<void>((resolve) => setTimeout(resolve, timeMs)));\n const arrowKey = param.direction === 'left' ? 'ArrowLeft' : 'ArrowRight';\n for (let i = 0; i < times; i++) {\n await config.keyboard.keyboardPress(arrowKey);\n await wait(100);\n }\n },\n });\n};\n\n// Pinch\nexport const ActionPinchParamSchema = z.object({\n locate: getMidsceneLocationSchema()\n .optional()\n .describe(\n 'The element to pinch on. If not specified, the center of the screen will be used',\n ),\n direction: z\n .enum(['in', 'out'])\n .describe(\n 'Pinch direction. \"in\" = pinch fingers together (zoom out / shrink), \"out\" = spread fingers apart (zoom in / enlarge).',\n ),\n distance: z\n .number()\n .positive()\n .optional()\n .describe(\n 'How far each finger moves in pixels. Defaults to a quarter of the shorter screen dimension.',\n ),\n duration: z\n .number()\n .default(500)\n .optional()\n .describe('Duration of the pinch gesture in milliseconds'),\n});\n\nexport type ActionPinchParam = {\n locate?: LocateResultElement;\n direction: 'in' | 'out';\n distance?: number;\n duration?: number;\n};\n\nexport const defineActionPinch = (config: {\n pinch: TouchInputPrimitives['pinch'];\n size(): Promise<Size>;\n}): DeviceAction<ActionPinchParam> | undefined => {\n if (!config.pinch) {\n return undefined;\n }\n\n return defineAction<typeof ActionPinchParamSchema, ActionPinchParam>({\n name: 'Pinch',\n description:\n 'Perform a two-finger pinch gesture. Use direction \"in\" to pinch fingers together (zoom out), or \"out\" to spread fingers apart (zoom in). Optionally specify distance for how far each finger moves.',\n interfaceAlias: 'aiPinch',\n paramSchema: ActionPinchParamSchema,\n sample: {\n locate: { prompt: 'the map area' },\n direction: 'out',\n distance: 200,\n },\n call: async (param) => {\n const { centerX, centerY, startDistance, endDistance, duration } =\n normalizePinchParam(param, await config.size());\n await config.pinch?.(\n { x: centerX, y: centerY },\n { startDistance, endDistance, duration },\n );\n },\n });\n};\n\nexport function normalizePinchParam(\n param: ActionPinchParam,\n screenSize: { width: number; height: number },\n): {\n centerX: number;\n centerY: number;\n startDistance: number;\n endDistance: number;\n duration: number;\n} {\n const { width, height } = screenSize;\n const element = param.locate;\n const centerX = element\n ? Math.round(element.center[0])\n : Math.round(width / 2);\n const centerY = element\n ? Math.round(element.center[1])\n : Math.round(height / 2);\n const duration = param.duration ?? 500;\n\n const baseDistance = Math.round(Math.min(width, height) / 4);\n const fingerDistance = param.distance ?? baseDistance;\n\n const startDistance = baseDistance;\n const endDistance =\n param.direction === 'out'\n ? baseDistance + fingerDistance\n : Math.max(10, baseDistance - fingerDistance);\n\n return { centerX, centerY, startDistance, endDistance, duration };\n}\n\nexport interface MobileInputActionContext {\n input: MobileInputPrimitives;\n size(): Promise<Size>;\n sleep?(timeMs: number): Promise<void>;\n getDefaultAutoDismissKeyboard?(): boolean | undefined;\n systemActions?: SystemInputActionOptions;\n}\n\nexport interface SystemInputActionConfig {\n name: string;\n description: string;\n interfaceAlias?: string;\n delayBeforeRunner?: number;\n delayAfterRunner?: number;\n}\n\nexport interface SystemInputActionOptions {\n backButton?: SystemInputActionConfig;\n homeButton?: SystemInputActionConfig;\n recentAppsButton?: SystemInputActionConfig;\n}\n\nexport interface InputPrimitiveActionOptions {\n size?: () => Promise<Size>;\n sleep?: (timeMs: number) => Promise<void>;\n includeSwipe?: boolean;\n includePinch?: boolean;\n systemActions?: SystemInputActionOptions;\n}\n\nfunction defineSystemInputAction(\n config: SystemInputActionConfig,\n call: () => Promise<void>,\n): DeviceAction<undefined, void> {\n return defineAction<undefined, undefined, void>({\n name: config.name,\n description: config.description,\n interfaceAlias: config.interfaceAlias,\n delayBeforeRunner: config.delayBeforeRunner,\n delayAfterRunner: config.delayAfterRunner,\n call,\n });\n}\n\nexport function defineActionsFromInputPrimitives(\n input: InputPrimitives,\n options: InputPrimitiveActionOptions = {},\n): DeviceAction<any>[] {\n const actions: Array<DeviceAction<any> | undefined> = [];\n const { pointer, keyboard, scroll, touch, system } = input;\n\n if (pointer) {\n actions.push(defineActionTap(pointer.tap));\n if (pointer.doubleClick) {\n actions.push(defineActionDoubleClick(pointer.doubleClick));\n }\n if (pointer.rightClick) {\n actions.push(defineActionRightClick(pointer.rightClick));\n }\n if (pointer.hover) {\n actions.push(defineActionHover(pointer.hover));\n }\n if (pointer.dragAndDrop) {\n actions.push(defineActionDragAndDrop(pointer.dragAndDrop));\n }\n if (pointer.longPress) {\n actions.push(defineActionLongPress(pointer.longPress));\n }\n }\n\n if (keyboard) {\n actions.push(\n defineActionInput(keyboard),\n defineActionClearInput(keyboard.clearInput),\n defineActionKeyboardPress(keyboard.keyboardPress),\n defineActionCursorMove({ keyboard, sleep: options.sleep }),\n );\n }\n\n if (scroll) {\n actions.push(defineActionScroll(scroll.scroll));\n }\n\n if (touch?.swipe && options.size && options.includeSwipe !== false) {\n actions.push(defineActionSwipe({ swipe: touch.swipe, size: options.size }));\n }\n\n if (touch?.pinch && options.size && options.includePinch !== false) {\n actions.push(defineActionPinch({ pinch: touch.pinch, size: options.size }));\n }\n\n if (system && options.systemActions) {\n const { systemActions } = options;\n if (system.backButton && systemActions.backButton) {\n actions.push(\n defineSystemInputAction(systemActions.backButton, system.backButton),\n );\n }\n if (system.homeButton && systemActions.homeButton) {\n actions.push(\n defineSystemInputAction(systemActions.homeButton, system.homeButton),\n );\n }\n if (system.recentAppsButton && systemActions.recentAppsButton) {\n actions.push(\n defineSystemInputAction(\n systemActions.recentAppsButton,\n system.recentAppsButton,\n ),\n );\n }\n }\n\n return actions.filter((action): action is DeviceAction<any> =>\n Boolean(action),\n );\n}\n\nexport function createDefaultMobileActions(\n context: MobileInputActionContext,\n): DeviceAction<any>[] {\n return defineActionsFromInputPrimitives(context.input, {\n size: context.size,\n sleep: context.sleep,\n systemActions: context.systemActions,\n });\n}\n\n// Sleep\nexport const ActionSleepParamSchema = z.object({\n timeMs: z\n .number()\n .default(1000)\n .optional()\n .describe('Sleep duration in milliseconds, defaults to 1000ms (1 second)'),\n});\n\nexport type ActionSleepParam = {\n timeMs?: number;\n};\n\nexport const defineActionSleep = (): DeviceAction<ActionSleepParam> => {\n return defineAction<typeof ActionSleepParamSchema, ActionSleepParam>({\n name: 'Sleep',\n description:\n 'Wait for a specified duration before continuing. Defaults to 1 second (1000ms) if not specified.',\n paramSchema: ActionSleepParamSchema,\n sample: {\n timeMs: 2000,\n },\n call: async (param) => {\n const duration = param?.timeMs ?? 1000;\n getDebug('device:common-action')(`Sleeping for ${duration}ms`);\n await new Promise((resolve) => setTimeout(resolve, duration));\n },\n });\n};\n\nexport type { DeviceAction } from '../types';\nexport type {\n AndroidDeviceOpt,\n AndroidDeviceInputOpt,\n IOSDeviceOpt,\n IOSDeviceInputOpt,\n HarmonyDeviceOpt,\n HarmonyDeviceInputOpt,\n} from './device-options';\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","AbstractInterface","defineAction","config","pointFromLocate","locate","missingMessage","Error","defineLocatedPointAction","param","actionTapParamSchema","z","getMidsceneLocationSchema","defineActionTap","tap","point","actionRightClickParamSchema","defineActionRightClick","rightClick","actionDoubleClickParamSchema","defineActionDoubleClick","doubleClick","actionHoverParamSchema","defineActionHover","hover","inputLocateDescription","actionInputParamSchema","val","String","defineActionInput","keyboard","actionKeyboardPressParamSchema","defineActionKeyboardPress","keyboardPress","actionScrollParamSchema","defineActionScroll","scroll","actionDragAndDropParamSchema","defineActionDragAndDrop","dragAndDrop","from","to","ActionLongPressParamSchema","defineActionLongPress","longPress","ActionSwipeParamSchema","normalizeMobileSwipeParam","screenSize","width","height","start","end","startPoint","endPoint","direction","Math","duration","repeatCount","defineActionSwipe","i","actionClearInputParamSchema","defineActionClearInput","clearInput","actionCursorMoveParamSchema","defineActionCursorMove","times","wait","timeMs","Promise","resolve","setTimeout","arrowKey","ActionPinchParamSchema","defineActionPinch","centerX","centerY","startDistance","endDistance","normalizePinchParam","element","baseDistance","fingerDistance","defineSystemInputAction","call","defineActionsFromInputPrimitives","input","options","actions","pointer","touch","system","systemActions","action","Boolean","createDefaultMobileActions","context","ActionSleepParamSchema","defineActionSleep","getDebug"],"mappings":"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"}
@@ -40,6 +40,7 @@ var __webpack_exports__ = {};
40
40
  __webpack_require__.r(__webpack_exports__);
41
41
  __webpack_require__.d(__webpack_exports__, {
42
42
  generateImageScriptTag: ()=>generateImageScriptTag,
43
+ generateAgentReportComment: ()=>generateAgentReportComment,
43
44
  getBaseUrlFixScript: ()=>getBaseUrlFixScript,
44
45
  parseDumpScriptAttributes: ()=>parseDumpScriptAttributes,
45
46
  extractImageByIdSync: ()=>extractImageByIdSync,
@@ -60,6 +61,68 @@ var __webpack_exports__ = {};
60
61
  const utils_namespaceObject = require("@midscene/shared/utils");
61
62
  const escapeContent = utils_namespaceObject.escapeScriptTag;
62
63
  const unescapeContent = utils_namespaceObject.antiEscapeScriptTag;
64
+ function cleanHtmlCommentValue(value) {
65
+ return String(value ?? 'N/A').replace(/\0/g, '').replace(/--/g, '- -');
66
+ }
67
+ function formatModelBriefForAgent(brief) {
68
+ const intent = brief.intent || 'default';
69
+ const model = brief.name || 'unknown';
70
+ const description = brief.modelDescription ? ` (${brief.modelDescription})` : '';
71
+ return `${intent}: ${model}${description}`;
72
+ }
73
+ function hasUsageModelInfo(usage) {
74
+ return Boolean(usage && (usage.model_name || usage.response_model_name || usage.model_description || usage.intent));
75
+ }
76
+ function formatUsageModelForAgent(source, usage) {
77
+ const intent = usage.intent || source;
78
+ const model = usage.model_name || usage.response_model_name || 'unknown';
79
+ const description = usage.model_description ? ` (${usage.model_description})` : '';
80
+ return `${intent}: ${model}${description}`;
81
+ }
82
+ function collectUsageModelsForAgent(report) {
83
+ const models = new Map();
84
+ const executions = Array.isArray(report.executions) ? report.executions : [];
85
+ for (const execution of executions){
86
+ const tasks = Array.isArray(execution.tasks) ? execution.tasks : [];
87
+ for (const task of tasks){
88
+ const taskWithUsage = task;
89
+ const usages = [
90
+ [
91
+ 'main',
92
+ taskWithUsage.usage
93
+ ],
94
+ [
95
+ 'searchArea',
96
+ taskWithUsage.searchAreaUsage
97
+ ]
98
+ ];
99
+ for (const [source, usage] of usages){
100
+ if (!hasUsageModelInfo(usage)) continue;
101
+ const formatted = formatUsageModelForAgent(source, usage);
102
+ models.set(formatted, formatted);
103
+ }
104
+ }
105
+ }
106
+ return Array.from(models.values()).join('; ');
107
+ }
108
+ function generateAgentReportComment(report) {
109
+ const executions = Array.isArray(report.executions) ? report.executions : [];
110
+ const taskCount = executions.reduce((sum, execution)=>sum + (Array.isArray(execution.tasks) ? execution.tasks.length : 0), 0);
111
+ const modelBriefs = report.modelBriefs?.length ? report.modelBriefs.map(formatModelBriefForAgent).join('; ') : collectUsageModelsForAgent(report) || 'No model metadata recorded';
112
+ const lines = [
113
+ 'For Agent Analysis:',
114
+ `Report: ${cleanHtmlCommentValue(report.groupName)}`,
115
+ `SDK: ${cleanHtmlCommentValue(report.sdkVersion)}`,
116
+ `Device: ${cleanHtmlCommentValue(report.deviceType)}`,
117
+ `Executions: ${executions.length}; Tasks: ${taskCount}`,
118
+ `Models: ${cleanHtmlCommentValue(modelBriefs)}`,
119
+ 'Structured report JSON is stored in script[type="midscene_web_dump"] tags near this comment.',
120
+ 'Screenshots are stored as script[type="midscene-image"] tags or files referenced by screenshot refs.',
121
+ 'For AI analysis, inspect each execution task for type, status, timing, param, output, usage, searchAreaUsage, recorder, and screenshot refs.',
122
+ 'Use the Markdown export when available; it contains the same report context plus image links for agent review.'
123
+ ];
124
+ return `\n<!--\n${lines.join('\n')}\n-->\n`;
125
+ }
63
126
  function htmlScriptCloseTag() {
64
127
  return String.fromCharCode(60) + "/script>";
65
128
  }
@@ -342,6 +405,7 @@ exports.escapeContent = __webpack_exports__.escapeContent;
342
405
  exports.extractAllDumpScriptsSync = __webpack_exports__.extractAllDumpScriptsSync;
343
406
  exports.extractImageByIdSync = __webpack_exports__.extractImageByIdSync;
344
407
  exports.extractLastDumpScriptSync = __webpack_exports__.extractLastDumpScriptSync;
408
+ exports.generateAgentReportComment = __webpack_exports__.generateAgentReportComment;
345
409
  exports.generateDumpScriptTag = __webpack_exports__.generateDumpScriptTag;
346
410
  exports.generateImageScriptTag = __webpack_exports__.generateImageScriptTag;
347
411
  exports.getBaseUrlFixScript = __webpack_exports__.getBaseUrlFixScript;
@@ -359,6 +423,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
359
423
  "extractAllDumpScriptsSync",
360
424
  "extractImageByIdSync",
361
425
  "extractLastDumpScriptSync",
426
+ "generateAgentReportComment",
362
427
  "generateDumpScriptTag",
363
428
  "generateImageScriptTag",
364
429
  "getBaseUrlFixScript",
@@ -1 +1 @@
1
- {"version":3,"file":"dump/html-utils.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/html-utils.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { closeSync, openSync, readSync, statSync } from 'node:fs';\nimport { antiEscapeScriptTag, escapeScriptTag } from '@midscene/shared/utils';\n\nexport const escapeContent = escapeScriptTag;\nexport const unescapeContent = antiEscapeScriptTag;\n\nfunction htmlScriptCloseTag(): string {\n // biome-ignore lint/style/useTemplate: keep this token runtime-built for inline report bundles\n return String.fromCharCode(60) + '/script>';\n}\n\n/** Chunk size for streaming file operations (64KB) */\nexport const STREAMING_CHUNK_SIZE = 64 * 1024;\n\n/**\n * Callback for processing matched tags during streaming.\n * @param content - The content between open and close tags\n * @returns true to stop scanning, false to continue\n */\ntype TagMatchCallback = (content: string) => boolean;\n\n/**\n * Stream through a file and find tags matching the pattern.\n * Memory usage: O(chunk_size + tag_size), not O(file_size).\n *\n * @param filePath - Absolute path to the file\n * @param openTag - Opening tag to search for\n * @param closeTag - Closing tag\n * @param onMatch - Callback for each matched tag content\n */\nexport function streamScanTags(\n filePath: string,\n openTag: string,\n closeTag: string,\n onMatch: TagMatchCallback,\n): void {\n const fd = openSync(filePath, 'r');\n const fileSize = statSync(filePath).size;\n const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n let position = 0;\n let leftover = '';\n let capturing = false;\n let currentContent = '';\n\n try {\n while (position < fileSize) {\n const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n position += bytesRead;\n\n let searchStart = 0;\n\n while (searchStart < chunk.length) {\n if (!capturing) {\n const startIdx = chunk.indexOf(openTag, searchStart);\n if (startIdx !== -1) {\n capturing = true;\n currentContent = chunk.slice(startIdx + openTag.length);\n const endIdx = currentContent.indexOf(closeTag);\n if (endIdx !== -1) {\n const shouldStop = onMatch(currentContent.slice(0, endIdx));\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n searchStart =\n startIdx + openTag.length + endIdx + closeTag.length;\n } else {\n leftover = currentContent.slice(-closeTag.length);\n currentContent = currentContent.slice(0, -closeTag.length);\n break;\n }\n } else {\n leftover = chunk.slice(-openTag.length);\n break;\n }\n } else {\n const endIdx = chunk.indexOf(closeTag, searchStart);\n if (endIdx !== -1) {\n currentContent += chunk.slice(searchStart, endIdx);\n const shouldStop = onMatch(currentContent);\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n searchStart = endIdx + closeTag.length;\n } else {\n currentContent += chunk.slice(searchStart, -closeTag.length);\n leftover = chunk.slice(-closeTag.length);\n break;\n }\n }\n }\n }\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Synchronously extract a specific image's base64 data from an HTML file by its id.\n * Uses streaming to avoid loading the entire file into memory.\n *\n * @param htmlPath - Absolute path to the HTML file\n * @param imageId - The id of the image to extract\n * @returns The base64 data string, or null if not found\n */\nexport function extractImageByIdSync(\n htmlPath: string,\n imageId: string,\n): string | null {\n const targetTag = `<script type=\"midscene-image\" data-id=\"${imageId}\">`;\n const closeTag = htmlScriptCloseTag();\n\n let result: string | null = null;\n\n streamScanTags(htmlPath, targetTag, closeTag, (content) => {\n result = unescapeContent(content);\n return true; // Stop after first match\n });\n\n return result;\n}\n\n/**\n * Stream image script tags from source file directly to output file.\n * Memory usage: O(single_image_size), not O(all_images_size).\n *\n * @param srcFilePath - Source HTML file path\n * @param destFilePath - Destination file path to append to\n */\nexport function streamImageScriptsToFile(\n srcFilePath: string,\n destFilePath: string,\n): void {\n const { appendFileSync } = require('node:fs');\n const openTag = '<script type=\"midscene-image\"';\n const closeTag = htmlScriptCloseTag();\n\n streamScanTags(srcFilePath, openTag, closeTag, (content) => {\n // Write complete tag immediately to destination, don't accumulate\n appendFileSync(destFilePath, `${openTag}${content}${closeTag}\\n`);\n return false; // Continue scanning for more tags\n });\n}\n\n/**\n * Extract the LAST dump script content from HTML file using streaming.\n * Memory usage: O(dump_size), not O(file_size).\n *\n * @param filePath - Absolute path to the HTML file\n * @returns The dump script content (trimmed), or empty string if not found\n */\nexport function extractLastDumpScriptSync(filePath: string): string {\n const openTagPrefix = '<script type=\"midscene_web_dump\"';\n const closeTag = htmlScriptCloseTag();\n\n let lastContent = '';\n\n // Custom streaming to handle the special case where open tag has variable attributes\n const fd = openSync(filePath, 'r');\n const fileSize = statSync(filePath).size;\n const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n let position = 0;\n let leftover = '';\n let capturing = false;\n let currentContent = '';\n\n try {\n while (position < fileSize) {\n const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n position += bytesRead;\n\n let searchStart = 0;\n\n while (searchStart < chunk.length) {\n if (!capturing) {\n const startIdx = chunk.indexOf(openTagPrefix, searchStart);\n if (startIdx !== -1) {\n // Find the end of the opening tag (the '>' character)\n const tagEndIdx = chunk.indexOf('>', startIdx);\n if (tagEndIdx !== -1) {\n capturing = true;\n currentContent = chunk.slice(tagEndIdx + 1);\n const endIdx = currentContent.indexOf(closeTag);\n if (endIdx !== -1) {\n lastContent = currentContent.slice(0, endIdx).trim();\n capturing = false;\n currentContent = '';\n searchStart = tagEndIdx + 1 + endIdx + closeTag.length;\n } else {\n leftover = currentContent.slice(-closeTag.length);\n currentContent = currentContent.slice(0, -closeTag.length);\n break;\n }\n } else {\n leftover = chunk.slice(startIdx);\n break;\n }\n } else {\n leftover = chunk.slice(-openTagPrefix.length);\n break;\n }\n } else {\n const endIdx = chunk.indexOf(closeTag, searchStart);\n if (endIdx !== -1) {\n currentContent += chunk.slice(searchStart, endIdx);\n lastContent = currentContent.trim();\n capturing = false;\n currentContent = '';\n searchStart = endIdx + closeTag.length;\n } else {\n currentContent += chunk.slice(searchStart, -closeTag.length);\n leftover = chunk.slice(-closeTag.length);\n break;\n }\n }\n }\n }\n } finally {\n closeSync(fd);\n }\n\n return lastContent;\n}\n\n/**\n * Extract ALL dump script contents from an HTML file using streaming.\n * Each entry includes the full opening tag (for attribute extraction) and the content.\n *\n * @param filePath - Absolute path to the HTML file\n * @returns Array of { openTag, content } for each dump script found\n */\nexport function extractAllDumpScriptsSync(\n filePath: string,\n): { openTag: string; content: string }[] {\n const results: { openTag: string; content: string }[] = [];\n streamDumpScriptsSync(filePath, (dumpScript) => {\n results.push(dumpScript);\n return false;\n });\n return results;\n}\n\n/**\n * Stream ALL dump scripts from an HTML file.\n * Calls onMatch for each dump script and keeps memory bounded to a single\n * dump script payload instead of accumulating every dump in memory.\n *\n * @param filePath - Absolute path to the HTML file\n * @param onMatch - Callback for each dump script; return true to stop early\n */\nexport function streamDumpScriptsSync(\n filePath: string,\n onMatch: (dumpScript: { openTag: string; content: string }) => boolean,\n): void {\n const openTagPrefix = '<script type=\"midscene_web_dump\"';\n const closeTag = htmlScriptCloseTag();\n\n const fd = openSync(filePath, 'r');\n const fileSize = statSync(filePath).size;\n const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n let position = 0;\n let leftover = '';\n let capturing = false;\n let currentContent = '';\n let currentOpenTag = '';\n\n try {\n while (position < fileSize) {\n const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n position += bytesRead;\n\n let searchStart = 0;\n\n while (searchStart < chunk.length) {\n if (!capturing) {\n const startIdx = chunk.indexOf(openTagPrefix, searchStart);\n if (startIdx !== -1) {\n const tagEndIdx = chunk.indexOf('>', startIdx);\n if (tagEndIdx !== -1) {\n capturing = true;\n currentOpenTag = chunk.slice(startIdx, tagEndIdx + 1);\n currentContent = chunk.slice(tagEndIdx + 1);\n const endIdx = currentContent.indexOf(closeTag);\n if (endIdx !== -1) {\n const shouldStop = onMatch({\n openTag: currentOpenTag,\n content: currentContent.slice(0, endIdx).trim(),\n });\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n currentOpenTag = '';\n searchStart = tagEndIdx + 1 + endIdx + closeTag.length;\n } else {\n leftover = currentContent.slice(-closeTag.length);\n currentContent = currentContent.slice(0, -closeTag.length);\n break;\n }\n } else {\n leftover = chunk.slice(startIdx);\n break;\n }\n } else {\n leftover = chunk.slice(-openTagPrefix.length);\n break;\n }\n } else {\n const endIdx = chunk.indexOf(closeTag, searchStart);\n if (endIdx !== -1) {\n currentContent += chunk.slice(searchStart, endIdx);\n const shouldStop = onMatch({\n openTag: currentOpenTag,\n content: currentContent.trim(),\n });\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n currentOpenTag = '';\n searchStart = endIdx + closeTag.length;\n } else {\n currentContent += chunk.slice(searchStart, -closeTag.length);\n leftover = chunk.slice(-closeTag.length);\n break;\n }\n }\n }\n }\n } finally {\n closeSync(fd);\n }\n}\n\nexport function parseImageScripts(html: string): Record<string, string> {\n const imageMap: Record<string, string> = {};\n const regex =\n /<script type=\"midscene-image\" data-id=\"([^\"]+)\">([\\s\\S]*?)<\\/script>/g;\n\n for (const match of html.matchAll(regex)) {\n const [, id, content] = match;\n imageMap[id] = unescapeContent(content);\n }\n\n return imageMap;\n}\n\nexport function parseDumpScript(html: string): string {\n // Use string search instead of regex to avoid ReDoS vulnerability\n // Find the LAST dump script tag (template may contain similar patterns in bundled JS)\n const scriptOpenTag = '<script type=\"midscene_web_dump\"';\n const closeTag = htmlScriptCloseTag();\n\n // Find the last occurrence of the opening tag\n const lastOpenIndex = html.lastIndexOf(scriptOpenTag);\n if (lastOpenIndex === -1) {\n throw new Error('No dump script found in HTML');\n }\n\n // Find the end of the opening tag (the '>' character)\n const tagEndIndex = html.indexOf('>', lastOpenIndex);\n if (tagEndIndex === -1) {\n throw new Error('No dump script found in HTML');\n }\n\n // Find the closing tag after the opening tag\n const closeIndex = html.indexOf(closeTag, tagEndIndex);\n if (closeIndex === -1) {\n throw new Error('No dump script found in HTML');\n }\n\n // Extract content between opening and closing tags\n const content = html.substring(tagEndIndex + 1, closeIndex);\n return unescapeContent(content);\n}\n\nexport function parseDumpScriptAttributes(\n html: string,\n): Record<string, string> {\n const regex = /<script type=\"midscene_web_dump\"([^>]*)>/;\n const match = regex.exec(html);\n\n if (!match) {\n return {};\n }\n\n const attrString = match[1];\n const attributes: Record<string, string> = {};\n const attrRegex = /(\\w+)=\"([^\"]*)\"/g;\n\n for (const attrMatch of attrString.matchAll(attrRegex)) {\n const [, key, value] = attrMatch;\n if (key !== 'type') {\n attributes[key] = decodeURIComponent(value);\n }\n }\n\n return attributes;\n}\n\nexport function generateImageScriptTag(id: string, data: string): string {\n // Do not use template string here, will cause bundle error with <script\n const closeTag = htmlScriptCloseTag();\n return (\n // biome-ignore lint/style/useTemplate: <explanation>\n '<script type=\"midscene-image\" data-id=\"' +\n id +\n '\">' +\n escapeContent(data) +\n closeTag\n );\n}\n\n/**\n * Inline script that fixes relative URL resolution for directory-mode reports.\n *\n * Problem: when a static server (e.g. `npx serve`) serves `name/index.html`\n * at URL `/name` (without trailing slash), relative paths like\n * `./screenshots/xxx.png` resolve to `/screenshots/xxx.png` instead of\n * `/name/screenshots/xxx.png`.\n *\n * Fix: dynamically insert a <base> tag so relative URLs resolve correctly.\n */\n// Do not use template string here, will cause bundle error with <script\n//\n// The closing script tag is built at runtime so bundlers cannot inline the\n// token that would prematurely close the report template's inline app bundle.\n//\n// Do NOT replace this with a string constant, hex escape (\\x3c), or literal\n// string concatenation. Bundlers may optimise those forms back to the unsafe\n// token.\nlet _baseUrlFixScript: string;\nexport function getBaseUrlFixScript(): string {\n if (!_baseUrlFixScript) {\n const close = htmlScriptCloseTag();\n _baseUrlFixScript =\n // biome-ignore lint/style/useTemplate: see above\n '\\n<script>(function(){' +\n 'var p=window.location.pathname;' +\n 'if(p.endsWith(\"/\")||/\\\\.\\\\w+$/.test(p))return;' +\n 'var b=document.createElement(\"base\");' +\n 'b.href=p+\"/\";' +\n 'document.head.insertBefore(b,document.head.firstChild)' +\n '})()' +\n close +\n '\\n';\n }\n return _baseUrlFixScript;\n}\n\n/**\n * Dump-script attribute that records how the report file stores screenshots.\n * Written by the report generator and the merger, read back when deciding\n * whether a report is in directory mode. Kept here, next to dump-tag\n * generation, so the writer and reader share one source of truth.\n */\nexport const DATA_SCREENSHOT_MODE_ATTR = 'data-screenshot-mode';\n\nexport function generateDumpScriptTag(\n json: string,\n attributes?: Record<string, string | number | boolean>,\n): string {\n const closeTag = htmlScriptCloseTag();\n let attrString = '';\n if (attributes && Object.keys(attributes).length > 0) {\n // Do not use template string here, will cause bundle error with <script\n attrString =\n // biome-ignore lint/style/useTemplate: <explanation>\n ' ' +\n Object.entries(attributes)\n // biome-ignore lint/style/useTemplate: <explanation>\n .map(([k, v]) => k + '=\"' + encodeURIComponent(v) + '\"')\n .join(' ');\n }\n\n // Do not use template string here, will cause bundle error with <script\n return (\n // biome-ignore lint/style/useTemplate: <explanation>\n '<script type=\"midscene_web_dump\"' +\n attrString +\n '>' +\n escapeContent(json) +\n closeTag\n );\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","escapeContent","escapeScriptTag","unescapeContent","antiEscapeScriptTag","htmlScriptCloseTag","String","STREAMING_CHUNK_SIZE","streamScanTags","filePath","openTag","closeTag","onMatch","fd","openSync","fileSize","statSync","buffer","Buffer","position","leftover","capturing","currentContent","bytesRead","readSync","chunk","searchStart","endIdx","shouldStop","startIdx","closeSync","extractImageByIdSync","htmlPath","imageId","targetTag","result","content","streamImageScriptsToFile","srcFilePath","destFilePath","appendFileSync","require","extractLastDumpScriptSync","openTagPrefix","lastContent","tagEndIdx","extractAllDumpScriptsSync","results","streamDumpScriptsSync","dumpScript","currentOpenTag","parseImageScripts","html","imageMap","regex","match","id","parseDumpScript","scriptOpenTag","lastOpenIndex","Error","tagEndIndex","closeIndex","parseDumpScriptAttributes","attrString","attributes","attrRegex","attrMatch","value","decodeURIComponent","generateImageScriptTag","data","_baseUrlFixScript","getBaseUrlFixScript","close","DATA_SCREENSHOT_MODE_ATTR","generateDumpScriptTag","json","k","v","encodeURIComponent"],"mappings":";;;;;;;;;;;;;;;;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;ICHO,MAAMI,gBAAgBC,sBAAAA,eAAeA;IACrC,MAAMC,kBAAkBC,sBAAAA,mBAAmBA;IAElD,SAASC;QAEP,OAAOC,OAAO,YAAY,CAAC,MAAM;IACnC;IAGO,MAAMC,uBAAuB;IAkB7B,SAASC,eACdC,QAAgB,EAChBC,OAAe,EACfC,QAAgB,EAChBC,OAAyB;QAEzB,MAAMC,KAAKC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASL,UAAU;QAC9B,MAAMM,WAAWC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASP,UAAU,IAAI;QACxC,MAAMQ,SAASC,OAAO,KAAK,CAACX;QAE5B,IAAIY,WAAW;QACf,IAAIC,WAAW;QACf,IAAIC,YAAY;QAChB,IAAIC,iBAAiB;QAErB,IAAI;YACF,MAAOH,WAAWJ,SAAU;gBAC1B,MAAMQ,YAAYC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASX,IAAII,QAAQ,GAAGV,sBAAsBY;gBAChE,MAAMM,QAAQL,WAAWH,OAAO,QAAQ,CAAC,SAAS,GAAGM;gBACrDJ,YAAYI;gBAEZ,IAAIG,cAAc;gBAElB,MAAOA,cAAcD,MAAM,MAAM,CAC/B,IAAKJ,WAsBE;oBACL,MAAMM,SAASF,MAAM,OAAO,CAACd,UAAUe;oBACvC,IAAIC,AAAW,OAAXA,QAAe;wBACjBL,kBAAkBG,MAAM,KAAK,CAACC,aAAaC;wBAC3C,MAAMC,aAAahB,QAAQU;wBAC3B,IAAIM,YAAY;wBAChBP,YAAY;wBACZC,iBAAiB;wBACjBI,cAAcC,SAAShB,SAAS,MAAM;oBACxC,OAAO;wBACLW,kBAAkBG,MAAM,KAAK,CAACC,aAAa,CAACf,SAAS,MAAM;wBAC3DS,WAAWK,MAAM,KAAK,CAAC,CAACd,SAAS,MAAM;wBACvC;oBACF;gBACF,OApCgB;oBACd,MAAMkB,WAAWJ,MAAM,OAAO,CAACf,SAASgB;oBACxC,IAAIG,AAAa,OAAbA,UAAiB;wBACnBR,YAAY;wBACZC,iBAAiBG,MAAM,KAAK,CAACI,WAAWnB,QAAQ,MAAM;wBACtD,MAAMiB,SAASL,eAAe,OAAO,CAACX;wBACtC,IAAIgB,AAAW,OAAXA,QAAe;4BACjB,MAAMC,aAAahB,QAAQU,eAAe,KAAK,CAAC,GAAGK;4BACnD,IAAIC,YAAY;4BAChBP,YAAY;4BACZC,iBAAiB;4BACjBI,cACEG,WAAWnB,QAAQ,MAAM,GAAGiB,SAAShB,SAAS,MAAM;wBACxD,OAAO;4BACLS,WAAWE,eAAe,KAAK,CAAC,CAACX,SAAS,MAAM;4BAChDW,iBAAiBA,eAAe,KAAK,CAAC,GAAG,CAACX,SAAS,MAAM;4BACzD;wBACF;oBACF,OAAO;wBACLS,WAAWK,MAAM,KAAK,CAAC,CAACf,QAAQ,MAAM;wBACtC;oBACF;gBACF;YAgBJ;QACF,SAAU;YACRoB,IAAAA,kBAAAA,SAAAA,AAAAA,EAAUjB;QACZ;IACF;IAUO,SAASkB,qBACdC,QAAgB,EAChBC,OAAe;QAEf,MAAMC,YAAY,CAAC,uCAAuC,EAAED,QAAQ,EAAE,CAAC;QACvE,MAAMtB,WAAWN;QAEjB,IAAI8B,SAAwB;QAE5B3B,eAAewB,UAAUE,WAAWvB,UAAU,CAACyB;YAC7CD,SAAShC,gBAAgBiC;YACzB,OAAO;QACT;QAEA,OAAOD;IACT;IASO,SAASE,yBACdC,WAAmB,EACnBC,YAAoB;QAEpB,MAAM,EAAEC,cAAc,EAAE,GAAGC,oBAAQ;QACnC,MAAM/B,UAAU;QAChB,MAAMC,WAAWN;QAEjBG,eAAe8B,aAAa5B,SAASC,UAAU,CAACyB;YAE9CI,eAAeD,cAAc,GAAG7B,UAAU0B,UAAUzB,SAAS,EAAE,CAAC;YAChE,OAAO;QACT;IACF;IASO,SAAS+B,0BAA0BjC,QAAgB;QACxD,MAAMkC,gBAAgB;QACtB,MAAMhC,WAAWN;QAEjB,IAAIuC,cAAc;QAGlB,MAAM/B,KAAKC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASL,UAAU;QAC9B,MAAMM,WAAWC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASP,UAAU,IAAI;QACxC,MAAMQ,SAASC,OAAO,KAAK,CAACX;QAE5B,IAAIY,WAAW;QACf,IAAIC,WAAW;QACf,IAAIC,YAAY;QAChB,IAAIC,iBAAiB;QAErB,IAAI;YACF,MAAOH,WAAWJ,SAAU;gBAC1B,MAAMQ,YAAYC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASX,IAAII,QAAQ,GAAGV,sBAAsBY;gBAChE,MAAMM,QAAQL,WAAWH,OAAO,QAAQ,CAAC,SAAS,GAAGM;gBACrDJ,YAAYI;gBAEZ,IAAIG,cAAc;gBAElB,MAAOA,cAAcD,MAAM,MAAM,CAC/B,IAAKJ,WA2BE;oBACL,MAAMM,SAASF,MAAM,OAAO,CAACd,UAAUe;oBACvC,IAAIC,AAAW,OAAXA,QAAe;wBACjBL,kBAAkBG,MAAM,KAAK,CAACC,aAAaC;wBAC3CiB,cAActB,eAAe,IAAI;wBACjCD,YAAY;wBACZC,iBAAiB;wBACjBI,cAAcC,SAAShB,SAAS,MAAM;oBACxC,OAAO;wBACLW,kBAAkBG,MAAM,KAAK,CAACC,aAAa,CAACf,SAAS,MAAM;wBAC3DS,WAAWK,MAAM,KAAK,CAAC,CAACd,SAAS,MAAM;wBACvC;oBACF;gBACF,OAxCgB;oBACd,MAAMkB,WAAWJ,MAAM,OAAO,CAACkB,eAAejB;oBAC9C,IAAIG,AAAa,OAAbA,UAAiB;wBAEnB,MAAMgB,YAAYpB,MAAM,OAAO,CAAC,KAAKI;wBACrC,IAAIgB,AAAc,OAAdA,WAAkB;4BACpBxB,YAAY;4BACZC,iBAAiBG,MAAM,KAAK,CAACoB,YAAY;4BACzC,MAAMlB,SAASL,eAAe,OAAO,CAACX;4BACtC,IAAIgB,AAAW,OAAXA,QAAe;gCACjBiB,cAActB,eAAe,KAAK,CAAC,GAAGK,QAAQ,IAAI;gCAClDN,YAAY;gCACZC,iBAAiB;gCACjBI,cAAcmB,YAAY,IAAIlB,SAAShB,SAAS,MAAM;4BACxD,OAAO;gCACLS,WAAWE,eAAe,KAAK,CAAC,CAACX,SAAS,MAAM;gCAChDW,iBAAiBA,eAAe,KAAK,CAAC,GAAG,CAACX,SAAS,MAAM;gCACzD;4BACF;wBACF,OAAO;4BACLS,WAAWK,MAAM,KAAK,CAACI;4BACvB;wBACF;oBACF,OAAO;wBACLT,WAAWK,MAAM,KAAK,CAAC,CAACkB,cAAc,MAAM;wBAC5C;oBACF;gBACF;YAeJ;QACF,SAAU;YACRb,IAAAA,kBAAAA,SAAAA,AAAAA,EAAUjB;QACZ;QAEA,OAAO+B;IACT;IASO,SAASE,0BACdrC,QAAgB;QAEhB,MAAMsC,UAAkD,EAAE;QAC1DC,sBAAsBvC,UAAU,CAACwC;YAC/BF,QAAQ,IAAI,CAACE;YACb,OAAO;QACT;QACA,OAAOF;IACT;IAUO,SAASC,sBACdvC,QAAgB,EAChBG,OAAsE;QAEtE,MAAM+B,gBAAgB;QACtB,MAAMhC,WAAWN;QAEjB,MAAMQ,KAAKC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASL,UAAU;QAC9B,MAAMM,WAAWC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASP,UAAU,IAAI;QACxC,MAAMQ,SAASC,OAAO,KAAK,CAACX;QAE5B,IAAIY,WAAW;QACf,IAAIC,WAAW;QACf,IAAIC,YAAY;QAChB,IAAIC,iBAAiB;QACrB,IAAI4B,iBAAiB;QAErB,IAAI;YACF,MAAO/B,WAAWJ,SAAU;gBAC1B,MAAMQ,YAAYC,AAAAA,IAAAA,kBAAAA,QAAAA,AAAAA,EAASX,IAAII,QAAQ,GAAGV,sBAAsBY;gBAChE,MAAMM,QAAQL,WAAWH,OAAO,QAAQ,CAAC,SAAS,GAAGM;gBACrDJ,YAAYI;gBAEZ,IAAIG,cAAc;gBAElB,MAAOA,cAAcD,MAAM,MAAM,CAC/B,IAAKJ,WAgCE;oBACL,MAAMM,SAASF,MAAM,OAAO,CAACd,UAAUe;oBACvC,IAAIC,AAAW,OAAXA,QAAe;wBACjBL,kBAAkBG,MAAM,KAAK,CAACC,aAAaC;wBAC3C,MAAMC,aAAahB,QAAQ;4BACzB,SAASsC;4BACT,SAAS5B,eAAe,IAAI;wBAC9B;wBACA,IAAIM,YAAY;wBAChBP,YAAY;wBACZC,iBAAiB;wBACjB4B,iBAAiB;wBACjBxB,cAAcC,SAAShB,SAAS,MAAM;oBACxC,OAAO;wBACLW,kBAAkBG,MAAM,KAAK,CAACC,aAAa,CAACf,SAAS,MAAM;wBAC3DS,WAAWK,MAAM,KAAK,CAAC,CAACd,SAAS,MAAM;wBACvC;oBACF;gBACF,OAlDgB;oBACd,MAAMkB,WAAWJ,MAAM,OAAO,CAACkB,eAAejB;oBAC9C,IAAIG,AAAa,OAAbA,UAAiB;wBACnB,MAAMgB,YAAYpB,MAAM,OAAO,CAAC,KAAKI;wBACrC,IAAIgB,AAAc,OAAdA,WAAkB;4BACpBxB,YAAY;4BACZ6B,iBAAiBzB,MAAM,KAAK,CAACI,UAAUgB,YAAY;4BACnDvB,iBAAiBG,MAAM,KAAK,CAACoB,YAAY;4BACzC,MAAMlB,SAASL,eAAe,OAAO,CAACX;4BACtC,IAAIgB,AAAW,OAAXA,QAAe;gCACjB,MAAMC,aAAahB,QAAQ;oCACzB,SAASsC;oCACT,SAAS5B,eAAe,KAAK,CAAC,GAAGK,QAAQ,IAAI;gCAC/C;gCACA,IAAIC,YAAY;gCAChBP,YAAY;gCACZC,iBAAiB;gCACjB4B,iBAAiB;gCACjBxB,cAAcmB,YAAY,IAAIlB,SAAShB,SAAS,MAAM;4BACxD,OAAO;gCACLS,WAAWE,eAAe,KAAK,CAAC,CAACX,SAAS,MAAM;gCAChDW,iBAAiBA,eAAe,KAAK,CAAC,GAAG,CAACX,SAAS,MAAM;gCACzD;4BACF;wBACF,OAAO;4BACLS,WAAWK,MAAM,KAAK,CAACI;4BACvB;wBACF;oBACF,OAAO;wBACLT,WAAWK,MAAM,KAAK,CAAC,CAACkB,cAAc,MAAM;wBAC5C;oBACF;gBACF;YAoBJ;QACF,SAAU;YACRb,IAAAA,kBAAAA,SAAAA,AAAAA,EAAUjB;QACZ;IACF;IAEO,SAASsC,kBAAkBC,IAAY;QAC5C,MAAMC,WAAmC,CAAC;QAC1C,MAAMC,QACJ;QAEF,KAAK,MAAMC,SAASH,KAAK,QAAQ,CAACE,OAAQ;YACxC,MAAM,GAAGE,IAAIpB,QAAQ,GAAGmB;YACxBF,QAAQ,CAACG,GAAG,GAAGrD,gBAAgBiC;QACjC;QAEA,OAAOiB;IACT;IAEO,SAASI,gBAAgBL,IAAY;QAG1C,MAAMM,gBAAgB;QACtB,MAAM/C,WAAWN;QAGjB,MAAMsD,gBAAgBP,KAAK,WAAW,CAACM;QACvC,IAAIC,AAAkB,OAAlBA,eACF,MAAM,IAAIC,MAAM;QAIlB,MAAMC,cAAcT,KAAK,OAAO,CAAC,KAAKO;QACtC,IAAIE,AAAgB,OAAhBA,aACF,MAAM,IAAID,MAAM;QAIlB,MAAME,aAAaV,KAAK,OAAO,CAACzC,UAAUkD;QAC1C,IAAIC,AAAe,OAAfA,YACF,MAAM,IAAIF,MAAM;QAIlB,MAAMxB,UAAUgB,KAAK,SAAS,CAACS,cAAc,GAAGC;QAChD,OAAO3D,gBAAgBiC;IACzB;IAEO,SAAS2B,0BACdX,IAAY;QAEZ,MAAME,QAAQ;QACd,MAAMC,QAAQD,MAAM,IAAI,CAACF;QAEzB,IAAI,CAACG,OACH,OAAO,CAAC;QAGV,MAAMS,aAAaT,KAAK,CAAC,EAAE;QAC3B,MAAMU,aAAqC,CAAC;QAC5C,MAAMC,YAAY;QAElB,KAAK,MAAMC,aAAaH,WAAW,QAAQ,CAACE,WAAY;YACtD,MAAM,GAAGtE,KAAKwE,MAAM,GAAGD;YACvB,IAAIvE,AAAQ,WAARA,KACFqE,UAAU,CAACrE,IAAI,GAAGyE,mBAAmBD;QAEzC;QAEA,OAAOH;IACT;IAEO,SAASK,uBAAuBd,EAAU,EAAEe,IAAY;QAE7D,MAAM5D,WAAWN;QACjB,OAEE,4CACAmD,KACA,OACAvD,cAAcsE,QACd5D;IAEJ;IAoBA,IAAI6D;IACG,SAASC;QACd,IAAI,CAACD,mBAAmB;YACtB,MAAME,QAAQrE;YACdmE,oBAEE,oNAOAE,QACA;QACJ;QACA,OAAOF;IACT;IAQO,MAAMG,4BAA4B;IAElC,SAASC,sBACdC,IAAY,EACZZ,UAAsD;QAEtD,MAAMtD,WAAWN;QACjB,IAAI2D,aAAa;QACjB,IAAIC,cAAcpE,OAAO,IAAI,CAACoE,YAAY,MAAM,GAAG,GAEjDD,aAEE,MACAnE,OAAO,OAAO,CAACoE,YAEZ,GAAG,CAAC,CAAC,CAACa,GAAGC,EAAE,GAAKD,IAAI,OAAOE,mBAAmBD,KAAK,KACnD,IAAI,CAAC;QAIZ,OAEE,qCACAf,aACA,MACA/D,cAAc4E,QACdlE;IAEJ"}
1
+ {"version":3,"file":"dump/html-utils.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/html-utils.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { closeSync, openSync, readSync, statSync } from 'node:fs';\nimport { antiEscapeScriptTag, escapeScriptTag } from '@midscene/shared/utils';\nimport type { AIUsageInfo, IReportActionDump, ModelBrief } from '../types';\n\nexport const escapeContent = escapeScriptTag;\nexport const unescapeContent = antiEscapeScriptTag;\n\nfunction cleanHtmlCommentValue(value: unknown): string {\n return String(value ?? 'N/A')\n .replace(/\\0/g, '')\n .replace(/--/g, '- -');\n}\n\nfunction formatModelBriefForAgent(brief: ModelBrief): string {\n const intent = brief.intent || 'default';\n const model = brief.name || 'unknown';\n const description = brief.modelDescription\n ? ` (${brief.modelDescription})`\n : '';\n return `${intent}: ${model}${description}`;\n}\n\nfunction hasUsageModelInfo(usage?: AIUsageInfo): usage is AIUsageInfo {\n return Boolean(\n usage &&\n (usage.model_name ||\n usage.response_model_name ||\n usage.model_description ||\n usage.intent),\n );\n}\n\nfunction formatUsageModelForAgent(source: string, usage: AIUsageInfo): string {\n const intent = usage.intent || source;\n const model = usage.model_name || usage.response_model_name || 'unknown';\n const description = usage.model_description\n ? ` (${usage.model_description})`\n : '';\n return `${intent}: ${model}${description}`;\n}\n\nfunction collectUsageModelsForAgent(report: IReportActionDump): string {\n const models = new Map<string, string>();\n const executions = Array.isArray(report.executions) ? report.executions : [];\n for (const execution of executions) {\n const tasks = Array.isArray(execution.tasks) ? execution.tasks : [];\n for (const task of tasks) {\n const taskWithUsage = task as {\n usage?: AIUsageInfo;\n searchAreaUsage?: AIUsageInfo;\n };\n const usages: Array<[string, AIUsageInfo | undefined]> = [\n ['main', taskWithUsage.usage],\n ['searchArea', taskWithUsage.searchAreaUsage],\n ];\n\n for (const [source, usage] of usages) {\n if (!hasUsageModelInfo(usage)) {\n continue;\n }\n const formatted = formatUsageModelForAgent(source, usage);\n models.set(formatted, formatted);\n }\n }\n }\n\n return Array.from(models.values()).join('; ');\n}\n\nexport function generateAgentReportComment(report: IReportActionDump): string {\n const executions = Array.isArray(report.executions) ? report.executions : [];\n const taskCount = executions.reduce(\n (sum, execution) =>\n sum + (Array.isArray(execution.tasks) ? execution.tasks.length : 0),\n 0,\n );\n const modelBriefs = report.modelBriefs?.length\n ? report.modelBriefs.map(formatModelBriefForAgent).join('; ')\n : collectUsageModelsForAgent(report) || 'No model metadata recorded';\n\n const lines = [\n 'For Agent Analysis:',\n `Report: ${cleanHtmlCommentValue(report.groupName)}`,\n `SDK: ${cleanHtmlCommentValue(report.sdkVersion)}`,\n `Device: ${cleanHtmlCommentValue(report.deviceType)}`,\n `Executions: ${executions.length}; Tasks: ${taskCount}`,\n `Models: ${cleanHtmlCommentValue(modelBriefs)}`,\n 'Structured report JSON is stored in script[type=\"midscene_web_dump\"] tags near this comment.',\n 'Screenshots are stored as script[type=\"midscene-image\"] tags or files referenced by screenshot refs.',\n 'For AI analysis, inspect each execution task for type, status, timing, param, output, usage, searchAreaUsage, recorder, and screenshot refs.',\n 'Use the Markdown export when available; it contains the same report context plus image links for agent review.',\n ];\n\n return `\\n<!--\\n${lines.join('\\n')}\\n-->\\n`;\n}\n\nfunction htmlScriptCloseTag(): string {\n // biome-ignore lint/style/useTemplate: keep this token runtime-built for inline report bundles\n return String.fromCharCode(60) + '/script>';\n}\n\n/** Chunk size for streaming file operations (64KB) */\nexport const STREAMING_CHUNK_SIZE = 64 * 1024;\n\n/**\n * Callback for processing matched tags during streaming.\n * @param content - The content between open and close tags\n * @returns true to stop scanning, false to continue\n */\ntype TagMatchCallback = (content: string) => boolean;\n\n/**\n * Stream through a file and find tags matching the pattern.\n * Memory usage: O(chunk_size + tag_size), not O(file_size).\n *\n * @param filePath - Absolute path to the file\n * @param openTag - Opening tag to search for\n * @param closeTag - Closing tag\n * @param onMatch - Callback for each matched tag content\n */\nexport function streamScanTags(\n filePath: string,\n openTag: string,\n closeTag: string,\n onMatch: TagMatchCallback,\n): void {\n const fd = openSync(filePath, 'r');\n const fileSize = statSync(filePath).size;\n const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n let position = 0;\n let leftover = '';\n let capturing = false;\n let currentContent = '';\n\n try {\n while (position < fileSize) {\n const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n position += bytesRead;\n\n let searchStart = 0;\n\n while (searchStart < chunk.length) {\n if (!capturing) {\n const startIdx = chunk.indexOf(openTag, searchStart);\n if (startIdx !== -1) {\n capturing = true;\n currentContent = chunk.slice(startIdx + openTag.length);\n const endIdx = currentContent.indexOf(closeTag);\n if (endIdx !== -1) {\n const shouldStop = onMatch(currentContent.slice(0, endIdx));\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n searchStart =\n startIdx + openTag.length + endIdx + closeTag.length;\n } else {\n leftover = currentContent.slice(-closeTag.length);\n currentContent = currentContent.slice(0, -closeTag.length);\n break;\n }\n } else {\n leftover = chunk.slice(-openTag.length);\n break;\n }\n } else {\n const endIdx = chunk.indexOf(closeTag, searchStart);\n if (endIdx !== -1) {\n currentContent += chunk.slice(searchStart, endIdx);\n const shouldStop = onMatch(currentContent);\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n searchStart = endIdx + closeTag.length;\n } else {\n currentContent += chunk.slice(searchStart, -closeTag.length);\n leftover = chunk.slice(-closeTag.length);\n break;\n }\n }\n }\n }\n } finally {\n closeSync(fd);\n }\n}\n\n/**\n * Synchronously extract a specific image's base64 data from an HTML file by its id.\n * Uses streaming to avoid loading the entire file into memory.\n *\n * @param htmlPath - Absolute path to the HTML file\n * @param imageId - The id of the image to extract\n * @returns The base64 data string, or null if not found\n */\nexport function extractImageByIdSync(\n htmlPath: string,\n imageId: string,\n): string | null {\n const targetTag = `<script type=\"midscene-image\" data-id=\"${imageId}\">`;\n const closeTag = htmlScriptCloseTag();\n\n let result: string | null = null;\n\n streamScanTags(htmlPath, targetTag, closeTag, (content) => {\n result = unescapeContent(content);\n return true; // Stop after first match\n });\n\n return result;\n}\n\n/**\n * Stream image script tags from source file directly to output file.\n * Memory usage: O(single_image_size), not O(all_images_size).\n *\n * @param srcFilePath - Source HTML file path\n * @param destFilePath - Destination file path to append to\n */\nexport function streamImageScriptsToFile(\n srcFilePath: string,\n destFilePath: string,\n): void {\n const { appendFileSync } = require('node:fs');\n const openTag = '<script type=\"midscene-image\"';\n const closeTag = htmlScriptCloseTag();\n\n streamScanTags(srcFilePath, openTag, closeTag, (content) => {\n // Write complete tag immediately to destination, don't accumulate\n appendFileSync(destFilePath, `${openTag}${content}${closeTag}\\n`);\n return false; // Continue scanning for more tags\n });\n}\n\n/**\n * Extract the LAST dump script content from HTML file using streaming.\n * Memory usage: O(dump_size), not O(file_size).\n *\n * @param filePath - Absolute path to the HTML file\n * @returns The dump script content (trimmed), or empty string if not found\n */\nexport function extractLastDumpScriptSync(filePath: string): string {\n const openTagPrefix = '<script type=\"midscene_web_dump\"';\n const closeTag = htmlScriptCloseTag();\n\n let lastContent = '';\n\n // Custom streaming to handle the special case where open tag has variable attributes\n const fd = openSync(filePath, 'r');\n const fileSize = statSync(filePath).size;\n const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n let position = 0;\n let leftover = '';\n let capturing = false;\n let currentContent = '';\n\n try {\n while (position < fileSize) {\n const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n position += bytesRead;\n\n let searchStart = 0;\n\n while (searchStart < chunk.length) {\n if (!capturing) {\n const startIdx = chunk.indexOf(openTagPrefix, searchStart);\n if (startIdx !== -1) {\n // Find the end of the opening tag (the '>' character)\n const tagEndIdx = chunk.indexOf('>', startIdx);\n if (tagEndIdx !== -1) {\n capturing = true;\n currentContent = chunk.slice(tagEndIdx + 1);\n const endIdx = currentContent.indexOf(closeTag);\n if (endIdx !== -1) {\n lastContent = currentContent.slice(0, endIdx).trim();\n capturing = false;\n currentContent = '';\n searchStart = tagEndIdx + 1 + endIdx + closeTag.length;\n } else {\n leftover = currentContent.slice(-closeTag.length);\n currentContent = currentContent.slice(0, -closeTag.length);\n break;\n }\n } else {\n leftover = chunk.slice(startIdx);\n break;\n }\n } else {\n leftover = chunk.slice(-openTagPrefix.length);\n break;\n }\n } else {\n const endIdx = chunk.indexOf(closeTag, searchStart);\n if (endIdx !== -1) {\n currentContent += chunk.slice(searchStart, endIdx);\n lastContent = currentContent.trim();\n capturing = false;\n currentContent = '';\n searchStart = endIdx + closeTag.length;\n } else {\n currentContent += chunk.slice(searchStart, -closeTag.length);\n leftover = chunk.slice(-closeTag.length);\n break;\n }\n }\n }\n }\n } finally {\n closeSync(fd);\n }\n\n return lastContent;\n}\n\n/**\n * Extract ALL dump script contents from an HTML file using streaming.\n * Each entry includes the full opening tag (for attribute extraction) and the content.\n *\n * @param filePath - Absolute path to the HTML file\n * @returns Array of { openTag, content } for each dump script found\n */\nexport function extractAllDumpScriptsSync(\n filePath: string,\n): { openTag: string; content: string }[] {\n const results: { openTag: string; content: string }[] = [];\n streamDumpScriptsSync(filePath, (dumpScript) => {\n results.push(dumpScript);\n return false;\n });\n return results;\n}\n\n/**\n * Stream ALL dump scripts from an HTML file.\n * Calls onMatch for each dump script and keeps memory bounded to a single\n * dump script payload instead of accumulating every dump in memory.\n *\n * @param filePath - Absolute path to the HTML file\n * @param onMatch - Callback for each dump script; return true to stop early\n */\nexport function streamDumpScriptsSync(\n filePath: string,\n onMatch: (dumpScript: { openTag: string; content: string }) => boolean,\n): void {\n const openTagPrefix = '<script type=\"midscene_web_dump\"';\n const closeTag = htmlScriptCloseTag();\n\n const fd = openSync(filePath, 'r');\n const fileSize = statSync(filePath).size;\n const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);\n\n let position = 0;\n let leftover = '';\n let capturing = false;\n let currentContent = '';\n let currentOpenTag = '';\n\n try {\n while (position < fileSize) {\n const bytesRead = readSync(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);\n const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);\n position += bytesRead;\n\n let searchStart = 0;\n\n while (searchStart < chunk.length) {\n if (!capturing) {\n const startIdx = chunk.indexOf(openTagPrefix, searchStart);\n if (startIdx !== -1) {\n const tagEndIdx = chunk.indexOf('>', startIdx);\n if (tagEndIdx !== -1) {\n capturing = true;\n currentOpenTag = chunk.slice(startIdx, tagEndIdx + 1);\n currentContent = chunk.slice(tagEndIdx + 1);\n const endIdx = currentContent.indexOf(closeTag);\n if (endIdx !== -1) {\n const shouldStop = onMatch({\n openTag: currentOpenTag,\n content: currentContent.slice(0, endIdx).trim(),\n });\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n currentOpenTag = '';\n searchStart = tagEndIdx + 1 + endIdx + closeTag.length;\n } else {\n leftover = currentContent.slice(-closeTag.length);\n currentContent = currentContent.slice(0, -closeTag.length);\n break;\n }\n } else {\n leftover = chunk.slice(startIdx);\n break;\n }\n } else {\n leftover = chunk.slice(-openTagPrefix.length);\n break;\n }\n } else {\n const endIdx = chunk.indexOf(closeTag, searchStart);\n if (endIdx !== -1) {\n currentContent += chunk.slice(searchStart, endIdx);\n const shouldStop = onMatch({\n openTag: currentOpenTag,\n content: currentContent.trim(),\n });\n if (shouldStop) return;\n capturing = false;\n currentContent = '';\n currentOpenTag = '';\n searchStart = endIdx + closeTag.length;\n } else {\n currentContent += chunk.slice(searchStart, -closeTag.length);\n leftover = chunk.slice(-closeTag.length);\n break;\n }\n }\n }\n }\n } finally {\n closeSync(fd);\n }\n}\n\nexport function parseImageScripts(html: string): Record<string, string> {\n const imageMap: Record<string, string> = {};\n const regex =\n /<script type=\"midscene-image\" data-id=\"([^\"]+)\">([\\s\\S]*?)<\\/script>/g;\n\n for (const match of html.matchAll(regex)) {\n const [, id, content] = match;\n imageMap[id] = unescapeContent(content);\n }\n\n return imageMap;\n}\n\nexport function parseDumpScript(html: string): string {\n // Use string search instead of regex to avoid ReDoS vulnerability\n // Find the LAST dump script tag (template may contain similar patterns in bundled JS)\n const scriptOpenTag = '<script type=\"midscene_web_dump\"';\n const closeTag = htmlScriptCloseTag();\n\n // Find the last occurrence of the opening tag\n const lastOpenIndex = html.lastIndexOf(scriptOpenTag);\n if (lastOpenIndex === -1) {\n throw new Error('No dump script found in HTML');\n }\n\n // Find the end of the opening tag (the '>' character)\n const tagEndIndex = html.indexOf('>', lastOpenIndex);\n if (tagEndIndex === -1) {\n throw new Error('No dump script found in HTML');\n }\n\n // Find the closing tag after the opening tag\n const closeIndex = html.indexOf(closeTag, tagEndIndex);\n if (closeIndex === -1) {\n throw new Error('No dump script found in HTML');\n }\n\n // Extract content between opening and closing tags\n const content = html.substring(tagEndIndex + 1, closeIndex);\n return unescapeContent(content);\n}\n\nexport function parseDumpScriptAttributes(\n html: string,\n): Record<string, string> {\n const regex = /<script type=\"midscene_web_dump\"([^>]*)>/;\n const match = regex.exec(html);\n\n if (!match) {\n return {};\n }\n\n const attrString = match[1];\n const attributes: Record<string, string> = {};\n const attrRegex = /(\\w+)=\"([^\"]*)\"/g;\n\n for (const attrMatch of attrString.matchAll(attrRegex)) {\n const [, key, value] = attrMatch;\n if (key !== 'type') {\n attributes[key] = decodeURIComponent(value);\n }\n }\n\n return attributes;\n}\n\nexport function generateImageScriptTag(id: string, data: string): string {\n // Do not use template string here, will cause bundle error with <script\n const closeTag = htmlScriptCloseTag();\n return (\n // biome-ignore lint/style/useTemplate: <explanation>\n '<script type=\"midscene-image\" data-id=\"' +\n id +\n '\">' +\n escapeContent(data) +\n closeTag\n );\n}\n\n/**\n * Inline script that fixes relative URL resolution for directory-mode reports.\n *\n * Problem: when a static server (e.g. `npx serve`) serves `name/index.html`\n * at URL `/name` (without trailing slash), relative paths like\n * `./screenshots/xxx.png` resolve to `/screenshots/xxx.png` instead of\n * `/name/screenshots/xxx.png`.\n *\n * Fix: dynamically insert a <base> tag so relative URLs resolve correctly.\n */\n// Do not use template string here, will cause bundle error with <script\n//\n// The closing script tag is built at runtime so bundlers cannot inline the\n// token that would prematurely close the report template's inline app bundle.\n//\n// Do NOT replace this with a string constant, hex escape (\\x3c), or literal\n// string concatenation. Bundlers may optimise those forms back to the unsafe\n// token.\nlet _baseUrlFixScript: string;\nexport function getBaseUrlFixScript(): string {\n if (!_baseUrlFixScript) {\n const close = htmlScriptCloseTag();\n _baseUrlFixScript =\n // biome-ignore lint/style/useTemplate: see above\n '\\n<script>(function(){' +\n 'var p=window.location.pathname;' +\n 'if(p.endsWith(\"/\")||/\\\\.\\\\w+$/.test(p))return;' +\n 'var b=document.createElement(\"base\");' +\n 'b.href=p+\"/\";' +\n 'document.head.insertBefore(b,document.head.firstChild)' +\n '})()' +\n close +\n '\\n';\n }\n return _baseUrlFixScript;\n}\n\n/**\n * Dump-script attribute that records how the report file stores screenshots.\n * Written by the report generator and the merger, read back when deciding\n * whether a report is in directory mode. Kept here, next to dump-tag\n * generation, so the writer and reader share one source of truth.\n */\nexport const DATA_SCREENSHOT_MODE_ATTR = 'data-screenshot-mode';\n\nexport function generateDumpScriptTag(\n json: string,\n attributes?: Record<string, string | number | boolean>,\n): string {\n const closeTag = htmlScriptCloseTag();\n let attrString = '';\n if (attributes && Object.keys(attributes).length > 0) {\n // Do not use template string here, will cause bundle error with <script\n attrString =\n // biome-ignore lint/style/useTemplate: <explanation>\n ' ' +\n Object.entries(attributes)\n // biome-ignore lint/style/useTemplate: <explanation>\n .map(([k, v]) => k + '=\"' + encodeURIComponent(v) + '\"')\n .join(' ');\n }\n\n // Do not use template string here, will cause bundle error with <script\n return (\n // biome-ignore lint/style/useTemplate: <explanation>\n '<script type=\"midscene_web_dump\"' +\n attrString +\n '>' +\n escapeContent(json) +\n closeTag\n );\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","escapeContent","escapeScriptTag","unescapeContent","antiEscapeScriptTag","cleanHtmlCommentValue","value","String","formatModelBriefForAgent","brief","intent","model","description","hasUsageModelInfo","usage","Boolean","formatUsageModelForAgent","source","collectUsageModelsForAgent","report","models","Map","executions","Array","execution","tasks","task","taskWithUsage","usages","formatted","generateAgentReportComment","taskCount","sum","modelBriefs","lines","htmlScriptCloseTag","STREAMING_CHUNK_SIZE","streamScanTags","filePath","openTag","closeTag","onMatch","fd","openSync","fileSize","statSync","buffer","Buffer","position","leftover","capturing","currentContent","bytesRead","readSync","chunk","searchStart","endIdx","shouldStop","startIdx","closeSync","extractImageByIdSync","htmlPath","imageId","targetTag","result","content","streamImageScriptsToFile","srcFilePath","destFilePath","appendFileSync","require","extractLastDumpScriptSync","openTagPrefix","lastContent","tagEndIdx","extractAllDumpScriptsSync","results","streamDumpScriptsSync","dumpScript","currentOpenTag","parseImageScripts","html","imageMap","regex","match","id","parseDumpScript","scriptOpenTag","lastOpenIndex","Error","tagEndIndex","closeIndex","parseDumpScriptAttributes","attrString","attributes","attrRegex","attrMatch","decodeURIComponent","generateImageScriptTag","data","_baseUrlFixScript","getBaseUrlFixScript","close","DATA_SCREENSHOT_MODE_ATTR","generateDumpScriptTag","json","k","v","encodeURIComponent"],"mappings":"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"}
@@ -45,6 +45,12 @@ function restoreImageReferences(data, resolveImage) {
45
45
  capturedAt: {
46
46
  value: refLike.capturedAt,
47
47
  enumerable: true
48
+ },
49
+ sourceRef: {
50
+ value: {
51
+ ...refLike
52
+ },
53
+ enumerable: true
48
54
  }
49
55
  });
50
56
  return lazy;
@@ -1 +1 @@
1
- {"version":3,"file":"dump/screenshot-restoration.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/screenshot-restoration.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { type ScreenshotRef, normalizeScreenshotRef } from './screenshot-store';\n\n/**\n * Recursively restore image references in parsed data.\n * Replaces ScreenshotRef with lazy\n * { get base64() {...}, capturedAt } objects.\n * The resolver is only called when .base64 is first accessed.\n */\nexport function restoreImageReferences<T>(\n data: T,\n resolveImage: (ref: ScreenshotRef) => string,\n): T {\n if (typeof data === 'string') {\n return data;\n }\n\n if (Array.isArray(data)) {\n return data.map((item) => restoreImageReferences(item, resolveImage)) as T;\n }\n\n if (typeof data === 'object' && data !== null) {\n const refLike = normalizeScreenshotRef(data);\n if (refLike) {\n let resolved: string | null = null;\n const lazy: { base64: string; capturedAt?: number } =\n Object.defineProperties({} as { base64: string; capturedAt?: number }, {\n base64: {\n get() {\n if (resolved === null) {\n resolved = resolveImage(refLike);\n }\n return resolved;\n },\n enumerable: true,\n },\n capturedAt: { value: refLike.capturedAt, enumerable: true },\n });\n return lazy as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[key] = restoreImageReferences(value, resolveImage);\n }\n return result as T;\n }\n\n return data;\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","restoreImageReferences","data","resolveImage","Array","item","refLike","normalizeScreenshotRef","resolved","lazy","result","value"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;ACEO,SAASI,uBACdC,IAAO,EACPC,YAA4C;IAE5C,IAAI,AAAgB,YAAhB,OAAOD,MACT,OAAOA;IAGT,IAAIE,MAAM,OAAO,CAACF,OAChB,OAAOA,KAAK,GAAG,CAAC,CAACG,OAASJ,uBAAuBI,MAAMF;IAGzD,IAAI,AAAgB,YAAhB,OAAOD,QAAqBA,AAAS,SAATA,MAAe;QAC7C,MAAMI,UAAUC,AAAAA,IAAAA,6CAAAA,sBAAAA,AAAAA,EAAuBL;QACvC,IAAII,SAAS;YACX,IAAIE,WAA0B;YAC9B,MAAMC,OACJZ,OAAO,gBAAgB,CAAC,CAAC,GAA8C;gBACrE,QAAQ;oBACN;wBACE,IAAIW,AAAa,SAAbA,UACFA,WAAWL,aAAaG;wBAE1B,OAAOE;oBACT;oBACA,YAAY;gBACd;gBACA,YAAY;oBAAE,OAAOF,QAAQ,UAAU;oBAAE,YAAY;gBAAK;YAC5D;YACF,OAAOG;QACT;QAEA,MAAMC,SAAkC,CAAC;QACzC,KAAK,MAAM,CAACd,KAAKe,MAAM,IAAId,OAAO,OAAO,CAACK,MACxCQ,MAAM,CAACd,IAAI,GAAGK,uBAAuBU,OAAOR;QAE9C,OAAOO;IACT;IAEA,OAAOR;AACT"}
1
+ {"version":3,"file":"dump/screenshot-restoration.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/dump/screenshot-restoration.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { type ScreenshotRef, normalizeScreenshotRef } from './screenshot-store';\n\n/**\n * Recursively restore image references in parsed data.\n * Replaces ScreenshotRef with lazy\n * { get base64() {...}, capturedAt, sourceRef } objects.\n * The resolver is only called when .base64 is first accessed.\n */\nexport function restoreImageReferences<T>(\n data: T,\n resolveImage: (ref: ScreenshotRef) => string,\n): T {\n if (typeof data === 'string') {\n return data;\n }\n\n if (Array.isArray(data)) {\n return data.map((item) => restoreImageReferences(item, resolveImage)) as T;\n }\n\n if (typeof data === 'object' && data !== null) {\n const refLike = normalizeScreenshotRef(data);\n if (refLike) {\n let resolved: string | null = null;\n const lazy: {\n base64: string;\n capturedAt?: number;\n sourceRef: ScreenshotRef;\n } = Object.defineProperties(\n {} as {\n base64: string;\n capturedAt?: number;\n sourceRef: ScreenshotRef;\n },\n {\n base64: {\n get() {\n if (resolved === null) {\n resolved = resolveImage(refLike);\n }\n return resolved;\n },\n enumerable: true,\n },\n capturedAt: { value: refLike.capturedAt, enumerable: true },\n sourceRef: { value: { ...refLike }, enumerable: true },\n },\n );\n return lazy as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[key] = restoreImageReferences(value, resolveImage);\n }\n return result as T;\n }\n\n return data;\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","restoreImageReferences","data","resolveImage","Array","item","refLike","normalizeScreenshotRef","resolved","lazy","result","value"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;ACEO,SAASI,uBACdC,IAAO,EACPC,YAA4C;IAE5C,IAAI,AAAgB,YAAhB,OAAOD,MACT,OAAOA;IAGT,IAAIE,MAAM,OAAO,CAACF,OAChB,OAAOA,KAAK,GAAG,CAAC,CAACG,OAASJ,uBAAuBI,MAAMF;IAGzD,IAAI,AAAgB,YAAhB,OAAOD,QAAqBA,AAAS,SAATA,MAAe;QAC7C,MAAMI,UAAUC,AAAAA,IAAAA,6CAAAA,sBAAAA,AAAAA,EAAuBL;QACvC,IAAII,SAAS;YACX,IAAIE,WAA0B;YAC9B,MAAMC,OAIFZ,OAAO,gBAAgB,CACzB,CAAC,GAKD;gBACE,QAAQ;oBACN;wBACE,IAAIW,AAAa,SAAbA,UACFA,WAAWL,aAAaG;wBAE1B,OAAOE;oBACT;oBACA,YAAY;gBACd;gBACA,YAAY;oBAAE,OAAOF,QAAQ,UAAU;oBAAE,YAAY;gBAAK;gBAC1D,WAAW;oBAAE,OAAO;wBAAE,GAAGA,OAAO;oBAAC;oBAAG,YAAY;gBAAK;YACvD;YAEF,OAAOG;QACT;QAEA,MAAMC,SAAkC,CAAC;QACzC,KAAK,MAAM,CAACd,KAAKe,MAAM,IAAId,OAAO,OAAO,CAACK,MACxCQ,MAAM,CAACd,IAAI,GAAGK,uBAAuBU,OAAOR;QAE9C,OAAOO;IACT;IAEA,OAAOR;AACT"}