@aiscene/core 8.0.2 → 8.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/es/agent/utils.mjs +26 -9
  2. package/dist/es/agent/utils.mjs.map +1 -1
  3. package/dist/es/utils.mjs +1 -1
  4. package/dist/lib/agent/utils.js +26 -9
  5. package/dist/lib/agent/utils.js.map +1 -1
  6. package/dist/lib/types.js +5 -5
  7. package/dist/lib/utils.js +1 -1
  8. package/package.json +2 -2
  9. package/dist/types/agent/agent.d.ts +0 -216
  10. package/dist/types/agent/common.d.ts +0 -0
  11. package/dist/types/agent/execution-session.d.ts +0 -36
  12. package/dist/types/agent/index.d.ts +0 -9
  13. package/dist/types/agent/task-builder.d.ts +0 -34
  14. package/dist/types/agent/task-cache.d.ts +0 -49
  15. package/dist/types/agent/tasks.d.ts +0 -69
  16. package/dist/types/agent/ui-utils.d.ts +0 -14
  17. package/dist/types/agent/utils.d.ts +0 -25
  18. package/dist/types/ai-model/auto-glm/actions.d.ts +0 -78
  19. package/dist/types/ai-model/auto-glm/index.d.ts +0 -6
  20. package/dist/types/ai-model/auto-glm/parser.d.ts +0 -18
  21. package/dist/types/ai-model/auto-glm/planning.d.ts +0 -12
  22. package/dist/types/ai-model/auto-glm/prompt.d.ts +0 -27
  23. package/dist/types/ai-model/auto-glm/util.d.ts +0 -13
  24. package/dist/types/ai-model/connectivity.d.ts +0 -20
  25. package/dist/types/ai-model/conversation-history.d.ts +0 -105
  26. package/dist/types/ai-model/index.d.ts +0 -16
  27. package/dist/types/ai-model/inspect.d.ts +0 -67
  28. package/dist/types/ai-model/llm-planning.d.ts +0 -19
  29. package/dist/types/ai-model/prompt/common.d.ts +0 -2
  30. package/dist/types/ai-model/prompt/describe.d.ts +0 -1
  31. package/dist/types/ai-model/prompt/extraction.d.ts +0 -7
  32. package/dist/types/ai-model/prompt/llm-locator.d.ts +0 -3
  33. package/dist/types/ai-model/prompt/llm-planning.d.ts +0 -10
  34. package/dist/types/ai-model/prompt/llm-section-locator.d.ts +0 -3
  35. package/dist/types/ai-model/prompt/order-sensitive-judge.d.ts +0 -2
  36. package/dist/types/ai-model/prompt/playwright-generator.d.ts +0 -26
  37. package/dist/types/ai-model/prompt/ui-tars-planning.d.ts +0 -2
  38. package/dist/types/ai-model/prompt/util.d.ts +0 -33
  39. package/dist/types/ai-model/prompt/yaml-generator.d.ts +0 -102
  40. package/dist/types/ai-model/service-caller/codex-app-server.d.ts +0 -42
  41. package/dist/types/ai-model/service-caller/image-detail.d.ts +0 -2
  42. package/dist/types/ai-model/service-caller/index.d.ts +0 -49
  43. package/dist/types/ai-model/ui-tars-planning.d.ts +0 -72
  44. package/dist/types/common.d.ts +0 -288
  45. package/dist/types/device/device-options.d.ts +0 -145
  46. package/dist/types/device/index.d.ts +0 -2528
  47. package/dist/types/dump/html-utils.d.ts +0 -75
  48. package/dist/types/dump/index.d.ts +0 -5
  49. package/dist/types/dump/screenshot-restoration.d.ts +0 -8
  50. package/dist/types/dump/screenshot-store.d.ts +0 -49
  51. package/dist/types/index.d.ts +0 -21
  52. package/dist/types/report-cli.d.ts +0 -36
  53. package/dist/types/report-generator.d.ts +0 -81
  54. package/dist/types/report-markdown.d.ts +0 -24
  55. package/dist/types/report.d.ts +0 -52
  56. package/dist/types/screenshot-item.d.ts +0 -67
  57. package/dist/types/service/index.d.ts +0 -24
  58. package/dist/types/service/utils.d.ts +0 -2
  59. package/dist/types/skill/index.d.ts +0 -25
  60. package/dist/types/task-runner.d.ts +0 -50
  61. package/dist/types/task-timing.d.ts +0 -8
  62. package/dist/types/tree.d.ts +0 -4
  63. package/dist/types/types.d.ts +0 -681
  64. package/dist/types/utils.d.ts +0 -45
  65. package/dist/types/yaml/builder.d.ts +0 -2
  66. package/dist/types/yaml/index.d.ts +0 -4
  67. package/dist/types/yaml/player.d.ts +0 -34
  68. package/dist/types/yaml/utils.d.ts +0 -9
  69. package/dist/types/yaml.d.ts +0 -215
@@ -26,14 +26,31 @@ async function commonContextParser(interfaceInstance, _opt) {
26
26
  if (!Number.isFinite(logicalWidth) || !Number.isFinite(logicalHeight)) throw new Error(`Invalid interface size: width and height must be finite numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`);
27
27
  if (logicalWidth <= 0 || logicalHeight <= 0) throw new Error(`Invalid interface size: width and height must be positive numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`);
28
28
  debug(`size: ${logicalWidth}x${logicalHeight}`);
29
- const screenshotBase64 = await interfaceInstance.screenshotBase64();
30
- const screenshotCapturedAt = Date.now();
31
- assert(screenshotBase64, 'screenshotBase64 is required');
32
- debug('will get screenshot dimensions');
33
- const { width: imgWidth, height: imgHeight } = await imageInfoOfBase64(screenshotBase64);
34
- if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) throw new Error(`Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
35
- if (imgWidth <= 0 || imgHeight <= 0) throw new Error(`Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
36
- debug('screenshot dimensions', imgWidth, 'x', imgHeight);
29
+ const maxRetries = 3;
30
+ let lastError = null;
31
+ let screenshotBase64 = null;
32
+ let screenshotCapturedAt = 0;
33
+ let imgWidth = 0;
34
+ let imgHeight = 0;
35
+ for(let attempt = 1; attempt <= maxRetries; attempt++)try {
36
+ screenshotBase64 = await interfaceInstance.screenshotBase64();
37
+ screenshotCapturedAt = Date.now();
38
+ assert(screenshotBase64, 'screenshotBase64 is required');
39
+ debug('will get screenshot dimensions');
40
+ const dimensions = await imageInfoOfBase64(screenshotBase64);
41
+ imgWidth = dimensions.width;
42
+ imgHeight = dimensions.height;
43
+ if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) throw new Error(`Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
44
+ if (imgWidth <= 0 || imgHeight <= 0) throw new Error(`Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
45
+ debug('screenshot dimensions', imgWidth, 'x', imgHeight);
46
+ break;
47
+ } catch (error) {
48
+ lastError = error instanceof Error ? error : new Error(String(error));
49
+ debug(`Screenshot capture/decode failed (attempt ${attempt}/${maxRetries}): ${lastError.message}`);
50
+ if (attempt === maxRetries) throw new Error(`Failed to capture valid screenshot after ${maxRetries} attempts: ${lastError.message}`);
51
+ await new Promise((resolve)=>setTimeout(resolve, 500));
52
+ }
53
+ if (!screenshotBase64) throw new Error('Screenshot data is null after retry loop');
37
54
  const logicalIsPortrait = logicalWidth < logicalHeight;
38
55
  const screenshotIsPortrait = imgWidth < imgHeight;
39
56
  let finalLogicalWidth = logicalWidth;
@@ -123,7 +140,7 @@ async function matchElementFromCache(context, cacheEntry, cachePrompt, cacheable
123
140
  return;
124
141
  }
125
142
  }
