"use strict";
var __webpack_require__ = {};
(()=>{
    __webpack_require__.d = (exports1, definition)=>{
        for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
            enumerable: true,
            get: definition[key]
        });
    };
})();
(()=>{
    __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
    __webpack_require__.r = (exports1)=>{
        if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
            value: 'Module'
        });
        Object.defineProperty(exports1, '__esModule', {
            value: true
        });
    };
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
    default: ()=>Service
});
const util_js_namespaceObject = require("../ai-model/auto-glm/util.js");
const index_js_namespaceObject = require("../ai-model/index.js");
const inspect_js_namespaceObject = require("../ai-model/inspect.js");
const describe_js_namespaceObject = require("../ai-model/prompt/describe.js");
const external_common_js_namespaceObject = require("../common.js");
const external_types_js_namespaceObject = require("../types.js");
const env_namespaceObject = require("@midscene/shared/env");
const img_namespaceObject = require("@midscene/shared/img");
const logger_namespaceObject = require("@midscene/shared/logger");
const utils_namespaceObject = require("@midscene/shared/utils");
const external_utils_js_namespaceObject = require("./utils.js");
function _define_property(obj, key, value) {
    if (key in obj) Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
    });
    else obj[key] = value;
    return obj;
}
const debug = (0, logger_namespaceObject.getDebug)('ai:service');
class Service {
    async locate(query, opt, modelConfig) {
        const queryPrompt = 'string' == typeof query ? query : query.prompt;
        (0, utils_namespaceObject.assert)(queryPrompt, 'query is required for locate');
        (0, utils_namespaceObject.assert)('object' == typeof query, 'query should be an object for locate');
        const globalDeepThinkSwitch = env_namespaceObject.globalConfigManager.getEnvConfigInBoolean(env_namespaceObject.MIDSCENE_FORCE_DEEP_THINK);
        if (globalDeepThinkSwitch) debug('globalDeepThinkSwitch', globalDeepThinkSwitch);
        let searchAreaPrompt;
        if (query.deepThink || globalDeepThinkSwitch) searchAreaPrompt = query.prompt;
        const { modelFamily } = modelConfig;
        if (searchAreaPrompt && !modelFamily) {
            console.warn('The "deepThink" feature is not supported with multimodal LLM. Please config VL model for Midscene. https://midscenejs.com/model-config');
            searchAreaPrompt = void 0;
        }
        if (searchAreaPrompt && (0, util_js_namespaceObject.isAutoGLM)(modelFamily)) {
            console.warn('The "deepThink" feature is not supported with AutoGLM.');
            searchAreaPrompt = void 0;
        }
        const context = opt?.context || await this.contextRetrieverFn();
        let searchArea;
        let searchAreaRawResponse;
        let searchAreaUsage;
        let searchAreaResponse;
        if (searchAreaPrompt) {
            searchAreaResponse = await (0, inspect_js_namespaceObject.AiLocateSection)({
                context,
                sectionDescription: searchAreaPrompt,
                modelConfig
            });
            (0, utils_namespaceObject.assert)(searchAreaResponse.rect, `cannot find search area for "${searchAreaPrompt}"${searchAreaResponse.error ? `: ${searchAreaResponse.error}` : ''}`);
            searchAreaRawResponse = searchAreaResponse.rawResponse;
            searchAreaUsage = searchAreaResponse.usage;
            searchArea = searchAreaResponse.rect;
        }
        const startTime = Date.now();
        const { parseResult, rect, rawResponse, usage, reasoning_content } = await (0, index_js_namespaceObject.AiLocateElement)({
            context,
            targetElementDescription: queryPrompt,
            searchConfig: searchAreaResponse,
            modelConfig
        });
        const timeCost = Date.now() - startTime;
        const taskInfo = {
            ...this.taskInfo ? this.taskInfo : {},
            durationMs: timeCost,
            rawResponse: JSON.stringify(rawResponse),
            formatResponse: JSON.stringify(parseResult),
            usage,
            searchArea,
            searchAreaRawResponse,
            searchAreaUsage,
            reasoning_content
        };
        let errorLog;
        if (parseResult.errors?.length) errorLog = `failed to locate element: \n${parseResult.errors.join('\n')}`;
        const dumpData = {
            type: 'locate',
            userQuery: {
                element: queryPrompt
            },
            matchedElement: [],
            matchedRect: rect,
            data: null,
            taskInfo,
            deepThink: !!searchArea,
            error: errorLog
        };
        const elements = parseResult.elements || [];
        const dump = (0, external_utils_js_namespaceObject.createServiceDump)({
            ...dumpData,
            matchedElement: elements
        });
        if (errorLog) throw new external_types_js_namespaceObject.ServiceError(errorLog, dump);
        if (elements.length > 1) throw new external_types_js_namespaceObject.ServiceError(`locate: multiple elements found, length = ${elements.length}`, dump);
        if (1 === elements.length) return {
            element: {
                center: elements[0].center,
                rect: elements[0].rect,
                description: elements[0].description
            },
            rect,
            dump
        };
        return {
            element: null,
            rect,
            dump
        };
    }
    async extract(dataDemand, modelConfig, opt, pageDescription, multimodalPrompt, context) {
        (0, utils_namespaceObject.assert)(context, 'context is required for extract');
        (0, utils_namespaceObject.assert)('object' == typeof dataDemand || 'string' == typeof dataDemand, `dataDemand should be object or string, but get ${typeof dataDemand}`);
        const startTime = Date.now();
        let parseResult;
        let rawResponse;
        let usage;
        let reasoning_content;
        try {
            const result = await (0, index_js_namespaceObject.AiExtractElementInfo)({
                context,
                dataQuery: dataDemand,
                multimodalPrompt,
                extractOption: opt,
                modelConfig,
                pageDescription
            });
            parseResult = result.parseResult;
            rawResponse = result.rawResponse;
            usage = result.usage;
            reasoning_content = result.reasoning_content;
        } catch (error) {
            if (error instanceof index_js_namespaceObject.AIResponseParseError) {
                const timeCost = Date.now() - startTime;
                const taskInfo = {
                    ...this.taskInfo ? this.taskInfo : {},
                    durationMs: timeCost,
                    rawResponse: error.rawResponse,
                    usage: error.usage
                };
                const dump = (0, external_utils_js_namespaceObject.createServiceDump)({
                    type: 'extract',
                    userQuery: {
                        dataDemand
                    },
                    matchedElement: [],
                    data: null,
                    taskInfo,
                    error: error.message
                });
                throw new external_types_js_namespaceObject.ServiceError(error.message, dump);
            }
            throw error;
        }
        const timeCost = Date.now() - startTime;
        const taskInfo = {
            ...this.taskInfo ? this.taskInfo : {},
            durationMs: timeCost,
            rawResponse,
            formatResponse: JSON.stringify(parseResult),
            usage,
            reasoning_content
        };
        let errorLog;
        if (parseResult.errors?.length) errorLog = `AI response error: \n${parseResult.errors.join('\n')}`;
        const dumpData = {
            type: 'extract',
            userQuery: {
                dataDemand
            },
            matchedElement: [],
            data: null,
            taskInfo,
            error: errorLog
        };
        const { data, thought } = parseResult || {};
        const dump = (0, external_utils_js_namespaceObject.createServiceDump)({
            ...dumpData,
            data
        });
        if (errorLog && !data) throw new external_types_js_namespaceObject.ServiceError(errorLog, dump);
        return {
            data,
            thought,
            usage,
            reasoning_content,
            dump
        };
    }
    async describe(target, modelConfig, opt) {
        (0, utils_namespaceObject.assert)(target, 'target is required for service.describe');
        const context = await this.contextRetrieverFn();
        const { shotSize } = context;
        const screenshotBase64 = context.screenshot.base64;
        (0, utils_namespaceObject.assert)(screenshotBase64, 'screenshot is required for service.describe');
        const { modelFamily } = modelConfig;
        const systemPrompt = (0, describe_js_namespaceObject.elementDescriberInstruction)();
        const defaultRectSize = 30;
        const targetRect = Array.isArray(target) ? {
            left: Math.floor(target[0] - defaultRectSize / 2),
            top: Math.floor(target[1] - defaultRectSize / 2),
            width: defaultRectSize,
            height: defaultRectSize
        } : target;
        let imagePayload = await (0, img_namespaceObject.compositeElementInfoImg)({
            inputImgBase64: screenshotBase64,
            size: shotSize,
            elementsPositionInfo: [
                {
                    rect: targetRect
                }
            ],
            borderThickness: 3
        });
        if (opt?.deepThink) {
            const searchArea = (0, external_common_js_namespaceObject.expandSearchArea)(targetRect, shotSize);
            const widthRatio = searchArea.width / shotSize.width;
            const heightRatio = searchArea.height / shotSize.height;
            if (widthRatio >= 0.5 && heightRatio >= 0.5) {
                debug('describe: cropping to searchArea', searchArea);
                const croppedResult = await (0, img_namespaceObject.cropByRect)(imagePayload, searchArea, 'qwen2.5-vl' === modelFamily);
                imagePayload = croppedResult.imageBase64;
            } else debug('describe: skip cropping, search area too small (%dx%d on %dx%d)', searchArea.width, searchArea.height, shotSize.width, shotSize.height);
        }
        const msgs = [
            {
                role: 'system',
                content: systemPrompt
            },
            {
                role: 'user',
                content: [
                    {
                        type: 'image_url',
                        image_url: {
                            url: imagePayload,
                            detail: 'high'
                        }
                    }
                ]
            }
        ];
        const res = await (0, index_js_namespaceObject.callAIWithObjectResponse)(msgs, modelConfig);
        const { content } = res;
        (0, utils_namespaceObject.assert)(!content.error, `describe failed: ${content.error}`);
        (0, utils_namespaceObject.assert)(content.description, 'failed to describe the element');
        return content;
    }
    constructor(context, opt){
        _define_property(this, "contextRetrieverFn", void 0);
        _define_property(this, "taskInfo", void 0);
        (0, utils_namespaceObject.assert)(context, 'context is required for Service');
        if ('function' == typeof context) this.contextRetrieverFn = context;
        else this.contextRetrieverFn = ()=>Promise.resolve(context);
        if (void 0 !== opt?.taskInfo) this.taskInfo = opt.taskInfo;
    }
}
exports["default"] = __webpack_exports__["default"];
for(var __rspack_i in __webpack_exports__)if (-1 === [
    "default"
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
Object.defineProperty(exports, '__esModule', {
    value: true
});

//# sourceMappingURL=index.js.map