@donggui/core 1.6.1 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/agent/cache-confidence.mjs +121 -0
- package/dist/es/agent/cache-confidence.mjs.map +1 -0
- package/dist/es/agent/task-builder.mjs +86 -18
- package/dist/es/agent/task-builder.mjs.map +1 -1
- package/dist/es/ai-model/prompt/semantic-anchor-search.mjs +34 -0
- package/dist/es/ai-model/prompt/semantic-anchor-search.mjs.map +1 -0
- package/dist/es/ai-model/prompt/semantic-anchor.mjs +41 -0
- package/dist/es/ai-model/prompt/semantic-anchor.mjs.map +1 -0
- package/dist/es/service/index.mjs +156 -0
- package/dist/es/service/index.mjs.map +1 -1
- package/dist/es/types.mjs.map +1 -1
- package/dist/lib/agent/cache-confidence.js +173 -0
- package/dist/lib/agent/cache-confidence.js.map +1 -0
- package/dist/lib/agent/task-builder.js +85 -17
- package/dist/lib/agent/task-builder.js.map +1 -1
- package/dist/lib/ai-model/prompt/semantic-anchor-search.js +68 -0
- package/dist/lib/ai-model/prompt/semantic-anchor-search.js.map +1 -0
- package/dist/lib/ai-model/prompt/semantic-anchor.js +75 -0
- package/dist/lib/ai-model/prompt/semantic-anchor.js.map +1 -0
- package/dist/lib/service/index.js +156 -0
- package/dist/lib/service/index.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/types/agent/cache-confidence.d.ts +13 -0
- package/dist/types/ai-model/prompt/semantic-anchor-search.d.ts +1 -0
- package/dist/types/ai-model/prompt/semantic-anchor.d.ts +1 -0
- package/dist/types/service/index.d.ts +3 -1
- package/dist/types/types.d.ts +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
semanticAnchorGenerateInstruction: ()=>semanticAnchorGenerateInstruction
|
|
28
|
+
});
|
|
29
|
+
const env_namespaceObject = require("@midscene/shared/env");
|
|
30
|
+
const semanticAnchorGenerateInstruction = ()=>{
|
|
31
|
+
const preferredLanguage = (0, env_namespaceObject.getPreferredLanguage)();
|
|
32
|
+
return `
|
|
33
|
+
Analyze the element in the red rectangle and its surrounding context.
|
|
34
|
+
|
|
35
|
+
TASK: Generate a semantic anchor for this element that can be used to relocate it even when the DOM structure changes.
|
|
36
|
+
|
|
37
|
+
IMPORTANT: Write all descriptions in ${preferredLanguage}.
|
|
38
|
+
|
|
39
|
+
RESPONSE FORMAT (JSON):
|
|
40
|
+
{
|
|
41
|
+
"visualFingerprint": "concise visual description of the element (color, shape, icon, text style)",
|
|
42
|
+
"contextDescription": "spatial and semantic context (e.g., 'second button in top navigation bar')",
|
|
43
|
+
"nearbyLandmarks": [
|
|
44
|
+
{
|
|
45
|
+
"description": "description of a nearby stable structural element",
|
|
46
|
+
"xpath": "XPath of the landmark element"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"error"?: "error message if any"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
RULES:
|
|
53
|
+
1. visualFingerprint: Focus on visual characteristics that survive DOM changes
|
|
54
|
+
- Colors, icons, text content, shape
|
|
55
|
+
- NOT CSS classes or IDs (they change)
|
|
56
|
+
2. contextDescription: Describe WHERE the element is relative to page structure
|
|
57
|
+
- Use spatial terms: "top-right", "below header", "in sidebar"
|
|
58
|
+
- Use structural terms: "in navigation bar", "in modal dialog"
|
|
59
|
+
3. nearbyLandmarks: Identify 1-3 STABLE structural elements near the target
|
|
60
|
+
- Prefer: <nav>, <header>, <footer>, <aside>, <main>, <form>
|
|
61
|
+
- Avoid: <div>, <span>, <li> (too generic, likely to change)
|
|
62
|
+
- Each landmark MUST have both description and xpath
|
|
63
|
+
4. Keep descriptions under 20 words each
|
|
64
|
+
5. Prioritize landmarks that are large and visually distinct
|
|
65
|
+
`;
|
|
66
|
+
};
|
|
67
|
+
exports.semanticAnchorGenerateInstruction = __webpack_exports__.semanticAnchorGenerateInstruction;
|
|
68
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
69
|
+
"semanticAnchorGenerateInstruction"
|
|
70
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
71
|
+
Object.defineProperty(exports, '__esModule', {
|
|
72
|
+
value: true
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=semantic-anchor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-model/prompt/semantic-anchor.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../../src/ai-model/prompt/semantic-anchor.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { getPreferredLanguage } from '@midscene/shared/env';\n\nexport const semanticAnchorGenerateInstruction = () => {\n const preferredLanguage = getPreferredLanguage();\n\n return `\nAnalyze the element in the red rectangle and its surrounding context.\n\nTASK: Generate a semantic anchor for this element that can be used to relocate it even when the DOM structure changes.\n\nIMPORTANT: Write all descriptions in ${preferredLanguage}.\n\nRESPONSE FORMAT (JSON):\n{\n \"visualFingerprint\": \"concise visual description of the element (color, shape, icon, text style)\",\n \"contextDescription\": \"spatial and semantic context (e.g., 'second button in top navigation bar')\",\n \"nearbyLandmarks\": [\n {\n \"description\": \"description of a nearby stable structural element\",\n \"xpath\": \"XPath of the landmark element\"\n }\n ],\n \"error\"?: \"error message if any\"\n}\n\nRULES:\n1. visualFingerprint: Focus on visual characteristics that survive DOM changes\n - Colors, icons, text content, shape\n - NOT CSS classes or IDs (they change)\n2. contextDescription: Describe WHERE the element is relative to page structure\n - Use spatial terms: \"top-right\", \"below header\", \"in sidebar\"\n - Use structural terms: \"in navigation bar\", \"in modal dialog\"\n3. nearbyLandmarks: Identify 1-3 STABLE structural elements near the target\n - Prefer: <nav>, <header>, <footer>, <aside>, <main>, <form>\n - Avoid: <div>, <span>, <li> (too generic, likely to change)\n - Each landmark MUST have both description and xpath\n4. Keep descriptions under 20 words each\n5. Prioritize landmarks that are large and visually distinct\n`;\n};\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","semanticAnchorGenerateInstruction","preferredLanguage","getPreferredLanguage"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;ACJO,MAAMI,oCAAoC;IAC/C,MAAMC,oBAAoBC,AAAAA,IAAAA,oBAAAA,oBAAAA,AAAAA;IAE1B,OAAO,CAAC;;;;;qCAK2B,EAAED,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BzD,CAAC;AACD"}
|
|
@@ -31,6 +31,8 @@ const index_js_namespaceObject = require("../ai-model/index.js");
|
|
|
31
31
|
const inspect_js_namespaceObject = require("../ai-model/inspect.js");
|
|
32
32
|
const cache_verify_js_namespaceObject = require("../ai-model/prompt/cache-verify.js");
|
|
33
33
|
const describe_js_namespaceObject = require("../ai-model/prompt/describe.js");
|
|
34
|
+
const semantic_anchor_js_namespaceObject = require("../ai-model/prompt/semantic-anchor.js");
|
|
35
|
+
const semantic_anchor_search_js_namespaceObject = require("../ai-model/prompt/semantic-anchor-search.js");
|
|
34
36
|
const external_common_js_namespaceObject = require("../common.js");
|
|
35
37
|
const external_types_js_namespaceObject = require("../types.js");
|
|
36
38
|
const img_namespaceObject = require("@midscene/shared/img");
|
|
@@ -345,6 +347,160 @@ class Service {
|
|
|
345
347
|
};
|
|
346
348
|
}
|
|
347
349
|
}
|
|
350
|
+
async generateSemanticAnchor(center, modelConfig, uiContext) {
|
|
351
|
+
const context = uiContext || await this.contextRetrieverFn();
|
|
352
|
+
const { shotSize } = context;
|
|
353
|
+
const screenshotBase64 = context.screenshot.base64;
|
|
354
|
+
if (!screenshotBase64) return;
|
|
355
|
+
const defaultRectSize = 60;
|
|
356
|
+
const targetRect = {
|
|
357
|
+
left: Math.floor(center[0] - defaultRectSize / 2),
|
|
358
|
+
top: Math.floor(center[1] - defaultRectSize / 2),
|
|
359
|
+
width: defaultRectSize,
|
|
360
|
+
height: defaultRectSize
|
|
361
|
+
};
|
|
362
|
+
const cropArea = (0, external_common_js_namespaceObject.expandSearchArea)(targetRect, shotSize);
|
|
363
|
+
let imagePayload = await (0, img_namespaceObject.compositeElementInfoImg)({
|
|
364
|
+
inputImgBase64: screenshotBase64,
|
|
365
|
+
size: shotSize,
|
|
366
|
+
elementsPositionInfo: [
|
|
367
|
+
{
|
|
368
|
+
rect: targetRect
|
|
369
|
+
}
|
|
370
|
+
],
|
|
371
|
+
borderThickness: 3
|
|
372
|
+
});
|
|
373
|
+
const croppedResult = await (0, img_namespaceObject.cropByRect)(imagePayload, cropArea, 'qwen2.5-vl' === modelConfig.modelFamily);
|
|
374
|
+
imagePayload = croppedResult.imageBase64;
|
|
375
|
+
const systemPrompt = (0, semantic_anchor_js_namespaceObject.semanticAnchorGenerateInstruction)();
|
|
376
|
+
const msgs = [
|
|
377
|
+
{
|
|
378
|
+
role: 'system',
|
|
379
|
+
content: systemPrompt
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
role: 'user',
|
|
383
|
+
content: [
|
|
384
|
+
{
|
|
385
|
+
type: 'image_url',
|
|
386
|
+
image_url: {
|
|
387
|
+
url: imagePayload,
|
|
388
|
+
detail: 'low'
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
]
|
|
392
|
+
}
|
|
393
|
+
];
|
|
394
|
+
try {
|
|
395
|
+
const res = await (0, index_js_namespaceObject.callAIWithObjectResponse)(msgs, modelConfig);
|
|
396
|
+
const content = res.content;
|
|
397
|
+
if (content.error || !content.visualFingerprint) return void debug('generateSemanticAnchor AI error:', content.error);
|
|
398
|
+
const landmarks = (content.nearbyLandmarks || []).filter((l)=>l.description && l.xpath).map((l)=>({
|
|
399
|
+
description: l.description,
|
|
400
|
+
xpath: l.xpath
|
|
401
|
+
}));
|
|
402
|
+
const anchor = {
|
|
403
|
+
visualFingerprint: content.visualFingerprint,
|
|
404
|
+
contextDescription: content.contextDescription || '',
|
|
405
|
+
nearbyLandmarks: landmarks
|
|
406
|
+
};
|
|
407
|
+
debug('generateSemanticAnchor result:', anchor);
|
|
408
|
+
return anchor;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
debug('generateSemanticAnchor failed:', error);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
async locateBySemanticAnchor(anchor, modelConfig, interfaceInstance, uiContext) {
|
|
415
|
+
const context = uiContext || await this.contextRetrieverFn();
|
|
416
|
+
const { shotSize } = context;
|
|
417
|
+
const screenshotBase64 = context.screenshot.base64;
|
|
418
|
+
if (!screenshotBase64) return null;
|
|
419
|
+
let landmarkRect;
|
|
420
|
+
for (const landmark of anchor.nearbyLandmarks)if (interfaceInstance.rectMatchesCacheFeature) try {
|
|
421
|
+
const rect = await interfaceInstance.rectMatchesCacheFeature({
|
|
422
|
+
xpaths: [
|
|
423
|
+
landmark.xpath
|
|
424
|
+
]
|
|
425
|
+
});
|
|
426
|
+
if (rect) {
|
|
427
|
+
landmarkRect = rect;
|
|
428
|
+
debug('semantic anchor: landmark XPath hit:', landmark.description);
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
} catch {
|
|
432
|
+
debug('semantic anchor: landmark XPath miss:', landmark.description);
|
|
433
|
+
}
|
|
434
|
+
let cropArea;
|
|
435
|
+
if (landmarkRect) {
|
|
436
|
+
const expandSize = 300;
|
|
437
|
+
cropArea = {
|
|
438
|
+
left: Math.max(0, landmarkRect.left - expandSize),
|
|
439
|
+
top: Math.max(0, landmarkRect.top - expandSize),
|
|
440
|
+
width: landmarkRect.width + 2 * expandSize,
|
|
441
|
+
height: landmarkRect.height + 2 * expandSize
|
|
442
|
+
};
|
|
443
|
+
} else cropArea = {
|
|
444
|
+
left: 0,
|
|
445
|
+
top: 0,
|
|
446
|
+
width: shotSize.width,
|
|
447
|
+
height: shotSize.height
|
|
448
|
+
};
|
|
449
|
+
const croppedResult = await (0, img_namespaceObject.cropByRect)(screenshotBase64, cropArea, 'qwen2.5-vl' === modelConfig.modelFamily);
|
|
450
|
+
const imagePayload = croppedResult.imageBase64;
|
|
451
|
+
const systemPrompt = (0, semantic_anchor_search_js_namespaceObject.semanticAnchorSearchInstruction)().replace('{{visualFingerprint}}', anchor.visualFingerprint).replace("{{contextDescription}}", anchor.contextDescription);
|
|
452
|
+
const msgs = [
|
|
453
|
+
{
|
|
454
|
+
role: 'system',
|
|
455
|
+
content: systemPrompt
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
role: 'user',
|
|
459
|
+
content: [
|
|
460
|
+
{
|
|
461
|
+
type: 'image_url',
|
|
462
|
+
image_url: {
|
|
463
|
+
url: imagePayload,
|
|
464
|
+
detail: 'low'
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
];
|
|
470
|
+
try {
|
|
471
|
+
const res = await (0, index_js_namespaceObject.callAIWithObjectResponse)(msgs, modelConfig);
|
|
472
|
+
const content = res.content;
|
|
473
|
+
if (!content.found || !content.center || (content.confidence ?? 0) < 0.5) {
|
|
474
|
+
debug('semantic anchor locate: not found or low confidence', content);
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
const adjustedCenter = [
|
|
478
|
+
content.center[0] + cropArea.left,
|
|
479
|
+
content.center[1] + cropArea.top
|
|
480
|
+
];
|
|
481
|
+
let adjustedRect;
|
|
482
|
+
if (content.rect) adjustedRect = {
|
|
483
|
+
left: content.rect.left + cropArea.left,
|
|
484
|
+
top: content.rect.top + cropArea.top,
|
|
485
|
+
width: content.rect.width,
|
|
486
|
+
height: content.rect.height
|
|
487
|
+
};
|
|
488
|
+
debug('semantic anchor locate: found at', adjustedCenter, 'confidence:', content.confidence);
|
|
489
|
+
return {
|
|
490
|
+
center: adjustedCenter,
|
|
491
|
+
rect: adjustedRect || {
|
|
492
|
+
left: adjustedCenter[0] - 30,
|
|
493
|
+
top: adjustedCenter[1] - 15,
|
|
494
|
+
width: 60,
|
|
495
|
+
height: 30
|
|
496
|
+
},
|
|
497
|
+
description: `semantic anchor: ${anchor.contextDescription}`
|
|
498
|
+
};
|
|
499
|
+
} catch (error) {
|
|
500
|
+
debug('locateBySemanticAnchor failed:', error);
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
348
504
|
constructor(context, opt){
|
|
349
505
|
_define_property(this, "contextRetrieverFn", void 0);
|
|
350
506
|
_define_property(this, "taskInfo", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/service/index.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { isAutoGLM, isUITars } from '@/ai-model/auto-glm/util';\nimport {\n AIResponseParseError,\n AiExtractElementInfo,\n AiLocateElement,\n callAIWithObjectResponse,\n} from '@/ai-model/index';\nimport { AiLocateSection } from '@/ai-model/inspect';\nimport { cacheVerifyInstruction } from '@/ai-model/prompt/cache-verify';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport { type AIArgs, expandSearchArea } from '@/common';\nimport type {\n AIDescribeElementResponse,\n AIUsageInfo,\n CacheVerificationResult,\n DetailedLocateParam,\n LocateResultWithDump,\n PartialServiceDumpFromSDK,\n Rect,\n ServiceExtractOption,\n ServiceExtractParam,\n ServiceExtractResult,\n ServiceTaskInfo,\n UIContext,\n} from '@/types';\nimport { ServiceError } from '@/types';\nimport type { IModelConfig } from '@midscene/shared/env';\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 { createServiceDump } from './utils';\n\nexport interface LocateOpts {\n context?: UIContext;\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\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: DetailedLocateParam,\n opt: LocateOpts,\n modelConfig: IModelConfig,\n abortSignal?: AbortSignal,\n ): Promise<LocateResultWithDump> {\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 let searchAreaPrompt;\n if (query.deepLocate) {\n searchAreaPrompt = query.prompt;\n }\n\n const { modelFamily } = modelConfig;\n\n if (searchAreaPrompt && !modelFamily) {\n console.warn(\n 'The \"deepLocate\" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config',\n );\n searchAreaPrompt = undefined;\n }\n\n if (searchAreaPrompt && isAutoGLM(modelFamily)) {\n console.warn('The \"deepLocate\" feature is not supported with AutoGLM.');\n searchAreaPrompt = undefined;\n }\n\n const context = opt?.context || (await this.contextRetrieverFn());\n\n let searchArea: Rect | undefined = undefined;\n let searchAreaRawResponse: string | undefined = undefined;\n let searchAreaUsage: AIUsageInfo | undefined = undefined;\n let searchAreaResponse:\n | Awaited<ReturnType<typeof AiLocateSection>>\n | undefined = undefined;\n if (searchAreaPrompt) {\n searchAreaResponse = await AiLocateSection({\n context,\n sectionDescription: searchAreaPrompt,\n modelConfig,\n abortSignal,\n });\n assert(\n searchAreaResponse.rect,\n `cannot find search area for \"${searchAreaPrompt}\"${\n searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\n }`,\n );\n searchAreaRawResponse = searchAreaResponse.rawResponse;\n searchAreaUsage = searchAreaResponse.usage;\n searchArea = searchAreaResponse.rect;\n }\n\n const startTime = Date.now();\n const { parseResult, rect, rawResponse, usage, reasoning_content } =\n await AiLocateElement({\n context,\n targetElementDescription: queryPrompt,\n searchConfig: searchAreaResponse,\n modelConfig,\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 formatResponse: JSON.stringify(parseResult),\n usage,\n searchArea,\n searchAreaRawResponse,\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 matchedElement: [],\n matchedRect: rect,\n data: null,\n deepLocate: !!searchArea || !!searchAreaPrompt,\n error: errorLog,\n taskInfo,\n };\n\n const elements = parseResult.elements || [];\n\n const dump = createServiceDump({\n ...dumpData,\n matchedElement: elements,\n });\n\n if (errorLog) {\n throw new ServiceError(errorLog, dump);\n }\n\n if (elements.length > 1) {\n throw new ServiceError(\n `locate: multiple elements found, length = ${elements.length}`,\n dump,\n );\n }\n\n if (elements.length === 1) {\n return {\n element: {\n center: elements[0]!.center,\n rect: elements[0]!.rect,\n description: elements[0]!.description,\n },\n rect,\n dump,\n };\n }\n\n return {\n element: null,\n rect,\n dump,\n };\n }\n\n async extract<T>(\n dataDemand: ServiceExtractParam,\n modelConfig: IModelConfig,\n opt?: ServiceExtractOption,\n pageDescription?: string,\n multimodalPrompt?: TMultimodalPrompt,\n context?: UIContext,\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 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 modelConfig,\n pageDescription,\n });\n parseResult = result.parseResult;\n rawResponse = result.rawResponse;\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 usage: error.usage,\n };\n const dump = createServiceDump({\n type: 'extract',\n userQuery: { dataDemand },\n matchedElement: [],\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 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 matchedElement: [],\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 modelConfig: IModelConfig,\n opt?: {\n deepLocate?: boolean;\n },\n ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n assert(target, 'target is required for service.describe');\n const context = await this.contextRetrieverFn();\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for service.describe');\n // The result of the \"describe\" function will be used for positioning, so essentially it is a form of grounding.\n const { modelFamily } = modelConfig;\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 debug('describe: cropping to searchArea', searchArea);\n const croppedResult = await cropByRect(\n imagePayload,\n searchArea,\n modelFamily === 'qwen2.5-vl',\n );\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 const res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n msgs,\n modelConfig,\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 async verifyCachedElement(\n center: [number, number],\n targetPrompt: TUserPrompt,\n modelConfig: IModelConfig,\n uiContext?: UIContext,\n ): Promise<CacheVerificationResult> {\n const context = uiContext || (await this.contextRetrieverFn());\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for verifyCachedElement');\n\n const defaultRectSize = 60;\n const targetRect: Rect = {\n left: Math.floor(center[0] - defaultRectSize / 2),\n top: Math.floor(center[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n };\n\n const cropArea = expandSearchArea(targetRect, shotSize);\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [{ rect: targetRect }],\n borderThickness: 3,\n });\n\n debug(\n 'verifyCachedElement: cropping to area',\n cropArea,\n 'from center',\n center,\n );\n const croppedResult = await cropByRect(\n imagePayload,\n cropArea,\n modelConfig.modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n\n const promptText =\n typeof targetPrompt === 'string'\n ? targetPrompt\n : targetPrompt.prompt || '';\n\n const systemPrompt = cacheVerifyInstruction().replace(\n /{{targetPrompt}}/g,\n promptText,\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: 'low',\n },\n },\n ],\n },\n ];\n\n try {\n const res = await callAIWithObjectResponse<{\n match: boolean;\n description?: string;\n reason?: string;\n error?: string;\n }>(msgs, modelConfig);\n const content = res.content as {\n match?: boolean;\n description?: string;\n reason?: string;\n error?: string;\n };\n\n if (content.error) {\n debug('verifyCachedElement AI returned error:', content.error);\n return { pass: false, reason: content.error };\n }\n\n const result: CacheVerificationResult = {\n pass: !!content.match,\n description: content.description,\n reason: content.reason,\n };\n\n debug('verifyCachedElement result:', {\n pass: result.pass,\n description: result.description,\n reason: result.reason,\n targetPrompt: promptText,\n });\n\n return result;\n } catch (error) {\n debug('verifyCachedElement failed:', error);\n return { pass: false, reason: String(error) };\n }\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","debug","getDebug","Service","query","opt","modelConfig","abortSignal","queryPrompt","assert","searchAreaPrompt","modelFamily","console","undefined","isAutoGLM","context","searchArea","searchAreaRawResponse","searchAreaResponse","AiLocateSection","startTime","Date","parseResult","rect","rawResponse","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","JSON","errorLog","dumpData","elements","dump","createServiceDump","ServiceError","dataDemand","pageDescription","multimodalPrompt","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","msgs","res","callAIWithObjectResponse","content","center","targetPrompt","uiContext","cropArea","promptText","cacheVerifyInstruction","String","Promise"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service/index.js","sources":["webpack/runtime/define_property_getters","webpack/runtime/has_own_property","webpack/runtime/make_namespace_object","../../../src/service/index.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { isAutoGLM, isUITars } from '@/ai-model/auto-glm/util';\nimport {\n AIResponseParseError,\n AiExtractElementInfo,\n AiLocateElement,\n callAIWithObjectResponse,\n} from '@/ai-model/index';\nimport { AiLocateSection } from '@/ai-model/inspect';\nimport { cacheVerifyInstruction } from '@/ai-model/prompt/cache-verify';\nimport { elementDescriberInstruction } from '@/ai-model/prompt/describe';\nimport { semanticAnchorGenerateInstruction } from '@/ai-model/prompt/semantic-anchor';\nimport { semanticAnchorSearchInstruction } from '@/ai-model/prompt/semantic-anchor-search';\nimport { type AIArgs, expandSearchArea } from '@/common';\nimport type {\n AIDescribeElementResponse,\n AIUsageInfo,\n CacheVerificationResult,\n DetailedLocateParam,\n Landmark,\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 type { IModelConfig } from '@midscene/shared/env';\nimport { compositeElementInfoImg, cropByRect } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport type { ChatCompletionUserMessageParam } from 'openai/resources/index';\nimport type { TMultimodalPrompt, TUserPrompt } from '../common';\nimport { createServiceDump } from './utils';\n\nexport interface LocateOpts {\n context?: UIContext;\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\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: DetailedLocateParam,\n opt: LocateOpts,\n modelConfig: IModelConfig,\n abortSignal?: AbortSignal,\n ): Promise<LocateResultWithDump> {\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 let searchAreaPrompt;\n if (query.deepLocate) {\n searchAreaPrompt = query.prompt;\n }\n\n const { modelFamily } = modelConfig;\n\n if (searchAreaPrompt && !modelFamily) {\n console.warn(\n 'The \"deepLocate\" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config',\n );\n searchAreaPrompt = undefined;\n }\n\n if (searchAreaPrompt && isAutoGLM(modelFamily)) {\n console.warn('The \"deepLocate\" feature is not supported with AutoGLM.');\n searchAreaPrompt = undefined;\n }\n\n const context = opt?.context || (await this.contextRetrieverFn());\n\n let searchArea: Rect | undefined = undefined;\n let searchAreaRawResponse: string | undefined = undefined;\n let searchAreaUsage: AIUsageInfo | undefined = undefined;\n let searchAreaResponse:\n | Awaited<ReturnType<typeof AiLocateSection>>\n | undefined = undefined;\n if (searchAreaPrompt) {\n searchAreaResponse = await AiLocateSection({\n context,\n sectionDescription: searchAreaPrompt,\n modelConfig,\n abortSignal,\n });\n assert(\n searchAreaResponse.rect,\n `cannot find search area for \"${searchAreaPrompt}\"${\n searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''\n }`,\n );\n searchAreaRawResponse = searchAreaResponse.rawResponse;\n searchAreaUsage = searchAreaResponse.usage;\n searchArea = searchAreaResponse.rect;\n }\n\n const startTime = Date.now();\n const { parseResult, rect, rawResponse, usage, reasoning_content } =\n await AiLocateElement({\n context,\n targetElementDescription: queryPrompt,\n searchConfig: searchAreaResponse,\n modelConfig,\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 formatResponse: JSON.stringify(parseResult),\n usage,\n searchArea,\n searchAreaRawResponse,\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 matchedElement: [],\n matchedRect: rect,\n data: null,\n deepLocate: !!searchArea || !!searchAreaPrompt,\n error: errorLog,\n taskInfo,\n };\n\n const elements = parseResult.elements || [];\n\n const dump = createServiceDump({\n ...dumpData,\n matchedElement: elements,\n });\n\n if (errorLog) {\n throw new ServiceError(errorLog, dump);\n }\n\n if (elements.length > 1) {\n throw new ServiceError(\n `locate: multiple elements found, length = ${elements.length}`,\n dump,\n );\n }\n\n if (elements.length === 1) {\n return {\n element: {\n center: elements[0]!.center,\n rect: elements[0]!.rect,\n description: elements[0]!.description,\n },\n rect,\n dump,\n };\n }\n\n return {\n element: null,\n rect,\n dump,\n };\n }\n\n async extract<T>(\n dataDemand: ServiceExtractParam,\n modelConfig: IModelConfig,\n opt?: ServiceExtractOption,\n pageDescription?: string,\n multimodalPrompt?: TMultimodalPrompt,\n context?: UIContext,\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 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 modelConfig,\n pageDescription,\n });\n parseResult = result.parseResult;\n rawResponse = result.rawResponse;\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 usage: error.usage,\n };\n const dump = createServiceDump({\n type: 'extract',\n userQuery: { dataDemand },\n matchedElement: [],\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 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 matchedElement: [],\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 modelConfig: IModelConfig,\n opt?: {\n deepLocate?: boolean;\n },\n ): Promise<Pick<AIDescribeElementResponse, 'description'>> {\n assert(target, 'target is required for service.describe');\n const context = await this.contextRetrieverFn();\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for service.describe');\n // The result of the \"describe\" function will be used for positioning, so essentially it is a form of grounding.\n const { modelFamily } = modelConfig;\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 debug('describe: cropping to searchArea', searchArea);\n const croppedResult = await cropByRect(\n imagePayload,\n searchArea,\n modelFamily === 'qwen2.5-vl',\n );\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 const res = await callAIWithObjectResponse<AIDescribeElementResponse>(\n msgs,\n modelConfig,\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 async verifyCachedElement(\n center: [number, number],\n targetPrompt: TUserPrompt,\n modelConfig: IModelConfig,\n uiContext?: UIContext,\n ): Promise<CacheVerificationResult> {\n const context = uiContext || (await this.contextRetrieverFn());\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n assert(screenshotBase64, 'screenshot is required for verifyCachedElement');\n\n const defaultRectSize = 60;\n const targetRect: Rect = {\n left: Math.floor(center[0] - defaultRectSize / 2),\n top: Math.floor(center[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n };\n\n const cropArea = expandSearchArea(targetRect, shotSize);\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [{ rect: targetRect }],\n borderThickness: 3,\n });\n\n debug(\n 'verifyCachedElement: cropping to area',\n cropArea,\n 'from center',\n center,\n );\n const croppedResult = await cropByRect(\n imagePayload,\n cropArea,\n modelConfig.modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n\n const promptText =\n typeof targetPrompt === 'string'\n ? targetPrompt\n : targetPrompt.prompt || '';\n\n const systemPrompt = cacheVerifyInstruction().replace(\n /{{targetPrompt}}/g,\n promptText,\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: 'low',\n },\n },\n ],\n },\n ];\n\n try {\n const res = await callAIWithObjectResponse<{\n match: boolean;\n description?: string;\n reason?: string;\n error?: string;\n }>(msgs, modelConfig);\n const content = res.content as {\n match?: boolean;\n description?: string;\n reason?: string;\n error?: string;\n };\n\n if (content.error) {\n debug('verifyCachedElement AI returned error:', content.error);\n return { pass: false, reason: content.error };\n }\n\n const result: CacheVerificationResult = {\n pass: !!content.match,\n description: content.description,\n reason: content.reason,\n };\n\n debug('verifyCachedElement result:', {\n pass: result.pass,\n description: result.description,\n reason: result.reason,\n targetPrompt: promptText,\n });\n\n return result;\n } catch (error) {\n debug('verifyCachedElement failed:', error);\n return { pass: false, reason: String(error) };\n }\n }\n\n async generateSemanticAnchor(\n center: [number, number],\n modelConfig: IModelConfig,\n uiContext?: UIContext,\n ): Promise<import('@/types').SemanticAnchor | undefined> {\n const context = uiContext || (await this.contextRetrieverFn());\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n if (!screenshotBase64) return undefined;\n\n const defaultRectSize = 60;\n const targetRect: Rect = {\n left: Math.floor(center[0] - defaultRectSize / 2),\n top: Math.floor(center[1] - defaultRectSize / 2),\n width: defaultRectSize,\n height: defaultRectSize,\n };\n\n const cropArea = expandSearchArea(targetRect, shotSize);\n\n let imagePayload = await compositeElementInfoImg({\n inputImgBase64: screenshotBase64,\n size: shotSize,\n elementsPositionInfo: [{ rect: targetRect }],\n borderThickness: 3,\n });\n\n const croppedResult = await cropByRect(\n imagePayload,\n cropArea,\n modelConfig.modelFamily === 'qwen2.5-vl',\n );\n imagePayload = croppedResult.imageBase64;\n\n const systemPrompt = semanticAnchorGenerateInstruction();\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url',\n image_url: { url: imagePayload, detail: 'low' },\n },\n ],\n },\n ];\n\n try {\n const res = await callAIWithObjectResponse<{\n visualFingerprint?: string;\n contextDescription?: string;\n nearbyLandmarks?: Array<{ description?: string; xpath?: string }>;\n error?: string;\n }>(msgs, modelConfig);\n const content = res.content as {\n visualFingerprint?: string;\n contextDescription?: string;\n nearbyLandmarks?: Array<{ description?: string; xpath?: string }>;\n error?: string;\n };\n\n if (content.error || !content.visualFingerprint) {\n debug('generateSemanticAnchor AI error:', content.error);\n return undefined;\n }\n\n const landmarks: Landmark[] = (content.nearbyLandmarks || [])\n .filter((l) => l.description && l.xpath)\n .map((l) => ({\n description: l.description!,\n xpath: l.xpath!,\n }));\n\n const anchor: import('@/types').SemanticAnchor = {\n visualFingerprint: content.visualFingerprint,\n contextDescription: content.contextDescription || '',\n nearbyLandmarks: landmarks,\n };\n\n debug('generateSemanticAnchor result:', anchor);\n return anchor;\n } catch (error) {\n debug('generateSemanticAnchor failed:', error);\n return undefined;\n }\n }\n\n async locateBySemanticAnchor(\n anchor: import('@/types').SemanticAnchor,\n modelConfig: IModelConfig,\n interfaceInstance: import('@/device').AbstractInterface,\n uiContext?: UIContext,\n ): Promise<LocateResultElement | null> {\n const context = uiContext || (await this.contextRetrieverFn());\n const { shotSize } = context;\n const screenshotBase64 = context.screenshot.base64;\n if (!screenshotBase64) return null;\n\n let landmarkRect: Rect | undefined;\n\n for (const landmark of anchor.nearbyLandmarks) {\n if (interfaceInstance.rectMatchesCacheFeature) {\n try {\n const rect = await interfaceInstance.rectMatchesCacheFeature({\n xpaths: [landmark.xpath],\n });\n if (rect) {\n landmarkRect = rect;\n debug('semantic anchor: landmark XPath hit:', landmark.description);\n break;\n }\n } catch {\n debug('semantic anchor: landmark XPath miss:', landmark.description);\n }\n }\n }\n\n let cropArea: Rect;\n if (landmarkRect) {\n const expandSize = 300;\n cropArea = {\n left: Math.max(0, landmarkRect.left - expandSize),\n top: Math.max(0, landmarkRect.top - expandSize),\n width: landmarkRect.width + expandSize * 2,\n height: landmarkRect.height + expandSize * 2,\n };\n } else {\n cropArea = {\n left: 0,\n top: 0,\n width: shotSize.width,\n height: shotSize.height,\n };\n }\n\n const croppedResult = await cropByRect(\n screenshotBase64,\n cropArea,\n modelConfig.modelFamily === 'qwen2.5-vl',\n );\n const imagePayload: string = croppedResult.imageBase64;\n\n const systemPrompt = semanticAnchorSearchInstruction()\n .replace('{{visualFingerprint}}', anchor.visualFingerprint)\n .replace('{{contextDescription}}', anchor.contextDescription);\n\n const msgs: AIArgs = [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: [\n {\n type: 'image_url' as const,\n image_url: { url: imagePayload, detail: 'low' },\n },\n ] as ChatCompletionUserMessageParam['content'],\n },\n ];\n\n try {\n const res = await callAIWithObjectResponse<{\n found?: boolean;\n center?: [number, number] | null;\n rect?: Rect | null;\n confidence?: number;\n reason?: string;\n }>(msgs, modelConfig);\n const content = res.content as {\n found?: boolean;\n center?: [number, number] | null;\n rect?: Rect | null;\n confidence?: number;\n reason?: string;\n };\n\n if (\n !content.found ||\n !content.center ||\n (content.confidence ?? 0) < 0.5\n ) {\n debug('semantic anchor locate: not found or low confidence', content);\n return null;\n }\n\n const adjustedCenter: [number, number] = [\n content.center[0] + cropArea.left,\n content.center[1] + cropArea.top,\n ];\n\n let adjustedRect: Rect | undefined;\n if (content.rect) {\n adjustedRect = {\n left: content.rect.left + cropArea.left,\n top: content.rect.top + cropArea.top,\n width: content.rect.width,\n height: content.rect.height,\n };\n }\n\n debug(\n 'semantic anchor locate: found at',\n adjustedCenter,\n 'confidence:',\n content.confidence,\n );\n\n return {\n center: adjustedCenter,\n rect: adjustedRect || {\n left: adjustedCenter[0] - 30,\n top: adjustedCenter[1] - 15,\n width: 60,\n height: 30,\n },\n description: `semantic anchor: ${anchor.contextDescription}`,\n };\n } catch (error) {\n debug('locateBySemanticAnchor failed:', error);\n return null;\n }\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","debug","getDebug","Service","query","opt","modelConfig","abortSignal","queryPrompt","assert","searchAreaPrompt","modelFamily","console","undefined","isAutoGLM","context","searchArea","searchAreaRawResponse","searchAreaResponse","AiLocateSection","startTime","Date","parseResult","rect","rawResponse","usage","reasoning_content","AiLocateElement","timeCost","taskInfo","JSON","errorLog","dumpData","elements","dump","createServiceDump","ServiceError","dataDemand","pageDescription","multimodalPrompt","result","AiExtractElementInfo","error","AIResponseParseError","data","thought","target","shotSize","screenshotBase64","systemPrompt","elementDescriberInstruction","defaultRectSize","targetRect","Array","Math","imagePayload","compositeElementInfoImg","expandSearchArea","croppedResult","cropByRect","msgs","res","callAIWithObjectResponse","content","center","targetPrompt","uiContext","cropArea","promptText","cacheVerifyInstruction","String","semanticAnchorGenerateInstruction","landmarks","l","anchor","interfaceInstance","landmarkRect","landmark","expandSize","semanticAnchorSearchInstruction","adjustedCenter","adjustedRect","Promise"],"mappings":";;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC4CA,MAAMI,QAAQC,AAAAA,IAAAA,uBAAAA,QAAAA,AAAAA,EAAS;AACR,MAAMC;IAqBnB,MAAM,OACJC,KAA0B,EAC1BC,GAAe,EACfC,WAAyB,EACzBC,WAAyB,EACM;QAC/B,MAAMC,cAAc,AAAiB,YAAjB,OAAOJ,QAAqBA,QAAQA,MAAM,MAAM;QACpEK,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOD,aAAa;QAEpBC,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,AAAiB,YAAjB,OAAOL,OAAoB;QAElC,IAAIM;QACJ,IAAIN,MAAM,UAAU,EAClBM,mBAAmBN,MAAM,MAAM;QAGjC,MAAM,EAAEO,WAAW,EAAE,GAAGL;QAExB,IAAII,oBAAoB,CAACC,aAAa;YACpCC,QAAQ,IAAI,CACV;YAEFF,mBAAmBG;QACrB;QAEA,IAAIH,oBAAoBI,AAAAA,IAAAA,wBAAAA,SAAAA,AAAAA,EAAUH,cAAc;YAC9CC,QAAQ,IAAI,CAAC;YACbF,mBAAmBG;QACrB;QAEA,MAAME,UAAUV,KAAK,WAAY,MAAM,IAAI,CAAC,kBAAkB;QAE9D,IAAIW;QACJ,IAAIC;QAEJ,IAAIC;QAGJ,IAAIR,kBAAkB;YACpBQ,qBAAqB,MAAMC,AAAAA,IAAAA,2BAAAA,eAAAA,AAAAA,EAAgB;gBACzCJ;gBACA,oBAAoBL;gBACpBJ;gBACAC;YACF;YACAE,IAAAA,sBAAAA,MAAAA,AAAAA,EACES,mBAAmB,IAAI,EACvB,CAAC,6BAA6B,EAAER,iBAAiB,CAAC,EAChDQ,mBAAmB,KAAK,GAAG,CAAC,EAAE,EAAEA,mBAAmB,KAAK,EAAE,GAAG,IAC7D;YAEJD,wBAAwBC,mBAAmB,WAAW;YACpCA,mBAAmB,KAAK;YAC1CF,aAAaE,mBAAmB,IAAI;QACtC;QAEA,MAAME,YAAYC,KAAK,GAAG;QAC1B,MAAM,EAAEC,WAAW,EAAEC,IAAI,EAAEC,WAAW,EAAEC,KAAK,EAAEC,iBAAiB,EAAE,GAChE,MAAMC,AAAAA,IAAAA,yBAAAA,eAAAA,AAAAA,EAAgB;YACpBZ;YACA,0BAA0BP;YAC1B,cAAcU;YACdZ;YACAC;QACF;QAEF,MAAMqB,WAAWP,KAAK,GAAG,KAAKD;QAC9B,MAAMS,WAA4B;YAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACtC,YAAYD;YACZ,aAAaE,KAAK,SAAS,CAACN;YAC5B,gBAAgBM,KAAK,SAAS,CAACR;YAC/BG;YACAT;YACAC;YACAS;QACF;QAEA,IAAIK;QACJ,IAAIT,YAAY,MAAM,EAAE,QACtBS,WAAW,CAAC,4BAA4B,EAAET,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO;QAG3E,MAAMU,WAAsC;YAC1C,MAAM;YACN,WAAW;gBACT,SAASxB;YACX;YACA,gBAAgB,EAAE;YAClB,aAAae;YACb,MAAM;YACN,YAAY,CAAC,CAACP,cAAc,CAAC,CAACN;YAC9B,OAAOqB;YACPF;QACF;QAEA,MAAMI,WAAWX,YAAY,QAAQ,IAAI,EAAE;QAE3C,MAAMY,OAAOC,AAAAA,IAAAA,kCAAAA,iBAAAA,AAAAA,EAAkB;YAC7B,GAAGH,QAAQ;YACX,gBAAgBC;QAClB;QAEA,IAAIF,UACF,MAAM,IAAIK,kCAAAA,YAAYA,CAACL,UAAUG;QAGnC,IAAID,SAAS,MAAM,GAAG,GACpB,MAAM,IAAIG,kCAAAA,YAAYA,CACpB,CAAC,0CAA0C,EAAEH,SAAS,MAAM,EAAE,EAC9DC;QAIJ,IAAID,AAAoB,MAApBA,SAAS,MAAM,EACjB,OAAO;YACL,SAAS;gBACP,QAAQA,QAAQ,CAAC,EAAE,CAAE,MAAM;gBAC3B,MAAMA,QAAQ,CAAC,EAAE,CAAE,IAAI;gBACvB,aAAaA,QAAQ,CAAC,EAAE,CAAE,WAAW;YACvC;YACAV;YACAW;QACF;QAGF,OAAO;YACL,SAAS;YACTX;YACAW;QACF;IACF;IAEA,MAAM,QACJG,UAA+B,EAC/B/B,WAAyB,EACzBD,GAA0B,EAC1BiC,eAAwB,EACxBC,gBAAoC,EACpCxB,OAAmB,EACe;QAClCN,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOM,SAAS;QAChBN,IAAAA,sBAAAA,MAAAA,AAAAA,EACE,AAAsB,YAAtB,OAAO4B,cAA2B,AAAsB,YAAtB,OAAOA,YACzC,CAAC,+CAA+C,EAAE,OAAOA,YAAY;QAGvE,MAAMjB,YAAYC,KAAK,GAAG;QAE1B,IAAIC;QAGJ,IAAIE;QACJ,IAAIC;QACJ,IAAIC;QAEJ,IAAI;YACF,MAAMc,SAAS,MAAMC,AAAAA,IAAAA,yBAAAA,oBAAAA,AAAAA,EAAwB;gBAC3C1B;gBACA,WAAWsB;gBACXE;gBACA,eAAelC;gBACfC;gBACAgC;YACF;YACAhB,cAAckB,OAAO,WAAW;YAChChB,cAAcgB,OAAO,WAAW;YAChCf,QAAQe,OAAO,KAAK;YACpBd,oBAAoBc,OAAO,iBAAiB;QAC9C,EAAE,OAAOE,OAAO;YACd,IAAIA,iBAAiBC,yBAAAA,oBAAoBA,EAAE;gBAEzC,MAAMf,WAAWP,KAAK,GAAG,KAAKD;gBAC9B,MAAMS,WAA4B;oBAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;oBACtC,YAAYD;oBACZ,aAAac,MAAM,WAAW;oBAC9B,OAAOA,MAAM,KAAK;gBACpB;gBACA,MAAMR,OAAOC,AAAAA,IAAAA,kCAAAA,iBAAAA,AAAAA,EAAkB;oBAC7B,MAAM;oBACN,WAAW;wBAAEE;oBAAW;oBACxB,gBAAgB,EAAE;oBAClB,MAAM;oBACNR;oBACA,OAAOa,MAAM,OAAO;gBACtB;gBACA,MAAM,IAAIN,kCAAAA,YAAYA,CAACM,MAAM,OAAO,EAAER;YACxC;YACA,MAAMQ;QACR;QAEA,MAAMd,WAAWP,KAAK,GAAG,KAAKD;QAC9B,MAAMS,WAA4B;YAChC,GAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACtC,YAAYD;YACZJ;YACA,gBAAgBM,KAAK,SAAS,CAACR;YAC/BG;YACAC;QACF;QAEA,IAAIK;QACJ,IAAIT,YAAY,MAAM,EAAE,QACtBS,WAAW,CAAC,qBAAqB,EAAET,YAAY,MAAM,CAAC,IAAI,CAAC,OAAO;QAGpE,MAAMU,WAAsC;YAC1C,MAAM;YACN,WAAW;gBACTK;YACF;YACA,gBAAgB,EAAE;YAClB,MAAM;YACNR;YACA,OAAOE;QACT;QAEA,MAAM,EAAEa,IAAI,EAAEC,OAAO,EAAE,GAAGvB,eAAe,CAAC;QAE1C,MAAMY,OAAOC,AAAAA,IAAAA,kCAAAA,iBAAAA,AAAAA,EAAkB;YAC7B,GAAGH,QAAQ;YACXY;QACF;QAEA,IAAIb,YAAY,CAACa,MACf,MAAM,IAAIR,kCAAAA,YAAYA,CAACL,UAAUG;QAGnC,OAAO;YACLU;YACAC;YACApB;YACAC;YACAQ;QACF;IACF;IAEA,MAAM,SACJY,MAA+B,EAC/BxC,WAAyB,EACzBD,GAEC,EACwD;QACzDI,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOqC,QAAQ;QACf,MAAM/B,UAAU,MAAM,IAAI,CAAC,kBAAkB;QAC7C,MAAM,EAAEgC,QAAQ,EAAE,GAAGhC;QACrB,MAAMiC,mBAAmBjC,QAAQ,UAAU,CAAC,MAAM;QAClDN,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOuC,kBAAkB;QAEzB,MAAM,EAAErC,WAAW,EAAE,GAAGL;QACxB,MAAM2C,eAAeC,AAAAA,IAAAA,4BAAAA,2BAAAA,AAAAA;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,AAAAA,IAAAA,oBAAAA,uBAAAA,AAAAA,EAAwB;YAC/C,gBAAgBR;YAChB,MAAMD;YACN,sBAAsB;gBACpB;oBACE,MAAMK;gBACR;aACD;YACD,iBAAiB;QACnB;QAEA,IAAI/C,KAAK,YAAY;YACnB,MAAMW,aAAayC,AAAAA,IAAAA,mCAAAA,gBAAAA,AAAAA,EAAiBL,YAAYL;YAMhD9C,MAAM,oCAAoCe;YAC1C,MAAM0C,gBAAgB,MAAMC,AAAAA,IAAAA,oBAAAA,UAAAA,AAAAA,EAC1BJ,cACAvC,YACAL,AAAgB,iBAAhBA;YAEF4C,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,MAAMM,MAAM,MAAMC,AAAAA,IAAAA,yBAAAA,wBAAAA,AAAAA,EAChBF,MACAtD;QAGF,MAAM,EAAEyD,OAAO,EAAE,GAAGF;QACpBpD,IAAAA,sBAAAA,MAAAA,AAAAA,EAAO,CAACsD,QAAQ,KAAK,EAAE,CAAC,iBAAiB,EAAEA,QAAQ,KAAK,EAAE;QAC1DtD,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOsD,QAAQ,WAAW,EAAE;QAC5B,OAAOA;IACT;IAEA,MAAM,oBACJC,MAAwB,EACxBC,YAAyB,EACzB3D,WAAyB,EACzB4D,SAAqB,EACa;QAClC,MAAMnD,UAAUmD,aAAc,MAAM,IAAI,CAAC,kBAAkB;QAC3D,MAAM,EAAEnB,QAAQ,EAAE,GAAGhC;QACrB,MAAMiC,mBAAmBjC,QAAQ,UAAU,CAAC,MAAM;QAClDN,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOuC,kBAAkB;QAEzB,MAAMG,kBAAkB;QACxB,MAAMC,aAAmB;YACvB,MAAME,KAAK,KAAK,CAACU,MAAM,CAAC,EAAE,GAAGb,kBAAkB;YAC/C,KAAKG,KAAK,KAAK,CAACU,MAAM,CAAC,EAAE,GAAGb,kBAAkB;YAC9C,OAAOA;YACP,QAAQA;QACV;QAEA,MAAMgB,WAAWV,AAAAA,IAAAA,mCAAAA,gBAAAA,AAAAA,EAAiBL,YAAYL;QAE9C,IAAIQ,eAAe,MAAMC,AAAAA,IAAAA,oBAAAA,uBAAAA,AAAAA,EAAwB;YAC/C,gBAAgBR;YAChB,MAAMD;YACN,sBAAsB;gBAAC;oBAAE,MAAMK;gBAAW;aAAE;YAC5C,iBAAiB;QACnB;QAEAnD,MACE,yCACAkE,UACA,eACAH;QAEF,MAAMN,gBAAgB,MAAMC,AAAAA,IAAAA,oBAAAA,UAAAA,AAAAA,EAC1BJ,cACAY,UACA7D,AAA4B,iBAA5BA,YAAY,WAAW;QAEzBiD,eAAeG,cAAc,WAAW;QAExC,MAAMU,aACJ,AAAwB,YAAxB,OAAOH,eACHA,eACAA,aAAa,MAAM,IAAI;QAE7B,MAAMhB,eAAeoB,AAAAA,IAAAA,gCAAAA,sBAAAA,AAAAA,IAAyB,OAAO,CACnD,qBACAD;QAGF,MAAMR,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,IAAI;YACF,MAAMM,MAAM,MAAMC,AAAAA,IAAAA,yBAAAA,wBAAAA,AAAAA,EAKfF,MAAMtD;YACT,MAAMyD,UAAUF,IAAI,OAAO;YAO3B,IAAIE,QAAQ,KAAK,EAAE;gBACjB9D,MAAM,0CAA0C8D,QAAQ,KAAK;gBAC7D,OAAO;oBAAE,MAAM;oBAAO,QAAQA,QAAQ,KAAK;gBAAC;YAC9C;YAEA,MAAMvB,SAAkC;gBACtC,MAAM,CAAC,CAACuB,QAAQ,KAAK;gBACrB,aAAaA,QAAQ,WAAW;gBAChC,QAAQA,QAAQ,MAAM;YACxB;YAEA9D,MAAM,+BAA+B;gBACnC,MAAMuC,OAAO,IAAI;gBACjB,aAAaA,OAAO,WAAW;gBAC/B,QAAQA,OAAO,MAAM;gBACrB,cAAc4B;YAChB;YAEA,OAAO5B;QACT,EAAE,OAAOE,OAAO;YACdzC,MAAM,+BAA+ByC;YACrC,OAAO;gBAAE,MAAM;gBAAO,QAAQ4B,OAAO5B;YAAO;QAC9C;IACF;IAEA,MAAM,uBACJsB,MAAwB,EACxB1D,WAAyB,EACzB4D,SAAqB,EACkC;QACvD,MAAMnD,UAAUmD,aAAc,MAAM,IAAI,CAAC,kBAAkB;QAC3D,MAAM,EAAEnB,QAAQ,EAAE,GAAGhC;QACrB,MAAMiC,mBAAmBjC,QAAQ,UAAU,CAAC,MAAM;QAClD,IAAI,CAACiC,kBAAkB;QAEvB,MAAMG,kBAAkB;QACxB,MAAMC,aAAmB;YACvB,MAAME,KAAK,KAAK,CAACU,MAAM,CAAC,EAAE,GAAGb,kBAAkB;YAC/C,KAAKG,KAAK,KAAK,CAACU,MAAM,CAAC,EAAE,GAAGb,kBAAkB;YAC9C,OAAOA;YACP,QAAQA;QACV;QAEA,MAAMgB,WAAWV,AAAAA,IAAAA,mCAAAA,gBAAAA,AAAAA,EAAiBL,YAAYL;QAE9C,IAAIQ,eAAe,MAAMC,AAAAA,IAAAA,oBAAAA,uBAAAA,AAAAA,EAAwB;YAC/C,gBAAgBR;YAChB,MAAMD;YACN,sBAAsB;gBAAC;oBAAE,MAAMK;gBAAW;aAAE;YAC5C,iBAAiB;QACnB;QAEA,MAAMM,gBAAgB,MAAMC,AAAAA,IAAAA,oBAAAA,UAAAA,AAAAA,EAC1BJ,cACAY,UACA7D,AAA4B,iBAA5BA,YAAY,WAAW;QAEzBiD,eAAeG,cAAc,WAAW;QAExC,MAAMT,eAAesB,AAAAA,IAAAA,mCAAAA,iCAAAA,AAAAA;QAErB,MAAMX,OAAe;YACnB;gBAAE,MAAM;gBAAU,SAASX;YAAa;YACxC;gBACE,MAAM;gBACN,SAAS;oBACP;wBACE,MAAM;wBACN,WAAW;4BAAE,KAAKM;4BAAc,QAAQ;wBAAM;oBAChD;iBACD;YACH;SACD;QAED,IAAI;YACF,MAAMM,MAAM,MAAMC,AAAAA,IAAAA,yBAAAA,wBAAAA,AAAAA,EAKfF,MAAMtD;YACT,MAAMyD,UAAUF,IAAI,OAAO;YAO3B,IAAIE,QAAQ,KAAK,IAAI,CAACA,QAAQ,iBAAiB,EAAE,YAC/C9D,MAAM,oCAAoC8D,QAAQ,KAAK;YAIzD,MAAMS,YAAyBT,AAAAA,CAAAA,QAAQ,eAAe,IAAI,EAAC,EACxD,MAAM,CAAC,CAACU,IAAMA,EAAE,WAAW,IAAIA,EAAE,KAAK,EACtC,GAAG,CAAC,CAACA,IAAO;oBACX,aAAaA,EAAE,WAAW;oBAC1B,OAAOA,EAAE,KAAK;gBAChB;YAEF,MAAMC,SAA2C;gBAC/C,mBAAmBX,QAAQ,iBAAiB;gBAC5C,oBAAoBA,QAAQ,kBAAkB,IAAI;gBAClD,iBAAiBS;YACnB;YAEAvE,MAAM,kCAAkCyE;YACxC,OAAOA;QACT,EAAE,OAAOhC,OAAO;YACdzC,MAAM,kCAAkCyC;YACxC;QACF;IACF;IAEA,MAAM,uBACJgC,MAAwC,EACxCpE,WAAyB,EACzBqE,iBAAuD,EACvDT,SAAqB,EACgB;QACrC,MAAMnD,UAAUmD,aAAc,MAAM,IAAI,CAAC,kBAAkB;QAC3D,MAAM,EAAEnB,QAAQ,EAAE,GAAGhC;QACrB,MAAMiC,mBAAmBjC,QAAQ,UAAU,CAAC,MAAM;QAClD,IAAI,CAACiC,kBAAkB,OAAO;QAE9B,IAAI4B;QAEJ,KAAK,MAAMC,YAAYH,OAAO,eAAe,CAC3C,IAAIC,kBAAkB,uBAAuB,EAC3C,IAAI;YACF,MAAMpD,OAAO,MAAMoD,kBAAkB,uBAAuB,CAAC;gBAC3D,QAAQ;oBAACE,SAAS,KAAK;iBAAC;YAC1B;YACA,IAAItD,MAAM;gBACRqD,eAAerD;gBACftB,MAAM,wCAAwC4E,SAAS,WAAW;gBAClE;YACF;QACF,EAAE,OAAM;YACN5E,MAAM,yCAAyC4E,SAAS,WAAW;QACrE;QAIJ,IAAIV;QACJ,IAAIS,cAAc;YAChB,MAAME,aAAa;YACnBX,WAAW;gBACT,MAAMb,KAAK,GAAG,CAAC,GAAGsB,aAAa,IAAI,GAAGE;gBACtC,KAAKxB,KAAK,GAAG,CAAC,GAAGsB,aAAa,GAAG,GAAGE;gBACpC,OAAOF,aAAa,KAAK,GAAGE,AAAa,IAAbA;gBAC5B,QAAQF,aAAa,MAAM,GAAGE,AAAa,IAAbA;YAChC;QACF,OACEX,WAAW;YACT,MAAM;YACN,KAAK;YACL,OAAOpB,SAAS,KAAK;YACrB,QAAQA,SAAS,MAAM;QACzB;QAGF,MAAMW,gBAAgB,MAAMC,AAAAA,IAAAA,oBAAAA,UAAAA,AAAAA,EAC1BX,kBACAmB,UACA7D,AAA4B,iBAA5BA,YAAY,WAAW;QAEzB,MAAMiD,eAAuBG,cAAc,WAAW;QAEtD,MAAMT,eAAe8B,AAAAA,IAAAA,0CAAAA,+BAAAA,AAAAA,IAClB,OAAO,CAAC,yBAAyBL,OAAO,iBAAiB,EACzD,OAAO,CAAC,0BAA0BA,OAAO,kBAAkB;QAE9D,MAAMd,OAAe;YACnB;gBAAE,MAAM;gBAAU,SAASX;YAAa;YACxC;gBACE,MAAM;gBACN,SAAS;oBACP;wBACE,MAAM;wBACN,WAAW;4BAAE,KAAKM;4BAAc,QAAQ;wBAAM;oBAChD;iBACD;YACH;SACD;QAED,IAAI;YACF,MAAMM,MAAM,MAAMC,AAAAA,IAAAA,yBAAAA,wBAAAA,AAAAA,EAMfF,MAAMtD;YACT,MAAMyD,UAAUF,IAAI,OAAO;YAQ3B,IACE,CAACE,QAAQ,KAAK,IACd,CAACA,QAAQ,MAAM,IACdA,AAAAA,CAAAA,QAAQ,UAAU,IAAI,KAAK,KAC5B;gBACA9D,MAAM,uDAAuD8D;gBAC7D,OAAO;YACT;YAEA,MAAMiB,iBAAmC;gBACvCjB,QAAQ,MAAM,CAAC,EAAE,GAAGI,SAAS,IAAI;gBACjCJ,QAAQ,MAAM,CAAC,EAAE,GAAGI,SAAS,GAAG;aACjC;YAED,IAAIc;YACJ,IAAIlB,QAAQ,IAAI,EACdkB,eAAe;gBACb,MAAMlB,QAAQ,IAAI,CAAC,IAAI,GAAGI,SAAS,IAAI;gBACvC,KAAKJ,QAAQ,IAAI,CAAC,GAAG,GAAGI,SAAS,GAAG;gBACpC,OAAOJ,QAAQ,IAAI,CAAC,KAAK;gBACzB,QAAQA,QAAQ,IAAI,CAAC,MAAM;YAC7B;YAGF9D,MACE,oCACA+E,gBACA,eACAjB,QAAQ,UAAU;YAGpB,OAAO;gBACL,QAAQiB;gBACR,MAAMC,gBAAgB;oBACpB,MAAMD,cAAc,CAAC,EAAE,GAAG;oBAC1B,KAAKA,cAAc,CAAC,EAAE,GAAG;oBACzB,OAAO;oBACP,QAAQ;gBACV;gBACA,aAAa,CAAC,iBAAiB,EAAEN,OAAO,kBAAkB,EAAE;YAC9D;QACF,EAAE,OAAOhC,OAAO;YACdzC,MAAM,kCAAkCyC;YACxC,OAAO;QACT;IACF;IAvpBA,YACE3B,OAA2D,EAC3DV,GAAoB,CACpB;QAPF;QAEA;QAMEI,IAAAA,sBAAAA,MAAAA,AAAAA,EAAOM,SAAS;QAChB,IAAI,AAAmB,cAAnB,OAAOA,SACT,IAAI,CAAC,kBAAkB,GAAGA;aAE1B,IAAI,CAAC,kBAAkB,GAAG,IAAMmE,QAAQ,OAAO,CAACnE;QAGlD,IAAI,AAAyB,WAAlBV,KAAK,UACd,IAAI,CAAC,QAAQ,GAAGA,IAAI,QAAQ;IAEhC;AA0oBF"}
|