@midscene/core 0.16.11-beta-20250516035357.0 → 0.16.11-beta-20250516080239.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.
@@ -644,6 +644,9 @@ Here is the item user want to find:
644
644
 
645
645
 
646
646
 
647
+
648
+
649
+
647
650
  function describeSize(size) {
648
651
  return `${size.width} x ${size.height}`;
649
652
  }
@@ -743,26 +746,13 @@ ${contentTree}`;
743
746
  return elementByPositionWithElementInfo(treeRoot, position);
744
747
  },
745
748
  insertElementByPosition(position) {
746
- const rect = {
747
- left: Math.max(position.x - 4, 0),
748
- top: Math.max(position.y - 4, 0),
749
- width: 8,
750
- height: 8
751
- };
752
- const id = _utils.generateHashId.call(void 0, rect);
753
- const element = {
754
- id,
755
- attributes: { nodeType: _constants.NodeType.POSITION },
756
- rect,
757
- content: "",
758
- center: [position.x, position.y]
759
- };
749
+ const element = _extractor.generateElementByPosition.call(void 0, position);
760
750
  treeRoot.children.push({
761
751
  node: element,
762
752
  children: []
763
753
  });
764
754
  flatElements.push(element);
765
- idElementMap[id] = element;
755
+ idElementMap[element.id] = element;
766
756
  return element;
767
757
  },
768
758
  size: { width, height }
@@ -2148,4 +2138,4 @@ async function resizeImageForUiTars(imageBase64, size) {
2148
2138
 
2149
2139
  exports.systemPromptToLocateElement = systemPromptToLocateElement; exports.elementByPositionWithElementInfo = elementByPositionWithElementInfo; exports.describeUserPage = describeUserPage; exports.callToGetJSONObject = callToGetJSONObject; exports.callAiFn = callAiFn; exports.adaptBboxToRect = adaptBboxToRect; exports.AiLocateElement = AiLocateElement; exports.AiLocateSection = AiLocateSection; exports.AiExtractElementInfo = AiExtractElementInfo; exports.AiAssert = AiAssert; exports.plan = plan; exports.vlmPlanning = vlmPlanning; exports.resizeImageForUiTars = resizeImageForUiTars;
2150
2140
 
2151
- //# sourceMappingURL=chunk-H3B2KXXR.js.map
2141
+ //# sourceMappingURL=chunk-UINI5TFU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"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","names":["vlLocateMode","getDebug","assert","plan","language","PromptTemplate","NodeType","treeToList","content","MIDSCENE_USE_QWEN_VL","MIDSCENE_USE_VLM_UI_TARS","getAIConfigInBoolean","paddingToMatchBlockByBase64","call"],"ignoreList":[],"sources":["../../src/ai-model/service-caller/index.ts","../../src/ai-model/common.ts","../../src/ai-model/prompt/ui-tars-planning.ts","../../src/ai-model/prompt/assertion.ts","../../src/ai-model/prompt/llm-locator.ts","../../src/ai-model/prompt/common.ts","../../src/ai-model/prompt/llm-planning.ts","../../src/image/index.ts","../../src/ai-model/prompt/util.ts","../../src/ai-model/inspect.ts","../../src/ai-model/prompt/extraction.ts","../../src/ai-model/prompt/llm-section-locator.ts","../../src/ai-model/llm-planning.ts","../../src/ai-model/ui-tars-planning.ts"],"sourcesContent":["import { AIResponseFormat, type AIUsageInfo } from '@/types';\nimport { Anthropic } from '@anthropic-ai/sdk';\nimport {\n DefaultAzureCredential,\n getBearerTokenProvider,\n} from '@azure/identity';\nimport {\n ANTHROPIC_API_KEY,\n AZURE_OPENAI_API_VERSION,\n AZURE_OPENAI_DEPLOYMENT,\n AZURE_OPENAI_ENDPOINT,\n AZURE_OPENAI_KEY,\n MIDSCENE_API_TYPE,\n MIDSCENE_AZURE_OPENAI_INIT_CONFIG_JSON,\n MIDSCENE_AZURE_OPENAI_SCOPE,\n MIDSCENE_DEBUG_AI_PROFILE,\n MIDSCENE_DEBUG_AI_RESPONSE,\n MIDSCENE_LANGSMITH_DEBUG,\n MIDSCENE_MODEL_NAME,\n MIDSCENE_OPENAI_HTTP_PROXY,\n MIDSCENE_OPENAI_INIT_CONFIG_JSON,\n MIDSCENE_OPENAI_SOCKS_PROXY,\n MIDSCENE_USE_ANTHROPIC_SDK,\n MIDSCENE_USE_AZURE_OPENAI,\n MIDSCENE_USE_QWEN_VL,\n MIDSCENE_USE_VLM_UI_TARS,\n OPENAI_API_KEY,\n OPENAI_BASE_URL,\n OPENAI_MAX_TOKENS,\n OPENAI_USE_AZURE,\n getAIConfig,\n getAIConfigInBoolean,\n getAIConfigInJson,\n vlLocateMode,\n} from '@midscene/shared/env';\nimport { enableDebug, getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport dJSON from 'dirty-json';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport OpenAI, { AzureOpenAI } from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources';\nimport { SocksProxyAgent } from 'socks-proxy-agent';\nimport { AIActionType } from '../common';\nimport { assertSchema } from '../prompt/assertion';\nimport { locatorSchema } from '../prompt/llm-locator';\nimport { planSchema } from '../prompt/llm-planning';\n\nexport function checkAIConfig() {\n if (getAIConfig(OPENAI_API_KEY)) return true;\n if (getAIConfig(MIDSCENE_USE_AZURE_OPENAI)) return true;\n if (getAIConfig(ANTHROPIC_API_KEY)) return true;\n\n return Boolean(getAIConfig(MIDSCENE_OPENAI_INIT_CONFIG_JSON));\n}\n\n// if debug config is initialized\nlet debugConfigInitialized = false;\n\nfunction initDebugConfig() {\n // if debug config is initialized, return\n if (debugConfigInitialized) return;\n\n const shouldPrintTiming = getAIConfigInBoolean(MIDSCENE_DEBUG_AI_PROFILE);\n let debugConfig = '';\n if (shouldPrintTiming) {\n console.warn(\n 'MIDSCENE_DEBUG_AI_PROFILE is deprecated, use DEBUG=midscene:ai:profile instead',\n );\n debugConfig = 'ai:profile';\n }\n const shouldPrintAIResponse = getAIConfigInBoolean(\n MIDSCENE_DEBUG_AI_RESPONSE,\n );\n if (shouldPrintAIResponse) {\n console.warn(\n 'MIDSCENE_DEBUG_AI_RESPONSE is deprecated, use DEBUG=midscene:ai:response instead',\n );\n if (debugConfig) {\n debugConfig = 'ai:*';\n } else {\n debugConfig = 'ai:call';\n }\n }\n if (debugConfig) {\n enableDebug(debugConfig);\n }\n\n // mark as initialized\n debugConfigInitialized = true;\n}\n\n// default model\nconst defaultModel = 'gpt-4o';\nexport function getModelName() {\n let modelName = defaultModel;\n const nameInConfig = getAIConfig(MIDSCENE_MODEL_NAME);\n if (nameInConfig) {\n modelName = nameInConfig;\n }\n return modelName;\n}\n\nasync function createChatClient({\n AIActionTypeValue,\n}: {\n AIActionTypeValue: AIActionType;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n style: 'openai' | 'anthropic';\n}> {\n initDebugConfig();\n let openai: OpenAI | AzureOpenAI | undefined;\n const extraConfig = getAIConfigInJson(MIDSCENE_OPENAI_INIT_CONFIG_JSON);\n\n const socksProxy = getAIConfig(MIDSCENE_OPENAI_SOCKS_PROXY);\n const httpProxy = getAIConfig(MIDSCENE_OPENAI_HTTP_PROXY);\n\n let proxyAgent = undefined;\n if (httpProxy) {\n proxyAgent = new HttpsProxyAgent(httpProxy);\n } else if (socksProxy) {\n proxyAgent = new SocksProxyAgent(socksProxy);\n }\n\n if (getAIConfig(OPENAI_USE_AZURE)) {\n // this is deprecated\n openai = new AzureOpenAI({\n baseURL: getAIConfig(OPENAI_BASE_URL),\n apiKey: getAIConfig(OPENAI_API_KEY),\n httpAgent: proxyAgent,\n ...extraConfig,\n dangerouslyAllowBrowser: true,\n }) as OpenAI;\n } else if (getAIConfig(MIDSCENE_USE_AZURE_OPENAI)) {\n const extraAzureConfig = getAIConfigInJson(\n MIDSCENE_AZURE_OPENAI_INIT_CONFIG_JSON,\n );\n\n // https://learn.microsoft.com/en-us/azure/ai-services/openai/chatgpt-quickstart?tabs=bash%2Cjavascript-key%2Ctypescript-keyless%2Cpython&pivots=programming-language-javascript#rest-api\n // keyless authentication\n const scope = getAIConfig(MIDSCENE_AZURE_OPENAI_SCOPE);\n let tokenProvider: any = undefined;\n if (scope) {\n assert(\n !ifInBrowser,\n 'Azure OpenAI is not supported in browser with Midscene.',\n );\n const credential = new DefaultAzureCredential();\n\n assert(scope, 'MIDSCENE_AZURE_OPENAI_SCOPE is required');\n tokenProvider = getBearerTokenProvider(credential, scope);\n\n openai = new AzureOpenAI({\n azureADTokenProvider: tokenProvider,\n endpoint: getAIConfig(AZURE_OPENAI_ENDPOINT),\n apiVersion: getAIConfig(AZURE_OPENAI_API_VERSION),\n deployment: getAIConfig(AZURE_OPENAI_DEPLOYMENT),\n ...extraConfig,\n ...extraAzureConfig,\n });\n } else {\n // endpoint, apiKey, apiVersion, deployment\n openai = new AzureOpenAI({\n apiKey: getAIConfig(AZURE_OPENAI_KEY),\n endpoint: getAIConfig(AZURE_OPENAI_ENDPOINT),\n apiVersion: getAIConfig(AZURE_OPENAI_API_VERSION),\n deployment: getAIConfig(AZURE_OPENAI_DEPLOYMENT),\n dangerouslyAllowBrowser: true,\n ...extraConfig,\n ...extraAzureConfig,\n });\n }\n } else if (!getAIConfig(MIDSCENE_USE_ANTHROPIC_SDK)) {\n const baseURL = getAIConfig(OPENAI_BASE_URL);\n if (typeof baseURL === 'string') {\n if (!/^https?:\\/\\//.test(baseURL)) {\n throw new Error(\n `OPENAI_BASE_URL must be a valid URL starting with http:// or https://, but got: ${baseURL}\\nPlease check your config.`,\n );\n }\n }\n\n openai = new OpenAI({\n baseURL: getAIConfig(OPENAI_BASE_URL),\n apiKey: getAIConfig(OPENAI_API_KEY),\n httpAgent: proxyAgent,\n ...extraConfig,\n defaultHeaders: {\n ...(extraConfig?.defaultHeaders || {}),\n [MIDSCENE_API_TYPE]: AIActionTypeValue.toString(),\n },\n dangerouslyAllowBrowser: true,\n });\n }\n\n if (openai && getAIConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n console.log('DEBUGGING MODE: langsmith wrapper enabled');\n const { wrapOpenAI } = await import('langsmith/wrappers');\n openai = wrapOpenAI(openai);\n }\n\n if (typeof openai !== 'undefined') {\n return {\n completion: openai.chat.completions,\n style: 'openai',\n };\n }\n\n // Anthropic\n if (getAIConfig(MIDSCENE_USE_ANTHROPIC_SDK)) {\n const apiKey = getAIConfig(ANTHROPIC_API_KEY);\n assert(apiKey, 'ANTHROPIC_API_KEY is required');\n openai = new Anthropic({\n apiKey,\n httpAgent: proxyAgent,\n dangerouslyAllowBrowser: true,\n }) as any;\n }\n\n if (typeof openai !== 'undefined' && (openai as any).messages) {\n return {\n completion: (openai as any).messages,\n style: 'anthropic',\n };\n }\n\n throw new Error('Openai SDK or Anthropic SDK is not initialized');\n}\n\nexport async function call(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n responseFormat?:\n | OpenAI.ChatCompletionCreateParams['response_format']\n | OpenAI.ResponseFormatJSONObject,\n): Promise<{ content: string; usage?: AIUsageInfo }> {\n const { completion, style } = await createChatClient({\n AIActionTypeValue,\n });\n\n const maxTokens = getAIConfig(OPENAI_MAX_TOKENS);\n const debugCall = getDebug('ai:call');\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n\n const startTime = Date.now();\n const model = getModelName();\n let content: string | undefined;\n let usage: OpenAI.CompletionUsage | undefined;\n const commonConfig = {\n temperature: getAIConfigInBoolean(MIDSCENE_USE_VLM_UI_TARS) ? 0.0 : 0.1,\n stream: false,\n max_tokens:\n typeof maxTokens === 'number'\n ? maxTokens\n : Number.parseInt(maxTokens || '2048', 10),\n ...(getAIConfigInBoolean(MIDSCENE_USE_QWEN_VL) // qwen specific config\n ? {\n vl_high_resolution_images: true,\n }\n : {}),\n };\n if (style === 'openai') {\n debugCall(`sending request to ${model}`);\n let result: Awaited<ReturnType<typeof completion.create>>;\n try {\n result = await completion.create({\n model,\n messages,\n response_format: responseFormat,\n ...commonConfig,\n } as any);\n } catch (e: any) {\n const newError = new Error(\n `failed to call AI model service: ${e.message}. Trouble shooting: https://midscenejs.com/model-provider.html`,\n {\n cause: e,\n },\n );\n throw newError;\n }\n\n debugProfileStats(\n `model, ${model}, mode, ${vlLocateMode() || 'default'}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${Date.now() - startTime}, requestId, ${result._request_id || ''}`,\n );\n\n debugProfileDetail(`model usage detail: ${JSON.stringify(result.usage)}`);\n\n assert(\n result.choices,\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n content = result.choices[0].message.content!;\n\n debugCall(`response: ${content}`);\n assert(content, 'empty content');\n usage = result.usage;\n // console.log('headers', result.headers);\n } else if (style === 'anthropic') {\n const convertImageContent = (content: any) => {\n if (content.type === 'image_url') {\n const imgBase64 = content.image_url.url;\n assert(imgBase64, 'image_url is required');\n return {\n source: {\n type: 'base64',\n media_type: imgBase64.includes('data:image/png;base64,')\n ? 'image/png'\n : 'image/jpeg',\n data: imgBase64.split(',')[1],\n },\n type: 'image',\n };\n }\n return content;\n };\n\n const result = await completion.create({\n model,\n system: 'You are a versatile professional in software UI automation',\n messages: messages.map((m) => ({\n role: 'user',\n content: Array.isArray(m.content)\n ? (m.content as any).map(convertImageContent)\n : m.content,\n })),\n response_format: responseFormat,\n ...commonConfig,\n } as any);\n content = (result as any).content[0].text as string;\n assert(content, 'empty content');\n usage = result.usage;\n }\n\n return { content: content || '', usage };\n}\n\nexport async function callToGetJSONObject<T>(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n): Promise<{ content: T; usage?: AIUsageInfo }> {\n let responseFormat:\n | OpenAI.ChatCompletionCreateParams['response_format']\n | OpenAI.ResponseFormatJSONObject\n | undefined;\n\n const model = getModelName();\n\n if (model.includes('gpt-4')) {\n switch (AIActionTypeValue) {\n case AIActionType.ASSERT:\n responseFormat = assertSchema;\n break;\n case AIActionType.INSPECT_ELEMENT:\n responseFormat = locatorSchema;\n break;\n case AIActionType.EXTRACT_DATA:\n //TODO: Currently the restriction type can only be a json subset of the constraint, and the way the extract api is used needs to be adjusted to limit the user's data to this as well\n // targetResponseFormat = extractDataSchema;\n responseFormat = { type: AIResponseFormat.JSON };\n break;\n case AIActionType.PLAN:\n responseFormat = planSchema;\n break;\n }\n }\n\n // gpt-4o-2024-05-13 only supports json_object response format\n if (model === 'gpt-4o-2024-05-13') {\n responseFormat = { type: AIResponseFormat.JSON };\n }\n\n const response = await call(messages, AIActionTypeValue, responseFormat);\n assert(response, 'empty response');\n const jsonContent = safeParseJson(response.content);\n return { content: jsonContent, usage: response.usage };\n}\n\nexport function extractJSONFromCodeBlock(response: string) {\n try {\n // First, try to match a JSON object directly in the response\n const jsonMatch = response.match(/^\\s*(\\{[\\s\\S]*\\})\\s*$/);\n if (jsonMatch) {\n return jsonMatch[1];\n }\n\n // If no direct JSON object is found, try to extract JSON from a code block\n const codeBlockMatch = response.match(\n /```(?:json)?\\s*(\\{[\\s\\S]*?\\})\\s*```/,\n );\n if (codeBlockMatch) {\n return codeBlockMatch[1];\n }\n\n // If no code block is found, try to find a JSON-like structure in the text\n const jsonLikeMatch = response.match(/\\{[\\s\\S]*\\}/);\n if (jsonLikeMatch) {\n return jsonLikeMatch[0];\n }\n } catch {}\n // If no JSON-like structure is found, return the original response\n return response;\n}\n\nexport function preprocessDoubaoBboxJson(input: string) {\n if (input.includes('bbox')) {\n // when its values like 940 445 969 490, replace all /\\d+\\s+\\d+/g with /$1,$2/g\n while (/\\d+\\s+\\d+/.test(input)) {\n input = input.replace(/(\\d+)\\s+(\\d+)/g, '$1,$2');\n }\n }\n return input;\n}\n\nexport function safeParseJson(input: string) {\n const cleanJsonString = extractJSONFromCodeBlock(input);\n // match the point\n if (cleanJsonString?.match(/\\((\\d+),(\\d+)\\)/)) {\n return cleanJsonString\n .match(/\\((\\d+),(\\d+)\\)/)\n ?.slice(1)\n .map(Number);\n }\n try {\n return JSON.parse(cleanJsonString);\n } catch {}\n try {\n return dJSON.parse(cleanJsonString);\n } catch (e) {}\n\n if (vlLocateMode() === 'doubao-vision' || vlLocateMode() === 'vlm-ui-tars') {\n const jsonString = preprocessDoubaoBboxJson(cleanJsonString);\n return dJSON.parse(jsonString);\n }\n throw Error(`failed to parse json response: ${input}`);\n}\n","import type {\n AIUsageInfo,\n BaseElement,\n ElementTreeNode,\n MidsceneYamlFlowItem,\n PlanningAction,\n PlanningActionParamInputOrKeyPress,\n PlanningActionParamScroll,\n PlanningActionParamSleep,\n Rect,\n Size,\n} from '@/types';\nimport { assert } from '@midscene/shared/utils';\n\nimport type {\n ChatCompletionSystemMessageParam,\n ChatCompletionUserMessageParam,\n} from 'openai/resources';\nimport {\n callToGetJSONObject,\n checkAIConfig,\n getModelName,\n} from './service-caller/index';\n\nimport type { PlanningLocateParam } from '@/types';\nimport { NodeType } from '@midscene/shared/constants';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport { treeToList } from '@midscene/shared/extractor';\nimport { compositeElementInfoImg } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\n\nexport type AIArgs = [\n ChatCompletionSystemMessageParam,\n ChatCompletionUserMessageParam,\n];\n\nexport enum AIActionType {\n ASSERT = 0,\n INSPECT_ELEMENT = 1,\n EXTRACT_DATA = 2,\n PLAN = 3,\n}\n\nexport async function callAiFn<T>(\n msgs: AIArgs,\n AIActionTypeValue: AIActionType,\n): Promise<{ content: T; usage?: AIUsageInfo }> {\n assert(\n checkAIConfig(),\n 'Cannot find config for AI model service. If you are using a self-hosted model without validating the API key, please set `OPENAI_API_KEY` to any non-null value. https://midscenejs.com/model-provider.html',\n );\n\n const { content, usage } = await callToGetJSONObject<T>(\n msgs,\n AIActionTypeValue,\n );\n return { content, usage };\n}\n\nconst defaultBboxSize = 20; // must be even number\nconst debugInspectUtils = getDebug('ai:common');\n\n// transform the param of locate from qwen mode\nexport function fillBboxParam(\n locate: PlanningLocateParam,\n width: number,\n height: number,\n) {\n // The Qwen model might have hallucinations of naming bbox as bbox_2d.\n if ((locate as any).bbox_2d && !locate?.bbox) {\n locate.bbox = (locate as any).bbox_2d;\n // biome-ignore lint/performance/noDelete: <explanation>\n delete (locate as any).bbox_2d;\n }\n\n if (locate?.bbox) {\n locate.bbox = adaptBbox(locate.bbox, width, height);\n }\n\n return locate;\n}\n\nexport function adaptQwenBbox(\n bbox: number[],\n): [number, number, number, number] {\n if (bbox.length < 2) {\n const msg = `invalid bbox data for qwen-vl mode: ${JSON.stringify(bbox)} `;\n throw new Error(msg);\n }\n\n const result: [number, number, number, number] = [\n Math.round(bbox[0]),\n Math.round(bbox[1]),\n typeof bbox[2] === 'number'\n ? Math.round(bbox[2])\n : Math.round(bbox[0] + defaultBboxSize),\n typeof bbox[3] === 'number'\n ? Math.round(bbox[3])\n : Math.round(bbox[1] + defaultBboxSize),\n ];\n return result;\n}\n\nexport function adaptDoubaoBbox(\n bbox: number[] | string,\n width: number,\n height: number,\n): [number, number, number, number] {\n assert(\n width > 0 && height > 0,\n 'width and height must be greater than 0 in doubao mode',\n );\n\n if (typeof bbox === 'string') {\n assert(\n /^(\\d+)\\s(\\d+)\\s(\\d+)\\s(\\d+)$/.test(bbox.trim()),\n `invalid bbox data string for doubao-vision mode: ${bbox}`,\n );\n const splitted = bbox.split(' ');\n if (splitted.length === 4) {\n return [\n Math.round((Number(splitted[0]) * width) / 1000),\n Math.round((Number(splitted[1]) * height) / 1000),\n Math.round((Number(splitted[2]) * width) / 1000),\n Math.round((Number(splitted[3]) * height) / 1000),\n ];\n }\n throw new Error(`invalid bbox data string for doubao-vision mode: ${bbox}`);\n }\n\n if (Array.isArray(bbox) && Array.isArray(bbox[0])) {\n bbox = bbox[0];\n }\n\n if (bbox.length === 4 || bbox.length === 5) {\n return [\n Math.round((bbox[0] * width) / 1000),\n Math.round((bbox[1] * height) / 1000),\n Math.round((bbox[2] * width) / 1000),\n Math.round((bbox[3] * height) / 1000),\n ];\n }\n\n // treat the bbox as a center point\n if (\n bbox.length === 6 ||\n bbox.length === 2 ||\n bbox.length === 3 ||\n bbox.length === 7\n ) {\n return [\n Math.max(0, Math.round((bbox[0] * width) / 1000) - defaultBboxSize / 2),\n Math.max(0, Math.round((bbox[1] * height) / 1000) - defaultBboxSize / 2),\n Math.min(\n width,\n Math.round((bbox[0] * width) / 1000) + defaultBboxSize / 2,\n ),\n Math.min(\n height,\n Math.round((bbox[1] * height) / 1000) + defaultBboxSize / 2,\n ),\n ];\n }\n\n if (bbox.length === 8) {\n return [\n Math.round((bbox[0] * width) / 1000),\n Math.round((bbox[1] * height) / 1000),\n Math.round((bbox[4] * width) / 1000),\n Math.round((bbox[5] * height) / 1000),\n ];\n }\n\n const msg = `invalid bbox data for doubao-vision mode: ${JSON.stringify(bbox)} `;\n throw new Error(msg);\n}\n\nexport function adaptBbox(\n bbox: number[],\n width: number,\n height: number,\n): [number, number, number, number] {\n if (vlLocateMode() === 'doubao-vision' || vlLocateMode() === 'vlm-ui-tars') {\n return adaptDoubaoBbox(bbox, width, height);\n }\n\n if (vlLocateMode() === 'gemini') {\n return adaptGeminiBbox(bbox, width, height);\n }\n\n return adaptQwenBbox(bbox);\n}\n\nexport function adaptGeminiBbox(\n bbox: number[],\n width: number,\n height: number,\n): [number, number, number, number] {\n const left = Math.round((bbox[1] * width) / 1000);\n const top = Math.round((bbox[0] * height) / 1000);\n const right = Math.round((bbox[3] * width) / 1000);\n const bottom = Math.round((bbox[2] * height) / 1000);\n return [left, top, right, bottom];\n}\n\nexport function adaptBboxToRect(\n bbox: number[],\n width: number,\n height: number,\n offsetX = 0,\n offsetY = 0,\n): Rect {\n debugInspectUtils('adaptBboxToRect', bbox, width, height, offsetX, offsetY);\n const [left, top, right, bottom] = adaptBbox(bbox, width, height);\n const rect = {\n left: left + offsetX,\n top: top + offsetY,\n width: right - left,\n height: bottom - top,\n };\n debugInspectUtils('adaptBboxToRect, result=', rect);\n return rect;\n}\n\nlet warned = false;\nexport function warnGPT4oSizeLimit(size: Size) {\n if (warned) return;\n if (getModelName()?.toLowerCase().includes('gpt-4o')) {\n const warningMsg = `GPT-4o has a maximum image input size of 2000x768 or 768x2000, but got ${size.width}x${size.height}. Please set your page to a smaller resolution. Otherwise, the result may be inaccurate.`;\n\n if (\n Math.max(size.width, size.height) > 2000 ||\n Math.min(size.width, size.height) > 768\n ) {\n console.warn(warningMsg);\n warned = true;\n }\n } else if (size.width > 1800 || size.height > 1800) {\n console.warn(\n `The image size seems too large (${size.width}x${size.height}). It may lead to more token usage, slower response, and inaccurate result.`,\n );\n warned = true;\n }\n}\n\nexport function mergeRects(rects: Rect[]) {\n const minLeft = Math.min(...rects.map((r) => r.left));\n const minTop = Math.min(...rects.map((r) => r.top));\n const maxRight = Math.max(...rects.map((r) => r.left + r.width));\n const maxBottom = Math.max(...rects.map((r) => r.top + r.height));\n return {\n left: minLeft,\n top: minTop,\n width: maxRight - minLeft,\n height: maxBottom - minTop,\n };\n}\n\n// expand the search area to at least 300 x 300, or add a default padding\nexport function expandSearchArea(rect: Rect, screenSize: Size) {\n const minEdgeSize = 300;\n const defaultPadding = 160;\n\n const paddingSizeHorizontal =\n rect.width < minEdgeSize\n ? Math.ceil((minEdgeSize - rect.width) / 2)\n : defaultPadding;\n const paddingSizeVertical =\n rect.height < minEdgeSize\n ? Math.ceil((minEdgeSize - rect.height) / 2)\n : defaultPadding;\n rect.left = Math.max(0, rect.left - paddingSizeHorizontal);\n rect.width = Math.min(\n rect.width + paddingSizeHorizontal * 2,\n screenSize.width - rect.left,\n );\n rect.top = Math.max(0, rect.top - paddingSizeVertical);\n rect.height = Math.min(\n rect.height + paddingSizeVertical * 2,\n screenSize.height - rect.top,\n );\n return rect;\n}\n\nexport async function markupImageForLLM(\n screenshotBase64: string,\n tree: ElementTreeNode<BaseElement>,\n size: Size,\n) {\n const elementsInfo = treeToList(tree);\n const elementsPositionInfoWithoutText = elementsInfo!.filter(\n (elementInfo) => {\n if (elementInfo.attributes.nodeType === NodeType.TEXT) {\n return false;\n }\n return true;\n },\n );\n\n const imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n elementsPositionInfo: elementsPositionInfoWithoutText as any,\n size,\n });\n return imagePayload;\n}\n\nexport function buildYamlFlowFromPlans(\n plans: PlanningAction[],\n sleep?: number,\n): MidsceneYamlFlowItem[] {\n const flow: MidsceneYamlFlowItem[] = [];\n\n for (const plan of plans) {\n const type = plan.type;\n const locate = plan.locate?.prompt!; // TODO: check if locate is null\n\n if (type === 'Tap') {\n flow.push({\n aiTap: locate!,\n });\n } else if (type === 'Hover') {\n flow.push({\n aiHover: locate!,\n });\n } else if (type === 'Input') {\n const param = plan.param as PlanningActionParamInputOrKeyPress;\n flow.push({\n aiInput: param.value,\n locate,\n });\n } else if (type === 'KeyboardPress') {\n const param = plan.param as PlanningActionParamInputOrKeyPress;\n flow.push({\n aiKeyboardPress: param.value,\n locate,\n });\n } else if (type === 'Scroll') {\n const param = plan.param as PlanningActionParamScroll;\n flow.push({\n aiScroll: null,\n locate,\n direction: param.direction,\n scrollType: param.scrollType,\n distance: param.distance,\n });\n } else if (type === 'Sleep') {\n const param = plan.param as PlanningActionParamSleep;\n flow.push({\n sleep: param.timeMs,\n });\n } else if (\n type === 'AndroidBackButton' ||\n type === 'AndroidHomeButton' ||\n type === 'AndroidRecentAppsButton'\n ) {\n // not implemented in yaml yet\n } else if (\n type === 'Error' ||\n type === 'ExpectedFalsyCondition' ||\n type === 'Assert' ||\n type === 'AssertWithoutThrow' ||\n type === 'Finished'\n ) {\n // do nothing\n } else {\n console.warn(\n `Cannot convert action ${type} to yaml flow. This should be a bug of Midscene.`,\n );\n }\n }\n\n if (sleep) {\n flow.push({\n sleep: sleep,\n });\n }\n\n return flow;\n}\n","export function getTimeZoneInfo(): { timezone: string; isChina: boolean } {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n const offset = -new Date().getTimezoneOffset() / 60;\n\n return {\n timezone: `UTC${offset >= 0 ? '+' : ''}${offset}`,\n isChina: timeZone === 'Asia/Shanghai',\n };\n}\n\nexport function getLanguage(): string {\n return getTimeZoneInfo().isChina ? 'Chinese' : 'English';\n}\n\nexport function getUiTarsPlanningPrompt(): string {\n const language = getLanguage();\n\n return `\nYou are a GUI agent. You are given a task and your action history, with screenshots. You need to perform the next action to complete the task. \n\n## Output Format\n\\`\\`\\`\nThought: ...\nAction: ...\n\\`\\`\\`\n\n## Action Space\n\nclick(start_box='[x1, y1, x2, y2]')\nleft_double(start_box='[x1, y1, x2, y2]')\nright_single(start_box='[x1, y1, x2, y2]')\ndrag(start_box='[x1, y1, x2, y2]', end_box='[x3, y3, x4, y4]')\nhotkey(key='')\ntype(content='xxx') # Use escape characters \\\\', \\\\\\\", and \\\\n in content part to ensure we can parse the content in normal python string format. If you want to submit your input, use \\\\n at the end of content. \nscroll(start_box='[x1, y1, x2, y2]', direction='down or up or right or left')\nwait() #Sleep for 5s and take a screenshot to check for any changes.\nfinished(content='xxx') # Use escape characters \\\\', \\\\\", and \\\\n in content part to ensure we can parse the content in normal python string format.\n\n\n## Note\n- Use ${language} in \\`Thought\\` part.\n- Write a small plan and finally summarize your next action (with its target element) in one sentence in \\`Thought\\` part.\n\n## User Instruction\n`;\n}\n\nexport const getSummary = (prediction: string) =>\n prediction\n .replace(/Reflection:[\\s\\S]*?(?=Action_Summary:|Action:|$)/g, '')\n .trim();\n","import type { ResponseFormatJSONSchema } from 'openai/resources';\nimport { getTimeZoneInfo } from './ui-tars-planning';\n\nexport const language = getTimeZoneInfo().isChina ? 'Chinese' : 'English';\nconst defaultAssertionPrompt =\n 'You are a senior testing engineer. User will give an assertion and a screenshot of a page. By carefully viewing the screenshot, please tell whether the assertion is truthy.';\n\nconst defaultAssertionResponseJsonFormat = `Return in the following JSON format:\n{\n pass: boolean, // whether the assertion is truthy\n thought: string | null, // string, if the result is falsy, give the reason why it is falsy. Otherwise, put null.\n}`;\n\nconst uiTarsAssertionResponseJsonFormat = `## Output Json String Format\n\\`\\`\\`\n\"{\n \"pass\": <<is a boolean value from the enum [true, false], true means the assertion is truthy>>, \n \"thought\": \"<<is a string, give the reason why the assertion is falsy or truthy. Otherwise.>>\"\n}\"\n\\`\\`\\`\n\n## Rules **MUST** follow\n- Make sure to return **only** the JSON, with **no additional** text or explanations.\n- Use ${language} in \\`thought\\` part.\n- You **MUST** strictly follow up the **Output Json String Format**.`;\n\nexport function systemPromptToAssert(model: { isUITars: boolean }) {\n return `${defaultAssertionPrompt}\n\n${model.isUITars ? uiTarsAssertionResponseJsonFormat : defaultAssertionResponseJsonFormat}`;\n}\n\nexport const assertSchema: ResponseFormatJSONSchema = {\n type: 'json_schema',\n json_schema: {\n name: 'assert',\n strict: true,\n schema: {\n type: 'object',\n properties: {\n pass: {\n type: 'boolean',\n description: 'Whether the assertion passed or failed',\n },\n thought: {\n type: ['string', 'null'],\n description: 'The thought process behind the assertion',\n },\n },\n required: ['pass', 'thought'],\n additionalProperties: false,\n },\n },\n};\n","import { PromptTemplate } from '@langchain/core/prompts';\nimport type { vlLocateMode } from '@midscene/shared/env';\nimport type { ResponseFormatJSONSchema } from 'openai/resources';\nimport { bboxDescription } from './common';\nexport function systemPromptToLocateElement(\n vlMode: ReturnType<typeof vlLocateMode>,\n) {\n if (vlMode) {\n const bboxComment = bboxDescription(vlMode);\n return `\n## Role:\nYou are an expert in software testing.\n\n## Objective:\n- Identify elements in screenshots and text that match the user's description.\n- Give the coordinates of the element that matches the user's description best in the screenshot.\n\n## Output Format:\n\\`\\`\\`json\n{\n \"bbox\": [number, number, number, number], // ${bboxComment}\n \"errors\"?: string[]\n}\n\\`\\`\\`\n\nFields:\n* \\`bbox\\` is the bounding box of the element that matches the user's description best in the screenshot\n* \\`errors\\` is an optional array of error messages (if any)\n\nFor example, when an element is found:\n\\`\\`\\`json\n{\n \"bbox\": [100, 100, 200, 200],\n \"errors\": []\n}\n\\`\\`\\`\n\nWhen no element is found:\n\\`\\`\\`json\n{\n \"bbox\": [],\n \"errors\": [\"I can see ..., but {some element} is not found\"]\n}\n\\`\\`\\`\n`;\n }\n\n return `\n## Role:\nYou are an expert in software page image (2D) and page element text analysis.\n\n## Objective:\n- Identify elements in screenshots and text that match the user's description.\n- Return JSON data containing the selection reason and element ID.\n\n## Skills:\n- Image analysis and recognition\n- Multilingual text understanding\n- Software UI design and testing\n\n## Workflow:\n1. Receive the user's element description, screenshot, and element description information. Note that the text may contain non-English characters (e.g., Chinese), indicating that the application may be non-English.\n2. Based on the user's description, locate the target element ID in the list of element descriptions and the screenshot.\n3. Found the required number of elements\n4. Return JSON data containing the selection reason and element ID.\n\n## Constraints:\n- Strictly adhere to the specified location when describing the required element; do not select elements from other locations.\n- Elements in the image with NodeType other than \"TEXT Node\" have been highlighted to identify the element among multiple non-text elements.\n- Accurately identify element information based on the user's description and return the corresponding element ID from the element description information, not extracted from the image.\n- If no elements are found, the \"elements\" array should be empty.\n- The returned data must conform to the specified JSON format.\n- The returned value id information must use the id from element info (important: **use id not indexId, id is hash content**)\n\n## Output Format:\n\nPlease return the result in JSON format as follows:\n\n\\`\\`\\`json\n{\n \"elements\": [\n // If no matching elements are found, return an empty array []\n {\n \"reason\": \"PLACEHOLDER\", // The thought process for finding the element, replace PLACEHOLDER with your thought process\n \"text\": \"PLACEHOLDER\", // Replace PLACEHOLDER with the text of elementInfo, if none, leave empty\n \"id\": \"PLACEHOLDER\" // Replace PLACEHOLDER with the ID (important: **use id not indexId, id is hash content**) of elementInfo\n }\n // More elements...\n ],\n \"errors\": [] // Array of strings containing any error messages\n}\n\\`\\`\\`\n\n## Example:\nExample 1:\nInput Example:\n\\`\\`\\`json\n// Description: \"Shopping cart icon in the upper right corner\"\n{\n \"description\": \"PLACEHOLDER\", // Description of the target element\n \"screenshot\": \"path/screenshot.png\",\n \"text\": '{\n \"pageSize\": {\n \"width\": 400, // Width of the page\n \"height\": 905 // Height of the page\n },\n \"elementInfos\": [\n {\n \"id\": \"1231\", // ID of the element\n \"indexId\": \"0\", // Index of the element,The image is labeled to the left of the element\n \"attributes\": { // Attributes of the element\n \"nodeType\": \"IMG Node\", // Type of element, types include: TEXT Node, IMG Node, BUTTON Node, INPUT Node\n \"src\": \"https://ap-southeast-3.m\",\n \"class\": \".img\"\n },\n \"content\": \"\", // Text content of the element\n \"rect\": {\n \"left\": 280, // Distance from the left side of the page\n \"top\": 8, // Distance from the top of the page\n \"width\": 44, // Width of the element\n \"height\": 44 // Height of the element\n }\n },\n {\n \"id\": \"66551\", // ID of the element\n \"indexId\": \"1\", // Index of the element,The image is labeled to the left of the element\n \"attributes\": { // Attributes of the element\n \"nodeType\": \"IMG Node\", // Type of element, types include: TEXT Node, IMG Node, BUTTON Node, INPUT Node\n \"src\": \"data:image/png;base64,iVBORw0KGgoAAAANSU...\",\n \"class\": \".icon\"\n },\n \"content\": \"\", // Text content of the element\n \"rect\": {\n \"left\": 350, // Distance from the left side of the page\n \"top\": 16, // Distance from the top of the page\n \"width\": 25, // Width of the element\n \"height\": 25 // Height of the element\n }\n },\n ...\n {\n \"id\": \"12344\",\n \"indexId\": \"2\", // Index of the element,The image is labeled to the left of the element\n \"attributes\": {\n \"nodeType\": \"TEXT Node\",\n \"class\": \".product-name\"\n },\n \"center\": [\n 288,\n 834\n ],\n \"content\": \"Mango Drink\",\n \"rect\": {\n \"left\": 188,\n \"top\": 827,\n \"width\": 199,\n \"height\": 13\n }\n },\n ...\n ]\n }\n '\n}\n\\`\\`\\`\nOutput Example:\n\\`\\`\\`json\n{\n \"elements\": [\n {\n // Describe the reason for finding this element, replace with actual value in practice\n \"reason\": \"Reason for finding element 4: It is located in the upper right corner, is an image type, and according to the screenshot, it is a shopping cart icon button\",\n \"text\": \"\",\n // ID(**use id not indexId**) of this element, replace with actual value in practice, **use id not indexId**\n \"id\": \"1231\"\n }\n ],\n \"errors\": []\n}\n\\`\\`\\`\n \n `;\n}\n\nexport const locatorSchema: ResponseFormatJSONSchema = {\n type: 'json_schema',\n json_schema: {\n name: 'find_elements',\n strict: true,\n schema: {\n type: 'object',\n properties: {\n elements: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n reason: {\n type: 'string',\n description: 'Reason for finding this element',\n },\n text: {\n type: 'string',\n description: 'Text content of the element',\n },\n id: {\n type: 'string',\n description: 'ID of this element',\n },\n },\n required: ['reason', 'text', 'id'],\n additionalProperties: false,\n },\n description: 'List of found elements',\n },\n errors: {\n type: 'array',\n items: {\n type: 'string',\n },\n description: 'List of error messages, if any',\n },\n },\n required: ['elements', 'errors'],\n additionalProperties: false,\n },\n },\n};\n\nexport const findElementPrompt = new PromptTemplate({\n template: `\nHere is the item user want to find:\n=====================================\n{targetElementDescription}\n=====================================\n\n{pageDescription}\n `,\n inputVariables: ['pageDescription', 'targetElementDescription'],\n});\n","import type { vlLocateMode } from '@midscene/shared/env';\nexport function bboxDescription(vlMode: ReturnType<typeof vlLocateMode>) {\n if (vlMode === 'gemini') {\n return '2d bounding box as [ymin, xmin, ymax, xmax]';\n }\n return '2d bounding box as [xmin, ymin, xmax, ymax]';\n}\n","import type { PageType } from '@/types';\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport type { vlLocateMode } from '@midscene/shared/env';\nimport type { ResponseFormatJSONSchema } from 'openai/resources';\nimport { bboxDescription } from './common';\nimport { samplePageDescription } from './util';\n// Note: put the log field first to trigger the CoT\nconst vlCoTLog = `\"what_the_user_wants_to_do_next_by_instruction\": string, // What the user wants to do according to the instruction and previous logs. `;\nconst vlCurrentLog = `\"log\": string, // Log what the next one action (ONLY ONE!) you can do according to the screenshot and the instruction. The typical log looks like \"Now i want to use action '{{ action-type }}' to do .. first\". If no action should be done, log the reason. \". Use the same language as the user's instruction.`;\nconst llmCurrentLog = `\"log\": string, // Log what the next actions you can do according to the screenshot and the instruction. The typical log looks like \"Now i want to use action '{{ action-type }}' to do ..\". If no action should be done, log the reason. \". Use the same language as the user's instruction.`;\n\nconst commonOutputFields = `\"error\"?: string, // Error messages about unexpected situations, if any. Only think it is an error when the situation is not expected according to the instruction. Use the same language as the user's instruction.\n \"more_actions_needed_by_instruction\": boolean, // Consider if there is still more action(s) to do after the action in \"Log\" is done, according to the instruction. If so, set this field to true. Otherwise, set it to false.`;\nconst vlLocateParam =\n 'locate: {bbox: [number, number, number, number], prompt: string }';\n\nconst systemTemplateOfVLPlanning = ({\n pageType,\n vlMode,\n}: {\n pageType: PageType;\n vlMode: ReturnType<typeof vlLocateMode>;\n}) => `\nTarget: User will give you a screenshot, an instruction and some previous logs indicating what have been done. Please tell what the next one action is (or null if no action should be done) to do the tasks the instruction requires. \n\nRestriction:\n- Don't give extra actions or plans beyond the instruction. ONLY plan for what the instruction requires. For example, don't try to submit the form if the instruction is only to fill something.\n- Always give ONLY ONE action in \\`log\\` field (or null if no action should be done), instead of multiple actions. Supported actions are Tap, Hover, Input, KeyboardPress, Scroll${pageType === 'android' ? ', AndroidBackButton, AndroidHomeButton, AndroidRecentAppsButton.' : '.'}\n- Don't repeat actions in the previous logs.\n- Bbox is the bounding box of the element to be located. It's an array of 4 numbers, representing ${bboxDescription(vlMode)}.\n\nSupporting actions:\n- Tap: { type: \"Tap\", ${vlLocateParam} }\n- Hover: { type: \"Hover\", ${vlLocateParam} }\n- Input: { type: \"Input\", ${vlLocateParam}, param: { value: string } } // \\`value\\` is the final that should be filled in the input box. No matter what modifications are required, just provide the final value to replace the existing input value. \n- KeyboardPress: { type: \"KeyboardPress\", param: { value: string } }\n- Scroll: { type: \"Scroll\", ${vlLocateParam} | null, param: { direction: 'down'(default) | 'up' | 'right' | 'left', scrollType: 'once' (default) | 'untilBottom' | 'untilTop' | 'untilRight' | 'untilLeft', distance: null | number }} // locate is the element to scroll. If it's a page scroll, put \\`null\\` in the \\`locate\\` field.\n${\n pageType === 'android'\n ? `- AndroidBackButton: { type: \"AndroidBackButton\", param: {} }\n- AndroidHomeButton: { type: \"AndroidHomeButton\", param: {} }\n- AndroidRecentAppsButton: { type: \"AndroidRecentAppsButton\", param: {} }`\n : ''\n}\n\nField description:\n* The \\`prompt\\` field inside the \\`locate\\` field is a short description that could be used to locate the element.\n\nReturn in JSON format:\n{\n ${vlCoTLog}\n ${vlCurrentLog}\n ${commonOutputFields}\n \"action\": \n {\n // one of the supporting actions\n } | null,\n ,\n \"sleep\"?: number, // The sleep time after the action, in milliseconds.\n}\n\nFor example, when the instruction is \"click 'Confirm' button, and click 'Yes' in popup\" and the log is \"I will use action Tap to click 'Confirm' button\", by viewing the screenshot and previous logs, you should consider: We have already clicked the 'Confirm' button, so next we should find and click 'Yes' in popup.\n\nthis and output the JSON:\n\n{\n \"what_the_user_wants_to_do_next_by_instruction\": \"We have already clicked the 'Confirm' button, so next we should find and click 'Yes' in popup\",\n \"log\": \"I will use action Tap to click 'Yes' in popup\",\n \"more_actions_needed_by_instruction\": false,\n \"action\": {\n \"type\": \"Tap\",\n \"locate\": {\n \"bbox\": [100, 100, 200, 200],\n \"prompt\": \"The 'Yes' button in popup\"\n }\n }\n}\n`;\n\nconst llmLocateParam = `locate: {{\"id\": string, \"prompt\": string}} | null`;\nconst systemTemplateOfLLM = ({ pageType }: { pageType: PageType }) => `\n## Role\n\nYou are a versatile professional in software UI automation. Your outstanding contributions will impact the user experience of billions of users.\n\n## Objective\n\n- Decompose the instruction user asked into a series of actions\n- Locate the target element if possible\n- If the instruction cannot be accomplished, give a further plan.\n\n## Workflow\n\n1. Receive the screenshot, element description of screenshot(if any), user's instruction and previous logs.\n2. Decompose the user's task into a sequence of actions, and place it in the \\`actions\\` field. There are different types of actions (Tap / Hover / Input / KeyboardPress / Scroll / FalsyConditionStatement / Sleep ${pageType === 'android' ? '/ AndroidBackButton / AndroidHomeButton / AndroidRecentAppsButton' : ''}). The \"About the action\" section below will give you more details.\n3. Precisely locate the target element if it's already shown in the screenshot, put the location info in the \\`locate\\` field of the action.\n4. If some target elements is not shown in the screenshot, consider the user's instruction is not feasible on this page. Follow the next steps.\n5. Consider whether the user's instruction will be accomplished after all the actions\n - If yes, set \\`taskWillBeAccomplished\\` to true\n - If no, don't plan more actions by closing the array. Get ready to reevaluate the task. Some talent people like you will handle this. Give him a clear description of what have been done and what to do next. Put your new plan in the \\`furtherPlan\\` field. The \"How to compose the \\`taskWillBeAccomplished\\` and \\`furtherPlan\\` fields\" section will give you more details.\n\n## Constraints\n\n- All the actions you composed MUST be based on the page context information you get.\n- Trust the \"What have been done\" field about the task (if any), don't repeat actions in it.\n- Respond only with valid JSON. Do not write an introduction or summary or markdown prefix like \\`\\`\\`json\\`\\`\\`.\n- If the screenshot and the instruction are totally irrelevant, set reason in the \\`error\\` field.\n\n## About the \\`actions\\` field\n\nThe \\`locate\\` param is commonly used in the \\`param\\` field of the action, means to locate the target element to perform the action, it conforms to the following scheme:\n\ntype LocateParam = {{\n \"id\": string, // the id of the element found. It should either be the id marked with a rectangle in the screenshot or the id described in the description.\n \"prompt\"?: string // the description of the element to find. It can only be omitted when locate is null.\n}} | null // If it's not on the page, the LocateParam should be null\n\n## Supported actions\n\nEach action has a \\`type\\` and corresponding \\`param\\`. To be detailed:\n- type: 'Tap'\n * {{ ${llmLocateParam} }}\n- type: 'Hover'\n * {{ ${llmLocateParam} }}\n- type: 'Input', replace the value in the input field\n * {{ ${llmLocateParam}, param: {{ value: string }} }}\n * \\`value\\` is the final value that should be filled in the input field. No matter what modifications are required, just provide the final value user should see after the action is done. \n- type: 'KeyboardPress', press a key\n * {{ param: {{ value: string }} }}\n- type: 'Scroll', scroll up or down.\n * {{ \n ${llmLocateParam}, \n param: {{ \n direction: 'down'(default) | 'up' | 'right' | 'left', \n scrollType: 'once' (default) | 'untilBottom' | 'untilTop' | 'untilRight' | 'untilLeft', \n distance: null | number \n }} \n }}\n * To scroll some specific element, put the element at the center of the region in the \\`locate\\` field. If it's a page scroll, put \\`null\\` in the \\`locate\\` field. \n * \\`param\\` is required in this action. If some fields are not specified, use direction \\`down\\`, \\`once\\` scroll type, and \\`null\\` distance.\n * {{ param: {{ button: 'Back' | 'Home' | 'RecentApp' }} }}\n- type: 'ExpectedFalsyCondition'\n * {{ param: {{ reason: string }} }}\n * use this action when the conditional statement talked about in the instruction is falsy.\n- type: 'Sleep'\n * {{ param: {{ timeMs: number }} }}\n${\n pageType === 'android'\n ? `- type: 'AndroidBackButton', trigger the system \"back\" operation on Android devices\n * {{ param: {{}} }}\n- type: 'AndroidHomeButton', trigger the system \"home\" operation on Android devices\n * {{ param: {{}} }}\n- type: 'AndroidRecentAppsButton', trigger the system \"recent apps\" operation on Android devices\n * {{ param: {{}} }}`\n : ''\n}\n`;\n\nconst outputTemplate = `\n## Output JSON Format:\n\nThe JSON format is as follows:\n\n{{\n \"actions\": [\n // ... some actions\n ],\n ${llmCurrentLog}\n ${commonOutputFields}\n}}\n\n## Examples\n\n### Example: Decompose a task\n\nWhen the instruction is 'Click the language switch button, wait 1s, click \"English\"', and not log is provided\n\nBy viewing the page screenshot and description, you should consider this and output the JSON:\n\n* The main steps should be: tap the switch button, sleep, and tap the 'English' option\n* The language switch button is shown in the screenshot, but it's not marked with a rectangle. So we have to use the page description to find the element. By carefully checking the context information (coordinates, attributes, content, etc.), you can find the element.\n* The \"English\" option button is not shown in the screenshot now, it means it may only show after the previous actions are finished. So don't plan any action to do this.\n* Log what these action do: Click the language switch button to open the language options. Wait for 1 second.\n* The task cannot be accomplished (because we cannot see the \"English\" option now), so the \\`more_actions_needed_by_instruction\\` field is true.\n\n{{\n \"actions\":[\n {{\n \"type\": \"Tap\", \n \"thought\": \"Click the language switch button to open the language options.\",\n \"param\": null,\n \"locate\": {{ id: \"c81c4e9a33\", prompt: \"The language switch button\" }},\n }},\n {{\n \"type\": \"Sleep\",\n \"thought\": \"Wait for 1 second to ensure the language options are displayed.\",\n \"param\": {{ \"timeMs\": 1000 }},\n }}\n ],\n \"error\": null,\n \"more_actions_needed_by_instruction\": true,\n \"log\": \"Click the language switch button to open the language options. Wait for 1 second\",\n}}\n\n### Example: What NOT to do\nWrong output:\n{{\n \"actions\":[\n {{\n \"type\": \"Tap\",\n \"thought\": \"Click the language switch button to open the language options.\",\n \"param\": null,\n \"locate\": {{\n {{ \"id\": \"c81c4e9a33\" }}, // WRONG: prompt is missing\n }}\n }},\n {{\n \"type\": \"Tap\", \n \"thought\": \"Click the English option\",\n \"param\": null,\n \"locate\": null, // This means the 'English' option is not shown in the screenshot, the task cannot be accomplished\n }}\n ],\n \"more_actions_needed_by_instruction\": false, // WRONG: should be true\n \"log\": \"Click the language switch button to open the language options\",\n}}\n\nReason:\n* The \\`prompt\\` is missing in the first 'Locate' action\n* Since the option button is not shown in the screenshot, there are still more actions to be done, so the \\`more_actions_needed_by_instruction\\` field should be true\n`;\n\nexport async function systemPromptToTaskPlanning({\n pageType,\n vlMode,\n}: {\n pageType: PageType;\n vlMode: ReturnType<typeof vlLocateMode>;\n}) {\n if (vlMode) {\n return systemTemplateOfVLPlanning({ pageType, vlMode });\n }\n\n const promptTemplate = new PromptTemplate({\n template: `${systemTemplateOfLLM({ pageType })}\\n\\n${outputTemplate}`,\n inputVariables: ['pageDescription'],\n });\n\n return await promptTemplate.format({\n pageDescription: samplePageDescription,\n });\n}\n\nexport const planSchema: ResponseFormatJSONSchema = {\n type: 'json_schema',\n json_schema: {\n name: 'action_items',\n strict: true,\n schema: {\n type: 'object',\n strict: true,\n properties: {\n actions: {\n // TODO\n type: 'array',\n items: {\n type: 'object',\n strict: true,\n properties: {\n thought: {\n type: 'string',\n description:\n 'Reasons for generating this task, and why this task is feasible on this page',\n },\n type: {\n type: 'string',\n description:\n 'Type of action, one of \"Tap\", \"Hover\" , \"Input\", \"KeyboardPress\", \"Scroll\", \"ExpectedFalsyCondition\", \"Sleep\", \"AndroidBackButton\", \"AndroidHomeButton\", \"AndroidRecentAppsButton\"',\n },\n param: {\n anyOf: [\n { type: 'null' },\n {\n type: 'object',\n properties: { value: { type: ['string', 'number'] } },\n required: ['value'],\n additionalProperties: false,\n },\n {\n type: 'object',\n properties: { timeMs: { type: ['number', 'string'] } },\n required: ['timeMs'],\n additionalProperties: false,\n },\n {\n type: 'object',\n properties: {\n direction: { type: 'string' },\n scrollType: { type: 'string' },\n distance: { type: ['number', 'string', 'null'] },\n },\n required: ['direction', 'scrollType', 'distance'],\n additionalProperties: false,\n },\n {\n type: 'object',\n properties: { reason: { type: 'string' } },\n required: ['reason'],\n additionalProperties: false,\n },\n {\n type: 'object',\n properties: { button: { type: 'string' } },\n required: ['button'],\n additionalProperties: false,\n },\n ],\n description:\n 'Parameter of the action, can be null ONLY when the type field is Tap or Hover',\n },\n locate: {\n type: ['object', 'null'],\n properties: {\n id: { type: 'string' },\n prompt: { type: 'string' },\n },\n required: ['id', 'prompt'],\n additionalProperties: false,\n description: 'Location information for the target element',\n },\n },\n required: ['thought', 'type', 'param', 'locate'],\n additionalProperties: false,\n },\n description: 'List of actions to be performed',\n },\n more_actions_needed_by_instruction: {\n type: 'boolean',\n description:\n 'If all the actions described in the instruction have been covered by this action and logs, set this field to false.',\n },\n log: {\n type: 'string',\n description:\n 'Log what these planned actions do. Do not include further actions that have not been planned.',\n },\n error: {\n type: ['string', 'null'],\n description: 'Error messages about unexpected situations',\n },\n },\n required: [\n 'actions',\n 'more_actions_needed_by_instruction',\n 'log',\n 'error',\n ],\n additionalProperties: false,\n },\n },\n};\n\nexport const generateTaskBackgroundContext = (\n userInstruction: string,\n log?: string,\n userActionContext?: string,\n) => {\n if (log) {\n return `\nHere is the user's instruction:\n\n<instruction>\n <high_priority_knowledge>\n ${userActionContext}\n </high_priority_knowledge>\n\n ${userInstruction}\n</instruction>\n\nThese are the logs from previous executions, which indicate what was done in the previous actions.\nDo NOT repeat these actions.\n<previous_logs>\n${log}\n</previous_logs>\n`;\n }\n\n return `\nHere is the user's instruction:\n<instruction>\n <high_priority_knowledge>\n ${userActionContext}\n </high_priority_knowledge>\n\n ${userInstruction}\n</instruction>\n`;\n};\n\nexport const automationUserPrompt = (\n vlMode: ReturnType<typeof vlLocateMode>,\n) => {\n if (vlMode) {\n return new PromptTemplate({\n template: '{taskBackgroundContext}',\n inputVariables: ['taskBackgroundContext'],\n });\n }\n\n return new PromptTemplate({\n template: `\npageDescription:\n=====================================\n{pageDescription}\n=====================================\n\n{taskBackgroundContext}`,\n inputVariables: ['pageDescription', 'taskBackgroundContext'],\n });\n};\n","export {\n imageInfo,\n imageInfoOfBase64,\n base64Encoded,\n resizeImg,\n transformImgPathToBase64,\n saveBase64Image,\n zoomForGPT4o,\n} from '@midscene/shared/img';\n","import { imageInfoOfBase64 } from '@/image/index';\nimport type { BaseElement, ElementTreeNode, Size, UIContext } from '@/types';\nimport { NodeType } from '@midscene/shared/constants';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport {\n descriptionOfTree,\n generateElementByPosition,\n treeToList,\n} from '@midscene/shared/extractor';\nimport { assert } from '@midscene/shared/utils';\n\nexport function describeSize(size: Size) {\n return `${size.width} x ${size.height}`;\n}\n\nexport function describeElement(\n elements: (Pick<BaseElement, 'rect' | 'content'> & { id: string })[],\n) {\n const sliceLength = 80;\n return elements\n .map((item) =>\n [\n item.id,\n item.rect.left,\n item.rect.top,\n item.rect.left + item.rect.width,\n item.rect.top + item.rect.height,\n item.content.length > sliceLength\n ? `${item.content.slice(0, sliceLength)}...`\n : item.content,\n ].join(', '),\n )\n .join('\\n');\n}\nexport const distanceThreshold = 16;\n\nexport function elementByPositionWithElementInfo(\n treeRoot: ElementTreeNode<BaseElement>,\n position: {\n x: number;\n y: number;\n },\n options?: {\n requireStrictDistance?: boolean;\n filterPositionElements?: boolean;\n },\n) {\n const requireStrictDistance = options?.requireStrictDistance ?? true;\n const filterPositionElements = options?.filterPositionElements ?? false;\n\n assert(typeof position !== 'undefined', 'position is required for query');\n\n const matchingElements: BaseElement[] = [];\n\n function dfs(node: ElementTreeNode<BaseElement>) {\n if (node?.node) {\n const item = node.node;\n if (\n item.rect.left <= position.x &&\n position.x <= item.rect.left + item.rect.width &&\n item.rect.top <= position.y &&\n position.y <= item.rect.top + item.rect.height\n ) {\n if (\n filterPositionElements &&\n item.attributes?.nodeType === NodeType.POSITION\n ) {\n // Skip POSITION elements if filterPositionElements is true\n return;\n }\n\n matchingElements.push(item);\n }\n }\n\n for (const child of node.children) {\n dfs(child);\n }\n }\n\n dfs(treeRoot);\n\n if (matchingElements.length === 0) {\n return undefined;\n }\n\n // Find the smallest element by area\n const element = matchingElements.reduce((smallest, current) => {\n const smallestArea = smallest.rect.width * smallest.rect.height;\n const currentArea = current.rect.width * current.rect.height;\n return currentArea < smallestArea ? current : smallest;\n });\n\n const distanceToCenter = distance(\n { x: element.center[0], y: element.center[1] },\n position,\n );\n\n if (requireStrictDistance) {\n return distanceToCenter <= distanceThreshold ? element : undefined;\n }\n\n return element;\n}\n\nexport function distance(\n point1: { x: number; y: number },\n point2: { x: number; y: number },\n) {\n return Math.sqrt((point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2);\n}\n\nexport const samplePageDescription = `\nAnd the page is described as follows:\n====================\nThe size of the page: 1280 x 720\nSome of the elements are marked with a rectangle in the screenshot corresponding to the markerId, some are not.\n\nDescription of all the elements in screenshot:\n<div id=\"969f1637\" markerId=\"1\" left=\"100\" top=\"100\" width=\"100\" height=\"100\"> // The markerId indicated by the rectangle label in the screenshot\n <h4 id=\"b211ecb2\" markerId=\"5\" left=\"150\" top=\"150\" width=\"90\" height=\"60\">\n The username is accepted\n </h4>\n ...many more\n</div>\n====================\n`;\n\nexport async function describeUserPage<\n ElementType extends BaseElement = BaseElement,\n>(\n context: Omit<UIContext<ElementType>, 'describer'>,\n opt?: {\n truncateTextLength?: number;\n filterNonTextContent?: boolean;\n },\n) {\n const { screenshotBase64 } = context;\n let width: number;\n let height: number;\n\n if (context.size) {\n ({ width, height } = context.size);\n } else {\n const imgSize = await imageInfoOfBase64(screenshotBase64);\n ({ width, height } = imgSize);\n }\n\n const treeRoot = context.tree;\n // dfs tree, save the id and element info\n const idElementMap: Record<string, ElementType> = {};\n const flatElements: ElementType[] = treeToList(treeRoot);\n flatElements.forEach((element) => {\n idElementMap[element.id] = element;\n if (typeof element.indexId !== 'undefined') {\n idElementMap[`${element.indexId}`] = element;\n }\n });\n\n const contentTree = await descriptionOfTree(\n treeRoot,\n opt?.truncateTextLength,\n opt?.filterNonTextContent,\n );\n\n // if match by position, don't need to provide the page description\n const sizeDescription = describeSize({ width, height });\n const pageDescription = vlLocateMode()\n ? ''\n : `The size of the page: ${sizeDescription} \\n Some of the elements are marked with a rectangle in the screenshot, some are not. \\n The page elements tree:\\n${contentTree}`;\n\n return {\n description: pageDescription,\n elementById(idOrIndexId: string) {\n assert(typeof idOrIndexId !== 'undefined', 'id is required for query');\n const item = idElementMap[`${idOrIndexId}`];\n return item;\n },\n elementByPosition(\n position: { x: number; y: number },\n size: { width: number; height: number },\n ) {\n return elementByPositionWithElementInfo(treeRoot, position);\n },\n insertElementByPosition(position: { x: number; y: number }) {\n const element = generateElementByPosition(position) as ElementType;\n\n treeRoot.children.push({\n node: element,\n children: [],\n });\n flatElements.push(element);\n idElementMap[element.id] = element;\n return element;\n },\n size: { width, height },\n };\n}\n","import type {\n AIAssertionResponse,\n AIDataExtractionResponse,\n AIElementLocatorResponse,\n AIElementResponse,\n AISectionLocatorResponse,\n AISingleElementResponse,\n AISingleElementResponseByPosition,\n AIUsageInfo,\n BaseElement,\n ElementById,\n ElementTreeNode,\n Rect,\n UIContext,\n} from '@/types';\nimport {\n MIDSCENE_USE_QWEN_VL,\n MIDSCENE_USE_VLM_UI_TARS,\n getAIConfigInBoolean,\n vlLocateMode,\n} from '@midscene/shared/env';\nimport { cropByRect, paddingToMatchBlockByBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type {\n ChatCompletionSystemMessageParam,\n ChatCompletionUserMessageParam,\n} from 'openai/resources';\nimport {\n AIActionType,\n adaptBboxToRect,\n callAiFn,\n expandSearchArea,\n markupImageForLLM,\n mergeRects,\n} from './common';\nimport { systemPromptToAssert } from './prompt/assertion';\nimport { extractDataPrompt, systemPromptToExtract } from './prompt/extraction';\nimport {\n findElementPrompt,\n systemPromptToLocateElement,\n} from './prompt/llm-locator';\nimport {\n sectionLocatorInstruction,\n systemPromptToLocateSection,\n} from './prompt/llm-section-locator';\nimport {\n describeUserPage,\n distance,\n distanceThreshold,\n elementByPositionWithElementInfo,\n} from './prompt/util';\nimport { callToGetJSONObject } from './service-caller/index';\n\nexport type AIArgs = [\n ChatCompletionSystemMessageParam,\n ChatCompletionUserMessageParam,\n];\n\nconst liteContextConfig = {\n filterNonTextContent: true,\n truncateTextLength: 200,\n};\n\nconst debugInspect = getDebug('ai:inspect');\nconst debugSection = getDebug('ai:section');\n\nexport async function AiLocateElement<\n ElementType extends BaseElement = BaseElement,\n>(options: {\n context: UIContext<ElementType>;\n targetElementDescription: string;\n callAI?: typeof callAiFn<AIElementResponse | [number, number]>;\n searchConfig?: Awaited<ReturnType<typeof AiLocateSection>>;\n}): Promise<{\n parseResult: AIElementLocatorResponse;\n rect?: Rect;\n rawResponse: string;\n elementById: ElementById;\n usage?: AIUsageInfo;\n}> {\n const { context, targetElementDescription, callAI } = options;\n const { screenshotBase64 } = context;\n const { description, elementById, insertElementByPosition } =\n await describeUserPage(context);\n\n assert(\n targetElementDescription,\n 'cannot find the target element description',\n );\n\n const userInstructionPrompt = await findElementPrompt.format({\n pageDescription: description,\n targetElementDescription,\n });\n const systemPrompt = systemPromptToLocateElement(vlLocateMode());\n\n let imagePayload = screenshotBase64;\n\n if (options.searchConfig) {\n assert(\n options.searchConfig.rect,\n 'searchArea is provided but its rect cannot be found. Failed to locate element',\n );\n assert(\n options.searchConfig.imageBase64,\n 'searchArea is provided but its imageBase64 cannot be found. Failed to locate element',\n );\n\n imagePayload = options.searchConfig.imageBase64;\n } else if (vlLocateMode() === 'qwen-vl') {\n imagePayload = await paddingToMatchBlockByBase64(imagePayload);\n } else if (!vlLocateMode()) {\n imagePayload = await markupImageForLLM(\n screenshotBase64,\n context.tree,\n context.size,\n );\n }\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n {\n type: 'text',\n text: userInstructionPrompt,\n },\n ],\n },\n ];\n\n const callAIFn =\n callAI || callToGetJSONObject<AIElementResponse | [number, number]>;\n\n const res = await callAIFn(msgs, AIActionType.INSPECT_ELEMENT);\n\n const rawResponse = JSON.stringify(res.content);\n\n let resRect: Rect | undefined;\n let matchedElements: AIElementLocatorResponse['elements'] =\n 'elements' in res.content ? res.content.elements : [];\n let errors: AIElementLocatorResponse['errors'] | undefined =\n 'errors' in res.content ? res.content.errors : [];\n try {\n if ('bbox' in res.content && Array.isArray(res.content.bbox)) {\n resRect = adaptBboxToRect(\n res.content.bbox,\n options.searchConfig?.rect?.width || context.size.width,\n options.searchConfig?.rect?.height || context.size.height,\n options.searchConfig?.rect?.left,\n options.searchConfig?.rect?.top,\n );\n debugInspect('resRect', resRect);\n\n const rectCenter = {\n x: resRect.left + resRect.width / 2,\n y: resRect.top + resRect.height / 2,\n };\n let element = elementByPositionWithElementInfo(context.tree, rectCenter);\n\n const distanceToCenter = element\n ? distance({ x: element.center[0], y: element.center[1] }, rectCenter)\n : 0;\n\n if (!element || distanceToCenter > distanceThreshold) {\n element = insertElementByPosition(rectCenter);\n }\n\n if (element) {\n matchedElements = [element];\n errors = [];\n }\n }\n } catch (e) {\n const msg =\n e instanceof Error\n ? `Failed to parse bbox: ${e.message}`\n : 'unknown error in locate';\n if (!errors || errors?.length === 0) {\n errors = [msg];\n } else {\n errors.push(`(${msg})`);\n }\n }\n\n return {\n rect: resRect,\n parseResult: {\n elements: matchedElements,\n errors,\n },\n rawResponse,\n elementById,\n usage: res.usage,\n };\n}\n\nexport async function AiLocateSection(options: {\n context: UIContext<BaseElement>;\n sectionDescription: string;\n callAI?: typeof callAiFn<AISectionLocatorResponse>;\n}): Promise<{\n rect?: Rect;\n imageBase64?: string;\n error?: string;\n rawResponse: string;\n usage?: AIUsageInfo;\n}> {\n const { context, sectionDescription } = options;\n const { screenshotBase64 } = context;\n\n const systemPrompt = systemPromptToLocateSection(vlLocateMode());\n const sectionLocatorInstructionText = await sectionLocatorInstruction.format({\n sectionDescription,\n });\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: screenshotBase64,\n detail: 'high',\n },\n },\n {\n type: 'text',\n text: sectionLocatorInstructionText,\n },\n ],\n },\n ];\n\n const result = await callAiFn<AISectionLocatorResponse>(\n msgs,\n AIActionType.EXTRACT_DATA,\n );\n\n let sectionRect: Rect | undefined;\n const sectionBbox = result.content.bbox;\n if (sectionBbox) {\n const targetRect = adaptBboxToRect(\n sectionBbox,\n context.size.width,\n context.size.height,\n );\n debugSection('original targetRect %j', targetRect);\n\n const referenceBboxList = result.content.references_bbox || [];\n debugSection('referenceBboxList %j', referenceBboxList);\n\n const referenceRects = referenceBboxList\n .filter((bbox) => Array.isArray(bbox))\n .map((bbox) => {\n return adaptBboxToRect(bbox, context.size.width, context.size.height);\n });\n debugSection('referenceRects %j', referenceRects);\n\n // merge the sectionRect and referenceRects\n const mergedRect = mergeRects([targetRect, ...referenceRects]);\n debugSection('mergedRect %j', mergedRect);\n\n // expand search area to at least 200 x 200\n sectionRect = expandSearchArea(mergedRect, context.size);\n debugSection('expanded sectionRect %j', sectionRect);\n }\n\n let imageBase64 = screenshotBase64;\n if (sectionRect) {\n imageBase64 = await cropByRect(\n screenshotBase64,\n sectionRect,\n getAIConfigInBoolean(MIDSCENE_USE_QWEN_VL),\n );\n }\n\n return {\n rect: sectionRect,\n imageBase64,\n error: result.content.error,\n rawResponse: JSON.stringify(result.content),\n usage: result.usage,\n };\n}\n\nexport async function AiExtractElementInfo<\n T,\n ElementType extends BaseElement = BaseElement,\n>(options: {\n dataQuery: string | Record<string, string>;\n context: UIContext<ElementType>;\n}) {\n const { dataQuery, context } = options;\n const systemPrompt = systemPromptToExtract();\n\n const { screenshotBase64 } = context;\n const { description, elementById } = await describeUserPage(\n context,\n liteContextConfig,\n );\n\n let dataKeys = '';\n let dataQueryText = '';\n if (typeof dataQuery === 'string') {\n dataKeys = '';\n dataQueryText = dataQuery;\n } else {\n dataKeys = `return in key-value style object, keys are ${Object.keys(dataQuery).join(',')}`;\n dataQueryText = JSON.stringify(dataQuery, null, 2);\n }\n const extractDataPromptText = await extractDataPrompt.format({\n pageDescription: description,\n dataKeys,\n dataQuery: dataQueryText,\n });\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: screenshotBase64,\n detail: 'high',\n },\n },\n {\n type: 'text',\n text: extractDataPromptText,\n },\n ],\n },\n ];\n\n const result = await callAiFn<AIDataExtractionResponse<T>>(\n msgs,\n AIActionType.EXTRACT_DATA,\n );\n return {\n parseResult: result.content,\n elementById,\n usage: result.usage,\n };\n}\n\nexport async function AiAssert<\n ElementType extends BaseElement = BaseElement,\n>(options: { assertion: string; context: UIContext<ElementType> }) {\n const { assertion, context } = options;\n\n assert(assertion, 'assertion should be a string');\n\n const { screenshotBase64 } = context;\n\n const systemPrompt = systemPromptToAssert({\n isUITars: getAIConfigInBoolean(MIDSCENE_USE_VLM_UI_TARS),\n });\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: screenshotBase64,\n detail: 'high',\n },\n },\n {\n type: 'text',\n text: `\nHere is the assertion. Please tell whether it is truthy according to the screenshot.\n=====================================\n${assertion}\n=====================================\n `,\n },\n ],\n },\n ];\n\n const { content: assertResult, usage } = await callAiFn<AIAssertionResponse>(\n msgs,\n AIActionType.ASSERT,\n );\n return {\n content: assertResult,\n usage,\n };\n}\n","import { PromptTemplate } from '@langchain/core/prompts';\nimport type { ResponseFormatJSONSchema } from 'openai/resources';\n\nexport function systemPromptToExtract() {\n return `\nYou are a versatile professional in software UI design and testing. Your outstanding contributions will impact the user experience of billions of users.\n\nThe user will give you a screenshot, the contents of it (optional), and some data requirements in DATA_DEMAND. You need to extract the data according to the DATA_DEMAND.\n\nReturn in the following JSON format:\n{\n data: any, // the extracted data. Make sure both the value and scheme meet the DATA_DEMAND. If you want to write some description in this field, use the same language as the DATA_DEMAND.\n errors: [], // string[], error message if any\n}\n`;\n}\n\nexport const extractDataPrompt = new PromptTemplate({\n template: `\npageDescription: {pageDescription}\n\nExtract the following data and place it in the \\`data\\` field. If a key specifies a JSON data type (such as Number, String, Boolean, Object, Array), ensure the returned value strictly matches that data type.\nDATA_DEMAND start:\n=====================================\n{dataKeys}\n\n{dataQuery}\n=====================================\nDATA_DEMAND ends.\n `,\n inputVariables: ['pageDescription', 'dataKeys', 'dataQuery'],\n});\n\nexport const extractDataSchema: ResponseFormatJSONSchema = {\n type: 'json_schema',\n json_schema: {\n name: 'extract_data',\n strict: true,\n schema: {\n type: 'object',\n properties: {\n data: {\n type: 'object',\n description: 'The extracted data',\n },\n errors: {\n type: 'array',\n items: {\n type: 'string',\n },\n description: 'Error messages, if any',\n },\n },\n required: ['data', 'errors'],\n additionalProperties: false,\n },\n },\n};\n","import { PromptTemplate } from '@langchain/core/prompts';\nimport type { vlLocateMode } from '@midscene/shared/env';\nimport { bboxDescription } from './common';\n\nexport function systemPromptToLocateSection(\n vlMode: ReturnType<typeof vlLocateMode>,\n) {\n return `\nYou goal is to find out one section containing the target element in the screenshot, put it in the \\`bbox\\` field. If the user describe the target element with some reference elements, you should also find the section containing the reference elements, put it in the \\`references_bbox\\` field.\n\nUsually, it should be approximately an area not more than 300x300px. Changes of the size are allowed if there are many elements to cover.\n\nreturn in this JSON format:\n\\`\\`\\`json\n{\n \"bbox\": [number, number, number, number],\n \"references_bbox\"?: [\n [number, number, number, number],\n [number, number, number, number],\n ...\n ],\n \"error\"?: string\n}\n\\`\\`\\`\n\nIn which, all the numbers in the \\`bbox\\` and \\`references_bbox\\` represent ${bboxDescription(vlMode)}.\n\nFor example, if the user describe the target element as \"the delete button on the second row with title 'Peter'\", you should put the bounding box of the delete button in the \\`bbox\\` field, and the bounding box of the second row in the \\`references_bbox\\` field.\n\nthe return value should be like this:\n\\`\\`\\`json\n{\n \"bbox\": [100, 100, 200, 200],\n \"references_bbox\": [[100, 100, 200, 200]]\n}\n\\`\\`\\`\n`;\n}\n\nexport const sectionLocatorInstruction = new PromptTemplate({\n template: `Here is the target element user interested in:\n<targetDescription>\n{sectionDescription}\n</targetDescription>\n `,\n inputVariables: ['sectionDescription'],\n});\n","import type { PageType, PlanningAIResponse, UIContext } from '@/types';\nimport { vlLocateMode } from '@midscene/shared/env';\nimport { paddingToMatchBlockByBase64 } from '@midscene/shared/img';\nimport { assert } from '@midscene/shared/utils';\nimport {\n AIActionType,\n type AIArgs,\n buildYamlFlowFromPlans,\n callAiFn,\n fillBboxParam,\n markupImageForLLM,\n warnGPT4oSizeLimit,\n} from './common';\nimport {\n automationUserPrompt,\n generateTaskBackgroundContext,\n systemPromptToTaskPlanning,\n} from './prompt/llm-planning';\nimport { describeUserPage } from './prompt/util';\n\nexport async function plan(\n userInstruction: string,\n opts: {\n context: UIContext;\n pageType: PageType;\n callAI?: typeof callAiFn<PlanningAIResponse>;\n log?: string;\n actionContext?: string;\n },\n): Promise<PlanningAIResponse> {\n const { callAI, context } = opts || {};\n const { screenshotBase64, size } = context;\n const { description: pageDescription, elementById } =\n await describeUserPage(context);\n\n const systemPrompt = await systemPromptToTaskPlanning({\n pageType: opts.pageType,\n vlMode: vlLocateMode(),\n });\n const taskBackgroundContextText = generateTaskBackgroundContext(\n userInstruction,\n opts.log,\n opts.actionContext,\n );\n const userInstructionPrompt = await automationUserPrompt(\n vlLocateMode(),\n ).format({\n pageDescription,\n taskBackgroundContext: taskBackgroundContextText,\n });\n\n let imagePayload = screenshotBase64;\n if (vlLocateMode() === 'qwen-vl') {\n imagePayload = await paddingToMatchBlockByBase64(imagePayload);\n } else if (!vlLocateMode()) {\n imagePayload = await markupImageForLLM(\n screenshotBase64,\n context.tree,\n context.size,\n );\n }\n\n warnGPT4oSizeLimit(size);\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: {\n url: imagePayload,\n detail: 'high',\n },\n },\n {\n type: 'text',\n text: userInstructionPrompt,\n },\n ],\n },\n ];\n\n const call = callAI || callAiFn;\n const { content, usage } = await call(msgs, AIActionType.PLAN);\n const rawResponse = JSON.stringify(content, undefined, 2);\n const planFromAI = content;\n\n const actions =\n (planFromAI.action?.type ? [planFromAI.action] : planFromAI.actions) || [];\n const returnValue: PlanningAIResponse = {\n ...planFromAI,\n actions,\n rawResponse,\n usage,\n yamlFlow: buildYamlFlowFromPlans(actions, planFromAI.sleep),\n };\n\n assert(planFromAI, \"can't get plans from AI\");\n\n if (vlLocateMode()) {\n actions.forEach((action) => {\n if (action.locate) {\n try {\n action.locate = fillBboxParam(action.locate, size.width, size.height);\n } catch (e) {\n throw new Error(\n `Failed to fill locate param: ${planFromAI.error} (${\n e instanceof Error ? e.message : 'unknown error'\n })`,\n {\n cause: e,\n },\n );\n }\n }\n });\n // in Qwen-VL, error means error. In GPT-4o, error may mean more actions are needed.\n assert(!planFromAI.error, `Failed to plan actions: ${planFromAI.error}`);\n } else {\n actions.forEach((action) => {\n if (action.locate?.id) {\n // The model may return indexId, need to perform a query correction to avoid exceptions\n const element = elementById(action.locate.id);\n if (element) {\n action.locate.id = element.id;\n }\n }\n });\n }\n\n if (\n actions.length === 0 &&\n returnValue.more_actions_needed_by_instruction &&\n !returnValue.sleep\n ) {\n console.warn(\n 'No actions planned for the prompt, but model said more actions are needed:',\n userInstruction,\n );\n }\n\n return returnValue;\n}\n","import type { MidsceneYamlFlowItem, PlanningAction, Size } from '@/types';\nimport {\n UITarsModelVersion,\n uiTarsModelVersion,\n vlLocateMode,\n} from '@midscene/shared/env';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport { transformHotkeyInput } from '@midscene/shared/keyboard-layout';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { actionParser } from '@ui-tars/action-parser';\nimport type { ChatCompletionMessageParam } from 'openai/resources';\nimport { AIActionType, buildYamlFlowFromPlans } from './common';\nimport { getSummary, getUiTarsPlanningPrompt } from './prompt/ui-tars-planning';\nimport { call } from './service-caller/index';\ntype ActionType =\n | 'click'\n | 'drag'\n | 'type'\n | 'hotkey'\n | 'finished'\n | 'scroll'\n | 'wait'\n | 'androidBackButton'\n | 'androidHomeButton'\n | 'androidRecentAppsButton';\n\nconst debug = getDebug('ui-tars-planning');\nconst bboxSize = 10;\nconst pointToBbox = (\n point: { x: number; y: number },\n width: number,\n height: number,\n): [number, number, number, number] => {\n return [\n Math.round(Math.max(point.x - bboxSize / 2, 0)),\n Math.round(Math.max(point.y - bboxSize / 2, 0)),\n Math.round(Math.min(point.x + bboxSize / 2, width)),\n Math.round(Math.min(point.y + bboxSize / 2, height)),\n ];\n};\n\nexport async function vlmPlanning(options: {\n userInstruction: string;\n conversationHistory: ChatCompletionMessageParam[];\n size: { width: number; height: number };\n}): Promise<{\n actions: PlanningAction<any>[];\n actionsFromModel: ReturnType<typeof actionParser>['parsed'];\n action_summary: string;\n yamlFlow: MidsceneYamlFlowItem[];\n}> {\n const { conversationHistory, userInstruction, size } = options;\n const systemPrompt = getUiTarsPlanningPrompt() + userInstruction;\n\n const res = await call(\n [\n {\n role: 'user',\n content: systemPrompt,\n },\n ...conversationHistory,\n ],\n AIActionType.INSPECT_ELEMENT,\n );\n const convertedText = convertBboxToCoordinates(res.content);\n\n const modelVer = uiTarsModelVersion();\n\n const { parsed } = actionParser({\n prediction: convertedText,\n factor: [1000, 1000],\n screenContext: {\n width: size.width,\n height: size.height,\n },\n modelVer: modelVer || undefined,\n });\n\n debug('modelVer', modelVer, 'parsed', JSON.stringify(parsed));\n\n const transformActions: PlanningAction[] = [];\n parsed.forEach((action) => {\n if (action.action_type === 'click') {\n assert(action.action_inputs.start_box, 'start_box is required');\n const point = getPoint(action.action_inputs.start_box, size);\n transformActions.push({\n type: 'Locate',\n param: {},\n locate: {\n prompt: action.thought || '',\n bbox: pointToBbox(\n { x: point[0], y: point[1] },\n size.width,\n size.height,\n ),\n },\n });\n transformActions.push({\n type: 'Tap',\n locate: {\n prompt: action.thought || '',\n bbox: pointToBbox(\n { x: point[0], y: point[1] },\n size.width,\n size.height,\n ),\n },\n param: action.thought || '',\n });\n } else if (action.action_type === 'drag') {\n assert(action.action_inputs.start_box, 'start_box is required');\n assert(action.action_inputs.end_box, 'end_box is required');\n const startPoint = getPoint(action.action_inputs.start_box, size);\n const endPoint = getPoint(action.action_inputs.end_box, size);\n transformActions.push({\n type: 'Drag',\n param: {\n start_box: { x: startPoint[0], y: startPoint[1] },\n end_box: { x: endPoint[0], y: endPoint[1] },\n },\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'type') {\n transformActions.push({\n type: 'Input',\n param: {\n value: action.action_inputs.content,\n },\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'scroll') {\n transformActions.push({\n type: 'Scroll',\n param: {\n direction: action.action_inputs.direction,\n },\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'finished') {\n transformActions.push({\n type: 'Finished',\n param: {},\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'hotkey') {\n if (!action.action_inputs.key) {\n console.warn(\n 'No key found in action: hotkey. Will not perform action.',\n );\n } else {\n const keys = transformHotkeyInput(action.action_inputs.key);\n\n transformActions.push({\n type: 'KeyboardPress',\n param: {\n value: keys,\n },\n locate: null,\n thought: action.thought || '',\n });\n }\n } else if (action.action_type === 'wait') {\n transformActions.push({\n type: 'Sleep',\n param: {\n timeMs: 1000,\n },\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'androidBackButton') {\n transformActions.push({\n type: 'AndroidBackButton',\n param: {},\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'androidHomeButton') {\n transformActions.push({\n type: 'AndroidHomeButton',\n param: {},\n locate: null,\n thought: action.thought || '',\n });\n } else if (action.action_type === 'androidRecentAppsButton') {\n transformActions.push({\n type: 'AndroidRecentAppsButton',\n param: {},\n });\n }\n });\n\n if (transformActions.length === 0) {\n throw new Error(`No actions found, response: ${res.content}`, {\n cause: {\n prediction: res.content,\n parsed,\n },\n });\n }\n\n return {\n actions: transformActions,\n actionsFromModel: parsed,\n action_summary: getSummary(res.content),\n yamlFlow: buildYamlFlowFromPlans(transformActions),\n };\n}\n\n/**\n * Converts bounding box notation to coordinate points\n * @param text - The text containing bbox tags to be converted\n * @returns The text with bbox tags replaced by coordinate points\n */\nfunction convertBboxToCoordinates(text: string): string {\n // Match the four numbers after <bbox>\n const pattern = /<bbox>(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)<\\/bbox>/g;\n\n function replaceMatch(\n match: string,\n x1: string,\n y1: string,\n x2: string,\n y2: string,\n ): string {\n // Convert strings to numbers and calculate center point\n const x1Num = Number.parseInt(x1, 10);\n const y1Num = Number.parseInt(y1, 10);\n const x2Num = Number.parseInt(x2, 10);\n const y2Num = Number.parseInt(y2, 10);\n\n // Use Math.floor to truncate and calculate center point\n const x = Math.floor((x1Num + x2Num) / 2);\n const y = Math.floor((y1Num + y2Num) / 2);\n\n // Return formatted coordinate string\n return `(${x},${y})`;\n }\n\n // Remove [EOS] and replace <bbox> coordinates\n const cleanedText = text.replace(/\\[EOS\\]/g, '');\n return cleanedText.replace(pattern, replaceMatch).trim();\n}\n\nfunction getPoint(startBox: string, size: { width: number; height: number }) {\n const [x, y] = JSON.parse(startBox);\n return [x * size.width, y * size.height];\n}\n\ninterface BaseAction {\n action_type: ActionType;\n action_inputs: Record<string, any>;\n reflection: string | null;\n thought: string | null;\n}\n\ninterface ClickAction extends BaseAction {\n action_type: 'click';\n action_inputs: {\n start_box: string; // JSON string of [x, y] coordinates\n };\n}\n\ninterface DragAction extends BaseAction {\n action_type: 'drag';\n action_inputs: {\n start_box: string; // JSON string of [x, y] coordinates\n end_box: string; // JSON string of [x, y] coordinates\n };\n}\n\ninterface WaitAction extends BaseAction {\n action_type: 'wait';\n action_inputs: {\n time: string; // JSON string of [x, y] coordinates\n };\n}\n\ninterface TypeAction extends BaseAction {\n action_type: 'type';\n action_inputs: {\n content: string;\n };\n}\n\ninterface HotkeyAction extends BaseAction {\n action_type: 'hotkey';\n action_inputs: {\n key: string;\n };\n}\n\ninterface ScrollAction extends BaseAction {\n action_type: 'scroll';\n action_inputs: {\n direction: 'up' | 'down';\n };\n}\n\ninterface FinishedAction extends BaseAction {\n action_type: 'finished';\n action_inputs: Record<string, never>;\n}\n\nexport type Action =\n | ClickAction\n | DragAction\n | TypeAction\n | HotkeyAction\n | ScrollAction\n | FinishedAction\n | WaitAction;\n\nexport async function resizeImageForUiTars(imageBase64: string, size: Size) {\n if (\n vlLocateMode() === 'vlm-ui-tars' &&\n uiTarsModelVersion() === UITarsModelVersion.V1_5\n ) {\n debug('ui-tars-v1.5, will check image size', size);\n const currentPixels = size.width * size.height;\n const maxPixels = 16384 * 28 * 28; //\n if (currentPixels > maxPixels) {\n const resizeFactor = Math.sqrt(maxPixels / currentPixels);\n const newWidth = Math.floor(size.width * resizeFactor);\n const newHeight = Math.floor(size.height * resizeFactor);\n debug(\n 'resize image for ui-tars, new width: %s, new height: %s',\n newWidth,\n newHeight,\n );\n const resizedImage = await resizeImgBase64(imageBase64, {\n width: newWidth,\n height: newHeight,\n });\n return resizedImage;\n }\n }\n return imageBase64;\n}\n"]}
package/dist/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkTOTKWQNQjs = require('./chunk-TOTKWQNQ.js');
3
+ var _chunkPGXQSLSPjs = require('./chunk-PGXQSLSP.js');
4
4
 
