"use strict";
var __webpack_require__ = {};
(()=>{
    __webpack_require__.n = (module)=>{
        var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
        __webpack_require__.d(getter, {
            a: getter
        });
        return getter;
    };
})();
(()=>{
    __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__, {
    callAIWithObjectResponse: ()=>callAIWithObjectResponse,
    extractJSONFromCodeBlock: ()=>extractJSONFromCodeBlock,
    preprocessDoubaoBboxJson: ()=>preprocessDoubaoBboxJson,
    resolveReasoningConfig: ()=>resolveReasoningConfig,
    safeParseJson: ()=>safeParseJson,
    callAI: ()=>callAI,
    AIResponseParseError: ()=>AIResponseParseError,
    callAIWithStringResponse: ()=>callAIWithStringResponse
});
const env_namespaceObject = require("@midscene/shared/env");
const logger_namespaceObject = require("@midscene/shared/logger");
const utils_namespaceObject = require("@midscene/shared/utils");
const external_jsonrepair_namespaceObject = require("jsonrepair");
const external_openai_namespaceObject = require("openai");
var external_openai_default = /*#__PURE__*/ __webpack_require__.n(external_openai_namespaceObject);
const util_js_namespaceObject = require("../auto-glm/util.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;
}
class AIResponseParseError extends Error {
    constructor(message, rawResponse, usage){
        super(message), _define_property(this, "usage", void 0), _define_property(this, "rawResponse", void 0);
        this.name = 'AIResponseParseError';
        this.rawResponse = rawResponse;
        this.usage = usage;
    }
}
async function createChatClient({ modelConfig }) {
    const { socksProxy, httpProxy, modelName, openaiBaseURL, openaiApiKey, openaiExtraConfig, modelDescription, uiTarsModelVersion, modelFamily, createOpenAIClient, timeout } = modelConfig;
    let proxyAgent;
    const warnClient = (0, logger_namespaceObject.getDebug)('ai:call', {
        console: true
    });
    const debugProxy = (0, logger_namespaceObject.getDebug)('ai:call:proxy');
    const warnProxy = (0, logger_namespaceObject.getDebug)('ai:call:proxy', {
        console: true
    });
    const sanitizeProxyUrl = (url)=>{
        try {
            const parsed = new URL(url);
            if (parsed.username) {
                parsed.password = '****';
                return parsed.href;
            }
            return url;
        } catch  {
            return url;
        }
    };
    if (httpProxy) {
        debugProxy('using http proxy', sanitizeProxyUrl(httpProxy));
        if (utils_namespaceObject.ifInBrowser) warnProxy('HTTP proxy is configured but not supported in browser environment');
        else {
            const moduleName = 'undici';
            const { ProxyAgent } = await import(moduleName);
            proxyAgent = new ProxyAgent({
                uri: httpProxy
            });
        }
    } else if (socksProxy) {
        debugProxy('using socks proxy', sanitizeProxyUrl(socksProxy));
        if (utils_namespaceObject.ifInBrowser) warnProxy('SOCKS proxy is configured but not supported in browser environment');
        else try {
            const moduleName = 'fetch-socks';
            const { socksDispatcher } = await import(moduleName);
            const proxyUrl = new URL(socksProxy);
            if (!proxyUrl.hostname) throw new Error('SOCKS proxy URL must include a valid hostname');
            const port = Number.parseInt(proxyUrl.port, 10);
            if (!proxyUrl.port || Number.isNaN(port)) throw new Error('SOCKS proxy URL must include a valid port');
            const protocol = proxyUrl.protocol.replace(':', '');
            const socksType = 'socks4' === protocol ? 4 : 'socks5' === protocol ? 5 : 5;
            proxyAgent = socksDispatcher({
                type: socksType,
                host: proxyUrl.hostname,
                port,
                ...proxyUrl.username ? {
                    userId: decodeURIComponent(proxyUrl.username),
                    password: decodeURIComponent(proxyUrl.password || '')
                } : {}
            });
            debugProxy('socks proxy configured successfully', {
                type: socksType,
                host: proxyUrl.hostname,
                port: port
            });
        } catch (error) {
            warnProxy('Failed to configure SOCKS proxy:', error);
            throw new Error(`Invalid SOCKS proxy URL: ${socksProxy}. Expected format: socks4://host:port, socks5://host:port, or with authentication: socks5://user:pass@host:port`);
        }
    }
    const openAIOptions = {
        baseURL: openaiBaseURL,
        apiKey: openaiApiKey,
        ...proxyAgent ? {
            fetchOptions: {
                dispatcher: proxyAgent
            }
        } : {},
        ...openaiExtraConfig,
        ...'number' == typeof timeout ? {
            timeout
        } : {},
        dangerouslyAllowBrowser: true
    };
    const baseOpenAI = new (external_openai_default())(openAIOptions);
    let openai = baseOpenAI;
    if (openai && env_namespaceObject.globalConfigManager.getEnvConfigInBoolean(env_namespaceObject.MIDSCENE_LANGSMITH_DEBUG)) {
        if (utils_namespaceObject.ifInBrowser) throw new Error('langsmith is not supported in browser');
        warnClient('DEBUGGING MODE: langsmith wrapper enabled');
        const langsmithModule = 'langsmith/wrappers';
        const { wrapOpenAI } = await import(langsmithModule);
        openai = wrapOpenAI(openai);
    }
    if (openai && env_namespaceObject.globalConfigManager.getEnvConfigInBoolean(env_namespaceObject.MIDSCENE_LANGFUSE_DEBUG)) {
        if (utils_namespaceObject.ifInBrowser) throw new Error('langfuse is not supported in browser');
        warnClient('DEBUGGING MODE: langfuse wrapper enabled');
        const langfuseModule = '@langfuse/openai';
        const { observeOpenAI } = await import(langfuseModule);
        openai = observeOpenAI(openai);
    }
    if (createOpenAIClient) {
        const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);
        if (wrappedClient) openai = wrappedClient;
    }
    return {
        completion: openai.chat.completions,
        modelName,
        modelDescription,
        uiTarsModelVersion,
        modelFamily
    };
}
async function callAI(messages, modelConfig, options) {
    const { completion, modelName, modelDescription, uiTarsModelVersion, modelFamily } = await createChatClient({
        modelConfig
    });
    const maxTokens = env_namespaceObject.globalConfigManager.getEnvConfigValueAsNumber(env_namespaceObject.MIDSCENE_MODEL_MAX_TOKENS) ?? env_namespaceObject.globalConfigManager.getEnvConfigValueAsNumber(env_namespaceObject.OPENAI_MAX_TOKENS);
    const debugCall = (0, logger_namespaceObject.getDebug)('ai:call');
    const warnCall = (0, logger_namespaceObject.getDebug)('ai:call', {
        console: true
    });
    const debugProfileStats = (0, logger_namespaceObject.getDebug)('ai:profile:stats');
    const debugProfileDetail = (0, logger_namespaceObject.getDebug)('ai:profile:detail');
    const startTime = Date.now();
    const temperature = modelConfig.temperature ?? 0;
    const isStreaming = options?.stream && options?.onChunk;
    let content;
    let accumulated = '';
    let accumulatedReasoning = '';
    let usage;
    let timeCost;
    let requestId;
    const buildUsageInfo = (usageData, requestId)=>{
        if (!usageData) return;
        const cachedInputTokens = usageData?.prompt_tokens_details?.cached_tokens;
        return {
            prompt_tokens: usageData.prompt_tokens ?? 0,
            completion_tokens: usageData.completion_tokens ?? 0,
            total_tokens: usageData.total_tokens ?? 0,
            cached_input: cachedInputTokens ?? 0,
            time_cost: timeCost ?? 0,
            model_name: modelName,
            model_description: modelDescription,
            intent: modelConfig.intent,
            request_id: requestId ?? void 0
        };
    };
    const commonConfig = {
        temperature,
        stream: !!isStreaming,
        max_tokens: maxTokens,
        ...'qwen2.5-vl' === modelFamily ? {
            vl_high_resolution_images: true
        } : {}
    };
    if ((0, util_js_namespaceObject.isAutoGLM)(modelFamily)) {
        commonConfig.top_p = 0.85;
        commonConfig.frequency_penalty = 0.2;
    }
    const mergedEnableReasoning = (()=>{
        const normalizedDeepThink = options?.deepThink === 'unset' ? void 0 : options?.deepThink;
        if (true === normalizedDeepThink) return true;
        if (false === normalizedDeepThink) return false;
        return modelConfig.reasoningEnabled;
    })();
    const { config: reasoningEffortConfig, debugMessage: reasoningEffortDebugMessage, warningMessage } = resolveReasoningConfig({
        reasoningEnabled: mergedEnableReasoning,
        reasoningEffort: modelConfig.reasoningEffort,
        reasoningBudget: modelConfig.reasoningBudget,
        modelFamily
    });
    if (reasoningEffortDebugMessage) debugCall(reasoningEffortDebugMessage);
    if (warningMessage) warnCall(warningMessage);
    try {
        debugCall(`sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`);
        if (isStreaming) {
            const stream = await completion.create({
                model: modelName,
                messages,
                ...commonConfig,
                ...reasoningEffortConfig
            }, {
                stream: true
            });
            requestId = stream._request_id;
            for await (const chunk of stream){
                const content = chunk.choices?.[0]?.delta?.content || '';
                const reasoning_content = chunk.choices?.[0]?.delta?.reasoning_content || '';
                if (chunk.usage) usage = chunk.usage;
                if (content || reasoning_content) {
                    accumulated += content;
                    accumulatedReasoning += reasoning_content;
                    const chunkData = {
                        content,
                        reasoning_content,
                        accumulated,
                        isComplete: false,
                        usage: void 0
                    };
                    options.onChunk(chunkData);
                }
                if (chunk.choices?.[0]?.finish_reason) {
                    timeCost = Date.now() - startTime;
                    if (!usage) {
                        const estimatedTokens = Math.max(1, Math.floor(accumulated.length / 4));
                        usage = {
                            prompt_tokens: estimatedTokens,
                            completion_tokens: estimatedTokens,
                            total_tokens: 2 * estimatedTokens
                        };
                    }
                    const finalChunk = {
                        content: '',
                        accumulated,
                        reasoning_content: '',
                        isComplete: true,
                        usage: buildUsageInfo(usage, requestId)
                    };
                    options.onChunk(finalChunk);
                    break;
                }
            }
            content = accumulated;
            debugProfileStats(`streaming model, ${modelName}, mode, ${modelFamily || 'default'}, cost-ms, ${timeCost}, temperature, ${temperature ?? ''}`);
        } else {
            const retryCount = modelConfig.retryCount ?? 1;
            const retryInterval = modelConfig.retryInterval ?? 2000;
            const maxAttempts = retryCount + 1;
            let lastError;
            for(let attempt = 1; attempt <= maxAttempts; attempt++)try {
                const result = await completion.create({
                    model: modelName,
                    messages,
                    ...commonConfig,
                    ...reasoningEffortConfig
                });
                timeCost = Date.now() - startTime;
                debugProfileStats(`model, ${modelName}, mode, ${modelFamily || 'default'}, ui-tars-version, ${uiTarsModelVersion}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${timeCost}, requestId, ${result._request_id || ''}, temperature, ${temperature ?? ''}`);
                debugProfileDetail(`model usage detail: ${JSON.stringify(result.usage)}`);
                if (!result.choices) throw new Error(`invalid response from LLM service: ${JSON.stringify(result)}`);
                content = result.choices[0].message.content;
                accumulatedReasoning = result.choices[0].message?.reasoning_content || '';
                usage = result.usage;
                requestId = result._request_id;
                if (!content && accumulatedReasoning && ('doubao-vision' === modelFamily || 'doubao-seed' === modelFamily)) {
                    warnCall('empty content from AI model, using reasoning content');
                    content = accumulatedReasoning;
                }
                if (!content) throw new Error('empty content from AI model');
                break;
            } catch (error) {
                lastError = error;
                if (attempt < maxAttempts) {
                    warnCall(`AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`);
                    await new Promise((resolve)=>setTimeout(resolve, retryInterval));
                }
            }
            if (!content) throw lastError;
        }
        debugCall(`response reasoning content: ${accumulatedReasoning}`);
        debugCall(`response content: ${content}`);
        if (isStreaming && !usage) {
            const estimatedTokens = Math.max(1, Math.floor((content || '').length / 4));
            usage = {
                prompt_tokens: estimatedTokens,
                completion_tokens: estimatedTokens,
                total_tokens: 2 * estimatedTokens
            };
        }
        return {
            content: content || '',
            reasoning_content: accumulatedReasoning || void 0,
            usage: buildUsageInfo(usage, requestId),
            isStreamed: !!isStreaming
        };
    } catch (e) {
        warnCall('call AI error', e);
        const newError = new Error(`failed to call ${isStreaming ? 'streaming ' : ''}AI model service (${modelName}): ${e.message}\nTrouble shooting: https://midscenejs.com/model-provider.html`, {
            cause: e
        });
        throw newError;
    }
}
async function callAIWithObjectResponse(messages, modelConfig, options) {
    const response = await callAI(messages, modelConfig, {
        deepThink: options?.deepThink
    });
    (0, utils_namespaceObject.assert)(response, 'empty response');
    const modelFamily = modelConfig.modelFamily;
    const jsonContent = safeParseJson(response.content, modelFamily);
    if ('object' != typeof jsonContent) throw new AIResponseParseError(`failed to parse json response from model (${modelConfig.modelName}): ${response.content}`, response.content, response.usage);
    return {
        content: jsonContent,
        contentString: response.content,
        usage: response.usage,
        reasoning_content: response.reasoning_content
    };
}
async function callAIWithStringResponse(msgs, modelConfig) {
    const { content, usage } = await callAI(msgs, modelConfig);
    return {
        content,
        usage
    };
}
function extractJSONFromCodeBlock(response) {
    try {
        const jsonMatch = response.match(/^\s*(\{[\s\S]*\})\s*$/);
        if (jsonMatch) return jsonMatch[1];
        const codeBlockMatch = response.match(/```(?:json)?\s*(\{[\s\S]*?\})\s*```/);
        if (codeBlockMatch) return codeBlockMatch[1];
        const jsonLikeMatch = response.match(/\{[\s\S]*\}/);
        if (jsonLikeMatch) return jsonLikeMatch[0];
    } catch  {}
    return response;
}
function preprocessDoubaoBboxJson(input) {
    if (input.includes('bbox')) while(/\d+\s+\d+/.test(input))input = input.replace(/(\d+)\s+(\d+)/g, '$1,$2');
    return input;
}
function resolveReasoningConfig({ reasoningEnabled, reasoningEffort, reasoningBudget, modelFamily }) {
    if (void 0 === reasoningEnabled && !reasoningEffort && void 0 === reasoningBudget) return {
        config: {}
    };
    const debugMessages = [];
    const config = {};
    if ('qwen3-vl' === modelFamily || 'qwen3.5' === modelFamily) {
        if (void 0 !== reasoningEnabled) {
            config.enable_thinking = reasoningEnabled;
            debugMessages.push(`enable_thinking=${reasoningEnabled}`);
        }
        if (void 0 !== reasoningBudget) {
            config.thinking_budget = reasoningBudget;
            debugMessages.push(`thinking_budget=${reasoningBudget}`);
        }
    } else if ('doubao-vision' === modelFamily || 'doubao-seed' === modelFamily) {
        if (void 0 !== reasoningEnabled) {
            config.thinking = {
                type: reasoningEnabled ? 'enabled' : 'disabled'
            };
            debugMessages.push(`thinking.type=${reasoningEnabled ? 'enabled' : 'disabled'}`);
        }
        if (reasoningEffort) {
            config.reasoning_effort = reasoningEffort;
            debugMessages.push(`reasoning_effort="${reasoningEffort}"`);
        }
    } else if ('glm-v' === modelFamily) {
        if (void 0 !== reasoningEnabled) {
            config.thinking = {
                type: reasoningEnabled ? 'enabled' : 'disabled'
            };
            debugMessages.push(`thinking.type=${reasoningEnabled ? 'enabled' : 'disabled'}`);
        }
    } else if ('gpt-5' === modelFamily) {
        if (reasoningEffort) {
            config.reasoning = {
                effort: reasoningEffort
            };
            debugMessages.push(`reasoning.effort="${reasoningEffort}"`);
        } else if (true === reasoningEnabled) {
            config.reasoning = {
                effort: 'high'
            };
            debugMessages.push('reasoning.effort="high" (from reasoningEnabled)');
        } else if (false === reasoningEnabled) {
            config.reasoning = {
                effort: 'low'
            };
            debugMessages.push('reasoning.effort="low" (from reasoningEnabled)');
        }
    } else if (!modelFamily) return {
        config: {},
        debugMessage: 'reasoning config ignored: no model_family configured',
        warningMessage: 'Reasoning config is set but no model_family is configured. Set MIDSCENE_MODEL_FAMILY to enable reasoning config pass-through.'
    };
    else if (reasoningEffort) {
        config.reasoning_effort = reasoningEffort;
        debugMessages.push(`reasoning_effort="${reasoningEffort}"`);
    }
    return {
        config,
        debugMessage: debugMessages.length ? `reasoning config for ${modelFamily}: ${debugMessages.join(', ')}` : void 0
    };
}
function normalizeJsonObject(obj) {
    if (null == obj) return obj;
    if (Array.isArray(obj)) return obj.map((item)=>normalizeJsonObject(item));
    if ('object' == typeof obj) {
        const normalized = {};
        for (const [key, value] of Object.entries(obj)){
            const trimmedKey = key.trim();
            let normalizedValue = normalizeJsonObject(value);
            if ('string' == typeof normalizedValue) normalizedValue = normalizedValue.trim();
            normalized[trimmedKey] = normalizedValue;
        }
        return normalized;
    }
    if ('string' == typeof obj) return obj.trim();
    return obj;
}
function safeParseJson(input, modelFamily) {
    const cleanJsonString = extractJSONFromCodeBlock(input);
    if (cleanJsonString?.match(/\((\d+),(\d+)\)/)) return cleanJsonString.match(/\((\d+),(\d+)\)/)?.slice(1).map(Number);
    let parsed;
    let lastError;
    try {
        parsed = JSON.parse(cleanJsonString);
        return normalizeJsonObject(parsed);
    } catch (error) {
        lastError = error;
    }
    try {
        parsed = JSON.parse((0, external_jsonrepair_namespaceObject.jsonrepair)(cleanJsonString));
        return normalizeJsonObject(parsed);
    } catch (error) {
        lastError = error;
    }
    if ('doubao-vision' === modelFamily || 'doubao-seed' === modelFamily || (0, util_js_namespaceObject.isUITars)(modelFamily)) {
        const jsonString = preprocessDoubaoBboxJson(cleanJsonString);
        try {
            parsed = JSON.parse((0, external_jsonrepair_namespaceObject.jsonrepair)(jsonString));
            return normalizeJsonObject(parsed);
        } catch (error) {
            lastError = error;
        }
    }
    throw Error(`failed to parse LLM response into JSON. Error - ${String(lastError ?? 'unknown error')}. Response - \n ${input}`);
}
exports.AIResponseParseError = __webpack_exports__.AIResponseParseError;
exports.callAI = __webpack_exports__.callAI;
exports.callAIWithObjectResponse = __webpack_exports__.callAIWithObjectResponse;
exports.callAIWithStringResponse = __webpack_exports__.callAIWithStringResponse;
exports.extractJSONFromCodeBlock = __webpack_exports__.extractJSONFromCodeBlock;
exports.preprocessDoubaoBboxJson = __webpack_exports__.preprocessDoubaoBboxJson;
exports.resolveReasoningConfig = __webpack_exports__.resolveReasoningConfig;
exports.safeParseJson = __webpack_exports__.safeParseJson;
for(var __rspack_i in __webpack_exports__)if (-1 === [
    "AIResponseParseError",
    "callAI",
    "callAIWithObjectResponse",
    "callAIWithStringResponse",
    "extractJSONFromCodeBlock",
    "preprocessDoubaoBboxJson",
    "resolveReasoningConfig",
    "safeParseJson"
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
Object.defineProperty(exports, '__esModule', {
    value: true
});

//# sourceMappingURL=index.js.map