{"version":3,"file":"service/index.mjs","sources":["../../../src/service/index.ts"],"sourcesContent":["import type { ModelRuntime } from '@/ai-model/models';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport {\n  AIResponseParseError,\n  callAIWithObjectResponse,\n} from '@/ai-model/service-caller';\nimport type { AIArgs } from '@/ai-model/service-caller/types';\nimport { defaultModelFamilyRequiredForLocateMessage } from '@/ai-model/shared/model-locate-result/errors';\nimport {\n  AiLocateElement,\n  AiLocateSection,\n  buildSearchAreaConfig,\n} from '@/ai-model/workflows/grounding';\nimport type { SearchAreaConfig } from '@/ai-model/workflows/grounding/types';\nimport { AiExtractElementInfo } from '@/ai-model/workflows/insight';\nimport type {\n  AIDescribeElementResponse,\n  AIUsageInfo,\n  DetailedLocateParam,\n  LocateResultElement,\n  LocateResultWithDump,\n  PartialServiceDumpFromSDK,\n  Rect,\n  ServiceExtractOption,\n  ServiceExtractParam,\n  ServiceExtractResult,\n  ServiceTaskInfo,\n  UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport {\n  compositeElementInfoImg,\n  compositePointMarkerImg,\n  cropByRect,\n  resizeBase64ImageToJpeg,\n} from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { ChatCompletionContentPart } from 'openai/resources/index';\nimport type { TMultimodalPrompt, TUserPrompt } from '../common';\nimport {\n  createServiceDump,\n  getDescribeDeepContextAreas,\n  getDescribeDeepLocateResizeSize,\n  getDescribeMarkerBorderThickness,\n  getDescribeMarkerRect,\n  getRectInCrop,\n  recoverDescribeResponseFromParseError,\n} from './utils';\n\nexport interface LocateOpts {\n  context?: UIContext;\n  planLocatedElement?: LocateResultElement;\n}\n\nexport type AnyValue<T> = {\n  [K in keyof T]: unknown extends T[K] ? any : T[K];\n};\n\ninterface ServiceOptions {\n  taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n}\n\ninterface LocateSearchAreaResult {\n  config?: SearchAreaConfig;\n  error?: string;\n  trace: {\n    sourceRect?: Rect;\n    rawResponse?: string;\n    rawChoiceMessage?: unknown;\n    usage?: AIUsageInfo;\n  };\n}\n\nconst debug = getDebug('ai:service');\n\nexport default class Service {\n  contextRetrieverFn: () => Promise<UIContext> | UIContext;\n\n  taskInfo?: Omit<ServiceTaskInfo, 'durationMs'>;\n\n  constructor(\n    context: UIContext | (() => Promise<UIContext> | UIContext),\n    opt?: ServiceOptions,\n  ) {\n    assert(context, 'context is required for Service');\n    if (typeof context === 'function') {\n      this.contextRetrieverFn = context;\n    } else {\n      this.contextRetrieverFn = () => Promise.resolve(context);\n    }\n\n    if (typeof opt?.taskInfo !== 'undefined') {\n      this.taskInfo = opt.taskInfo;\n    }\n  }\n\n  async locate(\n    query: DetailedLocateParam,\n    opt: LocateOpts,\n    modelRuntime: ModelRuntime,\n    abortSignal?: AbortSignal,\n  ): Promise<LocateResultWithDump> {\n    const { config: modelConfig } = modelRuntime;\n    const queryPrompt = query.prompt;\n    assert(queryPrompt, 'query is required for locate');\n\n    if (!modelConfig.modelFamily) {\n      throw new Error(defaultModelFamilyRequiredForLocateMessage);\n    }\n\n    const context = opt?.context || (await this.contextRetrieverFn());\n\n    const searchAreaStartTime = Date.now();\n    const searchArea = await this.resolveLocateSearchArea({\n      query,\n      queryPrompt,\n      opt,\n      context,\n      modelRuntime,\n      abortSignal,\n    });\n\n    if (!searchArea.config && searchArea.error) {\n      const errorMessage = `cannot find search area for \"${queryPrompt}\": ${searchArea.error}`;\n      const taskInfo: ServiceTaskInfo = {\n        ...(this.taskInfo ? this.taskInfo : {}),\n        durationMs: Date.now() - searchAreaStartTime,\n        searchAreaRawResponse: searchArea.trace.rawResponse,\n        searchAreaRawChoiceMessage: searchArea.trace.rawChoiceMessage,\n        searchAreaUsage: searchArea.trace.usage,\n      };\n      const dump = createServiceDump({\n        type: 'locate',\n        userQuery: { element: queryPrompt },\n        matchedElement: [],\n        data: null,\n        taskInfo,\n        deepLocate: true,\n        error: errorMessage,\n      });\n      throw new ServiceError(errorMessage, dump);\n    }\n\n    const startTime = Date.now();\n    const {\n      parseResult,\n      rect,\n      rawResponse,\n      rawChoiceMessage,\n      usage,\n      reasoning_content,\n    } = await AiLocateElement({\n      context,\n      targetElementDescription: queryPrompt,\n      searchConfig: searchArea.config,\n      modelRuntime,\n      abortSignal,\n    });\n\n    const timeCost = Date.now() - startTime;\n    const taskInfo: ServiceTaskInfo = {\n      ...(this.taskInfo ? this.taskInfo : {}),\n      durationMs: timeCost,\n      rawResponse,\n      rawChoiceMessage,\n      formatResponse: parseResult,\n      usage,\n      searchArea: searchArea.trace.sourceRect,\n      searchAreaRawResponse: searchArea.trace.rawResponse,\n      searchAreaRawChoiceMessage: searchArea.trace.rawChoiceMessage,\n      searchAreaUsage: searchArea.trace.usage,\n      reasoning_content,\n    };\n\n    let errorLog: string | undefined;\n    if (parseResult.errors?.length) {\n      errorLog = `failed to locate element: \\n${parseResult.errors.join('\\n')}`;\n    }\n\n    const dumpData: PartialServiceDumpFromSDK = {\n      type: 'locate',\n      userQuery: {\n        element: queryPrompt,\n      },\n      matchedRect: rect,\n      data: null,\n      taskInfo,\n      deepLocate: !!searchArea.trace.sourceRect,\n      error: errorLog,\n    };\n\n    const element = parseResult.element;\n\n    const dump = createServiceDump({\n      ...dumpData,\n      matchedElement: element ? [element] : [],\n    });\n\n    if (errorLog) {\n      throw new ServiceError(errorLog, dump);\n    }\n\n    if (element) {\n      return {\n        element: {\n          center: element.center,\n          rect: element.rect,\n          description: element.description,\n        },\n        rect,\n        dump,\n      };\n    }\n\n    return {\n      element: null,\n      rect,\n      dump,\n    };\n  }\n\n  private async resolveLocateSearchArea(options: {\n    query: DetailedLocateParam;\n    queryPrompt: TUserPrompt;\n    opt: LocateOpts;\n    context: UIContext;\n    modelRuntime: ModelRuntime;\n    abortSignal?: AbortSignal;\n  }): Promise<LocateSearchAreaResult> {\n    const { query, queryPrompt, opt, context, modelRuntime, abortSignal } =\n      options;\n    const { adapter } = modelRuntime;\n    const hasPlanLocatedElement = !!opt?.planLocatedElement?.rect;\n\n    if (!query.deepLocate) {\n      return { trace: {} };\n    }\n\n    // TODO: Make the plan, section-locate, and element-locate fallback paths\n    // resolve only the source rect, then build the search-area config once in\n    // this orchestration layer instead of building it inside AiLocateSection.\n    if (hasPlanLocatedElement) {\n      const config = await buildSearchAreaConfig({\n        context,\n        baseRect: opt.planLocatedElement!.rect,\n      });\n\n      return {\n        config,\n        trace: {\n          sourceRect: config.sourceRect,\n          rawResponse: JSON.stringify({\n            source: 'plan-located-element',\n            rect: opt.planLocatedElement!.rect,\n          }),\n        },\n      };\n    }\n\n    if (adapter.locate.kind === 'standard' && adapter.locate.searchArea) {\n      const searchAreaResponse = await AiLocateSection({\n        context,\n        sectionDescription: queryPrompt,\n        modelRuntime,\n        abortSignal,\n      });\n      const { searchAreaConfig } = searchAreaResponse;\n      if (!searchAreaConfig) {\n        return {\n          error: searchAreaResponse.error || 'unknown search area error',\n          trace: {\n            rawResponse: searchAreaResponse.rawResponse,\n            rawChoiceMessage: searchAreaResponse.rawChoiceMessage,\n            usage: searchAreaResponse.usage,\n          },\n        };\n      }\n\n      return {\n        config: searchAreaConfig,\n        trace: {\n          sourceRect: searchAreaConfig.sourceRect,\n          rawResponse: searchAreaResponse.rawResponse,\n          rawChoiceMessage: searchAreaResponse.rawChoiceMessage,\n          usage: searchAreaResponse.usage,\n        },\n      };\n    }\n\n    const firstPassLocateResult = await AiLocateElement({\n      context,\n      targetElementDescription: queryPrompt,\n      modelRuntime,\n      abortSignal,\n    });\n    assert(\n      firstPassLocateResult.rect,\n      `cannot find search area for \"${queryPrompt}\"${\n        firstPassLocateResult.parseResult.errors?.length\n          ? `: ${firstPassLocateResult.parseResult.errors.join('\\n')}`\n          : ''\n      }`,\n    );\n\n    const config = await buildSearchAreaConfig({\n      context,\n      baseRect: firstPassLocateResult.rect,\n    });\n\n    return {\n      config,\n      trace: {\n        sourceRect: config.sourceRect,\n        rawResponse: JSON.stringify({\n          source: 'deep-locate-first-pass',\n          rect: firstPassLocateResult.rect,\n          rawResponse: firstPassLocateResult.rawResponse,\n        }),\n        rawChoiceMessage: firstPassLocateResult.rawChoiceMessage,\n        usage: firstPassLocateResult.usage,\n      },\n    };\n  }\n\n  async extract<T>(\n    dataDemand: ServiceExtractParam,\n    modelRuntime: ModelRuntime,\n    opt?: ServiceExtractOption,\n    pageDescription?: string,\n    multimodalPrompt?: TMultimodalPrompt,\n    context?: UIContext,\n    executionOptions?: {\n      abortSignal?: AbortSignal;\n    },\n  ): Promise<ServiceExtractResult<T>> {\n    assert(context, 'context is required for extract');\n    assert(\n      typeof dataDemand === 'object' || typeof dataDemand === 'string',\n      `dataDemand should be object or string, but get ${typeof dataDemand}`,\n    );\n\n    const startTime = Date.now();\n\n    let parseResult: Awaited<\n      ReturnType<typeof AiExtractElementInfo<T>>\n    >['parseResult'];\n    let rawResponse: string;\n    let rawChoiceMessage: unknown;\n    let usage: Awaited<ReturnType<typeof AiExtractElementInfo<T>>>['usage'];\n    let reasoning_content: string | undefined;\n\n    try {\n      const result = await AiExtractElementInfo<T>({\n        context,\n        dataQuery: dataDemand,\n        multimodalPrompt,\n        extractOption: opt,\n        modelRuntime,\n        pageDescription,\n        abortSignal: executionOptions?.abortSignal,\n      });\n      parseResult = result.parseResult;\n      rawResponse = result.rawResponse;\n      rawChoiceMessage = result.rawChoiceMessage;\n      usage = result.usage;\n      reasoning_content = result.reasoning_content;\n    } catch (error) {\n      if (error instanceof AIResponseParseError) {\n        // Create dump with usage and rawResponse from the error\n        const timeCost = Date.now() - startTime;\n        const taskInfo: ServiceTaskInfo = {\n          ...(this.taskInfo ? this.taskInfo : {}),\n          durationMs: timeCost,\n          rawResponse: error.rawResponse,\n          rawChoiceMessage: error.rawChoiceMessage,\n          usage: error.usage,\n        };\n        const dump = createServiceDump({\n          type: 'extract',\n          userQuery: { dataDemand },\n          data: null,\n          taskInfo,\n          error: error.message,\n        });\n        throw new ServiceError(error.message, dump);\n      }\n      throw error;\n    }\n\n    const timeCost = Date.now() - startTime;\n    const taskInfo: ServiceTaskInfo = {\n      ...(this.taskInfo ? this.taskInfo : {}),\n      durationMs: timeCost,\n      rawResponse,\n      rawChoiceMessage,\n      formatResponse: parseResult,\n      usage,\n      reasoning_content,\n    };\n\n    let errorLog: string | undefined;\n    if (parseResult.errors?.length) {\n      errorLog = `AI response error: \\n${parseResult.errors.join('\\n')}`;\n    }\n\n    const dumpData: PartialServiceDumpFromSDK = {\n      type: 'extract',\n      userQuery: {\n        dataDemand,\n      },\n      data: null,\n      taskInfo,\n      error: errorLog,\n    };\n\n    const { data, thought } = parseResult || {};\n\n    const dump = createServiceDump({\n      ...dumpData,\n      data,\n    });\n\n    if (errorLog && !data) {\n      throw new ServiceError(errorLog, dump);\n    }\n\n    return {\n      data,\n      thought,\n      usage,\n      reasoning_content,\n      dump,\n    };\n  }\n\n  async describe(\n    target: Rect | [number, number],\n    modelRuntime: ModelRuntime,\n    opt?: {\n      deepDescribe?: boolean;\n      context?: UIContext;\n    },\n  ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n    assert(target, 'target is required for service.describe');\n    const context = opt?.context || (await this.contextRetrieverFn());\n    const { shotSize } = context;\n    const screenshotBase64 = context.screenshot.base64;\n    assert(screenshotBase64, 'screenshot is required for service.describe');\n    const systemPrompt = elementDescriberInstruction();\n\n    // Convert [x,y] center point to Rect if needed\n    const defaultRectSize = 30;\n    const targetFromPoint = Array.isArray(target);\n    const targetRect: Rect = targetFromPoint\n      ? {\n          left: Math.floor(target[0] - defaultRectSize / 2),\n          top: Math.floor(target[1] - defaultRectSize / 2),\n          width: defaultRectSize,\n          height: defaultRectSize,\n        }\n      : target;\n    const targetPoint = targetFromPoint\n      ? {\n          x: target[0],\n          y: target[1],\n        }\n      : undefined;\n\n    const usePointMarker = targetFromPoint;\n    const imagePayload = usePointMarker\n      ? await compositePointMarkerImg({\n          inputImgBase64: screenshotBase64,\n          size: shotSize,\n          point: targetPoint!,\n        })\n      : await compositeElementInfoImg({\n          inputImgBase64: screenshotBase64,\n          size: shotSize,\n          elementsPositionInfo: [\n            {\n              rect: getDescribeMarkerRect(targetRect),\n            },\n          ],\n          borderThickness: getDescribeMarkerBorderThickness(targetRect),\n          centerPoint: true,\n        });\n\n    const shouldDeepDescribe = opt?.deepDescribe;\n    let imageContent: ChatCompletionContentPart[];\n    if (shouldDeepDescribe) {\n      const contextAreas = getDescribeDeepContextAreas(targetRect, shotSize);\n      const contextImages = await Promise.all(\n        contextAreas.map(async (area) => {\n          debug('describe: cropping deep context area', area);\n          const croppedResult = await cropByRect(screenshotBase64, area.rect);\n          const cropSize = {\n            width: croppedResult.width,\n            height: croppedResult.height,\n          };\n          const targetInCrop = getRectInCrop(targetRect, area.rect, cropSize);\n          const markedCropPayload = targetFromPoint\n            ? await compositePointMarkerImg({\n                inputImgBase64: croppedResult.imageBase64,\n                size: cropSize,\n                point: {\n                  x: targetPoint!.x - area.rect.left,\n                  y: targetPoint!.y - area.rect.top,\n                },\n              })\n            : await compositeElementInfoImg({\n                inputImgBase64: croppedResult.imageBase64,\n                size: cropSize,\n                elementsPositionInfo: [\n                  {\n                    rect: getDescribeMarkerRect(targetInCrop),\n                  },\n                ],\n                borderThickness: getDescribeMarkerBorderThickness(targetInCrop),\n                centerPoint: true,\n              });\n          const resizeSize = getDescribeDeepLocateResizeSize(croppedResult);\n          return {\n            kind: area.kind,\n            imageBase64: resizeSize\n              ? await resizeBase64ImageToJpeg(markedCropPayload, {\n                  sourceSize: cropSize,\n                  targetSize: resizeSize,\n                })\n              : markedCropPayload,\n          };\n        }),\n      );\n      const contextImageContent =\n        contextImages.flatMap<ChatCompletionContentPart>((item, index) => [\n          {\n            type: 'text',\n            text: `Image ${index + 2}: focused detail crop around the target, for reading text, icon shape, and exact local boundaries.`,\n          },\n          {\n            type: 'image_url',\n            image_url: {\n              url: item.imageBase64,\n              detail: 'high',\n            },\n          },\n        ]);\n\n      imageContent = [\n        {\n          type: 'text' as const,\n          text: 'Use these images together to describe the real UI target marked by the temporary callout. Do not describe the marker itself.',\n        },\n        {\n          type: 'text' as const,\n          text: 'Image 1: full screenshot overview with the target marker, for page position and ownership context.',\n        },\n        {\n          type: 'image_url' as const,\n          image_url: {\n            url: imagePayload,\n            detail: 'high',\n          },\n        },\n        ...contextImageContent,\n      ];\n    } else {\n      imageContent = [\n        {\n          type: 'text' as const,\n          text: 'Full screenshot with a temporary callout marking the target:',\n        },\n        {\n          type: 'image_url' as const,\n          image_url: {\n            url: imagePayload,\n            detail: 'high',\n          },\n        },\n      ];\n    }\n\n    const msgs: AIArgs = [\n      { role: 'system', content: systemPrompt },\n      {\n        role: 'user',\n        content: imageContent,\n      },\n    ];\n\n    let res: Awaited<\n      ReturnType<typeof callAIWithObjectResponse<AIDescribeElementResponse>>\n    >;\n    try {\n      res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n        msgs,\n        modelRuntime,\n      );\n    } catch (error) {\n      const recoveredResponse = recoverDescribeResponseFromParseError(error);\n      if (!recoveredResponse) {\n        throw error;\n      }\n      debug('describe: recovered malformed description JSON response');\n      return recoveredResponse;\n    }\n\n    const { content } = res;\n    assert(!content.error, `describe failed: ${content.error}`);\n    assert(content.description, 'failed to describe the element');\n    return content;\n  }\n}\n"],"names":["debug","getDebug","Service","query","opt","modelRuntime","abortSignal","modelConfig","queryPrompt","assert","Error","defaultModelFamilyRequiredForLocateMessage","context","searchAreaStartTime","Date","searchArea","errorMessage","taskInfo","dump","createServiceDump","ServiceError","startTime","parseResult","rect","rawResponse","rawChoiceMessage","usage","reasoning_content","AiLocateElement","timeCost","errorLog","dumpData","element","options","adapter","hasPlanLocatedElement","config","buildSearchAreaConfig","JSON","searchAreaResponse","AiLocateSection","searchAreaConfig","firstPassLocateResult","dataDemand","pageDescription","multimodalPrompt","executionOptions","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetFromPoint","Array","targetRect","Math","targetPoint","undefined","usePointMarker","imagePayload","compositePointMarkerImg","compositeElementInfoImg","getDescribeMarkerRect","getDescribeMarkerBorderThickness","shouldDeepDescribe","imageContent","contextAreas","getDescribeDeepContextAreas","contextImages","Promise","area","croppedResult","cropByRect","cropSize","targetInCrop","getRectInCrop","markedCropPayload","resizeSize","getDescribeDeepLocateResizeSize","resizeBase64ImageToJpeg","contextImageContent","item","index","msgs","res","callAIWithObjectResponse","recoveredResponse","recoverDescribeResponseFromParseError","content"],"mappings":"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"}