126
- const getMidsceneVersion = ()=>"8.0.1";
143
+ const getMidsceneVersion = ()=>"8.0.3";
127
144
  const parsePrompt = (prompt)=>{
128
145
  if ('string' == typeof prompt) return {
129
146
  textPrompt: prompt,
@@ -1 +1 @@
1
- {"version":3,"file":"agent/utils.mjs","sources":["../../../src/agent/utils.ts"],"sourcesContent":["import type { TMultimodalPrompt, TUserPrompt } from '@/common';\nimport type { AbstractInterface } from '@/device';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n ElementCacheFeature,\n LocateResultElement,\n PlanningLocateParam,\n Rect,\n UIContext,\n} from '@/types';\nimport { uploadTestInfoToServer } from '@/utils';\nimport type { TModelFamily } from '@aiscene/shared/env';\nimport {\n MIDSCENE_REPORT_QUIET,\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@aiscene/shared/env';\nimport { generateElementByRect } from '@aiscene/shared/extractor';\nimport { imageInfoOfBase64, resizeImgBase64 } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { _keyDefinitions } from '@aiscene/shared/us-keyboard-layout';\nimport { assert, logMsg, uuid } from '@aiscene/shared/utils';\nimport dayjs from 'dayjs';\nimport type { TaskCache } from './task-cache';\nimport { debug as cacheDebug } from './task-cache';\n\nexport async function commonContextParser(\n interfaceInstance: AbstractInterface,\n _opt: {\n uploadServerUrl?: string;\n screenshotShrinkFactor?: number;\n modelFamily?: TModelFamily;\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\n // Get physical screenshot dimensions\n debug('will get screenshot dimensions');\n const { width: imgWidth, height: imgHeight } =\n await imageInfoOfBase64(screenshotBase64);\n\n if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\n if (imgWidth <= 0 || imgHeight <= 0) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\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 userShrinkFactor = _opt.screenshotShrinkFactor ?? 1;\n\n if (!Number.isFinite(userShrinkFactor) || userShrinkFactor < 1) {\n throw new Error(\n `Invalid screenshotShrinkFactor: must be a finite number >= 1. Received: ${userShrinkFactor}`,\n );\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 const targetWidth = Math.round(imgWidth / userShrinkFactor);\n const targetHeight = Math.round(imgHeight / userShrinkFactor);\n\n debug(\n `Applying screenshot shrink factor: ${userShrinkFactor} (physical: ${imgWidth}x${imgHeight} -> target: ${targetWidth}x${targetHeight})`,\n );\n\n const resizedBase64 = await resizeImgBase64(screenshotBase64, {\n width: targetWidth,\n height: targetHeight,\n });\n return {\n shotSize: {\n width: targetWidth,\n height: targetHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(resizedBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\n };\n }\n\n return {\n shotSize: {\n width: imgWidth,\n height: imgHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(screenshotBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\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\nexport function ifPlanLocateParamIsBbox(\n planLocateParam: PlanningLocateParam,\n): boolean {\n return !!(\n planLocateParam.bbox &&\n Array.isArray(planLocateParam.bbox) &&\n planLocateParam.bbox.length === 4\n );\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n): LocateResultElement | undefined {\n if (!planLocateParam) {\n return undefined;\n }\n\n if (planLocateParam.bbox) {\n // Convert bbox [x1, y1, x2, y2] to rect {left, top, width, height}\n const rect = {\n left: planLocateParam.bbox[0],\n top: planLocateParam.bbox[1],\n width: planLocateParam.bbox[2] - planLocateParam.bbox[0] + 1,\n height: planLocateParam.bbox[3] - planLocateParam.bbox[1] + 1,\n };\n\n const element = generateElementByRect(\n rect,\n typeof planLocateParam.prompt === 'string'\n ? planLocateParam.prompt\n : planLocateParam.prompt?.prompt || '',\n );\n return element;\n }\n\n return undefined;\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: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2),\n ],\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 Math.round(element.center[0] * shrunkShotToLogicalRatio),\n Math.round(element.center[1] * shrunkShotToLogicalRatio),\n ],\n rect: {\n ...element.rect,\n left: Math.round(element.rect.left * shrunkShotToLogicalRatio),\n top: Math.round(element.rect.top * shrunkShotToLogicalRatio),\n width: Math.round(element.rect.width * shrunkShotToLogicalRatio),\n height: Math.round(element.rect.height * shrunkShotToLogicalRatio),\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":["commonContextParser","interfaceInstance","_opt","debug","getDebug","assert","description","uploadTestInfoToServer","interfaceSize","logicalWidth","logicalHeight","console","Number","Error","screenshotBase64","screenshotCapturedAt","Date","imgWidth","imgHeight","imageInfoOfBase64","logicalIsPortrait","screenshotIsPortrait","finalLogicalWidth","userShrinkFactor","dpr","shrunkShotToLogicalRatio","targetWidth","Math","targetHeight","resizedBase64","resizeImgBase64","ScreenshotItem","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","MIDSCENE_REPORT_QUIET","logMsg","ifPlanLocateParamIsBbox","planLocateParam","Array","matchElementFromPlan","rect","element","generateElementByRect","matchElementFromCache","context","cacheEntry","cachePrompt","cacheable","cacheDebug","error","getMidsceneVersion","__VERSION__","parsePrompt","prompt","undefined","transformLogicalElementToScreenshot","transformLogicalRectToScreenshotRect"],"mappings":"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"}
1
+ {"version":3,"file":"agent/utils.mjs","sources":["../../../src/agent/utils.ts"],"sourcesContent":["import type { TMultimodalPrompt, TUserPrompt } from '@/common';\nimport type { AbstractInterface } from '@/device';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n ElementCacheFeature,\n LocateResultElement,\n PlanningLocateParam,\n Rect,\n UIContext,\n} from '@/types';\nimport { uploadTestInfoToServer } from '@/utils';\nimport type { TModelFamily } from '@aiscene/shared/env';\nimport {\n MIDSCENE_REPORT_QUIET,\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@aiscene/shared/env';\nimport { generateElementByRect } from '@aiscene/shared/extractor';\nimport { imageInfoOfBase64, resizeImgBase64 } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { _keyDefinitions } from '@aiscene/shared/us-keyboard-layout';\nimport { assert, logMsg, uuid } from '@aiscene/shared/utils';\nimport dayjs from 'dayjs';\nimport type { TaskCache } from './task-cache';\nimport { debug as cacheDebug } from './task-cache';\n\nexport async function commonContextParser(\n interfaceInstance: AbstractInterface,\n _opt: {\n uploadServerUrl?: string;\n screenshotShrinkFactor?: number;\n modelFamily?: TModelFamily;\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 // Retry logic for screenshot capture/decoding\n const maxRetries = 3;\n let lastError: Error | null = null;\n let screenshotBase64: string | null = null;\n let screenshotCapturedAt = 0;\n let imgWidth: number = 0;\n let imgHeight: number = 0;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n screenshotBase64 = await interfaceInstance.screenshotBase64();\n screenshotCapturedAt = Date.now();\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n // Get physical screenshot dimensions\n debug('will get screenshot dimensions');\n const dimensions = await imageInfoOfBase64(screenshotBase64);\n imgWidth = dimensions.width;\n imgHeight = dimensions.height;\n\n // Validate dimensions\n if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\n if (imgWidth <= 0 || imgHeight <= 0) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\n\n // If we get here, screenshot is valid\n debug('screenshot dimensions', imgWidth, 'x', imgHeight);\n break;\n } catch (error) {\n lastError =\n error instanceof Error ? error : new Error(String(error));\n debug(\n `Screenshot capture/decode failed (attempt ${attempt}/${maxRetries}): ${lastError.message}`,\n );\n\n if (attempt === maxRetries) {\n throw new Error(\n `Failed to capture valid screenshot after ${maxRetries} attempts: ${lastError.message}`,\n );\n }\n\n // Wait before retrying\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n }\n\n // This should never be null if we got past the retry loop\n if (!screenshotBase64) {\n throw new Error('Screenshot data is null after retry loop');\n }\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 userShrinkFactor = _opt.screenshotShrinkFactor ?? 1;\n\n if (!Number.isFinite(userShrinkFactor) || userShrinkFactor < 1) {\n throw new Error(\n `Invalid screenshotShrinkFactor: must be a finite number >= 1. Received: ${userShrinkFactor}`,\n );\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 const targetWidth = Math.round(imgWidth / userShrinkFactor);\n const targetHeight = Math.round(imgHeight / userShrinkFactor);\n\n debug(\n `Applying screenshot shrink factor: ${userShrinkFactor} (physical: ${imgWidth}x${imgHeight} -> target: ${targetWidth}x${targetHeight})`,\n );\n\n const resizedBase64 = await resizeImgBase64(screenshotBase64, {\n width: targetWidth,\n height: targetHeight,\n });\n return {\n shotSize: {\n width: targetWidth,\n height: targetHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(resizedBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\n };\n }\n\n return {\n shotSize: {\n width: imgWidth,\n height: imgHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(screenshotBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\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\nexport function ifPlanLocateParamIsBbox(\n planLocateParam: PlanningLocateParam,\n): boolean {\n return !!(\n planLocateParam.bbox &&\n Array.isArray(planLocateParam.bbox) &&\n planLocateParam.bbox.length === 4\n );\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n): LocateResultElement | undefined {\n if (!planLocateParam) {\n return undefined;\n }\n\n if (planLocateParam.bbox) {\n // Convert bbox [x1, y1, x2, y2] to rect {left, top, width, height}\n const rect = {\n left: planLocateParam.bbox[0],\n top: planLocateParam.bbox[1],\n width: planLocateParam.bbox[2] - planLocateParam.bbox[0] + 1,\n height: planLocateParam.bbox[3] - planLocateParam.bbox[1] + 1,\n };\n\n const element = generateElementByRect(\n rect,\n typeof planLocateParam.prompt === 'string'\n ? planLocateParam.prompt\n : planLocateParam.prompt?.prompt || '',\n );\n return element;\n }\n\n return undefined;\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: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2),\n ],\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 Math.round(element.center[0] * shrunkShotToLogicalRatio),\n Math.round(element.center[1] * shrunkShotToLogicalRatio),\n ],\n rect: {\n ...element.rect,\n left: Math.round(element.rect.left * shrunkShotToLogicalRatio),\n top: Math.round(element.rect.top * shrunkShotToLogicalRatio),\n width: Math.round(element.rect.width * shrunkShotToLogicalRatio),\n height: Math.round(element.rect.height * shrunkShotToLogicalRatio),\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":["commonContextParser","interfaceInstance","_opt","debug","getDebug","assert","description","uploadTestInfoToServer","interfaceSize","logicalWidth","logicalHeight","console","Number","Error","maxRetries","lastError","screenshotBase64","screenshotCapturedAt","imgWidth","imgHeight","attempt","Date","dimensions","imageInfoOfBase64","error","String","Promise","resolve","setTimeout","logicalIsPortrait","screenshotIsPortrait","finalLogicalWidth","userShrinkFactor","dpr","shrunkShotToLogicalRatio","targetWidth","Math","targetHeight","resizedBase64","resizeImgBase64","ScreenshotItem","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","MIDSCENE_REPORT_QUIET","logMsg","ifPlanLocateParamIsBbox","planLocateParam","Array","matchElementFromPlan","rect","element","generateElementByRect","matchElementFromCache","context","cacheEntry","cachePrompt","cacheable","cacheDebug","getMidsceneVersion","__VERSION__","parsePrompt","prompt","undefined","transformLogicalElementToScreenshot","transformLogicalRectToScreenshotRect"],"mappings":"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"}
package/dist/es/utils.mjs CHANGED
@@ -175,7 +175,7 @@ function stringifyDumpData(data, indents) {
175
175
  return JSON.stringify(data, replacerForPageObject, indents);
176
176
  }
177
177
  function getVersion() {
178
- return "8.0.1";
178
+ return "8.0.3";
179
179
  }
180
180
  function debugLog(...message) {
181
181
  const debugMode = process.env[MIDSCENE_DEBUG_MODE];
@@ -73,14 +73,31 @@ async function commonContextParser(interfaceInstance, _opt) {
73
73
  if (!Number.isFinite(logicalWidth) || !Number.isFinite(logicalHeight)) throw new Error(`Invalid interface size: width and height must be finite numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`);
74
74
  if (logicalWidth <= 0 || logicalHeight <= 0) throw new Error(`Invalid interface size: width and height must be positive numbers. Received width: ${logicalWidth}, height: ${logicalHeight}`);
75
75
  debug(`size: ${logicalWidth}x${logicalHeight}`);
76
- const screenshotBase64 = await interfaceInstance.screenshotBase64();
77
- const screenshotCapturedAt = Date.now();
78
- (0, utils_namespaceObject.assert)(screenshotBase64, 'screenshotBase64 is required');
79
- debug('will get screenshot dimensions');
80
- const { width: imgWidth, height: imgHeight } = await (0, img_namespaceObject.imageInfoOfBase64)(screenshotBase64);
81
- if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) throw new Error(`Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
82
- if (imgWidth <= 0 || imgHeight <= 0) throw new Error(`Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
83
- debug('screenshot dimensions', imgWidth, 'x', imgHeight);
76
+ const maxRetries = 3;
77
+ let lastError = null;
78
+ let screenshotBase64 = null;
79
+ let screenshotCapturedAt = 0;
80
+ let imgWidth = 0;
81
+ let imgHeight = 0;
82
+ for(let attempt = 1; attempt <= maxRetries; attempt++)try {
83
+ screenshotBase64 = await interfaceInstance.screenshotBase64();
84
+ screenshotCapturedAt = Date.now();
85
+ (0, utils_namespaceObject.assert)(screenshotBase64, 'screenshotBase64 is required');
86
+ debug('will get screenshot dimensions');
87
+ const dimensions = await (0, img_namespaceObject.imageInfoOfBase64)(screenshotBase64);
88
+ imgWidth = dimensions.width;
89
+ imgHeight = dimensions.height;
90
+ if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) throw new Error(`Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
91
+ if (imgWidth <= 0 || imgHeight <= 0) throw new Error(`Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`);
92
+ debug('screenshot dimensions', imgWidth, 'x', imgHeight);
93
+ break;
94
+ } catch (error) {
95
+ lastError = error instanceof Error ? error : new Error(String(error));
96
+ debug(`Screenshot capture/decode failed (attempt ${attempt}/${maxRetries}): ${lastError.message}`);
97
+ if (attempt === maxRetries) throw new Error(`Failed to capture valid screenshot after ${maxRetries} attempts: ${lastError.message}`);
98
+ await new Promise((resolve)=>setTimeout(resolve, 500));
99
+ }
100
+ if (!screenshotBase64) throw new Error('Screenshot data is null after retry loop');
84
101
  const logicalIsPortrait = logicalWidth < logicalHeight;
85
102
  const screenshotIsPortrait = imgWidth < imgHeight;
86
103
  let finalLogicalWidth = logicalWidth;
@@ -170,7 +187,7 @@ async function matchElementFromCache(context, cacheEntry, cachePrompt, cacheable
170
187
  return;
171
188
  }
172
189
  }
173
- const getMidsceneVersion = ()=>"8.0.1";
190
+ const getMidsceneVersion = ()=>"8.0.3";
174
191
  const parsePrompt = (prompt)=>{
175
192
  if ('string' == typeof prompt) return {
176
193
  textPrompt: prompt,
@@ -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 type { TMultimodalPrompt, TUserPrompt } from '@/common';\nimport type { AbstractInterface } from '@/device';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n ElementCacheFeature,\n LocateResultElement,\n PlanningLocateParam,\n Rect,\n UIContext,\n} from '@/types';\nimport { uploadTestInfoToServer } from '@/utils';\nimport type { TModelFamily } from '@aiscene/shared/env';\nimport {\n MIDSCENE_REPORT_QUIET,\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@aiscene/shared/env';\nimport { generateElementByRect } from '@aiscene/shared/extractor';\nimport { imageInfoOfBase64, resizeImgBase64 } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { _keyDefinitions } from '@aiscene/shared/us-keyboard-layout';\nimport { assert, logMsg, uuid } from '@aiscene/shared/utils';\nimport dayjs from 'dayjs';\nimport type { TaskCache } from './task-cache';\nimport { debug as cacheDebug } from './task-cache';\n\nexport async function commonContextParser(\n interfaceInstance: AbstractInterface,\n _opt: {\n uploadServerUrl?: string;\n screenshotShrinkFactor?: number;\n modelFamily?: TModelFamily;\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\n // Get physical screenshot dimensions\n debug('will get screenshot dimensions');\n const { width: imgWidth, height: imgHeight } =\n await imageInfoOfBase64(screenshotBase64);\n\n if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\n if (imgWidth <= 0 || imgHeight <= 0) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\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 userShrinkFactor = _opt.screenshotShrinkFactor ?? 1;\n\n if (!Number.isFinite(userShrinkFactor) || userShrinkFactor < 1) {\n throw new Error(\n `Invalid screenshotShrinkFactor: must be a finite number >= 1. Received: ${userShrinkFactor}`,\n );\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 const targetWidth = Math.round(imgWidth / userShrinkFactor);\n const targetHeight = Math.round(imgHeight / userShrinkFactor);\n\n debug(\n `Applying screenshot shrink factor: ${userShrinkFactor} (physical: ${imgWidth}x${imgHeight} -> target: ${targetWidth}x${targetHeight})`,\n );\n\n const resizedBase64 = await resizeImgBase64(screenshotBase64, {\n width: targetWidth,\n height: targetHeight,\n });\n return {\n shotSize: {\n width: targetWidth,\n height: targetHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(resizedBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\n };\n }\n\n return {\n shotSize: {\n width: imgWidth,\n height: imgHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(screenshotBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\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\nexport function ifPlanLocateParamIsBbox(\n planLocateParam: PlanningLocateParam,\n): boolean {\n return !!(\n planLocateParam.bbox &&\n Array.isArray(planLocateParam.bbox) &&\n planLocateParam.bbox.length === 4\n );\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n): LocateResultElement | undefined {\n if (!planLocateParam) {\n return undefined;\n }\n\n if (planLocateParam.bbox) {\n // Convert bbox [x1, y1, x2, y2] to rect {left, top, width, height}\n const rect = {\n left: planLocateParam.bbox[0],\n top: planLocateParam.bbox[1],\n width: planLocateParam.bbox[2] - planLocateParam.bbox[0] + 1,\n height: planLocateParam.bbox[3] - planLocateParam.bbox[1] + 1,\n };\n\n const element = generateElementByRect(\n rect,\n typeof planLocateParam.prompt === 'string'\n ? planLocateParam.prompt\n : planLocateParam.prompt?.prompt || '',\n );\n return element;\n }\n\n return undefined;\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: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2),\n ],\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 Math.round(element.center[0] * shrunkShotToLogicalRatio),\n Math.round(element.center[1] * shrunkShotToLogicalRatio),\n ],\n rect: {\n ...element.rect,\n left: Math.round(element.rect.left * shrunkShotToLogicalRatio),\n top: Math.round(element.rect.top * shrunkShotToLogicalRatio),\n width: Math.round(element.rect.width * shrunkShotToLogicalRatio),\n height: Math.round(element.rect.height * shrunkShotToLogicalRatio),\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","commonContextParser","interfaceInstance","_opt","debug","getDebug","assert","description","uploadTestInfoToServer","interfaceSize","logicalWidth","logicalHeight","console","Number","Error","screenshotBase64","screenshotCapturedAt","Date","imgWidth","imgHeight","imageInfoOfBase64","logicalIsPortrait","screenshotIsPortrait","finalLogicalWidth","userShrinkFactor","dpr","shrunkShotToLogicalRatio","targetWidth","Math","targetHeight","resizedBase64","resizeImgBase64","ScreenshotItem","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","MIDSCENE_REPORT_QUIET","logMsg","ifPlanLocateParamIsBbox","planLocateParam","Array","matchElementFromPlan","rect","element","generateElementByRect","matchElementFromCache","context","cacheEntry","cachePrompt","cacheable","cacheDebug","error","getMidsceneVersion","__VERSION__","parsePrompt","prompt","undefined","transformLogicalElementToScreenshot","transformLogicalRectToScreenshotRect"],"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;;;;;;;;;;;;;;;;;;;;;;;;;;ACoBO,eAAeI,oBACpBC,iBAAoC,EACpCC,IAIC;IAED,MAAMC,QAAQC,AAAAA,IAAAA,uBAAAA,QAAAA,AAAAA,EAAS;IAEvBC,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOJ,mBAAmB;IAE1BE,MAAM;IACN,MAAMG,cAAcL,kBAAkB,QAAQ,QAAQ;IACtDE,MAAM;IAENA,MAAM;IACNI,IAAAA,kCAAAA,sBAAAA,AAAAA,EAAuB;QACrB,SAASD;QACT,WAAWJ,KAAK,eAAe;IACjC;IACAC,MAAM;IAENA,MAAM;IACN,MAAMK,gBAAgB,MAAMP,kBAAkB,IAAI;IAClD,MAAM,EAAE,OAAOQ,YAAY,EAAE,QAAQC,aAAa,EAAE,GAAGF;IAEvD,IAAKA,cAA6C,GAAG,EACnDG,QAAQ,IAAI,CACV;IAIJ,IAAI,CAACC,OAAO,QAAQ,CAACH,iBAAiB,CAACG,OAAO,QAAQ,CAACF,gBACrD,MAAM,IAAIG,MACR,CAAC,iFAAiF,EAAEJ,aAAa,UAAU,EAAEC,eAAe;IAIhI,IAAID,gBAAgB,KAAKC,iBAAiB,GACxC,MAAM,IAAIG,MACR,CAAC,mFAAmF,EAAEJ,aAAa,UAAU,EAAEC,eAAe;IAIlIP,MAAM,CAAC,MAAM,EAAEM,aAAa,CAAC,EAAEC,eAAe;IAE9C,MAAMI,mBAAmB,MAAMb,kBAAkB,gBAAgB;IACjE,MAAMc,uBAAuBC,KAAK,GAAG;IACrCX,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOS,kBAAmB;IAG1BX,MAAM;IACN,MAAM,EAAE,OAAOc,QAAQ,EAAE,QAAQC,SAAS,EAAE,GAC1C,MAAMC,AAAAA,IAAAA,oBAAAA,iBAAAA,AAAAA,EAAkBL;IAE1B,IAAI,CAACF,OAAO,QAAQ,CAACK,aAAa,CAACL,OAAO,QAAQ,CAACM,YACjD,MAAM,IAAIL,MACR,CAAC,wFAAwF,EAAEI,SAAS,UAAU,EAAEC,WAAW;IAG/H,IAAID,YAAY,KAAKC,aAAa,GAChC,MAAM,IAAIL,MACR,CAAC,0FAA0F,EAAEI,SAAS,UAAU,EAAEC,WAAW;IAGjIf,MAAM,yBAAyBc,UAAU,KAAKC;IAM9C,MAAME,oBAAoBX,eAAeC;IACzC,MAAMW,uBAAuBJ,WAAWC;IACxC,IAAII,oBAAoBb;IAExB,IAAIW,sBAAsBC,sBAAsB;QAC9ClB,MACE,CAAC,4CAA4C,EAAEM,aAAa,CAAC,EAAEC,cAAc,EAAE,EAAEU,oBAAoB,aAAa,YAAY,gBAAgB,EAAEH,SAAS,CAAC,EAAEC,UAAU,EAAE,EAAEG,uBAAuB,aAAa,YAAY,+BAA+B,CAAC;QAE5PC,oBAAoBZ;IAEtB;IAEA,MAAMa,mBAAmBrB,KAAK,sBAAsB,IAAI;IAExD,IAAI,CAACU,OAAO,QAAQ,CAACW,qBAAqBA,mBAAmB,GAC3D,MAAM,IAAIV,MACR,CAAC,wEAAwE,EAAEU,kBAAkB;IAIjG,MAAMC,MAAMP,WAAWK;IAEvBnB,MAAM,mBAAmBqB;IAEzB,MAAMC,2BAA2BD,MAAMD;IAEvCpB,MAAM,4BAA4BsB;IAElC,IAAIF,AAAqB,MAArBA,kBAAwB;QAC1B,MAAMG,cAAcC,KAAK,KAAK,CAACV,WAAWM;QAC1C,MAAMK,eAAeD,KAAK,KAAK,CAACT,YAAYK;QAE5CpB,MACE,CAAC,mCAAmC,EAAEoB,iBAAiB,YAAY,EAAEN,SAAS,CAAC,EAAEC,UAAU,YAAY,EAAEQ,YAAY,CAAC,EAAEE,aAAa,CAAC,CAAC;QAGzI,MAAMC,gBAAgB,MAAMC,AAAAA,IAAAA,oBAAAA,eAAAA,AAAAA,EAAgBhB,kBAAkB;YAC5D,OAAOY;YACP,QAAQE;QACV;QACA,OAAO;YACL,UAAU;gBACR,OAAOF;gBACP,QAAQE;YACV;YACA,eAAeJ;YACf,YAAYO,4CAAAA,cAAAA,CAAAA,MAAqB,CAACF,eAAed;YACjDU;QACF;IACF;IAEA,OAAO;QACL,UAAU;YACR,OAAOR;YACP,QAAQC;QACV;QACA,eAAeM;QACf,YAAYO,4CAAAA,cAAAA,CAAAA,MAAqB,CAACjB,kBAAkBC;QACpDU;IACF;AACF;AAEO,SAASO,kBAAkBC,MAAM,KAAK;IAC3C,MAAMC,gBAAgBC,oBAAAA,mBAAAA,CAAAA,iBAAqC,CACzDC,oBAAAA,wBAAwBA;IAE1B,MAAMC,qBAAqBC,2BAAQ,MAAM,CAAC;IAE1C,MAAMC,WAAWC,AAAAA,IAAAA,sBAAAA,IAAAA,AAAAA,IAAO,SAAS,CAAC,GAAG;IACrC,OAAO,GAAGN,iBAAiBD,IAAI,CAAC,EAAEI,mBAAmB,CAAC,EAAEE,UAAU;AACpE;AAEO,SAASE,eAAeC,QAAgB;IAC7C,IAAIP,oBAAAA,mBAAAA,CAAAA,qBAAyC,CAACQ,oBAAAA,qBAAqBA,GACjE;IAEFC,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAAC,gCAAgC,EAAEF,UAAU;AACtD;AAEO,SAASG,wBACdC,eAAoC;IAEpC,OAAO,CAAC,CACNA,CAAAA,gBAAgB,IAAI,IACpBC,MAAM,OAAO,CAACD,gBAAgB,IAAI,KAClCA,AAAgC,MAAhCA,gBAAgB,IAAI,CAAC,MAAM,AAAK;AAEpC;AAEO,SAASE,qBACdF,eAAoC;IAEpC,IAAI,CAACA,iBACH;IAGF,IAAIA,gBAAgB,IAAI,EAAE;QAExB,MAAMG,OAAO;YACX,MAAMH,gBAAgB,IAAI,CAAC,EAAE;YAC7B,KAAKA,gBAAgB,IAAI,CAAC,EAAE;YAC5B,OAAOA,gBAAgB,IAAI,CAAC,EAAE,GAAGA,gBAAgB,IAAI,CAAC,EAAE,GAAG;YAC3D,QAAQA,gBAAgB,IAAI,CAAC,EAAE,GAAGA,gBAAgB,IAAI,CAAC,EAAE,GAAG;QAC9D;QAEA,MAAMI,UAAUC,AAAAA,IAAAA,0BAAAA,qBAAAA,AAAAA,EACdF,MACA,AAAkC,YAAlC,OAAOH,gBAAgB,MAAM,GACzBA,gBAAgB,MAAM,GACtBA,gBAAgB,MAAM,EAAE,UAAU;QAExC,OAAOI;IACT;AAGF;AAEO,eAAeE,sBACpBC,OAGC,EACDC,UAA2C,EAC3CC,WAAwB,EACxBC,SAA8B;IAE9B,IAAI,CAACF,YACH;IAGF,IAAIE,AAAc,UAAdA,WAAqB,YACvBC,AAAAA,IAAAA,uCAAAA,KAAAA,AAAAA,EAAW,iCAAiCF;IAI9C,IAAI,CAACF,QAAQ,SAAS,EAAE,mBACtB;IAGF,IAAI,CAACA,QAAQ,iBAAiB,CAAC,uBAAuB,EAAE,YACtDI,AAAAA,IAAAA,uCAAAA,KAAAA,AAAAA,EACE;IAKJ,IAAI;QACF,MAAMR,OACJ,MAAMI,QAAQ,iBAAiB,CAAC,uBAAuB,CAACC;QAC1D,MAAMJ,UAA+B;YACnC,QAAQ;gBACNvB,KAAK,KAAK,CAACsB,KAAK,IAAI,GAAGA,KAAK,KAAK,GAAG;gBACpCtB,KAAK,KAAK,CAACsB,KAAK,GAAG,GAAGA,KAAK,MAAM,GAAG;aACrC;YACDA;YACA,aACE,AAAuB,YAAvB,OAAOM,cACHA,cACAA,YAAY,MAAM,IAAI;QAC9B;QAEAE,IAAAA,uCAAAA,KAAAA,AAAAA,EAAW,yBAAyBF;QACpC,OAAOL;IACT,EAAE,OAAOQ,OAAO;QACdD,IAAAA,uCAAAA,KAAAA,AAAAA,EAAW,qCAAqCC;QAChD;IACF;AACF;AAIO,MAAMC,qBAAqB,IAEvBC;AAUJ,MAAMC,cAAc,CACzBC;IAKA,IAAI,AAAkB,YAAlB,OAAOA,QACT,OAAO;QACL,YAAYA;QACZ,kBAAkBC;IACpB;IAEF,OAAO;QACL,YAAYD,OAAO,MAAM;QACzB,kBAAkBA,OAAO,MAAM,GAC3B;YACE,QAAQA,OAAO,MAAM;YACrB,yBAAyB,CAAC,CAACA,OAAO,uBAAuB;QAC3D,IACAC;IACN;AACF;AAEO,MAAMC,sCAAsC,CACjDd,SACAzB;IAEA,IAAIA,AAA6B,MAA7BA,0BACF,OAAOyB;IAGT,OAAO;QACL,GAAGA,OAAO;QACV,QAAQ;YACNvB,KAAK,KAAK,CAACuB,QAAQ,MAAM,CAAC,EAAE,GAAGzB;YAC/BE,KAAK,KAAK,CAACuB,QAAQ,MAAM,CAAC,EAAE,GAAGzB;SAChC;QACD,MAAM;YACJ,GAAGyB,QAAQ,IAAI;YACf,MAAMvB,KAAK,KAAK,CAACuB,QAAQ,IAAI,CAAC,IAAI,GAAGzB;YACrC,KAAKE,KAAK,KAAK,CAACuB,QAAQ,IAAI,CAAC,GAAG,GAAGzB;YACnC,OAAOE,KAAK,KAAK,CAACuB,QAAQ,IAAI,CAAC,KAAK,GAAGzB;YACvC,QAAQE,KAAK,KAAK,CAACuB,QAAQ,IAAI,CAAC,MAAM,GAAGzB;QAC3C;IACF;AACF;AAEO,MAAMwC,uCAAuC,CAClDhB,MACAxB;IAEA,IAAIA,AAA6B,MAA7BA,0BACF,OAAOwB;IAGT,OAAO;QACL,GAAGA,IAAI;QACP,MAAMtB,KAAK,KAAK,CAACsB,KAAK,IAAI,GAAGxB;QAC7B,KAAKE,KAAK,KAAK,CAACsB,KAAK,GAAG,GAAGxB;QAC3B,OAAOE,KAAK,KAAK,CAACsB,KAAK,KAAK,GAAGxB;QAC/B,QAAQE,KAAK,KAAK,CAACsB,KAAK,MAAM,GAAGxB;IACnC;AACF"}
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 type { TMultimodalPrompt, TUserPrompt } from '@/common';\nimport type { AbstractInterface } from '@/device';\nimport { ScreenshotItem } from '@/screenshot-item';\nimport type {\n ElementCacheFeature,\n LocateResultElement,\n PlanningLocateParam,\n Rect,\n UIContext,\n} from '@/types';\nimport { uploadTestInfoToServer } from '@/utils';\nimport type { TModelFamily } from '@aiscene/shared/env';\nimport {\n MIDSCENE_REPORT_QUIET,\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@aiscene/shared/env';\nimport { generateElementByRect } from '@aiscene/shared/extractor';\nimport { imageInfoOfBase64, resizeImgBase64 } from '@aiscene/shared/img';\nimport { getDebug } from '@aiscene/shared/logger';\nimport { _keyDefinitions } from '@aiscene/shared/us-keyboard-layout';\nimport { assert, logMsg, uuid } from '@aiscene/shared/utils';\nimport dayjs from 'dayjs';\nimport type { TaskCache } from './task-cache';\nimport { debug as cacheDebug } from './task-cache';\n\nexport async function commonContextParser(\n interfaceInstance: AbstractInterface,\n _opt: {\n uploadServerUrl?: string;\n screenshotShrinkFactor?: number;\n modelFamily?: TModelFamily;\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 // Retry logic for screenshot capture/decoding\n const maxRetries = 3;\n let lastError: Error | null = null;\n let screenshotBase64: string | null = null;\n let screenshotCapturedAt = 0;\n let imgWidth: number = 0;\n let imgHeight: number = 0;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n screenshotBase64 = await interfaceInstance.screenshotBase64();\n screenshotCapturedAt = Date.now();\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n // Get physical screenshot dimensions\n debug('will get screenshot dimensions');\n const dimensions = await imageInfoOfBase64(screenshotBase64);\n imgWidth = dimensions.width;\n imgHeight = dimensions.height;\n\n // Validate dimensions\n if (!Number.isFinite(imgWidth) || !Number.isFinite(imgHeight)) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be finite numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\n if (imgWidth <= 0 || imgHeight <= 0) {\n throw new Error(\n `Invalid screenshot dimensions: width and height must be positive numbers. Received width: ${imgWidth}, height: ${imgHeight}`,\n );\n }\n\n // If we get here, screenshot is valid\n debug('screenshot dimensions', imgWidth, 'x', imgHeight);\n break;\n } catch (error) {\n lastError =\n error instanceof Error ? error : new Error(String(error));\n debug(\n `Screenshot capture/decode failed (attempt ${attempt}/${maxRetries}): ${lastError.message}`,\n );\n\n if (attempt === maxRetries) {\n throw new Error(\n `Failed to capture valid screenshot after ${maxRetries} attempts: ${lastError.message}`,\n );\n }\n\n // Wait before retrying\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n }\n\n // This should never be null if we got past the retry loop\n if (!screenshotBase64) {\n throw new Error('Screenshot data is null after retry loop');\n }\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 userShrinkFactor = _opt.screenshotShrinkFactor ?? 1;\n\n if (!Number.isFinite(userShrinkFactor) || userShrinkFactor < 1) {\n throw new Error(\n `Invalid screenshotShrinkFactor: must be a finite number >= 1. Received: ${userShrinkFactor}`,\n );\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 const targetWidth = Math.round(imgWidth / userShrinkFactor);\n const targetHeight = Math.round(imgHeight / userShrinkFactor);\n\n debug(\n `Applying screenshot shrink factor: ${userShrinkFactor} (physical: ${imgWidth}x${imgHeight} -> target: ${targetWidth}x${targetHeight})`,\n );\n\n const resizedBase64 = await resizeImgBase64(screenshotBase64, {\n width: targetWidth,\n height: targetHeight,\n });\n return {\n shotSize: {\n width: targetWidth,\n height: targetHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(resizedBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\n };\n }\n\n return {\n shotSize: {\n width: imgWidth,\n height: imgHeight,\n },\n deprecatedDpr: dpr,\n screenshot: ScreenshotItem.create(screenshotBase64, screenshotCapturedAt),\n shrunkShotToLogicalRatio,\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\nexport function ifPlanLocateParamIsBbox(\n planLocateParam: PlanningLocateParam,\n): boolean {\n return !!(\n planLocateParam.bbox &&\n Array.isArray(planLocateParam.bbox) &&\n planLocateParam.bbox.length === 4\n );\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n): LocateResultElement | undefined {\n if (!planLocateParam) {\n return undefined;\n }\n\n if (planLocateParam.bbox) {\n // Convert bbox [x1, y1, x2, y2] to rect {left, top, width, height}\n const rect = {\n left: planLocateParam.bbox[0],\n top: planLocateParam.bbox[1],\n width: planLocateParam.bbox[2] - planLocateParam.bbox[0] + 1,\n height: planLocateParam.bbox[3] - planLocateParam.bbox[1] + 1,\n };\n\n const element = generateElementByRect(\n rect,\n typeof planLocateParam.prompt === 'string'\n ? planLocateParam.prompt\n : planLocateParam.prompt?.prompt || '',\n );\n return element;\n }\n\n return undefined;\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: [\n Math.round(rect.left + rect.width / 2),\n Math.round(rect.top + rect.height / 2),\n ],\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 Math.round(element.center[0] * shrunkShotToLogicalRatio),\n Math.round(element.center[1] * shrunkShotToLogicalRatio),\n ],\n rect: {\n ...element.rect,\n left: Math.round(element.rect.left * shrunkShotToLogicalRatio),\n top: Math.round(element.rect.top * shrunkShotToLogicalRatio),\n width: Math.round(element.rect.width * shrunkShotToLogicalRatio),\n height: Math.round(element.rect.height * shrunkShotToLogicalRatio),\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","commonContextParser","interfaceInstance","_opt","debug","getDebug","assert","description","uploadTestInfoToServer","interfaceSize","logicalWidth","logicalHeight","console","Number","Error","maxRetries","lastError","screenshotBase64","screenshotCapturedAt","imgWidth","imgHeight","attempt","Date","dimensions","imageInfoOfBase64","error","String","Promise","resolve","setTimeout","logicalIsPortrait","screenshotIsPortrait","finalLogicalWidth","userShrinkFactor","dpr","shrunkShotToLogicalRatio","targetWidth","Math","targetHeight","resizedBase64","resizeImgBase64","ScreenshotItem","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","MIDSCENE_REPORT_QUIET","logMsg","ifPlanLocateParamIsBbox","planLocateParam","Array","matchElementFromPlan","rect","element","generateElementByRect","matchElementFromCache","context","cacheEntry","cachePrompt","cacheable","cacheDebug","getMidsceneVersion","__VERSION__","parsePrompt","prompt","undefined","transformLogicalElementToScreenshot","transformLogicalRectToScreenshotRect"],"mappings":"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"}
package/dist/lib/types.js CHANGED
@@ -6,7 +6,7 @@ var __webpack_modules__ = {
6
6
  "./dump/screenshot-store" (module) {
7
7
  module.exports = require("./dump/screenshot-store.js");
8
8
  },
9
- "./screenshot-item" (module) {
9
+ "@/screenshot-item" (module) {
10
10
  module.exports = require("./screenshot-item.js");
11
11
  },
12
12
  "./yaml" (module) {
@@ -73,16 +73,16 @@ var __webpack_exports__ = {};
73
73
  var node_path__rspack_import_1 = __webpack_require__("node:path");
74
74
  var _dump_screenshot_restoration__rspack_import_2 = __webpack_require__("./dump/screenshot-restoration");
75
75
  var _dump_screenshot_store__rspack_import_3 = __webpack_require__("./dump/screenshot-store");
76
- var _screenshot_item__rspack_import_4 = __webpack_require__("./screenshot-item");
76
+ var _screenshot_item__rspack_import_4 = __webpack_require__("@/screenshot-item");
77
77
  var _yaml__rspack_import_5 = __webpack_require__("./yaml");
78
78
  var __rspack_reexport = {};
79
79
  for(const __rspack_import_key in _yaml__rspack_import_5)if ([
80
80
  "UIContext",
81
- "GroupedActionDump",
81
+ "ServiceError",
82
82
  "default",
83
83
  "ReportActionDump",
84
- "ExecutionDump",
85
- "ServiceError"
84
+ "GroupedActionDump",
85
+ "ExecutionDump"
86
86
  ].indexOf(__rspack_import_key) < 0) __rspack_reexport[__rspack_import_key] = ()=>_yaml__rspack_import_5[__rspack_import_key];
87
87
  __webpack_require__.d(__webpack_exports__, __rspack_reexport);
88
88
  function _define_property(obj, key, value) {
package/dist/lib/utils.js CHANGED
@@ -219,7 +219,7 @@ function stringifyDumpData(data, indents) {
219
219
  return JSON.stringify(data, replacerForPageObject, indents);
220
220
  }
221
221
  function getVersion() {
222
- return "8.0.1";
222
+ return "8.0.3";
223
223
  }
224
224
  function debugLog(...message) {
225
225
  const debugMode = process.env[env_namespaceObject.MIDSCENE_DEBUG_MODE];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aiscene/core",
3
3
  "description": "Automate browser actions, extract data, and perform assertions using AI. It offers JavaScript SDK, Chrome extension, and support for scripting in YAML. See https://midscenejs.com/ for details.",
4
- "version": "8.0.2",
4
+ "version": "8.0.3",
5
5
  "repository": "https://github.com/web-infra-dev/midscene",
6
6
  "homepage": "https://midscenejs.com/",
7
7
  "main": "./dist/lib/index.js",
@@ -78,7 +78,7 @@
78
78
  "test:parse-action": "npm run test:ai -- tests/ai/parse-action.test.ts"
79
79
  },
80
80
  "dependencies": {
81
- "@aiscene/shared": "^8.0.1",
81
+ "@aiscene/shared": "^8.0.2",
82
82
  "@ui-tars/action-parser": "1.2.3",
83
83
  "dayjs": "^1.11.11",
84
84
  "dotenv": "^16.4.5",
@@ -1,216 +0,0 @@
1
- import type { TUserPrompt } from '../ai-model/index';
2
- import Service from '../service/index';
3
- import { type ActionParam, type ActionReturn, type AgentAssertOpt, type AgentDescribeElementAtPointResult, type AgentOpt, type AgentWaitForOpt, type DeepThinkOption, type DeviceAction, ExecutionDump, type LocateOption, type LocateValidatorResult, type LocatorValidatorOption, type OnTaskStartTip, ReportActionDump, type ScrollParam, type ServiceAction, type ServiceExtractOption, type ServiceExtractParam, type UIContext } from '../types';
4
- import type { AbstractInterface } from '../device';
5
- import type { TaskRunner } from '../task-runner';
6
- import { ModelConfigManager } from '@aiscene/shared/env';
7
- import { TaskCache } from './task-cache';
8
- import { TaskExecutor } from './tasks';
9
- export type AiActOptions = {
10
- cacheable?: boolean;
11
- fileChooserAccept?: string | string[];
12
- deepThink?: DeepThinkOption;
13
- deepLocate?: boolean;
14
- abortSignal?: AbortSignal;
15
- };
16
- export declare class Agent<InterfaceType extends AbstractInterface = AbstractInterface> {
17
- interface: InterfaceType;
18
- service: Service;
19
- dump: ReportActionDump;
20
- reportFile?: string | null;
21
- reportFileName?: string;
22
- taskExecutor: TaskExecutor;
23
- opts: AgentOpt;
24
- /**
25
- * If true, the agent will not perform any actions
26
- */
27
- dryMode: boolean;
28
- onTaskStartTip?: OnTaskStartTip;
29
- taskCache?: TaskCache;
30
- private dumpUpdateListeners;
31
- get onDumpUpdate(): ((dump: string, executionDump?: ExecutionDump) => void) | undefined;
32
- set onDumpUpdate(callback: ((dump: string, executionDump?: ExecutionDump) => void) | undefined);
33
- destroyed: boolean;
34
- modelConfigManager: ModelConfigManager;
35
- /**
36
- * Frozen page context for consistent AI operations
37
- */
38
- private frozenUIContext?;
39
- private get aiActContext();
40
- /**
41
- * Flag to track if VL model warning has been shown
42
- */
43
- private hasWarnedNonVLModel;
44
- private executionDumpIndexByRunner;
45
- private fullActionSpace;
46
- private reportGenerator;
47
- get page(): InterfaceType;
48
- /**
49
- * Ensures VL model warning is shown once when needed
50
- */
51
- private ensureVLModelWarning;
52
- private resolveReplanningCycleLimit;
53
- constructor(interfaceInstance: InterfaceType, opts?: AgentOpt);
54
- getActionSpace(): Promise<DeviceAction[]>;
55
- private static readonly CONTEXT_RETRY_MAX;
56
- private static readonly CONTEXT_RETRY_DELAY_MS;
57
- /**
58
- * Override in subclasses to indicate which errors are transient and should
59
- * trigger an automatic retry when building the UI context.
60
- * Returns `false` by default (no retry).
61
- */
62
- protected isRetryableContextError(_error: unknown): boolean;
63
- getUIContext(action?: ServiceAction): Promise<UIContext>;
64
- _snapshotContext(): Promise<UIContext>;
65
- /**
66
- * @deprecated Use {@link setAIActContext} instead.
67
- */
68
- setAIActionContext(prompt: string): Promise<void>;
69
- setAIActContext(prompt: string): Promise<void>;
70
- resetDump(): ReportActionDump;
71
- appendExecutionDump(execution: ExecutionDump, runner?: TaskRunner): void;
72
- dumpDataString(opt?: {
73
- inlineScreenshots?: boolean;
74
- }): string;
75
- reportHTMLString(opt?: {
76
- inlineScreenshots?: boolean;
77
- }): string;
78
- private lastExecutionDump?;
79
- writeOutActionDumps(executionDump?: ExecutionDump): void;
80
- private getReportMeta;
81
- private callbackOnTaskStartTip;
82
- wrapActionInActionSpace<T extends DeviceAction>(name: string): (param: ActionParam<T>) => Promise<ActionReturn<T>>;
83
- callActionInActionSpace<T = any>(type: string, opt?: T): Promise<any>;
84
- aiTap(locatePrompt: TUserPrompt, opt?: LocateOption & {
85
- fileChooserAccept?: string | string[];
86
- }): Promise<any>;
87
- aiRightClick(locatePrompt: TUserPrompt, opt?: LocateOption): Promise<any>;
88
- aiDoubleClick(locatePrompt: TUserPrompt, opt?: LocateOption): Promise<any>;
89
- aiHover(locatePrompt: TUserPrompt, opt?: LocateOption): Promise<any>;
90
- aiInput(locatePrompt: TUserPrompt, opt: LocateOption & {
91
- value: string | number;
92
- } & {
93
- autoDismissKeyboard?: boolean;
94
- } & {
95
- mode?: 'replace' | 'clear' | 'typeOnly' | 'append';
96
- }): Promise<any>;
97
- /**
98
- * @deprecated Use aiInput(locatePrompt, opt) instead where opt contains the value
99
- */
100
- aiInput(value: string | number, locatePrompt: TUserPrompt, opt?: LocateOption & {
101
- autoDismissKeyboard?: boolean;
102
- } & {
103
- mode?: 'replace' | 'clear' | 'typeOnly' | 'append';
104
- }): Promise<any>;
105
- aiKeyboardPress(locatePrompt: TUserPrompt, opt: LocateOption & {
106
- keyName: string;
107
- }): Promise<any>;
108
- /**
109
- * @deprecated Use aiKeyboardPress(locatePrompt, opt) instead where opt contains the keyName
110
- */
111
- aiKeyboardPress(keyName: string, locatePrompt?: TUserPrompt, opt?: LocateOption): Promise<any>;
112
- aiScroll(locatePrompt: TUserPrompt | undefined, opt: LocateOption & ScrollParam): Promise<any>;
113
- /**
114
- * @deprecated Use aiScroll(locatePrompt, opt) instead where opt contains the scroll parameters
115
- */
116
- aiScroll(scrollParam: ScrollParam, locatePrompt?: TUserPrompt, opt?: LocateOption): Promise<any>;
117
- aiPinch(locatePrompt: TUserPrompt | undefined, opt: LocateOption & {
118
- direction: 'in' | 'out';
119
- distance?: number;
120
- duration?: number;
121
- }): Promise<any>;
122
- aiAct(taskPrompt: string, opt?: AiActOptions): Promise<string | undefined>;
123
- /**
124
- * @deprecated Use {@link Agent.aiAct} instead.
125
- */
126
- aiAction(taskPrompt: string, opt?: AiActOptions): Promise<string | undefined>;
127
- aiQuery<ReturnType = any>(demand: ServiceExtractParam, opt?: ServiceExtractOption): Promise<ReturnType>;
128
- aiBoolean(prompt: TUserPrompt, opt?: ServiceExtractOption): Promise<boolean>;
129
- aiNumber(prompt: TUserPrompt, opt?: ServiceExtractOption): Promise<number>;
130
- aiString(prompt: TUserPrompt, opt?: ServiceExtractOption): Promise<string>;
131
- aiAsk(prompt: TUserPrompt, opt?: ServiceExtractOption): Promise<string>;
132
- describeElementAtPoint(center: [number, number], opt?: {
133
- verifyPrompt?: boolean;
134
- retryLimit?: number;
135
- deepLocate?: boolean;
136
- } & LocatorValidatorOption): Promise<AgentDescribeElementAtPointResult>;
137
- verifyLocator(prompt: string, locateOpt: LocateOption | undefined, expectCenter: [number, number], verifyLocateOption?: LocatorValidatorOption): Promise<LocateValidatorResult>;
138
- /**
139
- * Locate an element and return both its center point and an approximate rect.
140
- *
141
- * - In most locate flows, `rect` represents the matched element boundary.
142
- * - Some models only support point grounding instead of boundary grounding.
143
- * In those cases (for example, AutoGLM), `rect` falls back to a small 8x8
144
- * box centered on the located point.
145
- *
146
- * Because `rect` may vary with the underlying model capability, avoid relying
147
- * on it too heavily for strict boundary semantics. If you need a stable click
148
- * target, prefer `center`.
149
- */
150
- aiLocate(prompt: TUserPrompt, opt?: LocateOption): Promise<Pick<LocateResultElement, "rect" | "center">>;
151
- aiAssert(assertion: TUserPrompt, msg?: string, opt?: AgentAssertOpt & ServiceExtractOption): Promise<{
152
- pass: boolean;
153
- thought: string | undefined;
154
- message: string | undefined;
155
- } | undefined>;
156
- aiWaitFor(assertion: TUserPrompt, opt?: AgentWaitForOpt): Promise<void>;
157
- ai(...args: Parameters<typeof this.aiAct>): Promise<string | undefined>;
158
- runYaml(yamlScriptContent: string): Promise<{
159
- result: Record<string, any>;
160
- }>;
161
- evaluateJavaScript(script: string): Promise<any>;
162
- /**
163
- * Add a dump update listener
164
- * @param listener Listener function
165
- * @returns A remove function that can be called to remove this listener
166
- */
167
- addDumpUpdateListener(listener: (dump: string, executionDump?: ExecutionDump) => void): () => void;
168
- /**
169
- * Remove a dump update listener
170
- * @param listener The listener function to remove
171
- */
172
- removeDumpUpdateListener(listener: (dump: string, executionDump?: ExecutionDump) => void): void;
173
- /**
174
- * Clear all dump update listeners
175
- */
176
- clearDumpUpdateListeners(): void;
177
- destroy(): Promise<void>;
178
- recordToReport(title?: string, opt?: {
179
- content: string;
180
- }): Promise<void>;
181
- /**
182
- * @deprecated Use {@link Agent.recordToReport} instead.
183
- */
184
- logScreenshot(title?: string, opt?: {
185
- content: string;
186
- }): Promise<void>;
187
- _unstableLogContent(): {
188
- groupName: string;
189
- groupDescription: string | undefined;
190
- executions: ExecutionDump[];
191
- };
192
- /**
193
- * Freezes the current page context to be reused in subsequent AI operations
194
- * This avoids recalculating page context for each operation
195
- */
196
- freezePageContext(): Promise<void>;
197
- /**
198
- * Unfreezes the page context, allowing AI operations to calculate context dynamically
199
- */
200
- unfreezePageContext(): Promise<void>;
201
- /**
202
- * Process cache configuration and return normalized cache settings
203
- */
204
- private processCacheConfig;
205
- private normalizeFilePaths;
206
- private normalizeFileInput;
207
- /**
208
- * Manually flush cache to file
209
- * @param options - Optional configuration
210
- * @param options.cleanUnused - If true, removes unused cache records before flushing
211
- */
212
- flushCache(options?: {
213
- cleanUnused?: boolean;
214
- }): Promise<void>;
215
- }
216
- export declare const createAgent: (interfaceInstance: AbstractInterface, opts?: AgentOpt) => Agent<AbstractInterface>;
File without changes
@@ -1,36 +0,0 @@
1
- import { type TaskExecutionError, TaskRunner } from '../task-runner';
2
- import type { ExecutionTaskApply, ExecutionTaskProgressOptions, UIContext } from '../types';
3
- type ExecutionSessionOptions = ExecutionTaskProgressOptions & {
4
- tasks?: ExecutionTaskApply[];
5
- onTaskUpdate?: (runner: TaskRunner, error?: TaskExecutionError) => Promise<void> | void;
6
- };
7
- /**
8
- * Thin wrapper around {@link TaskRunner} that represents a single linear execution run.
9
- */
10
- export declare class ExecutionSession {
11
- private readonly runner;
12
- constructor(name: string, contextProvider: () => Promise<UIContext>, options?: ExecutionSessionOptions);
13
- append(tasks: ExecutionTaskApply[] | ExecutionTaskApply, options?: {
14
- allowWhenError?: boolean;
15
- }): Promise<void>;
16
- appendAndRun(tasks: ExecutionTaskApply[] | ExecutionTaskApply, options?: {
17
- allowWhenError?: boolean;
18
- }): Promise<{
19
- output: any;
20
- thought?: string;
21
- } | undefined>;
22
- run(options?: {
23
- allowWhenError?: boolean;
24
- }): Promise<{
25
- output: any;
26
- thought?: string;
27
- } | undefined>;
28
- isInErrorState(): boolean;
29
- latestErrorTask(): import("../types").ExecutionTask | null;
30
- appendErrorPlan(errorMsg: string): Promise<{
31
- output: undefined;
32
- runner: TaskRunner;
33
- }>;
34
- getRunner(): TaskRunner;
35
- }
36
- export {};
@@ -1,9 +0,0 @@
1
- export { Agent, createAgent } from './agent';
2
- export { commonContextParser } from './utils';
3
- export { getReportFileName, printReportMsg, } from './utils';
4
- export { extractInsightParam, locateParamStr, paramStr, taskTitleStr, typeStr, } from './ui-utils';
5
- export { type LocateCache, type PlanningCache, TaskCache } from './task-cache';
6
- export { cacheFileExt } from './task-cache';
7
- export { TaskExecutor } from './tasks';
8
- export type { AgentOpt } from '../types';
9
- export type { AiActOptions } from './agent';