@midscene/core 1.12.5 → 1.12.6-beta-20260909034232.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/es/agent/agent.mjs +42 -1
  2. package/dist/es/agent/agent.mjs.map +1 -1
  3. package/dist/es/agent/report-file-name.mjs +12 -0
  4. package/dist/es/agent/report-file-name.mjs.map +1 -0
  5. package/dist/es/agent/utils.mjs +4 -10
  6. package/dist/es/agent/utils.mjs.map +1 -1
  7. package/dist/es/ai-model/service-caller/index.mjs +21 -36
  8. package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
  9. package/dist/es/index.mjs +3 -2
  10. package/dist/es/index.mjs.map +1 -1
  11. package/dist/es/report-html-template.mjs +1 -1
  12. package/dist/es/report.mjs +181 -4
  13. package/dist/es/report.mjs.map +1 -1
  14. package/dist/es/test-run-report.mjs +4 -0
  15. package/dist/es/test-run-report.mjs.map +1 -0
  16. package/dist/es/utils.mjs +1 -1
  17. package/dist/es/yaml/player.mjs +6 -6
  18. package/dist/es/yaml/player.mjs.map +1 -1
  19. package/dist/lib/agent/agent.js +41 -0
  20. package/dist/lib/agent/agent.js.map +1 -1
  21. package/dist/lib/agent/report-file-name.js +56 -0
  22. package/dist/lib/agent/report-file-name.js.map +1 -0
  23. package/dist/lib/agent/utils.js +3 -19
  24. package/dist/lib/agent/utils.js.map +1 -1
  25. package/dist/lib/ai-model/service-caller/index.js +21 -36
  26. package/dist/lib/ai-model/service-caller/index.js.map +1 -1
  27. package/dist/lib/index.js +10 -3
  28. package/dist/lib/index.js.map +1 -1
  29. package/dist/lib/report-html-template.js +1 -1
  30. package/dist/lib/report.js +183 -3
  31. package/dist/lib/report.js.map +1 -1
  32. package/dist/lib/test-run-report.js +38 -0
  33. package/dist/lib/test-run-report.js.map +1 -0
  34. package/dist/lib/utils.js +1 -1
  35. package/dist/lib/yaml/player.js +1 -1
  36. package/dist/lib/yaml/player.js.map +1 -1
  37. package/dist/types/agent/agent.d.ts +6 -0
  38. package/dist/types/agent/report-file-name.d.ts +1 -0
  39. package/dist/types/agent/utils.d.ts +1 -2
  40. package/dist/types/index.d.ts +3 -1
  41. package/dist/types/report.d.ts +11 -0
  42. package/dist/types/test-run-report.d.ts +167 -0
  43. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"agent/utils.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/agent/utils.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__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 { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { PixelLocateResult } from '@/ai-model/shared/model-locate-result';\nimport type { TMultimodalPrompt, TUserPrompt } from '@/common';\nimport type { AbstractInterface } from '@/device';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n DetailedLocateParam,\n ElementCacheFeature,\n LocateResultElement,\n Rect,\n ScrollParam,\n Size,\n UIContext,\n} from '@/types';\nimport { uploadTestInfoToServer } from '@/utils';\nimport {\n MIDSCENE_REPORT_QUIET,\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport {\n createImgBase64ByFormat,\n imageInfoOfBase64,\n} from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { _keyDefinitions } from '@midscene/shared/us-keyboard-layout';\nimport { assert, ifInBrowser, logMsg, uuid } from '@midscene/shared/utils';\nimport dayjs from 'dayjs';\nimport { prepareRawScreenshot } from './screenshot-preparation';\nimport type { TaskCache } from './task-cache';\nimport { debug as cacheDebug } from './task-cache';\n\nconst agentDebug = getDebug('agent');\nconst screenshotDataUrlPattern = /^data:image\\/[a-zA-Z0-9.+-]+;base64,/i;\n\nconst inferBase64ImageFormat = (base64Body: string) => {\n if (base64Body.startsWith('iVBORw0KGgo')) {\n return 'png';\n }\n return 'jpeg';\n};\n\nconst normalizeScreenshotBase64 = (screenshotBase64: string) => {\n const trimmedBase64 = screenshotBase64.trim();\n if (screenshotDataUrlPattern.test(trimmedBase64)) {\n return trimmedBase64;\n }\n\n const base64Body = trimmedBase64.replace(/\\s/g, '');\n assert(base64Body, 'screenshotBase64 must include image data');\n return createImgBase64ByFormat(\n inferBase64ImageFormat(base64Body),\n base64Body,\n );\n};\n\nconst legacyScrollTypeMap = {\n once: 'singleAction',\n untilBottom: 'scrollToBottom',\n untilTop: 'scrollToTop',\n untilRight: 'scrollToRight',\n untilLeft: 'scrollToLeft',\n} as const;\n\nexport const normalizeScrollType = (\n scrollType: string | undefined,\n): ScrollParam['scrollType'] | undefined => {\n if (!scrollType) {\n return undefined;\n }\n\n if (scrollType in legacyScrollTypeMap) {\n return legacyScrollTypeMap[scrollType as keyof typeof legacyScrollTypeMap];\n }\n\n return scrollType as ScrollParam['scrollType'];\n};\n\nexport async function commonContextParser(\n interfaceInstance: AbstractInterface,\n _opt: {\n uploadServerUrl?: string;\n screenshotShrinkFactor?: number;\n },\n): Promise<UIContext> {\n const debug = getDebug('commonContextParser');\n\n assert(interfaceInstance, 'interfaceInstance is required');\n\n debug('Getting interface description');\n const description = interfaceInstance.describe?.() || '';\n debug('Interface description end');\n\n debug('Uploading test info to server');\n uploadTestInfoToServer({\n testUrl: description,\n serverUrl: _opt.uploadServerUrl,\n });\n debug('UploadTestInfoToServer end');\n\n debug('will get size');\n const interfaceSize = await interfaceInstance.size();\n const { width: logicalWidth, height: logicalHeight } = interfaceSize;\n\n if ((interfaceSize as unknown as { dpr: number }).dpr) {\n console.warn(\n 'Warning: return value of interface.size() include a dpr property, which is not expected and ignored. ',\n );\n }\n\n if (!Number.isFinite(logicalWidth) || !Number.isFinite(logicalHeight)) {\n throw new Error(\n `Invalid interface size: width and height must be finite numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`,\n );\n }\n\n if (logicalWidth <= 0 || logicalHeight <= 0) {\n throw new Error(\n `Invalid interface size: width and height must be positive numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`,\n );\n }\n\n debug(`size: ${logicalWidth}x${logicalHeight}`);\n\n const screenshotBase64 = await interfaceInstance.screenshotBase64();\n const screenshotCapturedAt = Date.now();\n assert(screenshotBase64!, 'screenshotBase64 is required');\n const userShrinkFactor = _opt.screenshotShrinkFactor ?? 1;\n\n debug('will get screenshot dimensions');\n const preparedScreenshot = await prepareRawScreenshot(screenshotBase64, {\n shrinkFactor: userShrinkFactor,\n });\n const { width: imgWidth, height: imgHeight } =\n preparedScreenshot.originalSize;\n debug('screenshot dimensions', imgWidth, 'x', imgHeight);\n\n // Detect orientation mismatch between logical size and screenshot.\n // Some devices (e.g. OPPO) report wrong orientation via ADB, causing\n // size() to return portrait dimensions even when the device is landscape.\n // We detect this by comparing aspect ratios and swap if they disagree.\n const logicalIsPortrait = logicalWidth < logicalHeight;\n const screenshotIsPortrait = imgWidth < imgHeight;\n let finalLogicalWidth = logicalWidth;\n let finalLogicalHeight = logicalHeight;\n if (logicalIsPortrait !== screenshotIsPortrait) {\n debug(\n `Orientation mismatch detected: logical size ${logicalWidth}x${logicalHeight} (${logicalIsPortrait ? 'portrait' : 'landscape'}) vs screenshot ${imgWidth}x${imgHeight} (${screenshotIsPortrait ? 'portrait' : 'landscape'}). Swapping logical dimensions.`,\n );\n finalLogicalWidth = logicalHeight;\n finalLogicalHeight = logicalWidth;\n }\n\n const dpr = imgWidth / finalLogicalWidth;\n\n debug('calculated dpr:', dpr);\n\n const shrunkShotToLogicalRatio = dpr / userShrinkFactor;\n\n debug('shrunkShotToLogicalRatio', shrunkShotToLogicalRatio);\n\n if (userShrinkFactor > 1) {\n debug(\n `Applied screenshot shrink factor: ${userShrinkFactor} (physical: ${imgWidth}x${imgHeight} -> target: ${preparedScreenshot.shotSize.width}x${preparedScreenshot.shotSize.height})`,\n );\n }\n\n return {\n shotSize: preparedScreenshot.shotSize,\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(\n preparedScreenshot.base64,\n screenshotCapturedAt,\n ),\n shrunkShotToLogicalRatio,\n };\n}\n\nexport async function createScreenshotBoundUIContext(\n screenshotBase64: string,\n opt: {\n screenshotSize?: Size;\n },\n): Promise<UIContext> {\n const normalizedScreenshotBase64 =\n normalizeScreenshotBase64(screenshotBase64);\n const actualScreenshotSize = await imageInfoOfBase64(\n normalizedScreenshotBase64,\n );\n if (\n opt.screenshotSize &&\n (opt.screenshotSize.width !== actualScreenshotSize.width ||\n opt.screenshotSize.height !== actualScreenshotSize.height)\n ) {\n agentDebug(\n 'describeElementAtPoint screenshotSize mismatch, use actual size',\n {\n provided: opt.screenshotSize,\n actual: actualScreenshotSize,\n },\n );\n }\n\n return {\n screenshot: ScreenshotItem.create(normalizedScreenshotBase64, Date.now()),\n shotSize: actualScreenshotSize,\n shrunkShotToLogicalRatio: 1,\n _isFrozen: true,\n };\n}\n\nexport function getReportFileName(tag = 'web') {\n const reportTagName = globalConfigManager.getEnvConfigValue(\n MIDSCENE_REPORT_TAG_NAME,\n );\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\n}\n\nexport function printReportMsg(filepath: string) {\n if (globalConfigManager.getEnvConfigInBoolean(MIDSCENE_REPORT_QUIET)) {\n return;\n }\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\ntype NormalizeFilePathsOptions = {\n fileExists?: (path: string) => boolean;\n isInBrowser?: boolean;\n resolvePath?: (path: string) => string;\n wslDistroName?: string;\n cwd?: string;\n};\n\nexport function normalizeFilePaths(\n files: string[],\n options: NormalizeFilePathsOptions = {},\n): string[] {\n const {\n fileExists = existsSync,\n isInBrowser = ifInBrowser,\n resolvePath = resolve,\n wslDistroName = process.env.WSL_DISTRO_NAME,\n cwd = process.cwd(),\n } = options;\n\n if (isInBrowser) {\n throw new Error('File chooser is not supported in browser environment');\n }\n\n return files.map((file) => {\n const absolutePath = resolvePath(file);\n if (!fileExists(absolutePath)) {\n throw new Error(\n `File not found: ${file}. Resolved to: ${absolutePath}. Current working directory: ${cwd}`,\n );\n }\n\n if (!wslDistroName) {\n return absolutePath;\n }\n\n const wslMount = absolutePath.match(/^\\/mnt\\/([a-z])\\//);\n if (wslMount) {\n return `${wslMount[1].toUpperCase()}:\\\\${absolutePath.slice(7).replace(/\\//g, '\\\\')}`;\n }\n\n return `\\\\\\\\wsl$\\\\${wslDistroName}${absolutePath.replace(/\\//g, '\\\\')}`;\n });\n}\n\ntype LocateParamWithMaybeLocatedPixelResult = DetailedLocateParam & {\n locatedPixelResult?: unknown;\n};\n\ntype LocateParamWithLocatedPixelResult = DetailedLocateParam & {\n locatedPixelResult: PixelLocateResult;\n};\n\nexport function ifLocateParamHasLocatedPixelResult(\n planLocateParam: LocateParamWithMaybeLocatedPixelResult,\n): planLocateParam is LocateParamWithLocatedPixelResult {\n const result = planLocateParam.locatedPixelResult;\n if (!result || typeof result !== 'object' || !('center' in result)) {\n return false;\n }\n const point = result.center;\n return (\n Array.isArray(point) &&\n point.length === 2 &&\n point.every((v) => typeof v === 'number' && Number.isFinite(v))\n );\n}\n\nexport function matchElementFromPlan(\n planLocateParam: LocateParamWithLocatedPixelResult,\n): LocateResultElement | undefined {\n if (!planLocateParam) {\n return undefined;\n }\n\n const { center, rect } = planLocateParam.locatedPixelResult;\n return {\n center: [...center],\n description:\n typeof planLocateParam.prompt === 'string'\n ? planLocateParam.prompt\n : planLocateParam.prompt?.prompt || '',\n ...(rect ? { rect } : {}),\n };\n}\n\nexport async function matchElementFromCache(\n context: {\n taskCache?: TaskCache;\n interfaceInstance: AbstractInterface;\n },\n cacheEntry: ElementCacheFeature | undefined,\n cachePrompt: TUserPrompt,\n cacheable: boolean | undefined,\n): Promise<LocateResultElement | undefined> {\n if (!cacheEntry) {\n return undefined;\n }\n\n if (cacheable === false) {\n cacheDebug('cache disabled for prompt: %s', cachePrompt);\n return undefined;\n }\n\n if (!context.taskCache?.isCacheResultUsed) {\n return undefined;\n }\n\n if (!context.interfaceInstance.rectMatchesCacheFeature) {\n cacheDebug(\n 'interface does not implement rectMatchesCacheFeature, skip cache',\n );\n return undefined;\n }\n\n try {\n const rect =\n await context.interfaceInstance.rectMatchesCacheFeature(cacheEntry);\n const element: LocateResultElement = {\n center: [rect.left + rect.width / 2, rect.top + rect.height / 2],\n rect,\n description:\n typeof cachePrompt === 'string'\n ? cachePrompt\n : cachePrompt.prompt || '',\n };\n\n cacheDebug('cache hit, prompt: %s', cachePrompt);\n return element;\n } catch (error) {\n cacheDebug('rectMatchesCacheFeature error: %s', error);\n return undefined;\n }\n}\n\ndeclare const __VERSION__: string | undefined;\n\nexport const getMidsceneVersion = (): string => {\n if (typeof __VERSION__ !== 'undefined') {\n return __VERSION__;\n } else if (\n process.env.__VERSION__ &&\n process.env.__VERSION__ !== 'undefined'\n ) {\n return process.env.__VERSION__;\n }\n throw new Error('__VERSION__ inject failed during build');\n};\n\nexport const parsePrompt = (\n prompt: TUserPrompt,\n): {\n textPrompt: string;\n multimodalPrompt?: TMultimodalPrompt;\n} => {\n if (typeof prompt === 'string') {\n return {\n textPrompt: prompt,\n multimodalPrompt: undefined,\n };\n }\n return {\n textPrompt: prompt.prompt,\n multimodalPrompt: prompt.images\n ? {\n images: prompt.images,\n convertHttpImage2Base64: !!prompt.convertHttpImage2Base64,\n }\n : undefined,\n };\n};\n\nexport const transformLogicalElementToScreenshot = (\n element: LocateResultElement,\n shrunkShotToLogicalRatio: number,\n): LocateResultElement => {\n if (shrunkShotToLogicalRatio === 1) {\n return element;\n }\n\n return {\n ...element,\n center: [\n element.center[0] * shrunkShotToLogicalRatio,\n element.center[1] * shrunkShotToLogicalRatio,\n ],\n ...(element.rect\n ? {\n rect: transformLogicalRectToScreenshotRect(\n element.rect,\n shrunkShotToLogicalRatio,\n ),\n }\n : {}),\n };\n};\n\nexport const transformLogicalRectToScreenshotRect = (\n rect: Rect,\n shrunkShotToLogicalRatio: number,\n): Rect => {\n if (shrunkShotToLogicalRatio === 1) {\n return rect;\n }\n\n return {\n ...rect,\n left: Math.round(rect.left * shrunkShotToLogicalRatio),\n top: Math.round(rect.top * shrunkShotToLogicalRatio),\n width: Math.round(rect.width * shrunkShotToLogicalRatio),\n height: Math.round(rect.height * shrunkShotToLogicalRatio),\n };\n};\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","agentDebug","getDebug","screenshotDataUrlPattern","inferBase64ImageFormat","base64Body","normalizeScreenshotBase64","screenshotBase64","trimmedBase64","assert","createImgBase64ByFormat","legacyScrollTypeMap","normalizeScrollType","scrollType","commonContextParser","interfaceInstance","_opt","debug","description","uploadTestInfoToServer","interfaceSize","logicalWidth","logicalHeight","console","Number","Error","screenshotCapturedAt","Date","userShrinkFactor","preparedScreenshot","prepareRawScreenshot","imgWidth","imgHeight","logicalIsPortrait","screenshotIsPortrait","finalLogicalWidth","dpr","shrunkShotToLogicalRatio","ScreenshotItem","createScreenshotBoundUIContext","opt","normalizedScreenshotBase64","actualScreenshotSize","imageInfoOfBase64","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","MIDSCENE_REPORT_QUIET","logMsg","normalizeFilePaths","files","options","fileExists","existsSync","isInBrowser","ifInBrowser","resolvePath","resolve","wslDistroName","process","cwd","file","absolutePath","wslMount","ifLocateParamHasLocatedPixelResult","planLocateParam","result","point","Array","v","matchElementFromPlan","center","rect","matchElementFromCache","context","cacheEntry","cachePrompt","cacheable","cacheDebug","element","error","getMidsceneVersion","__VERSION__","parsePrompt","prompt","undefined","transformLogicalElementToScreenshot","transformLogicalRectToScreenshotRect","Math"],"mappings":"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"}