5
5
 
6
6
 
@@ -9,7 +9,7 @@ var _chunkTOTKWQNQjs = require('./chunk-TOTKWQNQ.js');
9
9
 
10
10
 
11
11
 
12
- var _chunkH3B2KXXRjs = require('./chunk-H3B2KXXR.js');
12
+ var _chunkUINI5TFUjs = require('./chunk-UINI5TFU.js');
13
13
 
14
14
  // src/ai-model/action-executor.ts
15
15
  var _env = require('@midscene/shared/env');
@@ -156,7 +156,7 @@ ${_optionalChain([this, 'access', _7 => _7.latestErrorTask, 'call', _8 => _8(),
156
156
  }
157
157
  dump() {
158
158
  const dumpData = {
159
- sdkVersion: _chunkTOTKWQNQjs.getVersion.call(void 0, ),
159
+ sdkVersion: _chunkPGXQSLSPjs.getVersion.call(void 0, ),
160
160
  model_name: _env.getAIConfig.call(void 0, _env.MIDSCENE_MODEL_NAME) || "",
161
161
  logTime: Date.now(),
162
162
  name: this.name,
@@ -194,7 +194,7 @@ function emitInsightDump(data, dumpSubscriber) {
194
194
  }
195
195
  }
196
196
  const baseData = {
197
- sdkVersion: _chunkTOTKWQNQjs.getVersion.call(void 0, ),
197
+ sdkVersion: _chunkPGXQSLSPjs.getVersion.call(void 0, ),
198
198
  logTime: Date.now(),
199
199
  model_name: _env.getAIConfig.call(void 0, _env.MIDSCENE_MODEL_NAME) || "",
200
200
  model_description: modelDescription
@@ -211,7 +211,7 @@ function emitInsightDump(data, dumpSubscriber) {
211
211
  var debug = _logger.getDebug.call(void 0, "ai:insight");
212
212
  var Insight = class {
213
213
  constructor(context, opt) {
214
- this.aiVendorFn = _chunkH3B2KXXRjs.callAiFn;
214
+ this.aiVendorFn = _chunkUINI5TFUjs.callAiFn;
215
215
  _utils.assert.call(void 0, context, "context is required for Insight");
216
216
  if (typeof context === "function") {
217
217
  this.contextRetrieverFn = context;
@@ -254,7 +254,7 @@ var Insight = class {
254
254
  let searchAreaUsage = void 0;
255
255
  let searchAreaResponse = void 0;
256
256
  if (searchAreaPrompt) {
257
- searchAreaResponse = await _chunkH3B2KXXRjs.AiLocateSection.call(void 0, {
257
+ searchAreaResponse = await _chunkUINI5TFUjs.AiLocateSection.call(void 0, {
258
258
  context,
259
259
  sectionDescription: searchAreaPrompt
260
260
  });
@@ -267,7 +267,7 @@ var Insight = class {
267
267
  searchArea = searchAreaResponse.rect;
268
268
  }
269
269
  const startTime = Date.now();
270
- const { parseResult, rect, elementById, rawResponse, usage } = await _chunkH3B2KXXRjs.AiLocateElement.call(void 0, {
270
+ const { parseResult, rect, elementById, rawResponse, usage } = await _chunkUINI5TFUjs.AiLocateElement.call(void 0, {
271
271
  callAI: callAI || this.aiVendorFn,
272
272
  context,
273
273
  targetElementDescription: queryPrompt,
@@ -355,7 +355,7 @@ ${parseResult.errors.join("\n")}`;
355
355
  this.onceDumpUpdatedFn = void 0;
356
356
  const context = await this.contextRetrieverFn("extract");
357
357
  const startTime = Date.now();
358
- const { parseResult, usage } = await _chunkH3B2KXXRjs.AiExtractElementInfo.call(void 0, {
358
+ const { parseResult, usage } = await _chunkUINI5TFUjs.AiExtractElementInfo.call(void 0, {
359
359
  context,
360
360
  dataQuery: dataDemand
361
361
  });
@@ -406,7 +406,7 @@ ${parseResult.errors.join("\n")}`;
406
406
  this.onceDumpUpdatedFn = void 0;
407
407
  const context = await this.contextRetrieverFn("assert");
408
408
  const startTime = Date.now();
409
- const assertResult = await _chunkH3B2KXXRjs.AiAssert.call(void 0, {
409
+ const assertResult = await _chunkUINI5TFUjs.AiAssert.call(void 0, {
410
410
  assertion,
411
411
  context
412
412
  });
@@ -452,6 +452,6 @@ var src_default = Insight;
452
452
 
453
453
 
454
454
 
455
- exports.AiAssert = _chunkH3B2KXXRjs.AiAssert; exports.AiLocateElement = _chunkH3B2KXXRjs.AiLocateElement; exports.Executor = Executor; exports.Insight = Insight; exports.MIDSCENE_MODEL_NAME = _env.MIDSCENE_MODEL_NAME; exports.default = src_default; exports.describeUserPage = _chunkH3B2KXXRjs.describeUserPage; exports.getAIConfig = _env.getAIConfig; exports.getVersion = _chunkTOTKWQNQjs.getVersion; exports.plan = _chunkH3B2KXXRjs.plan;
455
+ exports.AiAssert = _chunkUINI5TFUjs.AiAssert; exports.AiLocateElement = _chunkUINI5TFUjs.AiLocateElement; exports.Executor = Executor; exports.Insight = Insight; exports.MIDSCENE_MODEL_NAME = _env.MIDSCENE_MODEL_NAME; exports.default = src_default; exports.describeUserPage = _chunkUINI5TFUjs.describeUserPage; exports.getAIConfig = _env.getAIConfig; exports.getVersion = _chunkPGXQSLSPjs.getVersion; exports.plan = _chunkUINI5TFUjs.plan;
456
456
 
457
457
  //# sourceMappingURL=index.js.map
package/dist/lib/utils.js CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
 
15
15
 
16
- var _chunkTOTKWQNQjs = require('./chunk-TOTKWQNQ.js');
16
+ var _chunkPGXQSLSPjs = require('./chunk-PGXQSLSP.js');
17
17
 
18
18
 
19
19
 
@@ -29,4 +29,4 @@ var _chunkTOTKWQNQjs = require('./chunk-TOTKWQNQ.js');
29
29
 
30
30
 
31
31
 
32
- exports.getLogDir = _chunkTOTKWQNQjs.getLogDir; exports.getTmpDir = _chunkTOTKWQNQjs.getTmpDir; exports.getTmpFile = _chunkTOTKWQNQjs.getTmpFile; exports.getVersion = _chunkTOTKWQNQjs.getVersion; exports.groupedActionDumpFileExt = _chunkTOTKWQNQjs.groupedActionDumpFileExt; exports.overlapped = _chunkTOTKWQNQjs.overlapped; exports.replaceStringWithFirstAppearance = _chunkTOTKWQNQjs.replaceStringWithFirstAppearance; exports.replacerForPageObject = _chunkTOTKWQNQjs.replacerForPageObject; exports.reportHTMLContent = _chunkTOTKWQNQjs.reportHTMLContent; exports.sleep = _chunkTOTKWQNQjs.sleep; exports.stringifyDumpData = _chunkTOTKWQNQjs.stringifyDumpData; exports.uploadTestInfoToServer = _chunkTOTKWQNQjs.uploadTestInfoToServer; exports.writeDumpReport = _chunkTOTKWQNQjs.writeDumpReport; exports.writeLogFile = _chunkTOTKWQNQjs.writeLogFile;
32
+ exports.getLogDir = _chunkPGXQSLSPjs.getLogDir; exports.getTmpDir = _chunkPGXQSLSPjs.getTmpDir; exports.getTmpFile = _chunkPGXQSLSPjs.getTmpFile; exports.getVersion = _chunkPGXQSLSPjs.getVersion; exports.groupedActionDumpFileExt = _chunkPGXQSLSPjs.groupedActionDumpFileExt; exports.overlapped = _chunkPGXQSLSPjs.overlapped; exports.replaceStringWithFirstAppearance = _chunkPGXQSLSPjs.replaceStringWithFirstAppearance; exports.replacerForPageObject = _chunkPGXQSLSPjs.replacerForPageObject; exports.reportHTMLContent = _chunkPGXQSLSPjs.reportHTMLContent; exports.sleep = _chunkPGXQSLSPjs.sleep; exports.stringifyDumpData = _chunkPGXQSLSPjs.stringifyDumpData; exports.uploadTestInfoToServer = _chunkPGXQSLSPjs.uploadTestInfoToServer; exports.writeDumpReport = _chunkPGXQSLSPjs.writeDumpReport; exports.writeLogFile = _chunkPGXQSLSPjs.writeLogFile;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@midscene/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": "0.16.11-beta-20250516035357.0",
4
+ "version": "0.16.11-beta-20250516080239.0",
5
5
  "repository": "https://github.com/web-infra-dev/midscene",
6
6
  "homepage": "https://midscenejs.com/",
7
7
  "jsnext:source": "./src/index.ts",
@@ -44,7 +44,7 @@
44
44
  "langsmith": "0.3.7",
45
45
  "openai": "4.81.0",
46
46
  "socks-proxy-agent": "8.0.4",
47
- "@midscene/shared": "0.16.11-beta-20250516035357.0"
47
+ "@midscene/shared": "0.16.11-beta-20250516080239.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@modern-js/module-tools": "2.60.6",