{"version":3,"file":"service/index.mjs","sources":["../../../src/service/index.ts"],"sourcesContent":["import { defaultModelFamilyRequiredForLocateMessage } from '@/ai-model/errors';\nimport {\n  AiExtractElementInfo,\n  AiLocateElement,\n  AiLocateSection,\n  buildSearchAreaConfig,\n} from '@/ai-model/inspect';\nimport 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/types';\nimport type { SearchAreaConfig } from '@/ai-model/workflows/inspect/types';\nimport { expandSearchArea } from '@/common';\nimport type {\n  AIDescribeElementResponse,\n  AIUsageInfo,\n  DetailedLocateParam,\n  LocateResultElement,\n  LocateResultWithDump,\n  PartialServiceDumpFromSDK,\n  PlanningLocateParam,\n  Rect,\n  ServiceExtractOption,\n  ServiceExtractParam,\n  ServiceExtractResult,\n  ServiceTaskInfo,\n  UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport { compositeElementInfoImg, cropByRect } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { TMultimodalPrompt, TUserPrompt } from '../common';\nimport {\n  createServiceDump,\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  trace: {\n    sourceRect?: Rect;\n    rawResponse?: string;\n    rawChoiceMessage?: unknown;\n    usage?: AIUsageInfo;\n  };\n}\n\nconst debug = getDebug('ai:service');\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: PlanningLocateParam,\n    opt: LocateOpts,\n    modelRuntime: ModelRuntime,\n    abortSignal?: AbortSignal,\n  ): Promise<LocateResultWithDump> {\n    const { config: modelConfig } = modelRuntime;\n    const queryPrompt = typeof query === 'string' ? query : query.prompt;\n    assert(queryPrompt, 'query is required for locate');\n\n    assert(typeof query === 'object', 'query should be an object 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 searchArea = await this.resolveLocateSearchArea({\n      query,\n      queryPrompt,\n      opt,\n      context,\n      modelRuntime,\n      abortSignal,\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: JSON.stringify(rawResponse),\n      rawChoiceMessage,\n      formatResponse: JSON.stringify(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: PlanningLocateParam;\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    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.supportsSearchArea) {\n      const searchAreaResponse = await AiLocateSection({\n        context,\n        sectionDescription: queryPrompt,\n        modelRuntime,\n        abortSignal,\n      });\n      const { searchAreaConfig } = searchAreaResponse;\n      assert(\n        searchAreaConfig,\n        `cannot find search area for \"${queryPrompt}\"${\n          searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\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: JSON.stringify(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      deepLocate?: 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 targetRect: Rect = Array.isArray(target)\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\n    let imagePayload = await compositeElementInfoImg({\n      inputImgBase64: screenshotBase64,\n      size: shotSize,\n      elementsPositionInfo: [\n        {\n          rect: targetRect,\n        },\n      ],\n      borderThickness: 3,\n    });\n\n    if (opt?.deepLocate) {\n      const searchArea = expandSearchArea(targetRect, shotSize);\n      // Always crop in describe mode. Unlike locate's deepLocate (where\n      // cropping too small loses context for finding elements), describe's\n      // deepLocate intentionally zooms in so the model produces a more\n      // precise description from a focused view. expandSearchArea already\n      // guarantees a minimum 400x400 area with surrounding context.\n      // Describe is not a coordinate-parsing flow, so it does not need image\n      // padding for bbox normalization.\n      debug('describe: cropping to searchArea', searchArea);\n      const croppedResult = await cropByRect(imagePayload, searchArea);\n      imagePayload = croppedResult.imageBase64;\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      },\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","searchArea","startTime","Date","parseResult","rect","rawResponse","rawChoiceMessage","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","JSON","errorLog","dumpData","element","dump","createServiceDump","ServiceError","options","adapter","hasPlanLocatedElement","config","buildSearchAreaConfig","searchAreaResponse","AiLocateSection","searchAreaConfig","firstPassLocateResult","dataDemand","pageDescription","multimodalPrompt","executionOptions","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","msgs","res","callAIWithObjectResponse","recoveredResponse","recoverDescribeResponseFromParseError","content","Promise"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgEA,MAAMA,QAAQC,SAAS;AACR,MAAMC;IAqBnB,MAAM,OACJC,KAA0B,EAC1BC,GAAe,EACfC,YAA0B,EAC1BC,WAAyB,EACM;QAC/B,MAAM,EAAE,QAAQC,WAAW,EAAE,GAAGF;QAChC,MAAMG,cAAc,AAAiB,YAAjB,OAAOL,QAAqBA,QAAQA,MAAM,MAAM;QACpEM,OAAOD,aAAa;QAEpBC,OAAO,AAAiB,YAAjB,OAAON,OAAoB;QAElC,IAAI,CAACI,YAAY,WAAW,EAC1B,MAAM,IAAIG,MAAMC;QAGlB,MAAMC,UAAUR,KAAK,WAAY,MAAM,IAAI,CAAC,kBAAkB;QAE9D,MAAMS,aAAa,MAAM,IAAI,CAAC,uBAAuB,CAAC;YACpDV;YACAK;YACAJ;YACAQ;YACAP;YACAC;QACF;QAEA,MAAMQ,YAAYC,KAAK,GAAG;QAC1B,MAAM,EACJC,WAAW,EACXC,IAAI,EACJC,WAAW,EACXC,gBAAgB,EAChBC,KAAK,EACLC,iBAAiB,EAClB,GAAG,MAAMC,gBAAgB;YACxBV;YACA,0BAA0BJ;YAC1B,cAAcK,WAAW,MAAM;YAC/BR;YACAC;QACF;QAEA,MAAMiB,WAAWR,KAAK,GAAG,KAAKD;QAC9B,MAAMU,WAA4B;YAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACtC,YAAYD;YACZ,aAAaE,KAAK,SAAS,CAACP;YAC5BC;YACA,gBAAgBM,KAAK,SAAS,CAACT;YAC/BI;YACA,YAAYP,WAAW,KAAK,CAAC,UAAU;YACvC,uBAAuBA,WAAW,KAAK,CAAC,WAAW;YACnD,4BAA4BA,WAAW,KAAK,CAAC,gBAAgB;YAC7D,iBAAiBA,WAAW,KAAK,CAAC,KAAK;YACvCQ;QACF;QAEA,IAAIK;QACJ,IAAIV,YAAY,MAAM,EAAE,QACtBU,WAAW,CAAC,4BAA4B,EAAEV,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO;QAG3E,MAAMW,WAAsC;YAC1C,MAAM;YACN,WAAW;gBACT,SAASnB;YACX;YACA,aAAaS;YACb,MAAM;YACNO;YACA,YAAY,CAAC,CAACX,WAAW,KAAK,CAAC,UAAU;YACzC,OAAOa;QACT;QAEA,MAAME,UAAUZ,YAAY,OAAO;QAEnC,MAAMa,OAAOC,kBAAkB;YAC7B,GAAGH,QAAQ;YACX,gBAAgBC,UAAU;gBAACA;aAAQ,GAAG,EAAE;QAC1C;QAEA,IAAIF,UACF,MAAM,IAAIK,aAAaL,UAAUG;QAGnC,IAAID,SACF,OAAO;YACL,SAAS;gBACP,QAAQA,QAAQ,MAAM;gBACtB,MAAMA,QAAQ,IAAI;gBAClB,aAAaA,QAAQ,WAAW;YAClC;YACAX;YACAY;QACF;QAGF,OAAO;YACL,SAAS;YACTZ;YACAY;QACF;IACF;IAEA,MAAc,wBAAwBG,OAOrC,EAAmC;QAClC,MAAM,EAAE7B,KAAK,EAAEK,WAAW,EAAEJ,GAAG,EAAEQ,OAAO,EAAEP,YAAY,EAAEC,WAAW,EAAE,GACnE0B;QACF,MAAM,EAAEC,OAAO,EAAE,GAAG5B;QACpB,MAAM6B,wBAAwB,CAAC,CAAC9B,KAAK,oBAAoB;QAEzD,IAAI,CAACD,MAAM,UAAU,EACnB,OAAO;YAAE,OAAO,CAAC;QAAE;QAGrB,IAAI+B,uBAAuB;YACzB,MAAMC,SAAS,MAAMC,sBAAsB;gBACzCxB;gBACA,UAAUR,IAAI,kBAAkB,CAAE,IAAI;YACxC;YAEA,OAAO;gBACL+B;gBACA,OAAO;oBACL,YAAYA,OAAO,UAAU;oBAC7B,aAAaV,KAAK,SAAS,CAAC;wBAC1B,QAAQ;wBACR,MAAMrB,IAAI,kBAAkB,CAAE,IAAI;oBACpC;gBACF;YACF;QACF;QAEA,IAAI6B,QAAQ,MAAM,CAAC,kBAAkB,EAAE;YACrC,MAAMI,qBAAqB,MAAMC,gBAAgB;gBAC/C1B;gBACA,oBAAoBJ;gBACpBH;gBACAC;YACF;YACA,MAAM,EAAEiC,gBAAgB,EAAE,GAAGF;YAC7B5B,OACE8B,kBACA,CAAC,6BAA6B,EAAE/B,YAAY,CAAC,EAC3C6B,mBAAmB,KAAK,GAAG,CAAC,EAAE,EAAEA,mBAAmB,KAAK,EAAE,GAAG,IAC7D;YAGJ,OAAO;gBACL,QAAQE;gBACR,OAAO;oBACL,YAAYA,iBAAiB,UAAU;oBACvC,aAAaF,mBAAmB,WAAW;oBAC3C,kBAAkBA,mBAAmB,gBAAgB;oBACrD,OAAOA,mBAAmB,KAAK;gBACjC;YACF;QACF;QAEA,MAAMG,wBAAwB,MAAMlB,gBAAgB;YAClDV;YACA,0BAA0BJ;YAC1BH;YACAC;QACF;QACAG,OACE+B,sBAAsB,IAAI,EAC1B,CAAC,6BAA6B,EAAEhC,YAAY,CAAC,EAC3CgC,sBAAsB,WAAW,CAAC,MAAM,EAAE,SACtC,CAAC,EAAE,EAAEA,sBAAsB,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,GAC1D,IACJ;QAGJ,MAAML,SAAS,MAAMC,sBAAsB;YACzCxB;YACA,UAAU4B,sBAAsB,IAAI;QACtC;QAEA,OAAO;YACLL;YACA,OAAO;gBACL,YAAYA,OAAO,UAAU;gBAC7B,aAAaV,KAAK,SAAS,CAAC;oBAC1B,QAAQ;oBACR,MAAMe,sBAAsB,IAAI;oBAChC,aAAaA,sBAAsB,WAAW;gBAChD;gBACA,kBAAkBA,sBAAsB,gBAAgB;gBACxD,OAAOA,sBAAsB,KAAK;YACpC;QACF;IACF;IAEA,MAAM,QACJC,UAA+B,EAC/BpC,YAA0B,EAC1BD,GAA0B,EAC1BsC,eAAwB,EACxBC,gBAAoC,EACpC/B,OAAmB,EACnBgC,gBAEC,EACiC;QAClCnC,OAAOG,SAAS;QAChBH,OACE,AAAsB,YAAtB,OAAOgC,cAA2B,AAAsB,YAAtB,OAAOA,YACzC,CAAC,+CAA+C,EAAE,OAAOA,YAAY;QAGvE,MAAM3B,YAAYC,KAAK,GAAG;QAE1B,IAAIC;QAGJ,IAAIE;QACJ,IAAIC;QACJ,IAAIC;QACJ,IAAIC;QAEJ,IAAI;YACF,MAAMwB,SAAS,MAAMC,qBAAwB;gBAC3ClC;gBACA,WAAW6B;gBACXE;gBACA,eAAevC;gBACfC;gBACAqC;gBACA,aAAaE,kBAAkB;YACjC;YACA5B,cAAc6B,OAAO,WAAW;YAChC3B,cAAc2B,OAAO,WAAW;YAChC1B,mBAAmB0B,OAAO,gBAAgB;YAC1CzB,QAAQyB,OAAO,KAAK;YACpBxB,oBAAoBwB,OAAO,iBAAiB;QAC9C,EAAE,OAAOE,OAAO;YACd,IAAIA,iBAAiBC,sBAAsB;gBAEzC,MAAMzB,WAAWR,KAAK,GAAG,KAAKD;gBAC9B,MAAMU,WAA4B;oBAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;oBACtC,YAAYD;oBACZ,aAAawB,MAAM,WAAW;oBAC9B,kBAAkBA,MAAM,gBAAgB;oBACxC,OAAOA,MAAM,KAAK;gBACpB;gBACA,MAAMlB,OAAOC,kBAAkB;oBAC7B,MAAM;oBACN,WAAW;wBAAEW;oBAAW;oBACxB,MAAM;oBACNjB;oBACA,OAAOuB,MAAM,OAAO;gBACtB;gBACA,MAAM,IAAIhB,aAAagB,MAAM,OAAO,EAAElB;YACxC;YACA,MAAMkB;QACR;QAEA,MAAMxB,WAAWR,KAAK,GAAG,KAAKD;QAC9B,MAAMU,WAA4B;YAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACtC,YAAYD;YACZL;YACAC;YACA,gBAAgBM,KAAK,SAAS,CAACT;YAC/BI;YACAC;QACF;QAEA,IAAIK;QACJ,IAAIV,YAAY,MAAM,EAAE,QACtBU,WAAW,CAAC,qBAAqB,EAAEV,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO;QAGpE,MAAMW,WAAsC;YAC1C,MAAM;YACN,WAAW;gBACTc;YACF;YACA,MAAM;YACNjB;YACA,OAAOE;QACT;QAEA,MAAM,EAAEuB,IAAI,EAAEC,OAAO,EAAE,GAAGlC,eAAe,CAAC;QAE1C,MAAMa,OAAOC,kBAAkB;YAC7B,GAAGH,QAAQ;YACXsB;QACF;QAEA,IAAIvB,YAAY,CAACuB,MACf,MAAM,IAAIlB,aAAaL,UAAUG;QAGnC,OAAO;YACLoB;YACAC;YACA9B;YACAC;YACAQ;QACF;IACF;IAEA,MAAM,SACJsB,MAA+B,EAC/B9C,YAA0B,EAC1BD,GAGC,EACwD;QACzDK,OAAO0C,QAAQ;QACf,MAAMvC,UAAUR,KAAK,WAAY,MAAM,IAAI,CAAC,kBAAkB;QAC9D,MAAM,EAAEgD,QAAQ,EAAE,GAAGxC;QACrB,MAAMyC,mBAAmBzC,QAAQ,UAAU,CAAC,MAAM;QAClDH,OAAO4C,kBAAkB;QACzB,MAAMC,eAAeC;QAGrB,MAAMC,kBAAkB;QACxB,MAAMC,aAAmBC,MAAM,OAAO,CAACP,UACnC;YACE,MAAMQ,KAAK,KAAK,CAACR,MAAM,CAAC,EAAE,GAAGK,kBAAkB;YAC/C,KAAKG,KAAK,KAAK,CAACR,MAAM,CAAC,EAAE,GAAGK,kBAAkB;YAC9C,OAAOA;YACP,QAAQA;QACV,IACAL;QAEJ,IAAIS,eAAe,MAAMC,wBAAwB;YAC/C,gBAAgBR;YAChB,MAAMD;YACN,sBAAsB;gBACpB;oBACE,MAAMK;gBACR;aACD;YACD,iBAAiB;QACnB;QAEA,IAAIrD,KAAK,YAAY;YACnB,MAAMS,aAAaiD,iBAAiBL,YAAYL;YAQhDpD,MAAM,oCAAoCa;YAC1C,MAAMkD,gBAAgB,MAAMC,WAAWJ,cAAc/C;YACrD+C,eAAeG,cAAc,WAAW;QAC1C;QAEA,MAAME,OAAe;YACnB;gBAAE,MAAM;gBAAU,SAASX;YAAa;YACxC;gBACE,MAAM;gBACN,SAAS;oBACP;wBACE,MAAM;wBACN,WAAW;4BACT,KAAKM;4BACL,QAAQ;wBACV;oBACF;iBACD;YACH;SACD;QAED,IAAIM;QAGJ,IAAI;YACFA,MAAM,MAAMC,yBACVF,MACA5D;QAEJ,EAAE,OAAO0C,OAAO;YACd,MAAMqB,oBAAoBC,sCAAsCtB;YAChE,IAAI,CAACqB,mBACH,MAAMrB;YAER/C,MAAM;YACN,OAAOoE;QACT;QAEA,MAAM,EAAEE,OAAO,EAAE,GAAGJ;QACpBzD,OAAO,CAAC6D,QAAQ,KAAK,EAAE,CAAC,iBAAiB,EAAEA,QAAQ,KAAK,EAAE;QAC1D7D,OAAO6D,QAAQ,WAAW,EAAE;QAC5B,OAAOA;IACT;IAhaA,YACE1D,OAA2D,EAC3DR,GAAoB,CACpB;QAPF;QAEA;QAMEK,OAAOG,SAAS;QAChB,IAAI,AAAmB,cAAnB,OAAOA,SACT,IAAI,CAAC,kBAAkB,GAAGA;aAE1B,IAAI,CAAC,kBAAkB,GAAG,IAAM2D,QAAQ,OAAO,CAAC3D;QAGlD,IAAI,AAAyB,WAAlBR,KAAK,UACd,IAAI,CAAC,QAAQ,GAAGA,IAAI,QAAQ;IAEhC;AAmZF"}