1
+ {"version":3,"file":"agent/utils.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/agent/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 { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { PixelLocateResult } from '@/ai-model/shared/model-locate-result';\nimport type { TMultimodalPrompt, TUserPrompt } from '@/common';\nimport type { AbstractInterface } from '@/device';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n DetailedLocateParam,\n ElementCacheFeature,\n LocateResultElement,\n Rect,\n ScrollParam,\n Size,\n UIContext,\n} from '@/types';\nimport { uploadTestInfoToServer } from '@/utils';\nimport {\n MIDSCENE_REPORT_QUIET,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport {\n createImgBase64ByFormat,\n imageInfoOfBase64,\n} from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { _keyDefinitions } from '@midscene/shared/us-keyboard-layout';\nimport { assert, ifInBrowser, logMsg } from '@midscene/shared/utils';\nimport { prepareRawScreenshot } from './screenshot-preparation';\nimport type { TaskCache } from './task-cache';\nimport { debug as cacheDebug } from './task-cache';\n\nexport { getReportFileName } from './report-file-name';\n\nconst agentDebug = getDebug('agent');\nconst screenshotDataUrlPattern = /^data:image\\/[a-zA-Z0-9.+-]+;base64,/i;\n\nconst inferBase64ImageFormat = (base64Body: string) => {\n if (base64Body.startsWith('iVBORw0KGgo')) {\n return 'png';\n }\n return 'jpeg';\n};\n\nconst normalizeScreenshotBase64 = (screenshotBase64: string) => {\n const trimmedBase64 = screenshotBase64.trim();\n if (screenshotDataUrlPattern.test(trimmedBase64)) {\n return trimmedBase64;\n }\n\n const base64Body = trimmedBase64.replace(/\\s/g, '');\n assert(base64Body, 'screenshotBase64 must include image data');\n return createImgBase64ByFormat(\n inferBase64ImageFormat(base64Body),\n base64Body,\n );\n};\n\nconst legacyScrollTypeMap = {\n once: 'singleAction',\n untilBottom: 'scrollToBottom',\n untilTop: 'scrollToTop',\n untilRight: 'scrollToRight',\n untilLeft: 'scrollToLeft',\n} as const;\n\nexport const normalizeScrollType = (\n scrollType: string | undefined,\n): ScrollParam['scrollType'] | undefined => {\n if (!scrollType) {\n return undefined;\n }\n\n if (scrollType in legacyScrollTypeMap) {\n return legacyScrollTypeMap[scrollType as keyof typeof legacyScrollTypeMap];\n }\n\n return scrollType as ScrollParam['scrollType'];\n};\n\nexport async function commonContextParser(\n interfaceInstance: AbstractInterface,\n _opt: {\n uploadServerUrl?: string;\n screenshotShrinkFactor?: number;\n },\n): Promise<UIContext> {\n const debug = getDebug('commonContextParser');\n\n assert(interfaceInstance, 'interfaceInstance is required');\n\n debug('Getting interface description');\n const description = interfaceInstance.describe?.() || '';\n debug('Interface description end');\n\n debug('Uploading test info to server');\n uploadTestInfoToServer({\n testUrl: description,\n serverUrl: _opt.uploadServerUrl,\n });\n debug('UploadTestInfoToServer end');\n\n debug('will get size');\n const interfaceSize = await interfaceInstance.size();\n const { width: logicalWidth, height: logicalHeight } = interfaceSize;\n\n if ((interfaceSize as unknown as { dpr: number }).dpr) {\n console.warn(\n 'Warning: return value of interface.size() include a dpr property, which is not expected and ignored. ',\n );\n }\n\n if (!Number.isFinite(logicalWidth) || !Number.isFinite(logicalHeight)) {\n throw new Error(\n `Invalid interface size: width and height must be finite numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`,\n );\n }\n\n if (logicalWidth <= 0 || logicalHeight <= 0) {\n throw new Error(\n `Invalid interface size: width and height must be positive numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`,\n );\n }\n\n debug(`size: ${logicalWidth}x${logicalHeight}`);\n\n const screenshotBase64 = await interfaceInstance.screenshotBase64();\n const screenshotCapturedAt = Date.now();\n assert(screenshotBase64!, 'screenshotBase64 is required');\n const userShrinkFactor = _opt.screenshotShrinkFactor ?? 1;\n\n debug('will get screenshot dimensions');\n const preparedScreenshot = await prepareRawScreenshot(screenshotBase64, {\n shrinkFactor: userShrinkFactor,\n });\n const { width: imgWidth, height: imgHeight } =\n preparedScreenshot.originalSize;\n debug('screenshot dimensions', imgWidth, 'x', imgHeight);\n\n // Detect orientation mismatch between logical size and screenshot.\n // Some devices (e.g. OPPO) report wrong orientation via ADB, causing\n // size() to return portrait dimensions even when the device is landscape.\n // We detect this by comparing aspect ratios and swap if they disagree.\n const logicalIsPortrait = logicalWidth < logicalHeight;\n const screenshotIsPortrait = imgWidth < imgHeight;\n let finalLogicalWidth = logicalWidth;\n let finalLogicalHeight = logicalHeight;\n if (logicalIsPortrait !== screenshotIsPortrait) {\n debug(\n `Orientation mismatch detected: logical size ${logicalWidth}x${logicalHeight} (${logicalIsPortrait ? 'portrait' : 'landscape'}) vs screenshot ${imgWidth}x${imgHeight} (${screenshotIsPortrait ? 'portrait' : 'landscape'}). Swapping logical dimensions.`,\n );\n finalLogicalWidth = logicalHeight;\n finalLogicalHeight = logicalWidth;\n }\n\n const dpr = imgWidth / finalLogicalWidth;\n\n debug('calculated dpr:', dpr);\n\n const shrunkShotToLogicalRatio = dpr / userShrinkFactor;\n\n debug('shrunkShotToLogicalRatio', shrunkShotToLogicalRatio);\n\n if (userShrinkFactor > 1) {\n debug(\n `Applied screenshot shrink factor: ${userShrinkFactor} (physical: ${imgWidth}x${imgHeight} -> target: ${preparedScreenshot.shotSize.width}x${preparedScreenshot.shotSize.height})`,\n );\n }\n\n return {\n shotSize: preparedScreenshot.shotSize,\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(\n preparedScreenshot.base64,\n screenshotCapturedAt,\n ),\n shrunkShotToLogicalRatio,\n };\n}\n\nexport async function createScreenshotBoundUIContext(\n screenshotBase64: string,\n opt: {\n screenshotSize?: Size;\n },\n): Promise<UIContext> {\n const normalizedScreenshotBase64 =\n normalizeScreenshotBase64(screenshotBase64);\n const actualScreenshotSize = await imageInfoOfBase64(\n normalizedScreenshotBase64,\n );\n if (\n opt.screenshotSize &&\n (opt.screenshotSize.width !== actualScreenshotSize.width ||\n opt.screenshotSize.height !== actualScreenshotSize.height)\n ) {\n agentDebug(\n 'describeElementAtPoint screenshotSize mismatch, use actual size',\n {\n provided: opt.screenshotSize,\n actual: actualScreenshotSize,\n },\n );\n }\n\n return {\n screenshot: ScreenshotItem.create(normalizedScreenshotBase64, Date.now()),\n shotSize: actualScreenshotSize,\n shrunkShotToLogicalRatio: 1,\n _isFrozen: true,\n };\n}\n\nexport function printReportMsg(filepath: string) {\n if (globalConfigManager.getEnvConfigInBoolean(MIDSCENE_REPORT_QUIET)) {\n return;\n }\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\ntype NormalizeFilePathsOptions = {\n fileExists?: (path: string) => boolean;\n isInBrowser?: boolean;\n resolvePath?: (path: string) => string;\n wslDistroName?: string;\n cwd?: string;\n};\n\nexport function normalizeFilePaths(\n files: string[],\n options: NormalizeFilePathsOptions = {},\n): string[] {\n const {\n fileExists = existsSync,\n isInBrowser = ifInBrowser,\n resolvePath = resolve,\n wslDistroName = process.env.WSL_DISTRO_NAME,\n cwd = process.cwd(),\n } = options;\n\n if (isInBrowser) {\n throw new Error('File chooser is not supported in browser environment');\n }\n\n return files.map((file) => {\n const absolutePath = resolvePath(file);\n if (!fileExists(absolutePath)) {\n throw new Error(\n `File not found: ${file}. Resolved to: ${absolutePath}. Current working directory: ${cwd}`,\n );\n }\n\n if (!wslDistroName) {\n return absolutePath;\n }\n\n const wslMount = absolutePath.match(/^\\/mnt\\/([a-z])\\//);\n if (wslMount) {\n return `${wslMount[1].toUpperCase()}:\\\\${absolutePath.slice(7).replace(/\\//g, '\\\\')}`;\n }\n\n return `\\\\\\\\wsl$\\\\${wslDistroName}${absolutePath.replace(/\\//g, '\\\\')}`;\n });\n}\n\ntype LocateParamWithMaybeLocatedPixelResult = DetailedLocateParam & {\n locatedPixelResult?: unknown;\n};\n\ntype LocateParamWithLocatedPixelResult = DetailedLocateParam & {\n locatedPixelResult: PixelLocateResult;\n};\n\nexport function ifLocateParamHasLocatedPixelResult(\n planLocateParam: LocateParamWithMaybeLocatedPixelResult,\n): planLocateParam is LocateParamWithLocatedPixelResult {\n const result = planLocateParam.locatedPixelResult;\n if (!result || typeof result !== 'object' || !('center' in result)) {\n return false;\n }\n const point = result.center;\n return (\n Array.isArray(point) &&\n point.length === 2 &&\n point.every((v) => typeof v === 'number' && Number.isFinite(v))\n );\n}\n\nexport function matchElementFromPlan(\n planLocateParam: LocateParamWithLocatedPixelResult,\n): LocateResultElement | undefined {\n if (!planLocateParam) {\n return undefined;\n }\n\n const { center, rect } = planLocateParam.locatedPixelResult;\n return {\n center: [...center],\n description:\n typeof planLocateParam.prompt === 'string'\n ? planLocateParam.prompt\n : planLocateParam.prompt?.prompt || '',\n ...(rect ? { rect } : {}),\n };\n}\n\nexport async function matchElementFromCache(\n context: {\n taskCache?: TaskCache;\n interfaceInstance: AbstractInterface;\n },\n cacheEntry: ElementCacheFeature | undefined,\n cachePrompt: TUserPrompt,\n cacheable: boolean | undefined,\n): Promise<LocateResultElement | undefined> {\n if (!cacheEntry) {\n return undefined;\n }\n\n if (cacheable === false) {\n cacheDebug('cache disabled for prompt: %s', cachePrompt);\n return undefined;\n }\n\n if (!context.taskCache?.isCacheResultUsed) {\n return undefined;\n }\n\n if (!context.interfaceInstance.rectMatchesCacheFeature) {\n cacheDebug(\n 'interface does not implement rectMatchesCacheFeature, skip cache',\n );\n return undefined;\n }\n\n try {\n const rect =\n await context.interfaceInstance.rectMatchesCacheFeature(cacheEntry);\n const element: LocateResultElement = {\n center: [rect.left + rect.width / 2, rect.top + rect.height / 2],\n rect,\n description:\n typeof cachePrompt === 'string'\n ? cachePrompt\n : cachePrompt.prompt || '',\n };\n\n cacheDebug('cache hit, prompt: %s', cachePrompt);\n return element;\n } catch (error) {\n cacheDebug('rectMatchesCacheFeature error: %s', error);\n return undefined;\n }\n}\n\ndeclare const __VERSION__: string | undefined;\n\nexport const getMidsceneVersion = (): string => {\n if (typeof __VERSION__ !== 'undefined') {\n return __VERSION__;\n } else if (\n process.env.__VERSION__ &&\n process.env.__VERSION__ !== 'undefined'\n ) {\n return process.env.__VERSION__;\n }\n throw new Error('__VERSION__ inject failed during build');\n};\n\nexport const parsePrompt = (\n prompt: TUserPrompt,\n): {\n textPrompt: string;\n multimodalPrompt?: TMultimodalPrompt;\n} => {\n if (typeof prompt === 'string') {\n return {\n textPrompt: prompt,\n multimodalPrompt: undefined,\n };\n }\n return {\n textPrompt: prompt.prompt,\n multimodalPrompt: prompt.images\n ? {\n images: prompt.images,\n convertHttpImage2Base64: !!prompt.convertHttpImage2Base64,\n }\n : undefined,\n };\n};\n\nexport const transformLogicalElementToScreenshot = (\n element: LocateResultElement,\n shrunkShotToLogicalRatio: number,\n): LocateResultElement => {\n if (shrunkShotToLogicalRatio === 1) {\n return element;\n }\n\n return {\n ...element,\n center: [\n element.center[0] * shrunkShotToLogicalRatio,\n element.center[1] * shrunkShotToLogicalRatio,\n ],\n ...(element.rect\n ? {\n rect: transformLogicalRectToScreenshotRect(\n element.rect,\n shrunkShotToLogicalRatio,\n ),\n }\n : {}),\n };\n};\n\nexport const transformLogicalRectToScreenshotRect = (\n rect: Rect,\n shrunkShotToLogicalRatio: number,\n): Rect => {\n if (shrunkShotToLogicalRatio === 1) {\n return rect;\n }\n\n return {\n ...rect,\n left: Math.round(rect.left * shrunkShotToLogicalRatio),\n top: Math.round(rect.top * shrunkShotToLogicalRatio),\n width: Math.round(rect.width * shrunkShotToLogicalRatio),\n height: Math.round(rect.height * shrunkShotToLogicalRatio),\n };\n};\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","agentDebug","getDebug","screenshotDataUrlPattern","inferBase64ImageFormat","base64Body","normalizeScreenshotBase64","screenshotBase64","trimmedBase64","assert","createImgBase64ByFormat","legacyScrollTypeMap","normalizeScrollType","scrollType","commonContextParser","interfaceInstance","_opt","debug","description","uploadTestInfoToServer","interfaceSize","logicalWidth","logicalHeight","console","Number","Error","screenshotCapturedAt","Date","userShrinkFactor","preparedScreenshot","prepareRawScreenshot","imgWidth","imgHeight","logicalIsPortrait","screenshotIsPortrait","finalLogicalWidth","dpr","shrunkShotToLogicalRatio","ScreenshotItem","createScreenshotBoundUIContext","opt","normalizedScreenshotBase64","actualScreenshotSize","imageInfoOfBase64","printReportMsg","filepath","globalConfigManager","MIDSCENE_REPORT_QUIET","logMsg","normalizeFilePaths","files","options","fileExists","existsSync","isInBrowser","ifInBrowser","resolvePath","resolve","wslDistroName","process","cwd","file","absolutePath","wslMount","ifLocateParamHasLocatedPixelResult","planLocateParam","result","point","Array","v","matchElementFromPlan","center","rect","matchElementFromCache","context","cacheEntry","cachePrompt","cacheable","cacheDebug","element","error","getMidsceneVersion","__VERSION__","parsePrompt","prompt","undefined","transformLogicalElementToScreenshot","transformLogicalRectToScreenshotRect","Math"],"mappings":"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"}
@@ -416,7 +416,11 @@ async function callAI(messages, modelRuntime, options) {
416
416
  model: modelName,
417
417
  messages: messagesWithImageDetail,
418
418
  ...requestConfig,
419
- stream: true
419
+ stream: true,
420
+ stream_options: {
421
+ ...requestConfig.stream_options,
422
+ include_usage: true
423
+ }
420
424
  }, {
421
425
  stream: true,
422
426
  signal: streamSignal
@@ -449,34 +453,23 @@ async function callAI(messages, modelRuntime, options) {
449
453
  };
450
454
  options.onChunk(chunkData);
451
455
  }
452
- if (chunk.choices?.[0]?.finish_reason) {
453
- timeCost = Date.now() - startTime;
454
- if (!usage) {
455
- const estimatedTokens = Math.max(1, Math.floor(accumulated.length / 4));
456
- usage = {
457
- prompt_tokens: estimatedTokens,
458
- completion_tokens: estimatedTokens,
459
- total_tokens: 2 * estimatedTokens
460
- };
461
- }
462
- const finalAccumulated = resolveContentWithReasoningFallback(accumulated, accumulatedReasoning);
463
- accumulated = finalAccumulated || '';
464
- const finalUsage = buildUsageInfo(usage, requestId);
465
- if (finalUsage && modelRuntime.onUsage) {
466
- modelRuntime.onUsage(finalUsage);
467
- usageReported = true;
468
- }
469
- const finalChunk = {
470
- content: '',
471
- accumulated,
472
- reasoning_content: '',
473
- isComplete: true,
474
- usage: finalUsage
475
- };
476
- options.onChunk(finalChunk);
477
- break;
478
- }
479
456
  }
457
+ timeCost = Date.now() - startTime;
458
+ const finalAccumulated = resolveContentWithReasoningFallback(accumulated, accumulatedReasoning);
459
+ accumulated = finalAccumulated || '';
460
+ const finalUsage = buildUsageInfo(usage, requestId);
461
+ if (finalUsage && modelRuntime.onUsage) {
462
+ modelRuntime.onUsage(finalUsage);
463
+ usageReported = true;
464
+ }
465
+ const finalChunk = {
466
+ content: '',
467
+ accumulated,
468
+ reasoning_content: '',
469
+ isComplete: true,
470
+ usage: finalUsage
471
+ };
472
+ options.onChunk(finalChunk);
480
473
  } catch (error) {
481
474
  throw (0, external_request_timeout_js_namespaceObject.restoreHardTimeoutError)(toError(error), streamSignal);
482
475
  } finally{
@@ -543,14 +536,6 @@ async function callAI(messages, modelRuntime, options) {
543
536
  }
544
537
  debugCall(`response reasoning content: ${accumulatedReasoning}`);
545
538
  debugCall(`response content: ${content}`);
546
- if (isStreaming && !usage) {
547
- const estimatedTokens = Math.max(1, Math.floor((content || '').length / 4));
548
- usage = {
549
- prompt_tokens: estimatedTokens,
550
- completion_tokens: estimatedTokens,
551
- total_tokens: 2 * estimatedTokens
552
- };
553
- }
554
539
  const finalUsage = buildUsageInfo(usage, requestId);
555
540
  if (!usageReported && finalUsage && modelRuntime.onUsage) modelRuntime.onUsage(finalUsage);
556
541
  const response = {
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model/service-caller/index.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../../src/ai-model/service-caller/index.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__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 { AIUsageInfo } from '@/types';\nimport type { CodeGenerationChunk, StreamingCallback } from '@/types';\n\n// Error class that preserves usage and rawResponse when AI call parsing fails\nexport class AIResponseParseError extends Error {\n usage?: AIUsageInfo;\n /**\n * Adapter-extracted content used by Midscene for parsing. This is not the\n * full provider response or choices[0].message.\n */\n rawResponse: string;\n rawChoiceMessage?: unknown;\n reasoningContent?: string;\n\n constructor(\n message: string,\n rawResponse: string,\n usage?: AIUsageInfo,\n rawChoiceMessage?: unknown,\n reasoningContent?: string,\n ) {\n super(message);\n this.name = 'AIResponseParseError';\n this.rawResponse = rawResponse;\n this.usage = usage;\n this.rawChoiceMessage = rawChoiceMessage;\n this.reasoningContent = reasoningContent;\n }\n}\nimport {\n type IModelConfig,\n MIDSCENE_LANGFUSE_DEBUG,\n MIDSCENE_LANGSMITH_DEBUG,\n type TModelFamily,\n globalConfigManager,\n} from '@midscene/shared/env';\n\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { Stream } from 'openai/streaming';\nimport { getVersion } from '../../utils';\nimport type { ModelRuntime } from '../models';\nimport { type JsonParserSource, assertJsonObject } from '../shared/json';\nimport {\n callAIWithCodexAppServer,\n isCodexAppServerProvider,\n} from './codex-app-server';\nimport type { CodexAppServerRecordEvent } from './codex-app-server';\nimport {\n isModelCallRecordingEnabled,\n recordModelCallEvent,\n} from './model-call-recorder';\nimport {\n type OpenAIErrorResponseContext,\n formatOpenAIAPIErrorDetails,\n wrapOpenAICompatibleFetch,\n} from './openai-error';\nimport {\n buildRequestAbortSignal,\n isHardTimeoutError,\n resolveEffectiveTimeoutMs,\n restoreHardTimeoutError,\n} from './request-timeout';\nimport {\n callAiAndParseWithRetry,\n withSemanticRetryFeedback,\n} from './semantic-retry';\nimport type { AIArgs } from './types';\nexport {\n extractJSONFromCodeBlock,\n parseModelResponseJson,\n} from '../shared/json';\nexport type { JsonParser } from '../shared/json';\n\n/**\n * Internal field name stamped onto every AIUsageInfo shaped by callAI().\n * Used for cross-path dedup when the provider does not return a request_id.\n */\nexport const INTERNAL_CALL_ID_FIELD = '_midscene_call_id';\n\nlet internalCallIdCounter = 0;\nfunction nextInternalCallId(): string {\n internalCallIdCounter += 1;\n return `call_${internalCallIdCounter}`;\n}\n\nfunction stringifyForDebug(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch (_error) {\n return String(value);\n }\n}\n\nfunction getLatestSuccessfulResponseRequestId(\n context: OpenAIErrorResponseContext,\n): string | undefined {\n return context.responseRequestIds?.reduce<string | undefined>(\n (latestRequestId, response) =>\n response.ok ? response.requestId : latestRequestId,\n undefined,\n );\n}\n\nfunction getLatestResponseAttempt(context: OpenAIErrorResponseContext) {\n return context.httpResponses?.at(-1)?.attempt ?? 1;\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction normalizeRetryCount(retryCount: unknown): number {\n if (typeof retryCount !== 'number' || !Number.isFinite(retryCount)) {\n return 1;\n }\n\n return Math.max(0, Math.floor(retryCount));\n}\n\nfunction appendAIRequestFailureSummary<T extends Error>(\n error: T,\n attemptErrors: Array<{ attempt: number; error: unknown }>,\n maxAttempts: number,\n): T {\n const failedAttempts = attemptErrors.length;\n const retries = Math.max(0, failedAttempts - 1);\n const retryLabel = retries === 1 ? 'retry' : 'retries';\n const originalMessage = error.message;\n const previousAttemptErrors = attemptErrors.slice(0, -1);\n\n error.message = `AI model request failed after ${retries} ${retryLabel} (${failedAttempts}/${maxAttempts} attempts). Last error: ${originalMessage}`;\n\n if (previousAttemptErrors.length === 0) {\n return error;\n }\n\n const details = previousAttemptErrors\n .map(\n ({ attempt, error }) => `Attempt ${attempt}: ${getErrorMessage(error)}`,\n )\n .join('\\n');\n\n error.message = `${error.message}\\nPrevious AI call attempt errors:\\n${details}`;\n return error;\n}\n\nexport async function createChatClient({\n modelConfig,\n executionId,\n recordEvent,\n}: {\n modelConfig: IModelConfig;\n executionId: string;\n recordEvent?: (event: Record<string, unknown>) => void;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n modelName: string;\n modelDescription: string;\n modelFamily: TModelFamily | undefined;\n openAIErrorResponseContext: OpenAIErrorResponseContext;\n}> {\n const {\n socksProxy,\n httpProxy,\n modelName,\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n modelDescription,\n modelFamily,\n createOpenAIClient,\n timeout,\n } = modelConfig;\n\n let proxyAgent: any = undefined;\n const warnClient = getDebug('ai:call', { console: true });\n const debugProxy = getDebug('ai:call:proxy');\n const warnProxy = getDebug('ai:call:proxy', { console: true });\n\n // Helper function to sanitize proxy URL for logging (remove credentials)\n // Uses URL API instead of regex to avoid ReDoS vulnerabilities\n const sanitizeProxyUrl = (url: string): string => {\n try {\n const parsed = new URL(url);\n if (parsed.username) {\n // Keep username for debugging, hide password for security\n parsed.password = '****';\n return parsed.href;\n }\n return url;\n } catch {\n // If URL parsing fails, return original URL (will be caught later)\n return url;\n }\n };\n\n if (httpProxy) {\n debugProxy('using http proxy', sanitizeProxyUrl(httpProxy));\n if (ifInBrowser) {\n warnProxy(\n 'HTTP proxy is configured but not supported in browser environment',\n );\n } else {\n const { loadUndici } = await import('#proxy-deps');\n const { ProxyAgent } = await loadUndici();\n proxyAgent = new ProxyAgent({\n uri: httpProxy,\n // Note: authentication is handled via the URI (e.g., http://user:pass@proxy.com:8080)\n });\n }\n } else if (socksProxy) {\n debugProxy('using socks proxy', sanitizeProxyUrl(socksProxy));\n if (ifInBrowser) {\n warnProxy(\n 'SOCKS proxy is configured but not supported in browser environment',\n );\n } else {\n try {\n const { loadFetchSocks } = await import('#proxy-deps');\n const { socksDispatcher } = await loadFetchSocks();\n // Parse SOCKS proxy URL (e.g., socks5://127.0.0.1:1080)\n const proxyUrl = new URL(socksProxy);\n\n // Validate hostname\n if (!proxyUrl.hostname) {\n throw new Error('SOCKS proxy URL must include a valid hostname');\n }\n\n // Validate and parse port\n const port = Number.parseInt(proxyUrl.port, 10);\n if (!proxyUrl.port || Number.isNaN(port)) {\n throw new Error('SOCKS proxy URL must include a valid port');\n }\n\n // Parse SOCKS version from protocol\n const protocol = proxyUrl.protocol.replace(':', '');\n const socksType =\n protocol === 'socks4' ? 4 : protocol === 'socks5' ? 5 : 5;\n\n proxyAgent = socksDispatcher({\n type: socksType,\n host: proxyUrl.hostname,\n port,\n ...(proxyUrl.username\n ? {\n userId: decodeURIComponent(proxyUrl.username),\n password: decodeURIComponent(proxyUrl.password || ''),\n }\n : {}),\n });\n debugProxy('socks proxy configured successfully', {\n type: socksType,\n host: proxyUrl.hostname,\n port: port,\n });\n } catch (error) {\n warnProxy('Failed to configure SOCKS proxy:', error);\n throw new Error(\n `Invalid SOCKS proxy URL: ${socksProxy}. Expected format: socks4://host:port, socks5://host:port, or with authentication: socks5://user:pass@host:port`,\n );\n }\n }\n }\n\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs({ timeout });\n const openAIErrorResponseContext: OpenAIErrorResponseContext = {\n recordEvent,\n };\n const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n // Note: Type assertion needed due to undici version mismatch between dependencies\n ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n ...openaiExtraConfig,\n // Midscene exposes this setting through MIDSCENE_*_INIT_CONFIG_JSON, so\n // defaultHeaders is expected to be a plain JSON object rather than another\n // HeadersLike representation supported by the OpenAI SDK.\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders as\n | Record<string, string>\n | undefined),\n // These Midscene-owned headers intentionally override user-supplied\n // headers with the same names.\n 'x-midscene-version': getVersion(),\n 'x-midscene-execution-id': executionId,\n },\n fetch: wrapOpenAICompatibleFetch(openAIErrorResponseContext),\n // Midscene already handles retries in callAI(), so disable SDK-level retries\n // to avoid duplicate attempts and duplicated backoff latency.\n maxRetries: 0,\n // When disabled (timeoutMs === null) fall through to the SDK default so\n // only the caller-provided abortSignal can cancel the request.\n ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n // LangSmith wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langsmithModule = 'langsmith/wrappers';\n const { wrapOpenAI } = await import(langsmithModule);\n openai = wrapOpenAI(openai);\n }\n\n // Langfuse wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langfuse is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langfuseModule = '@langfuse/openai';\n const { observeOpenAI } = await import(langfuseModule);\n openai = observeOpenAI(openai);\n }\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return {\n completion: openai.chat.completions,\n modelName,\n modelDescription,\n modelFamily,\n openAIErrorResponseContext,\n };\n}\n\ninterface CallAIOptions {\n stream?: boolean;\n onChunk?: StreamingCallback;\n abortSignal?: AbortSignal;\n requiresOriginalImageDetail?: boolean;\n expectedJsonObjectResponse?: boolean;\n /**\n * Number of preceding semantic parsing failures for this request.\n * Network retries are intentionally excluded.\n */\n semanticRetryAttempt?: number;\n}\n\nexport async function callAI(\n messages: ChatCompletionMessageParam[],\n modelRuntime: ModelRuntime,\n options?: CallAIOptions,\n): Promise<{\n content: string;\n reasoning_content?: string;\n rawChoiceMessage?: unknown;\n usage?: AIUsageInfo;\n isStreamed: boolean;\n}> {\n const { config: modelConfig, adapter } = modelRuntime;\n // Low-level callers without a TaskRunner still need a stable ID for the\n // lifetime of this model call (including its network retries).\n const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;\n\n // Stable internal ID for this call, used by the agent to deduplicate usage\n // across the onUsage callback and the task-dump-based collectUsageMetrics()\n // path when the provider does not return a request_id.\n const internalCallId = nextInternalCallId();\n const recordEvent = isModelCallRecordingEnabled()\n ? (event: Record<string, unknown>) => {\n void recordModelCallEvent({\n executionId,\n callId: internalCallId,\n semanticRetryAttempt: options?.semanticRetryAttempt,\n slot: modelConfig.slot,\n intent: modelConfig.intent,\n modelFamily: modelConfig.modelFamily,\n ...event,\n });\n }\n : undefined;\n const modelCallInput = {\n intent: modelConfig.intent,\n userConfig: {\n temperature: modelConfig.temperature,\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n responseFormat: modelConfig.responseFormat,\n },\n semanticRetryAttempt: options?.semanticRetryAttempt,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n expectedJsonObjectResponse: options?.expectedJsonObjectResponse,\n };\n if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) {\n let protocolChunkSequence = 0;\n const codexStartTime = Date.now();\n const recordCodexEvent = recordEvent\n ? (event: CodexAppServerRecordEvent) => {\n if (event.type === 'chunk') {\n protocolChunkSequence += 1;\n recordEvent({\n ...event,\n attempt: 1,\n sequence: protocolChunkSequence,\n provider: 'codex-app-server',\n });\n return;\n }\n\n recordEvent({\n ...event,\n attempt: 1,\n provider: 'codex-app-server',\n });\n }\n : undefined;\n\n try {\n const { config, imageDetail } =\n adapter.buildCodexAppServerParams(modelCallInput);\n const codexResult = await callAIWithCodexAppServer(\n messages,\n modelConfig,\n {\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: config,\n abortSignal: options?.abortSignal,\n imageDetail,\n onRecordEvent: recordCodexEvent,\n },\n );\n const { protocolMetadata, ...response } = codexResult;\n recordEvent?.({\n type: 'response',\n attempt: 1,\n provider: 'codex-app-server',\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: response.usage,\n timeCost: Date.now() - codexStartTime,\n protocol: protocolMetadata,\n },\n });\n if (response.usage) {\n (response.usage as any)[INTERNAL_CALL_ID_FIELD] = internalCallId;\n if (modelRuntime.onUsage) {\n modelRuntime.onUsage(response.usage);\n }\n }\n return {\n ...response,\n };\n } catch (error) {\n recordEvent?.({\n type: 'error',\n attempt: 1,\n provider: 'codex-app-server',\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : String(error),\n });\n throw error;\n }\n }\n\n const imageDetail = adapter.chatCompletion.resolveImageDetail(modelCallInput);\n\n const {\n completion,\n modelName,\n modelDescription,\n modelFamily,\n openAIErrorResponseContext,\n } = await createChatClient({\n modelConfig,\n executionId,\n recordEvent,\n });\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig);\n\n const extraBody = modelConfig.extraBody;\n\n const debugCall = getDebug('ai:call');\n const warnCall = getDebug('ai:call', { console: true });\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n\n const startTime = Date.now();\n\n const isStreaming = options?.stream && options?.onChunk;\n const { config: adapterChatCompletionParams } =\n adapter.chatCompletion.buildChatCompletionParams(modelCallInput);\n debugCall(\n `adapter chat completion params: ${stringifyForDebug({\n config: adapterChatCompletionParams,\n })}`,\n );\n let content: string | undefined;\n let accumulated = '';\n let accumulatedReasoning = '';\n let rawChoiceMessage: unknown;\n let usage: OpenAI.CompletionUsage | undefined;\n let timeCost: number | undefined;\n let requestId: string | null | undefined;\n let responseModelName: string | undefined;\n // Tracks whether onUsage has already been fired for this call (e.g. from\n // the streaming final-chunk handler), so the final return does not double-fire.\n let usageReported = false;\n\n const hasUsableText = (value: string | null | undefined): value is string =>\n typeof value === 'string' && value.trim().length > 0;\n\n const resolveContentWithReasoningFallback = (\n contentValue: string | undefined,\n reasoningContent: string,\n ) => {\n if (\n !hasUsableText(contentValue) &&\n adapter.chatCompletion.useReasoningAsContentFallback &&\n hasUsableText(reasoningContent)\n ) {\n warnCall('empty content from AI model, using reasoning content');\n return reasoningContent;\n }\n\n return contentValue;\n };\n\n const buildUsageInfo = (\n usageData?: OpenAI.CompletionUsage,\n requestId?: string | null,\n ) => {\n if (!usageData) return undefined;\n\n const cachedInputTokens = (\n usageData as { prompt_tokens_details?: { cached_tokens?: number } }\n )?.prompt_tokens_details?.cached_tokens;\n\n return {\n ...usageData,\n prompt_tokens: usageData.prompt_tokens ?? 0,\n completion_tokens: usageData.completion_tokens ?? 0,\n total_tokens: usageData.total_tokens ?? 0,\n cached_input: cachedInputTokens ?? 0,\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n response_model_name: responseModelName,\n slot: modelConfig.slot,\n // Left undefined at the raw call layer. The agent's onUsage callback\n // fills it from modelConfig.slot for metrics collection, and task\n // layers use withUsageIntent() to stamp a more specific semantic\n // intent (e.g. 'planning', 'insight') when attaching usage to tasks.\n intent: undefined,\n request_id: requestId ?? undefined,\n // Internal stable ID for cross-path dedup when request_id is absent.\n [INTERNAL_CALL_ID_FIELD]: internalCallId,\n } satisfies AIUsageInfo;\n };\n\n const requestConfig = {\n ...adapterChatCompletionParams,\n ...(extraBody ?? {}),\n };\n const temperature = requestConfig.temperature;\n\n // Some adapters request original image detail to preserve screenshot\n // resolution for localization-sensitive tasks.\n const messagesWithImageDetail: ChatCompletionMessageParam[] = (() => {\n if (!imageDetail) {\n return messages;\n }\n\n return messages.map((msg) => {\n if (!Array.isArray(msg.content)) {\n return msg;\n }\n\n const content = msg.content.map((part) => {\n if (part && part.type === 'image_url' && part.image_url?.url) {\n return {\n ...part,\n image_url: {\n ...part.image_url,\n detail: imageDetail,\n },\n };\n }\n return part;\n });\n\n return {\n ...msg,\n content,\n } as ChatCompletionMessageParam;\n });\n })();\n\n try {\n debugCall(\n `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n );\n\n if (isStreaming) {\n const { signal: streamSignal, cleanup: cleanupStreamSignal } =\n buildRequestAbortSignal(effectiveTimeoutMs, options?.abortSignal);\n try {\n const stream = (await completion.create(\n {\n model: modelName,\n messages: messagesWithImageDetail,\n ...requestConfig,\n stream: true,\n },\n {\n stream: true,\n signal: streamSignal,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n requestId =\n getLatestSuccessfulResponseRequestId(openAIErrorResponseContext) ??\n stream._request_id;\n const streamAttempt = getLatestResponseAttempt(\n openAIErrorResponseContext,\n );\n\n let chunkSequence = 0;\n for await (const chunk of stream) {\n chunkSequence += 1;\n recordEvent?.({\n type: 'chunk',\n attempt: streamAttempt,\n sequence: chunkSequence,\n chunk,\n });\n const parsedChunk = adapter.chatCompletion.extractContentAndReasoning(\n chunk.choices?.[0]?.delta,\n );\n const content = parsedChunk.content || '';\n const reasoning_content = parsedChunk.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n if (chunk.model) {\n responseModelName = chunk.model;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n accumulatedReasoning += reasoning_content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n options.onChunk!(chunkData);\n }\n\n // Check if stream is complete\n if (chunk.choices?.[0]?.finish_reason) {\n timeCost = Date.now() - startTime;\n\n // If usage is not available from the stream, provide a basic usage info\n if (!usage) {\n // Estimate token counts based on content length (rough approximation)\n const estimatedTokens = Math.max(\n 1,\n Math.floor(accumulated.length / 4),\n );\n usage = {\n prompt_tokens: estimatedTokens,\n completion_tokens: estimatedTokens,\n total_tokens: estimatedTokens * 2,\n };\n }\n\n const finalAccumulated = resolveContentWithReasoningFallback(\n accumulated,\n accumulatedReasoning,\n );\n accumulated = finalAccumulated || '';\n\n // Send final chunk\n const finalUsage = buildUsageInfo(usage, requestId);\n if (finalUsage && modelRuntime.onUsage) {\n modelRuntime.onUsage(finalUsage);\n usageReported = true;\n }\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage: finalUsage,\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n } catch (error) {\n throw restoreHardTimeoutError(toError(error), streamSignal);\n } finally {\n cleanupStreamSignal();\n }\n content = accumulated;\n debugProfileStats(\n `streaming model, ${modelName}, mode, ${modelFamily || 'default'}, cost-ms, ${timeCost}, temperature, ${temperature ?? ''}`,\n );\n } else {\n // Non-streaming with retry logic\n const retryCount = normalizeRetryCount(modelConfig.retryCount);\n const retryInterval = modelConfig.retryInterval ?? 2000;\n const maxAttempts = retryCount + 1; // retryCount=1 means 2 total attempts (1 initial + 1 retry)\n\n let lastError: Error | undefined;\n const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const { signal: attemptSignal, cleanup: cleanupAttemptSignal } =\n buildRequestAbortSignal(effectiveTimeoutMs, options?.abortSignal);\n try {\n const result = await completion.create(\n {\n model: modelName,\n messages: messagesWithImageDetail,\n ...requestConfig,\n stream: false,\n } as any,\n { signal: attemptSignal },\n );\n\n timeCost = Date.now() - startTime;\n requestId =\n getLatestSuccessfulResponseRequestId(openAIErrorResponseContext) ??\n result._request_id;\n\n debugProfileStats(\n `model, ${modelName}, mode, ${modelFamily || 'default'}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${timeCost}, requestId, ${requestId || ''}, temperature, ${temperature ?? ''}`,\n );\n\n debugProfileDetail(\n `model usage detail: ${JSON.stringify(result.usage)}`,\n );\n\n if (!result.choices) {\n throw new Error(\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n }\n\n rawChoiceMessage = result.choices[0].message;\n const parsedMessage =\n adapter.chatCompletion.extractContentAndReasoning(\n result.choices[0].message,\n );\n content = parsedMessage.content;\n accumulatedReasoning = parsedMessage.reasoning_content;\n usage = result.usage;\n responseModelName = result.model;\n\n content = resolveContentWithReasoningFallback(\n content,\n accumulatedReasoning,\n );\n\n if (!hasUsableText(content)) {\n const errorUsage = buildUsageInfo(usage, requestId);\n if (errorUsage && modelRuntime.onUsage) {\n modelRuntime.onUsage(errorUsage);\n }\n throw new AIResponseParseError(\n 'empty content from AI model',\n content || '',\n errorUsage,\n rawChoiceMessage,\n );\n }\n\n break; // Success, exit retry loop\n } catch (error) {\n lastError = restoreHardTimeoutError(toError(error), attemptSignal);\n attemptErrors.push({ attempt, error: lastError });\n const wasHardTimeout = isHardTimeoutError(lastError);\n if (wasHardTimeout) {\n warnCall(\n `AI call hit hard timeout (${effectiveTimeoutMs}ms, attempt ${attempt}/${maxAttempts}, model ${modelName}, slot ${modelConfig.slot})`,\n );\n }\n // Do not retry if the request was aborted by the caller\n if (options?.abortSignal?.aborted) {\n break;\n }\n if (attempt < maxAttempts) {\n warnCall(\n `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n );\n await new Promise((resolve) => setTimeout(resolve, retryInterval));\n }\n } finally {\n cleanupAttemptSignal();\n }\n }\n\n if (!content) {\n assert(\n lastError,\n 'AI model request failed without recording an attempt error',\n );\n throw appendAIRequestFailureSummary(\n lastError,\n attemptErrors,\n maxAttempts,\n );\n }\n }\n\n debugCall(`response reasoning content: ${accumulatedReasoning}`);\n debugCall(`response content: ${content}`);\n\n // Ensure we always have usage info for streaming responses\n if (isStreaming && !usage) {\n // Estimate token counts based on content length (rough approximation)\n const estimatedTokens = Math.max(\n 1,\n Math.floor((content || '').length / 4),\n );\n usage = {\n prompt_tokens: estimatedTokens,\n completion_tokens: estimatedTokens,\n total_tokens: estimatedTokens * 2,\n } as OpenAI.CompletionUsage;\n }\n\n const finalUsage = buildUsageInfo(usage, requestId);\n // Report usage to the runtime-level collector if not already reported\n // (e.g. from the streaming final-chunk handler).\n if (!usageReported && finalUsage && modelRuntime.onUsage) {\n modelRuntime.onUsage(finalUsage);\n }\n\n const response = {\n content: content || '',\n reasoning_content: accumulatedReasoning || undefined,\n rawChoiceMessage,\n usage: finalUsage,\n isStreamed: !!isStreaming,\n };\n recordEvent?.({\n type: 'response',\n attempt: getLatestResponseAttempt(openAIErrorResponseContext),\n http: openAIErrorResponseContext.httpResponses?.at(-1),\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: response.usage,\n requestId,\n timeCost,\n responseModelName,\n },\n });\n return response;\n } catch (e: any) {\n warnCall('call AI error', e);\n\n if (e instanceof AIResponseParseError) {\n throw e;\n }\n\n const newError = new Error(\n `failed to call ${isStreaming ? 'streaming ' : ''}AI model service (${modelName}): ${e.message}${formatOpenAIAPIErrorDetails(e, openAIErrorResponseContext)}\\nTrouble shooting: https://midscenejs.com/model-provider.html`,\n {\n cause: e,\n },\n );\n throw newError;\n }\n}\n\nexport type AIObjectResponse<T> = {\n // TODO: `content` is a misleading name here because this is already the parsed object response. Consider renaming it to `object` or `data`.\n content: T;\n contentString: string;\n usage?: AIUsageInfo;\n reasoning_content?: string;\n rawChoiceMessage?: unknown;\n};\n\nexport function parseAIObjectResponse<T>(\n response: Awaited<ReturnType<typeof callAI>>,\n modelRuntime: ModelRuntime,\n jsonParserSource: JsonParserSource = 'generic-object',\n): AIObjectResponse<T> {\n const { adapter } = modelRuntime;\n assert(response, 'empty response');\n const jsonContent = adapter.jsonParser(response.content, {\n source: jsonParserSource,\n });\n assertJsonObject(jsonContent);\n return {\n content: jsonContent as T,\n contentString: response.content,\n usage: response.usage,\n reasoning_content: response.reasoning_content,\n rawChoiceMessage: response.rawChoiceMessage,\n };\n}\n\nexport async function callAIWithObjectResponse<T>(\n messages: ChatCompletionMessageParam[],\n modelRuntime: ModelRuntime,\n options?: {\n abortSignal?: AbortSignal;\n jsonParserSource?: JsonParserSource;\n retryTimes?: number;\n retryInterval?: number;\n },\n): Promise<AIObjectResponse<T>> {\n const { config: modelConfig } = modelRuntime;\n return callAiAndParseWithRetry({\n callAi: (retryAttempt, previousParseError) =>\n callAI(\n withSemanticRetryFeedback(messages, previousParseError),\n modelRuntime,\n {\n abortSignal: options?.abortSignal,\n expectedJsonObjectResponse: true,\n semanticRetryAttempt: retryAttempt,\n },\n ),\n parseResponse: (response) =>\n parseAIObjectResponse<T>(\n response,\n modelRuntime,\n options?.jsonParserSource,\n ),\n toParseError: (error, response) => {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return new AIResponseParseError(\n errorMessage,\n response.content,\n response.usage,\n response.rawChoiceMessage,\n response.reasoning_content,\n );\n },\n parseRetryTimes: options?.retryTimes ?? modelConfig.retryCount,\n parseRetryInterval: options?.retryInterval ?? modelConfig.retryInterval,\n abortSignal: options?.abortSignal,\n });\n}\n\nexport async function callAIWithStringResponse(\n msgs: AIArgs,\n modelRuntime: ModelRuntime,\n options?: Pick<CallAIOptions, 'abortSignal' | 'requiresOriginalImageDetail'>,\n): Promise<{\n content: string;\n usage?: AIUsageInfo;\n rawChoiceMessage?: unknown;\n}> {\n const { content, usage, rawChoiceMessage } = await callAI(\n msgs,\n modelRuntime,\n options,\n );\n return { content, usage, rawChoiceMessage };\n}\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","AIResponseParseError","Error","message","rawResponse","usage","rawChoiceMessage","reasoningContent","INTERNAL_CALL_ID_FIELD","internalCallIdCounter","nextInternalCallId","stringifyForDebug","value","JSON","_error","String","getLatestSuccessfulResponseRequestId","context","latestRequestId","response","undefined","getLatestResponseAttempt","getErrorMessage","error","toError","normalizeRetryCount","retryCount","Number","Math","appendAIRequestFailureSummary","attemptErrors","maxAttempts","failedAttempts","retries","retryLabel","originalMessage","previousAttemptErrors","details","attempt","createChatClient","modelConfig","executionId","recordEvent","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","modelDescription","modelFamily","createOpenAIClient","timeout","proxyAgent","warnClient","getDebug","debugProxy","warnProxy","sanitizeProxyUrl","url","parsed","URL","ifInBrowser","loadUndici","ProxyAgent","loadFetchSocks","socksDispatcher","proxyUrl","port","protocol","socksType","decodeURIComponent","effectiveTimeoutMs","resolveEffectiveTimeoutMs","openAIErrorResponseContext","openAIOptions","getVersion","wrapOpenAICompatibleFetch","baseOpenAI","OpenAI","openai","globalConfigManager","MIDSCENE_LANGSMITH_DEBUG","langsmithModule","wrapOpenAI","MIDSCENE_LANGFUSE_DEBUG","langfuseModule","observeOpenAI","wrappedClient","callAI","messages","modelRuntime","options","adapter","uuid","internalCallId","isModelCallRecordingEnabled","event","recordModelCallEvent","modelCallInput","isCodexAppServerProvider","protocolChunkSequence","codexStartTime","Date","recordCodexEvent","config","imageDetail","codexResult","callAIWithCodexAppServer","protocolMetadata","completion","extraBody","debugCall","warnCall","debugProfileStats","debugProfileDetail","startTime","isStreaming","adapterChatCompletionParams","content","accumulated","accumulatedReasoning","timeCost","requestId","responseModelName","usageReported","hasUsableText","resolveContentWithReasoningFallback","contentValue","buildUsageInfo","usageData","cachedInputTokens","requestConfig","temperature","messagesWithImageDetail","msg","Array","part","streamSignal","cleanupStreamSignal","buildRequestAbortSignal","stream","streamAttempt","chunkSequence","chunk","parsedChunk","reasoning_content","chunkData","estimatedTokens","finalAccumulated","finalUsage","finalChunk","restoreHardTimeoutError","retryInterval","lastError","attemptSignal","cleanupAttemptSignal","result","parsedMessage","errorUsage","wasHardTimeout","isHardTimeoutError","Promise","resolve","setTimeout","assert","e","newError","formatOpenAIAPIErrorDetails","parseAIObjectResponse","jsonParserSource","jsonContent","assertJsonObject","callAIWithObjectResponse","callAiAndParseWithRetry","retryAttempt","previousParseError","withSemanticRetryFeedback","errorMessage","callAIWithStringResponse","msgs"],"mappings":"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"}
1
+ {"version":3,"file":"ai-model/service-caller/index.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../../src/ai-model/service-caller/index.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__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 { AIUsageInfo } from '@/types';\nimport type { CodeGenerationChunk, StreamingCallback } from '@/types';\n\n// Error class that preserves usage and rawResponse when AI call parsing fails\nexport class AIResponseParseError extends Error {\n usage?: AIUsageInfo;\n /**\n * Adapter-extracted content used by Midscene for parsing. This is not the\n * full provider response or choices[0].message.\n */\n rawResponse: string;\n rawChoiceMessage?: unknown;\n reasoningContent?: string;\n\n constructor(\n message: string,\n rawResponse: string,\n usage?: AIUsageInfo,\n rawChoiceMessage?: unknown,\n reasoningContent?: string,\n ) {\n super(message);\n this.name = 'AIResponseParseError';\n this.rawResponse = rawResponse;\n this.usage = usage;\n this.rawChoiceMessage = rawChoiceMessage;\n this.reasoningContent = reasoningContent;\n }\n}\nimport {\n type IModelConfig,\n MIDSCENE_LANGFUSE_DEBUG,\n MIDSCENE_LANGSMITH_DEBUG,\n type TModelFamily,\n globalConfigManager,\n} from '@midscene/shared/env';\n\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { Stream } from 'openai/streaming';\nimport { getVersion } from '../../utils';\nimport type { ModelRuntime } from '../models';\nimport { type JsonParserSource, assertJsonObject } from '../shared/json';\nimport {\n callAIWithCodexAppServer,\n isCodexAppServerProvider,\n} from './codex-app-server';\nimport type { CodexAppServerRecordEvent } from './codex-app-server';\nimport {\n isModelCallRecordingEnabled,\n recordModelCallEvent,\n} from './model-call-recorder';\nimport {\n type OpenAIErrorResponseContext,\n formatOpenAIAPIErrorDetails,\n wrapOpenAICompatibleFetch,\n} from './openai-error';\nimport {\n buildRequestAbortSignal,\n isHardTimeoutError,\n resolveEffectiveTimeoutMs,\n restoreHardTimeoutError,\n} from './request-timeout';\nimport {\n callAiAndParseWithRetry,\n withSemanticRetryFeedback,\n} from './semantic-retry';\nimport type { AIArgs } from './types';\nexport {\n extractJSONFromCodeBlock,\n parseModelResponseJson,\n} from '../shared/json';\nexport type { JsonParser } from '../shared/json';\n\n/**\n * Internal field name stamped onto every AIUsageInfo shaped by callAI().\n * Used for cross-path dedup when the provider does not return a request_id.\n */\nexport const INTERNAL_CALL_ID_FIELD = '_midscene_call_id';\n\nlet internalCallIdCounter = 0;\nfunction nextInternalCallId(): string {\n internalCallIdCounter += 1;\n return `call_${internalCallIdCounter}`;\n}\n\nfunction stringifyForDebug(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch (_error) {\n return String(value);\n }\n}\n\nfunction getLatestSuccessfulResponseRequestId(\n context: OpenAIErrorResponseContext,\n): string | undefined {\n return context.responseRequestIds?.reduce<string | undefined>(\n (latestRequestId, response) =>\n response.ok ? response.requestId : latestRequestId,\n undefined,\n );\n}\n\nfunction getLatestResponseAttempt(context: OpenAIErrorResponseContext) {\n return context.httpResponses?.at(-1)?.attempt ?? 1;\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction normalizeRetryCount(retryCount: unknown): number {\n if (typeof retryCount !== 'number' || !Number.isFinite(retryCount)) {\n return 1;\n }\n\n return Math.max(0, Math.floor(retryCount));\n}\n\nfunction appendAIRequestFailureSummary<T extends Error>(\n error: T,\n attemptErrors: Array<{ attempt: number; error: unknown }>,\n maxAttempts: number,\n): T {\n const failedAttempts = attemptErrors.length;\n const retries = Math.max(0, failedAttempts - 1);\n const retryLabel = retries === 1 ? 'retry' : 'retries';\n const originalMessage = error.message;\n const previousAttemptErrors = attemptErrors.slice(0, -1);\n\n error.message = `AI model request failed after ${retries} ${retryLabel} (${failedAttempts}/${maxAttempts} attempts). Last error: ${originalMessage}`;\n\n if (previousAttemptErrors.length === 0) {\n return error;\n }\n\n const details = previousAttemptErrors\n .map(\n ({ attempt, error }) => `Attempt ${attempt}: ${getErrorMessage(error)}`,\n )\n .join('\\n');\n\n error.message = `${error.message}\\nPrevious AI call attempt errors:\\n${details}`;\n return error;\n}\n\nexport async function createChatClient({\n modelConfig,\n executionId,\n recordEvent,\n}: {\n modelConfig: IModelConfig;\n executionId: string;\n recordEvent?: (event: Record<string, unknown>) => void;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n modelName: string;\n modelDescription: string;\n modelFamily: TModelFamily | undefined;\n openAIErrorResponseContext: OpenAIErrorResponseContext;\n}> {\n const {\n socksProxy,\n httpProxy,\n modelName,\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n modelDescription,\n modelFamily,\n createOpenAIClient,\n timeout,\n } = modelConfig;\n\n let proxyAgent: any = undefined;\n const warnClient = getDebug('ai:call', { console: true });\n const debugProxy = getDebug('ai:call:proxy');\n const warnProxy = getDebug('ai:call:proxy', { console: true });\n\n // Helper function to sanitize proxy URL for logging (remove credentials)\n // Uses URL API instead of regex to avoid ReDoS vulnerabilities\n const sanitizeProxyUrl = (url: string): string => {\n try {\n const parsed = new URL(url);\n if (parsed.username) {\n // Keep username for debugging, hide password for security\n parsed.password = '****';\n return parsed.href;\n }\n return url;\n } catch {\n // If URL parsing fails, return original URL (will be caught later)\n return url;\n }\n };\n\n if (httpProxy) {\n debugProxy('using http proxy', sanitizeProxyUrl(httpProxy));\n if (ifInBrowser) {\n warnProxy(\n 'HTTP proxy is configured but not supported in browser environment',\n );\n } else {\n const { loadUndici } = await import('#proxy-deps');\n const { ProxyAgent } = await loadUndici();\n proxyAgent = new ProxyAgent({\n uri: httpProxy,\n // Note: authentication is handled via the URI (e.g., http://user:pass@proxy.com:8080)\n });\n }\n } else if (socksProxy) {\n debugProxy('using socks proxy', sanitizeProxyUrl(socksProxy));\n if (ifInBrowser) {\n warnProxy(\n 'SOCKS proxy is configured but not supported in browser environment',\n );\n } else {\n try {\n const { loadFetchSocks } = await import('#proxy-deps');\n const { socksDispatcher } = await loadFetchSocks();\n // Parse SOCKS proxy URL (e.g., socks5://127.0.0.1:1080)\n const proxyUrl = new URL(socksProxy);\n\n // Validate hostname\n if (!proxyUrl.hostname) {\n throw new Error('SOCKS proxy URL must include a valid hostname');\n }\n\n // Validate and parse port\n const port = Number.parseInt(proxyUrl.port, 10);\n if (!proxyUrl.port || Number.isNaN(port)) {\n throw new Error('SOCKS proxy URL must include a valid port');\n }\n\n // Parse SOCKS version from protocol\n const protocol = proxyUrl.protocol.replace(':', '');\n const socksType =\n protocol === 'socks4' ? 4 : protocol === 'socks5' ? 5 : 5;\n\n proxyAgent = socksDispatcher({\n type: socksType,\n host: proxyUrl.hostname,\n port,\n ...(proxyUrl.username\n ? {\n userId: decodeURIComponent(proxyUrl.username),\n password: decodeURIComponent(proxyUrl.password || ''),\n }\n : {}),\n });\n debugProxy('socks proxy configured successfully', {\n type: socksType,\n host: proxyUrl.hostname,\n port: port,\n });\n } catch (error) {\n warnProxy('Failed to configure SOCKS proxy:', error);\n throw new Error(\n `Invalid SOCKS proxy URL: ${socksProxy}. Expected format: socks4://host:port, socks5://host:port, or with authentication: socks5://user:pass@host:port`,\n );\n }\n }\n }\n\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs({ timeout });\n const openAIErrorResponseContext: OpenAIErrorResponseContext = {\n recordEvent,\n };\n const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n // Note: Type assertion needed due to undici version mismatch between dependencies\n ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n ...openaiExtraConfig,\n // Midscene exposes this setting through MIDSCENE_*_INIT_CONFIG_JSON, so\n // defaultHeaders is expected to be a plain JSON object rather than another\n // HeadersLike representation supported by the OpenAI SDK.\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders as\n | Record<string, string>\n | undefined),\n // These Midscene-owned headers intentionally override user-supplied\n // headers with the same names.\n 'x-midscene-version': getVersion(),\n 'x-midscene-execution-id': executionId,\n },\n fetch: wrapOpenAICompatibleFetch(openAIErrorResponseContext),\n // Midscene already handles retries in callAI(), so disable SDK-level retries\n // to avoid duplicate attempts and duplicated backoff latency.\n maxRetries: 0,\n // When disabled (timeoutMs === null) fall through to the SDK default so\n // only the caller-provided abortSignal can cancel the request.\n ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n // LangSmith wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langsmithModule = 'langsmith/wrappers';\n const { wrapOpenAI } = await import(langsmithModule);\n openai = wrapOpenAI(openai);\n }\n\n // Langfuse wrapper\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langfuse is not supported in browser');\n }\n warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n // Use variable to prevent static analysis by bundlers\n const langfuseModule = '@langfuse/openai';\n const { observeOpenAI } = await import(langfuseModule);\n openai = observeOpenAI(openai);\n }\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return {\n completion: openai.chat.completions,\n modelName,\n modelDescription,\n modelFamily,\n openAIErrorResponseContext,\n };\n}\n\ninterface CallAIOptions {\n stream?: boolean;\n onChunk?: StreamingCallback;\n abortSignal?: AbortSignal;\n requiresOriginalImageDetail?: boolean;\n expectedJsonObjectResponse?: boolean;\n /**\n * Number of preceding semantic parsing failures for this request.\n * Network retries are intentionally excluded.\n */\n semanticRetryAttempt?: number;\n}\n\nexport async function callAI(\n messages: ChatCompletionMessageParam[],\n modelRuntime: ModelRuntime,\n options?: CallAIOptions,\n): Promise<{\n content: string;\n reasoning_content?: string;\n rawChoiceMessage?: unknown;\n usage?: AIUsageInfo;\n isStreamed: boolean;\n}> {\n const { config: modelConfig, adapter } = modelRuntime;\n // Low-level callers without a TaskRunner still need a stable ID for the\n // lifetime of this model call (including its network retries).\n const executionId = modelRuntime.executionId ?? `unscoped-${uuid()}`;\n\n // Stable internal ID for this call, used by the agent to deduplicate usage\n // across the onUsage callback and the task-dump-based collectUsageMetrics()\n // path when the provider does not return a request_id.\n const internalCallId = nextInternalCallId();\n const recordEvent = isModelCallRecordingEnabled()\n ? (event: Record<string, unknown>) => {\n void recordModelCallEvent({\n executionId,\n callId: internalCallId,\n semanticRetryAttempt: options?.semanticRetryAttempt,\n slot: modelConfig.slot,\n intent: modelConfig.intent,\n modelFamily: modelConfig.modelFamily,\n ...event,\n });\n }\n : undefined;\n const modelCallInput = {\n intent: modelConfig.intent,\n userConfig: {\n temperature: modelConfig.temperature,\n reasoningEnabled: modelConfig.reasoningEnabled,\n reasoningEffort: modelConfig.reasoningEffort,\n reasoningBudget: modelConfig.reasoningBudget,\n responseFormat: modelConfig.responseFormat,\n },\n semanticRetryAttempt: options?.semanticRetryAttempt,\n requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n expectedJsonObjectResponse: options?.expectedJsonObjectResponse,\n };\n if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) {\n let protocolChunkSequence = 0;\n const codexStartTime = Date.now();\n const recordCodexEvent = recordEvent\n ? (event: CodexAppServerRecordEvent) => {\n if (event.type === 'chunk') {\n protocolChunkSequence += 1;\n recordEvent({\n ...event,\n attempt: 1,\n sequence: protocolChunkSequence,\n provider: 'codex-app-server',\n });\n return;\n }\n\n recordEvent({\n ...event,\n attempt: 1,\n provider: 'codex-app-server',\n });\n }\n : undefined;\n\n try {\n const { config, imageDetail } =\n adapter.buildCodexAppServerParams(modelCallInput);\n const codexResult = await callAIWithCodexAppServer(\n messages,\n modelConfig,\n {\n stream: options?.stream,\n onChunk: options?.onChunk,\n params: config,\n abortSignal: options?.abortSignal,\n imageDetail,\n onRecordEvent: recordCodexEvent,\n },\n );\n const { protocolMetadata, ...response } = codexResult;\n recordEvent?.({\n type: 'response',\n attempt: 1,\n provider: 'codex-app-server',\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: response.usage,\n timeCost: Date.now() - codexStartTime,\n protocol: protocolMetadata,\n },\n });\n if (response.usage) {\n (response.usage as any)[INTERNAL_CALL_ID_FIELD] = internalCallId;\n if (modelRuntime.onUsage) {\n modelRuntime.onUsage(response.usage);\n }\n }\n return {\n ...response,\n };\n } catch (error) {\n recordEvent?.({\n type: 'error',\n attempt: 1,\n provider: 'codex-app-server',\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : String(error),\n });\n throw error;\n }\n }\n\n const imageDetail = adapter.chatCompletion.resolveImageDetail(modelCallInput);\n\n const {\n completion,\n modelName,\n modelDescription,\n modelFamily,\n openAIErrorResponseContext,\n } = await createChatClient({\n modelConfig,\n executionId,\n recordEvent,\n });\n const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig);\n\n const extraBody = modelConfig.extraBody;\n\n const debugCall = getDebug('ai:call');\n const warnCall = getDebug('ai:call', { console: true });\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n\n const startTime = Date.now();\n\n const isStreaming = options?.stream && options?.onChunk;\n const { config: adapterChatCompletionParams } =\n adapter.chatCompletion.buildChatCompletionParams(modelCallInput);\n debugCall(\n `adapter chat completion params: ${stringifyForDebug({\n config: adapterChatCompletionParams,\n })}`,\n );\n let content: string | undefined;\n let accumulated = '';\n let accumulatedReasoning = '';\n let rawChoiceMessage: unknown;\n let usage: OpenAI.CompletionUsage | undefined;\n let timeCost: number | undefined;\n let requestId: string | null | undefined;\n let responseModelName: string | undefined;\n // Tracks whether onUsage has already been fired for this call (e.g. from\n // the streaming final-chunk handler), so the final return does not double-fire.\n let usageReported = false;\n\n const hasUsableText = (value: string | null | undefined): value is string =>\n typeof value === 'string' && value.trim().length > 0;\n\n const resolveContentWithReasoningFallback = (\n contentValue: string | undefined,\n reasoningContent: string,\n ) => {\n if (\n !hasUsableText(contentValue) &&\n adapter.chatCompletion.useReasoningAsContentFallback &&\n hasUsableText(reasoningContent)\n ) {\n warnCall('empty content from AI model, using reasoning content');\n return reasoningContent;\n }\n\n return contentValue;\n };\n\n const buildUsageInfo = (\n usageData?: OpenAI.CompletionUsage,\n requestId?: string | null,\n ) => {\n if (!usageData) return undefined;\n\n const cachedInputTokens = (\n usageData as { prompt_tokens_details?: { cached_tokens?: number } }\n )?.prompt_tokens_details?.cached_tokens;\n\n return {\n ...usageData,\n prompt_tokens: usageData.prompt_tokens ?? 0,\n completion_tokens: usageData.completion_tokens ?? 0,\n total_tokens: usageData.total_tokens ?? 0,\n cached_input: cachedInputTokens ?? 0,\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n response_model_name: responseModelName,\n slot: modelConfig.slot,\n // Left undefined at the raw call layer. The agent's onUsage callback\n // fills it from modelConfig.slot for metrics collection, and task\n // layers use withUsageIntent() to stamp a more specific semantic\n // intent (e.g. 'planning', 'insight') when attaching usage to tasks.\n intent: undefined,\n request_id: requestId ?? undefined,\n // Internal stable ID for cross-path dedup when request_id is absent.\n [INTERNAL_CALL_ID_FIELD]: internalCallId,\n } satisfies AIUsageInfo;\n };\n\n const requestConfig = {\n ...adapterChatCompletionParams,\n ...(extraBody ?? {}),\n };\n const temperature = requestConfig.temperature;\n\n // Some adapters request original image detail to preserve screenshot\n // resolution for localization-sensitive tasks.\n const messagesWithImageDetail: ChatCompletionMessageParam[] = (() => {\n if (!imageDetail) {\n return messages;\n }\n\n return messages.map((msg) => {\n if (!Array.isArray(msg.content)) {\n return msg;\n }\n\n const content = msg.content.map((part) => {\n if (part && part.type === 'image_url' && part.image_url?.url) {\n return {\n ...part,\n image_url: {\n ...part.image_url,\n detail: imageDetail,\n },\n };\n }\n return part;\n });\n\n return {\n ...msg,\n content,\n } as ChatCompletionMessageParam;\n });\n })();\n\n try {\n debugCall(\n `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n );\n\n if (isStreaming) {\n const { signal: streamSignal, cleanup: cleanupStreamSignal } =\n buildRequestAbortSignal(effectiveTimeoutMs, options?.abortSignal);\n try {\n const stream = (await completion.create(\n {\n model: modelName,\n messages: messagesWithImageDetail,\n ...requestConfig,\n stream: true,\n stream_options: {\n ...(requestConfig.stream_options as\n | Record<string, unknown>\n | undefined),\n include_usage: true,\n },\n },\n {\n stream: true,\n signal: streamSignal,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n requestId =\n getLatestSuccessfulResponseRequestId(openAIErrorResponseContext) ??\n stream._request_id;\n const streamAttempt = getLatestResponseAttempt(\n openAIErrorResponseContext,\n );\n\n let chunkSequence = 0;\n for await (const chunk of stream) {\n chunkSequence += 1;\n recordEvent?.({\n type: 'chunk',\n attempt: streamAttempt,\n sequence: chunkSequence,\n chunk,\n });\n const parsedChunk = adapter.chatCompletion.extractContentAndReasoning(\n chunk.choices?.[0]?.delta,\n );\n const content = parsedChunk.content || '';\n const reasoning_content = parsedChunk.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n if (chunk.model) {\n responseModelName = chunk.model;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n accumulatedReasoning += reasoning_content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n options.onChunk!(chunkData);\n }\n }\n\n timeCost = Date.now() - startTime;\n\n const finalAccumulated = resolveContentWithReasoningFallback(\n accumulated,\n accumulatedReasoning,\n );\n accumulated = finalAccumulated || '';\n\n // Send final chunk\n const finalUsage = buildUsageInfo(usage, requestId);\n if (finalUsage && modelRuntime.onUsage) {\n modelRuntime.onUsage(finalUsage);\n usageReported = true;\n }\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage: finalUsage,\n };\n options.onChunk!(finalChunk);\n } catch (error) {\n throw restoreHardTimeoutError(toError(error), streamSignal);\n } finally {\n cleanupStreamSignal();\n }\n content = accumulated;\n debugProfileStats(\n `streaming model, ${modelName}, mode, ${modelFamily || 'default'}, cost-ms, ${timeCost}, temperature, ${temperature ?? ''}`,\n );\n } else {\n // Non-streaming with retry logic\n const retryCount = normalizeRetryCount(modelConfig.retryCount);\n const retryInterval = modelConfig.retryInterval ?? 2000;\n const maxAttempts = retryCount + 1; // retryCount=1 means 2 total attempts (1 initial + 1 retry)\n\n let lastError: Error | undefined;\n const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const { signal: attemptSignal, cleanup: cleanupAttemptSignal } =\n buildRequestAbortSignal(effectiveTimeoutMs, options?.abortSignal);\n try {\n const result = await completion.create(\n {\n model: modelName,\n messages: messagesWithImageDetail,\n ...requestConfig,\n stream: false,\n } as any,\n { signal: attemptSignal },\n );\n\n timeCost = Date.now() - startTime;\n requestId =\n getLatestSuccessfulResponseRequestId(openAIErrorResponseContext) ??\n result._request_id;\n\n debugProfileStats(\n `model, ${modelName}, mode, ${modelFamily || 'default'}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${timeCost}, requestId, ${requestId || ''}, temperature, ${temperature ?? ''}`,\n );\n\n debugProfileDetail(\n `model usage detail: ${JSON.stringify(result.usage)}`,\n );\n\n if (!result.choices) {\n throw new Error(\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n }\n\n rawChoiceMessage = result.choices[0].message;\n const parsedMessage =\n adapter.chatCompletion.extractContentAndReasoning(\n result.choices[0].message,\n );\n content = parsedMessage.content;\n accumulatedReasoning = parsedMessage.reasoning_content;\n usage = result.usage;\n responseModelName = result.model;\n\n content = resolveContentWithReasoningFallback(\n content,\n accumulatedReasoning,\n );\n\n if (!hasUsableText(content)) {\n const errorUsage = buildUsageInfo(usage, requestId);\n if (errorUsage && modelRuntime.onUsage) {\n modelRuntime.onUsage(errorUsage);\n }\n throw new AIResponseParseError(\n 'empty content from AI model',\n content || '',\n errorUsage,\n rawChoiceMessage,\n );\n }\n\n break; // Success, exit retry loop\n } catch (error) {\n lastError = restoreHardTimeoutError(toError(error), attemptSignal);\n attemptErrors.push({ attempt, error: lastError });\n const wasHardTimeout = isHardTimeoutError(lastError);\n if (wasHardTimeout) {\n warnCall(\n `AI call hit hard timeout (${effectiveTimeoutMs}ms, attempt ${attempt}/${maxAttempts}, model ${modelName}, slot ${modelConfig.slot})`,\n );\n }\n // Do not retry if the request was aborted by the caller\n if (options?.abortSignal?.aborted) {\n break;\n }\n if (attempt < maxAttempts) {\n warnCall(\n `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n );\n await new Promise((resolve) => setTimeout(resolve, retryInterval));\n }\n } finally {\n cleanupAttemptSignal();\n }\n }\n\n if (!content) {\n assert(\n lastError,\n 'AI model request failed without recording an attempt error',\n );\n throw appendAIRequestFailureSummary(\n lastError,\n attemptErrors,\n maxAttempts,\n );\n }\n }\n\n debugCall(`response reasoning content: ${accumulatedReasoning}`);\n debugCall(`response content: ${content}`);\n\n const finalUsage = buildUsageInfo(usage, requestId);\n // Report usage to the runtime-level collector if not already reported\n // (e.g. from the streaming final-chunk handler).\n if (!usageReported && finalUsage && modelRuntime.onUsage) {\n modelRuntime.onUsage(finalUsage);\n }\n\n const response = {\n content: content || '',\n reasoning_content: accumulatedReasoning || undefined,\n rawChoiceMessage,\n usage: finalUsage,\n isStreamed: !!isStreaming,\n };\n recordEvent?.({\n type: 'response',\n attempt: getLatestResponseAttempt(openAIErrorResponseContext),\n http: openAIErrorResponseContext.httpResponses?.at(-1),\n final: {\n content: response.content,\n reasoningContent: response.reasoning_content,\n usage: response.usage,\n requestId,\n timeCost,\n responseModelName,\n },\n });\n return response;\n } catch (e: any) {\n warnCall('call AI error', e);\n\n if (e instanceof AIResponseParseError) {\n throw e;\n }\n\n const newError = new Error(\n `failed to call ${isStreaming ? 'streaming ' : ''}AI model service (${modelName}): ${e.message}${formatOpenAIAPIErrorDetails(e, openAIErrorResponseContext)}\\nTrouble shooting: https://midscenejs.com/model-provider.html`,\n {\n cause: e,\n },\n );\n throw newError;\n }\n}\n\nexport type AIObjectResponse<T> = {\n // TODO: `content` is a misleading name here because this is already the parsed object response. Consider renaming it to `object` or `data`.\n content: T;\n contentString: string;\n usage?: AIUsageInfo;\n reasoning_content?: string;\n rawChoiceMessage?: unknown;\n};\n\nexport function parseAIObjectResponse<T>(\n response: Awaited<ReturnType<typeof callAI>>,\n modelRuntime: ModelRuntime,\n jsonParserSource: JsonParserSource = 'generic-object',\n): AIObjectResponse<T> {\n const { adapter } = modelRuntime;\n assert(response, 'empty response');\n const jsonContent = adapter.jsonParser(response.content, {\n source: jsonParserSource,\n });\n assertJsonObject(jsonContent);\n return {\n content: jsonContent as T,\n contentString: response.content,\n usage: response.usage,\n reasoning_content: response.reasoning_content,\n rawChoiceMessage: response.rawChoiceMessage,\n };\n}\n\nexport async function callAIWithObjectResponse<T>(\n messages: ChatCompletionMessageParam[],\n modelRuntime: ModelRuntime,\n options?: {\n abortSignal?: AbortSignal;\n jsonParserSource?: JsonParserSource;\n retryTimes?: number;\n retryInterval?: number;\n },\n): Promise<AIObjectResponse<T>> {\n const { config: modelConfig } = modelRuntime;\n return callAiAndParseWithRetry({\n callAi: (retryAttempt, previousParseError) =>\n callAI(\n withSemanticRetryFeedback(messages, previousParseError),\n modelRuntime,\n {\n abortSignal: options?.abortSignal,\n expectedJsonObjectResponse: true,\n semanticRetryAttempt: retryAttempt,\n },\n ),\n parseResponse: (response) =>\n parseAIObjectResponse<T>(\n response,\n modelRuntime,\n options?.jsonParserSource,\n ),\n toParseError: (error, response) => {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return new AIResponseParseError(\n errorMessage,\n response.content,\n response.usage,\n response.rawChoiceMessage,\n response.reasoning_content,\n );\n },\n parseRetryTimes: options?.retryTimes ?? modelConfig.retryCount,\n parseRetryInterval: options?.retryInterval ?? modelConfig.retryInterval,\n abortSignal: options?.abortSignal,\n });\n}\n\nexport async function callAIWithStringResponse(\n msgs: AIArgs,\n modelRuntime: ModelRuntime,\n options?: Pick<CallAIOptions, 'abortSignal' | 'requiresOriginalImageDetail'>,\n): Promise<{\n content: string;\n usage?: AIUsageInfo;\n rawChoiceMessage?: unknown;\n}> {\n const { content, usage, rawChoiceMessage } = await callAI(\n msgs,\n modelRuntime,\n options,\n );\n return { content, usage, rawChoiceMessage };\n}\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","AIResponseParseError","Error","message","rawResponse","usage","rawChoiceMessage","reasoningContent","INTERNAL_CALL_ID_FIELD","internalCallIdCounter","nextInternalCallId","stringifyForDebug","value","JSON","_error","String","getLatestSuccessfulResponseRequestId","context","latestRequestId","response","undefined","getLatestResponseAttempt","getErrorMessage","error","toError","normalizeRetryCount","retryCount","Number","Math","appendAIRequestFailureSummary","attemptErrors","maxAttempts","failedAttempts","retries","retryLabel","originalMessage","previousAttemptErrors","details","attempt","createChatClient","modelConfig","executionId","recordEvent","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","modelDescription","modelFamily","createOpenAIClient","timeout","proxyAgent","warnClient","getDebug","debugProxy","warnProxy","sanitizeProxyUrl","url","parsed","URL","ifInBrowser","loadUndici","ProxyAgent","loadFetchSocks","socksDispatcher","proxyUrl","port","protocol","socksType","decodeURIComponent","effectiveTimeoutMs","resolveEffectiveTimeoutMs","openAIErrorResponseContext","openAIOptions","getVersion","wrapOpenAICompatibleFetch","baseOpenAI","OpenAI","openai","globalConfigManager","MIDSCENE_LANGSMITH_DEBUG","langsmithModule","wrapOpenAI","MIDSCENE_LANGFUSE_DEBUG","langfuseModule","observeOpenAI","wrappedClient","callAI","messages","modelRuntime","options","adapter","uuid","internalCallId","isModelCallRecordingEnabled","event","recordModelCallEvent","modelCallInput","isCodexAppServerProvider","protocolChunkSequence","codexStartTime","Date","recordCodexEvent","config","imageDetail","codexResult","callAIWithCodexAppServer","protocolMetadata","completion","extraBody","debugCall","warnCall","debugProfileStats","debugProfileDetail","startTime","isStreaming","adapterChatCompletionParams","content","accumulated","accumulatedReasoning","timeCost","requestId","responseModelName","usageReported","hasUsableText","resolveContentWithReasoningFallback","contentValue","buildUsageInfo","usageData","cachedInputTokens","requestConfig","temperature","messagesWithImageDetail","msg","Array","part","streamSignal","cleanupStreamSignal","buildRequestAbortSignal","stream","streamAttempt","chunkSequence","chunk","parsedChunk","reasoning_content","chunkData","finalAccumulated","finalUsage","finalChunk","restoreHardTimeoutError","retryInterval","lastError","attemptSignal","cleanupAttemptSignal","result","parsedMessage","errorUsage","wasHardTimeout","isHardTimeoutError","Promise","resolve","setTimeout","assert","e","newError","formatOpenAIAPIErrorDetails","parseAIObjectResponse","jsonParserSource","jsonContent","assertJsonObject","callAIWithObjectResponse","callAiAndParseWithRetry","retryAttempt","previousParseError","withSemanticRetryFeedback","errorMessage","callAIWithStringResponse","msgs"],"mappings":"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"}
package/dist/lib/index.js CHANGED
@@ -39,15 +39,16 @@ __webpack_require__.d(__webpack_exports__, {
39
39
  getTaskServiceDump: ()=>task_service_dump_js_namespaceObject.getTaskServiceDump,
40
40
  reportToMarkdown: ()=>external_report_markdown_js_namespaceObject.reportToMarkdown,
41
41
  collectDedupedExecutions: ()=>external_report_js_namespaceObject.collectDedupedExecutions,
42
+ TEST_RUN_REPORT_SCRIPT_TYPE: ()=>external_test_run_report_js_namespaceObject.TEST_RUN_REPORT_SCRIPT_TYPE,
42
43
  generateImageScriptTag: ()=>external_dump_index_js_namespaceObject.generateImageScriptTag,
43
44
  restoreImageReferences: ()=>external_dump_index_js_namespaceObject.restoreImageReferences,
44
- runConnectivityTest: ()=>external_ai_model_index_js_namespaceObject.runConnectivityTest,
45
45
  getTaskSearchArea: ()=>task_service_dump_js_namespaceObject.getTaskSearchArea,
46
46
  parseDumpScriptAttributes: ()=>external_dump_index_js_namespaceObject.parseDumpScriptAttributes,
47
+ runConnectivityTest: ()=>external_ai_model_index_js_namespaceObject.runConnectivityTest,
47
48
  splitReportHtmlByExecution: ()=>external_report_js_namespaceObject.splitReportHtmlByExecution,
48
- z: ()=>external_zod_namespaceObject.z,
49
49
  generateDumpScriptTag: ()=>external_dump_index_js_namespaceObject.generateDumpScriptTag,
50
50
  SizeSchema: ()=>external_ai_model_index_js_namespaceObject.SizeSchema,
51
+ z: ()=>external_zod_namespaceObject.z,
51
52
  default: ()=>src,
52
53
  getVersion: ()=>external_utils_js_namespaceObject.getVersion,
53
54
  getMidsceneLocationSchema: ()=>external_ai_model_index_js_namespaceObject.getMidsceneLocationSchema,
@@ -66,8 +67,8 @@ __webpack_require__.d(__webpack_exports__, {
66
67
  ScreenshotStore: ()=>screenshot_store_js_namespaceObject.ScreenshotStore,
67
68
  Service: ()=>index_js_default(),
68
69
  mergeReportFiles: ()=>external_report_cli_js_namespaceObject.mergeReportFiles,
70
+ TestRunReportAssembler: ()=>external_report_js_namespaceObject.TestRunReportAssembler,
69
71
  standardPlan: ()=>external_ai_model_index_js_namespaceObject.standardPlan,
70
- verifyLocator: ()=>external_element_describer_js_namespaceObject.verifyLocator,
71
72
  deriveCaseStatus: ()=>external_dump_index_js_namespaceObject.deriveCaseStatus,
72
73
  AiLocateElement: ()=>external_ai_model_index_js_namespaceObject.AiLocateElement,
73
74
  createReportCliCommands: ()=>external_report_cli_js_namespaceObject.createReportCliCommands,
@@ -79,6 +80,7 @@ __webpack_require__.d(__webpack_exports__, {
79
80
  describeElementAtPoint: ()=>external_element_describer_js_namespaceObject.describeElementAtPoint,
80
81
  TaskRunner: ()=>external_task_runner_js_namespaceObject.TaskRunner,
81
82
  escapeContent: ()=>external_dump_index_js_namespaceObject.escapeContent,
83
+ verifyLocator: ()=>external_element_describer_js_namespaceObject.verifyLocator,
82
84
  ReportActionDump: ()=>external_types_js_namespaceObject.ReportActionDump,
83
85
  GroupedActionDump: ()=>external_types_js_namespaceObject.GroupedActionDump,
84
86
  TMultimodalPromptSchema: ()=>external_ai_model_index_js_namespaceObject.TMultimodalPromptSchema,
@@ -101,6 +103,7 @@ const external_dump_index_js_namespaceObject = require("./dump/index.js");
101
103
  const task_service_dump_js_namespaceObject = require("./dump/task-service-dump.js");
102
104
  const external_report_generator_js_namespaceObject = require("./report-generator.js");
103
105
  const external_report_js_namespaceObject = require("./report.js");
106
+ const external_test_run_report_js_namespaceObject = require("./test-run-report.js");
104
107
  const external_report_cli_js_namespaceObject = require("./report-cli.js");
105
108
  const external_screenshot_item_js_namespaceObject = require("./screenshot-item.js");
106
109
  const screenshot_store_js_namespaceObject = require("./dump/screenshot-store.js");
@@ -122,9 +125,11 @@ exports.ScreenshotStore = __webpack_exports__.ScreenshotStore;
122
125
  exports.Service = __webpack_exports__.Service;
123
126
  exports.ServiceError = __webpack_exports__.ServiceError;
124
127
  exports.SizeSchema = __webpack_exports__.SizeSchema;
128
+ exports.TEST_RUN_REPORT_SCRIPT_TYPE = __webpack_exports__.TEST_RUN_REPORT_SCRIPT_TYPE;
125
129
  exports.TMultimodalPromptSchema = __webpack_exports__.TMultimodalPromptSchema;
126
130
  exports.TUserPromptSchema = __webpack_exports__.TUserPromptSchema;
127
131
  exports.TaskRunner = __webpack_exports__.TaskRunner;
132
+ exports.TestRunReportAssembler = __webpack_exports__.TestRunReportAssembler;
128
133
  exports.collectDedupedExecutions = __webpack_exports__.collectDedupedExecutions;
129
134
  exports.createAgent = __webpack_exports__.createAgent;
130
135
  exports.createInlineImageResolver = __webpack_exports__.createInlineImageResolver;
@@ -176,9 +181,11 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
176
181
  "Service",
177
182
  "ServiceError",
178
183
  "SizeSchema",
184
+ "TEST_RUN_REPORT_SCRIPT_TYPE",
179
185
  "TMultimodalPromptSchema",
180
186
  "TUserPromptSchema",
181
187
  "TaskRunner",
188
+ "TestRunReportAssembler",
182
189
  "collectDedupedExecutions",
183
190
  "createAgent",
184
191
  "createInlineImageResolver",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/index.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__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 { z } from 'zod';\nimport Service from './service/index';\nimport { TaskRunner } from './task-runner';\nimport { getVersion } from './utils';\n\nexport {\n standardPlan,\n AiLocateElement,\n runConnectivityTest,\n getMidsceneLocationSchema,\n PointSchema,\n SizeSchema,\n RectSchema,\n TMultimodalPromptSchema,\n TUserPromptSchema,\n type TMultimodalPrompt,\n type TUserPrompt,\n type ConnectivityTestConfig,\n type ConnectivityTestResult,\n} from './ai-model/index';\n\nexport {\n MIDSCENE_MODEL_NAME,\n type CreateOpenAIClientFn,\n} from '@midscene/shared/env';\n\nexport type * from './types';\nexport {\n ServiceError,\n ExecutionDump,\n ReportActionDump,\n GroupedActionDump,\n type IExecutionDump,\n type IReportActionDump,\n type IGroupedActionDump,\n type ReportMeta,\n type GroupMeta,\n} from './types';\n\nexport { z };\n\nexport default Service;\nexport { TaskRunner, Service, getVersion };\n\nexport type {\n MidsceneYamlScript,\n MidsceneYamlTask,\n MidsceneYamlFlowItem,\n MidsceneYamlConfigResult,\n MidsceneYamlConfig,\n MidsceneYamlScriptWebEnv,\n MidsceneYamlScriptAndroidEnv,\n MidsceneYamlScriptIOSEnv,\n MidsceneYamlScriptHarmonyEnv,\n MidsceneYamlTargetConfig,\n MidsceneYamlTargetKey,\n MidsceneYamlScriptEnv,\n LocateOption,\n DetailedLocateParam,\n} from './yaml';\n\nexport {\n Agent,\n type AgentOpt,\n type AiActOptions,\n type GherkinStepKeyword,\n type MidsceneUsageMetrics,\n type RunGherkinScenarioOptions,\n type UsageBucket,\n createAgent,\n type UIObservation,\n type UIObserver,\n type UIObserverOption,\n} from './agent';\nexport {\n describeElementAtPoint,\n verifyElementDescriptionAtPoint,\n verifyLocator,\n type DescribeElementAtPointOptions,\n type DescribeElementCoordinateSpace,\n type ElementDescriberRuntime,\n type VerifyElementDescriptionAtPointOptions,\n} from './element-describer';\n\n// Dump utilities\nexport {\n createInlineImageResolver,\n restoreImageReferences,\n restoreReportImageReferences,\n escapeContent,\n unescapeContent,\n parseImageScripts,\n parseDumpScript,\n parseDumpScriptAttributes,\n generateImageScriptTag,\n generateDumpScriptTag,\n deriveTaskStatus,\n deriveCaseStatus,\n} from './dump';\nexport type {\n TaskStatusFields,\n DerivedTaskStatus,\n RestoredScreenshotReference,\n StoredImageReferenceResolver,\n} from './dump';\nexport {\n getTaskSearchArea,\n getTaskServiceDump,\n} from './dump/task-service-dump';\n\n// Report generator\nexport type { IReportGenerator } from './report-generator';\nexport { ReportGenerator, nullReportGenerator } from './report-generator';\nexport {\n collectDedupedExecutions,\n ReportMergingTool,\n dedupeExecutionsKeepLatest,\n splitReportHtmlByExecution,\n} from './report';\nexport {\n createReportCliCommands,\n reportFileToMarkdown,\n splitReportFile,\n mergeReportFiles,\n type ConsumeReportFileAction,\n type ReportFileToMarkdownOptions,\n type ReportCliCommandDefinition,\n type ReportCliCommandEntry,\n type SplitReportFileOptions,\n type MergeReportFilesOptions,\n type MergeReportFilesResult,\n} from './report-cli';\n\n// ScreenshotItem\nexport { ScreenshotItem } from './screenshot-item';\nexport type {\n ImageUrlRef,\n ScreenshotRef,\n StoredImageRef,\n} from './dump/image-reference';\nexport {\n ReportImageStore,\n ScreenshotStore,\n} from './dump/screenshot-store';\n\nexport {\n executionToMarkdown,\n reportToMarkdown,\n type ExecutionMarkdownOptions,\n type ExecutionMarkdownResult,\n type ReportMarkdownOptions,\n type ReportMarkdownResult,\n type MarkdownAttachment,\n} from './report-markdown';\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","Service"],"mappings":";;;IACAA,oBAAoB,CAAC,GAAG,CAACC;QACxB,IAAIC,SAASD,UAAUA,OAAO,UAAU,GACvC,IAAOA,MAAM,CAAC,UAAU,GACxB,IAAOA;QACRD,oBAAoB,CAAC,CAACE,QAAQ;YAAE,GAAGA;QAAO;QAC1C,OAAOA;IACR;;;ICPAF,oBAAoB,CAAC,GAAG,CAAC,UAASG;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGH,oBAAoB,CAAC,CAACG,YAAYC,QAAQ,CAACJ,oBAAoB,CAAC,CAAC,UAASI,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAJ,oBAAoB,CAAC,GAAG,CAACM,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFP,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOQ,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACmCA,YAAeI"}
1
+ {"version":3,"file":"index.js","sources":["webpack/runtime/compat_get_default_export","webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../src/index.ts"],"sourcesContent":["// getDefaultExport function for compatibility with non-ESM modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};\n","__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 { z } from 'zod';\nimport Service from './service/index';\nimport { TaskRunner } from './task-runner';\nimport { getVersion } from './utils';\n\nexport {\n standardPlan,\n AiLocateElement,\n runConnectivityTest,\n getMidsceneLocationSchema,\n PointSchema,\n SizeSchema,\n RectSchema,\n TMultimodalPromptSchema,\n TUserPromptSchema,\n type TMultimodalPrompt,\n type TUserPrompt,\n type ConnectivityTestConfig,\n type ConnectivityTestResult,\n} from './ai-model/index';\n\nexport {\n MIDSCENE_MODEL_NAME,\n type CreateOpenAIClientFn,\n} from '@midscene/shared/env';\n\nexport type * from './types';\nexport {\n ServiceError,\n ExecutionDump,\n ReportActionDump,\n GroupedActionDump,\n type IExecutionDump,\n type IReportActionDump,\n type IGroupedActionDump,\n type ReportMeta,\n type GroupMeta,\n} from './types';\n\nexport { z };\n\nexport default Service;\nexport { TaskRunner, Service, getVersion };\n\nexport type {\n MidsceneYamlScript,\n MidsceneYamlTask,\n MidsceneYamlFlowItem,\n MidsceneYamlConfigResult,\n MidsceneYamlConfig,\n MidsceneYamlScriptWebEnv,\n MidsceneYamlScriptAndroidEnv,\n MidsceneYamlScriptIOSEnv,\n MidsceneYamlScriptHarmonyEnv,\n MidsceneYamlTargetConfig,\n MidsceneYamlTargetKey,\n MidsceneYamlScriptEnv,\n LocateOption,\n DetailedLocateParam,\n} from './yaml';\n\nexport {\n Agent,\n type AgentOpt,\n type AiActOptions,\n type GherkinStepKeyword,\n type MidsceneUsageMetrics,\n type RunGherkinScenarioOptions,\n type UsageBucket,\n createAgent,\n type UIObservation,\n type UIObserver,\n type UIObserverOption,\n} from './agent';\nexport {\n describeElementAtPoint,\n verifyElementDescriptionAtPoint,\n verifyLocator,\n type DescribeElementAtPointOptions,\n type DescribeElementCoordinateSpace,\n type ElementDescriberRuntime,\n type VerifyElementDescriptionAtPointOptions,\n} from './element-describer';\n\n// Dump utilities\nexport {\n createInlineImageResolver,\n restoreImageReferences,\n restoreReportImageReferences,\n escapeContent,\n unescapeContent,\n parseImageScripts,\n parseDumpScript,\n parseDumpScriptAttributes,\n generateImageScriptTag,\n generateDumpScriptTag,\n deriveTaskStatus,\n deriveCaseStatus,\n} from './dump';\nexport type {\n TaskStatusFields,\n DerivedTaskStatus,\n RestoredScreenshotReference,\n StoredImageReferenceResolver,\n} from './dump';\nexport {\n getTaskSearchArea,\n getTaskServiceDump,\n} from './dump/task-service-dump';\n\n// Report generator\nexport type { IReportGenerator } from './report-generator';\nexport { ReportGenerator, nullReportGenerator } from './report-generator';\nexport {\n collectDedupedExecutions,\n ReportMergingTool,\n TestRunReportAssembler,\n dedupeExecutionsKeepLatest,\n splitReportHtmlByExecution,\n} from './report';\nexport type * from './test-run-report';\nexport { TEST_RUN_REPORT_SCRIPT_TYPE } from './test-run-report';\nexport {\n createReportCliCommands,\n reportFileToMarkdown,\n splitReportFile,\n mergeReportFiles,\n type ConsumeReportFileAction,\n type ReportFileToMarkdownOptions,\n type ReportCliCommandDefinition,\n type ReportCliCommandEntry,\n type SplitReportFileOptions,\n type MergeReportFilesOptions,\n type MergeReportFilesResult,\n} from './report-cli';\n\n// ScreenshotItem\nexport { ScreenshotItem } from './screenshot-item';\nexport type {\n ImageUrlRef,\n ScreenshotRef,\n StoredImageRef,\n} from './dump/image-reference';\nexport {\n ReportImageStore,\n ScreenshotStore,\n} from './dump/screenshot-store';\n\nexport {\n executionToMarkdown,\n reportToMarkdown,\n type ExecutionMarkdownOptions,\n type ExecutionMarkdownResult,\n type ReportMarkdownOptions,\n type ReportMarkdownResult,\n type MarkdownAttachment,\n} from './report-markdown';\n"],"names":["__webpack_require__","module","getter","definition","key","Object","obj","prop","Symbol","Service"],"mappings":";;;IACAA,oBAAoB,CAAC,GAAG,CAACC;QACxB,IAAIC,SAASD,UAAUA,OAAO,UAAU,GACvC,IAAOA,MAAM,CAAC,UAAU,GACxB,IAAOA;QACRD,oBAAoB,CAAC,CAACE,QAAQ;YAAE,GAAGA;QAAO;QAC1C,OAAOA;IACR;;;ICPAF,oBAAoB,CAAC,GAAG,CAAC,UAASG;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGH,oBAAoB,CAAC,CAACG,YAAYC,QAAQ,CAACJ,oBAAoB,CAAC,CAAC,UAASI,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAJ,oBAAoB,CAAC,GAAG,CAACM,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFP,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOQ,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACmCA,YAAeI"}