"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);
})();
var __webpack_exports__ = {};
const external_node_path_namespaceObject = require("node:path");
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
const prompts_namespaceObject = require("@inquirer/prompts");
const playground_namespaceObject = require("@midscene/playground");
const constants_namespaceObject = require("@midscene/shared/constants");
const node_namespaceObject = require("@midscene/shared/node");
const agent_namespaceObject = require("@midscene/core/agent");
const logger_namespaceObject = require("@midscene/shared/logger");
const utils_namespaceObject = require("@midscene/shared/utils");
const defaultAppNameMapping = {
    微信: 'com.tencent.xin',
    企业微信: 'com.tencent.ww',
    微信读书: 'com.tencent.weread',
    微信听书: 'com.tencent.wehear',
    QQ: 'com.tencent.mqq',
    QQ音乐: 'com.tencent.QQMusic',
    QQ阅读: 'com.tencent.qqreaderiphone',
    QQ邮箱: 'com.tencent.qqmail',
    QQ浏览器: 'com.tencent.mttlite',
    TIM: 'com.tencent.tim',
    微视: 'com.tencent.microvision',
    腾讯新闻: 'com.tencent.info',
    腾讯视频: 'com.tencent.live4iphone',
    腾讯动漫: 'com.tencent.ied.app.comic',
    腾讯微云: 'com.tencent.weiyun',
    腾讯体育: 'com.tencent.sportskbs',
    腾讯文档: 'com.tencent.txdocs',
    腾讯翻译君: 'com.tencent.qqtranslator',
    腾讯课堂: 'com.tencent.edu',
    腾讯地图: 'com.tencent.sosomap',
    小鹅拼拼: 'com.tencent.dwdcoco',
    全民k歌: 'com.tencent.QQKSong',
    支付宝: 'com.alipay.iphoneclient',
    钉钉: 'com.laiwang.DingTalk',
    闲鱼: 'com.taobao.fleamarket',
    淘宝: 'com.taobao.taobao4iphone',
    斗鱼: 'tv.douyu.live',
    天猫: 'com.taobao.tmall',
    口碑: 'com.taobao.kbmeishi',
    饿了么: 'me.ele.ios.eleme',
    高德地图: 'com.autonavi.amap',
    UC浏览器: 'com.ucweb.iphone.lowversion',
    一淘: 'com.taobao.etaocoupon',
    飞猪: 'com.taobao.travel',
    虾米音乐: 'com.xiami.spark',
    淘票票: 'com.taobao.movie.MoviePhoneClient',
    优酷: 'com.youku.YouKu',
    菜鸟裹裹: 'com.cainiao.cnwireless',
    土豆视频: 'com.tudou.tudouiphone',
    抖音: 'com.ss.iphone.ugc.Aweme',
    抖音极速版: 'com.ss.iphone.ugc.aweme.lite',
    抖音火山版: 'com.ss.iphone.ugc.Live',
    懂车帝: 'com.ss.ios.auto',
    Tiktok: 'com.zhiliaoapp.musically',
    飞书: 'com.bytedance.ee.lark',
    今日头条: 'com.ss.iphone.article.News',
    西瓜视频: 'com.ss.iphone.article.Video',
    皮皮虾: 'com.bd.iphone.super',
    美团: 'com.meituan.imeituan',
    美团外卖: 'com.meituan.itakeaway',
    大众点评: 'com.dianping.dpscope',
    美团优选: 'com.meituan.iyouxuan',
    美团优选团长: 'com.meituan.igrocery.gh',
    美团骑手: 'com.meituan.banma.homebrew',
    美团开店宝: 'com.meituan.imerchantbiz',
    美团拍店: 'com.meituan.pai',
    美团众包: 'com.meituan.banma.crowdsource',
    美团买菜: 'com.baobaoaichi.imaicai',
    京东: 'com.360buy.jdmobile',
    京东读书: 'com.jd.reader',
    网易新闻: 'com.netease.news',
    网易云音乐: 'com.netease.cloudmusic',
    网易邮箱大师: 'com.netease.macmail',
    网易严选: 'com.netease.yanxuan',
    网易公开课: 'com.netease.videoHD',
    网易有道词典: 'youdaoPro',
    有道云笔记: 'com.youdao.note.YoudaoNoteMac',
    百度: 'com.baidu.BaiduMobile',
    百度网盘: 'com.baidu.netdisk',
    百度贴吧: 'com.baidu.tieba',
    百度地图: 'com.baidu.map',
    百度阅读: 'com.baidu.yuedu',
    百度翻译: 'com.baidu.translate',
    百度文库: 'com.baidu.Wenku',
    百度视频: 'com.baidu.videoiphone',
    百度输入法: 'com.baidu.inputMethod',
    快手: 'com.jiangjia.gif',
    快手极速版: 'com.kuaishou.nebula',
    哔哩哔哩: 'tv.danmaku.bilianime',
    芒果TV: 'com.hunantv.imgotv',
    苏宁易购: 'SuningEMall',
    微博: 'com.sina.weibo',
    微博极速版: 'com.sina.weibolite',
    微博国际: 'com.weibo.international',
    墨客: 'com.moke.moke.iphone',
    豆瓣: 'com.douban.frodo',
    知乎: 'com.zhihu.ios',
    小红书: 'com.xingin.discover',
    喜马拉雅: 'com.gemd.iting',
    得到: 'com.luojilab.LuoJiFM-IOS',
    得物: 'com.siwuai.duapp',
    起点读书: 'm.qidian.QDReaderAppStore',
    番茄小说: 'com.dragon.read',
    书旗小说: 'com.shuqicenter.reader',
    拼多多: 'com.xunmeng.pinduoduo',
    多点: 'com.dmall.dmall',
    便利蜂: 'com.bianlifeng.customer.ios',
    亿通行: 'com.ruubypay.yitongxing',
    云闪付: 'com.unionpay.chsp',
    大都会Metro: 'com.DDH.SHSubway',
    爱奇艺视频: 'com.qiyi.iphone',
    搜狐视频: 'com.sohu.iPhoneVideo',
    搜狐新闻: 'com.sohu.newspaper',
    搜狗浏览器: 'com.sogou.SogouExplorerMobile',
    虎牙: 'com.yy.kiwi',
    比心: 'com.yitan.bixin',
    转转: 'com.wuba.zhuanzhuan',
    YY: 'yyvoice',
    绿洲: 'com.sina.oasis',
    陌陌: 'com.wemomo.momoappdemo1',
    什么值得买: 'com.smzdm.client.ios',
    美团秀秀: 'com.meitu.mtxx',
    唯品会: 'com.vipshop.iphone',
    唱吧: 'com.changba.ktv',
    酷狗音乐: 'com.kugou.kugou1002',
    CSDN: 'net.csdn.CsdnPlus',
    多抓鱼: 'com.duozhuyu.dejavu',
    自如: 'com.ziroom.ZiroomProject',
    携程: 'ctrip.com',
    去哪儿旅行: 'com.qunar.iphoneclient8',
    Xmind: 'net.xmind.brownieapp',
    印象笔记: 'com.yinxiang.iPhone',
    欧陆词典: 'eusoft.eudic.pro',
    115: 'com.115.personal',
    名片全能王: 'com.intsig.camcard.lite',
    中国银行: 'com.boc.BOCMBCI',
    '58同城': 'com.taofang.iphone',
    'Google Chrome': 'com.google.chrome.ios',
    Gmail: 'com.google.Gmail',
    Facebook: 'com.facebook.Facebook',
    Firefox: 'org.mozilla.ios.Firefox',
    Messenger: 'com.facebook.Messenger',
    Instagram: 'com.burbn.instagram',
    Starbucks: 'com.starbucks.mystarbucks',
    'Luckin Coffee': 'com.bjlc.luckycoffee',
    Line: 'jp.naver.line',
    Linkedin: 'com.linkedin.LinkedIn',
    Dcard: 'com.dcard.app.Dcard',
    Youtube: 'com.google.ios.youtube',
    Spotify: 'com.spotify.client',
    Netflix: 'com.netflix.Netflix',
    Twitter: 'com.atebits.Tweetie2',
    WhatsApp: 'net.whatsapp.WhatsApp',
    Safari: 'com.apple.mobilesafari',
    'App Store': 'com.apple.AppStore',
    设置: 'com.apple.Preferences',
    相机: 'com.apple.camera',
    照片: 'com.apple.mobileslideshow',
    时钟: 'com.apple.mobiletimer',
    闹钟: 'com.apple.mobiletimer',
    备忘录: 'com.apple.mobilenotes',
    提醒事项: 'com.apple.reminders',
    快捷指令: 'com.apple.shortcuts',
    天气: 'com.apple.weather',
    日历: 'com.apple.mobilecal',
    地图: 'com.apple.Maps',
    电话: 'com.apple.mobilephone',
    通讯录: 'com.apple.MobileAddressBook',
    信息: 'com.apple.MobileSMS',
    FaceTime: 'com.apple.facetime',
    计算器: 'com.apple.calculator',
    家庭: 'com.apple.Home',
    健康: 'com.apple.Health',
    钱包: 'com.apple.Passbook',
    股市: 'com.apple.stocks',
    图书: 'com.apple.iBooks',
    新闻: 'com.apple.news',
    视频: 'com.apple.tv',
    文件: 'com.apple.DocumentsApp',
    邮件: 'com.apple.mobilemail',
    查找: 'com.apple.findmy',
    翻译: 'com.apple.Translate',
    音乐: 'com.apple.Music',
    播客: 'com.apple.podcasts',
    库乐队: 'com.apple.mobilegarageband',
    语音备忘录: 'com.apple.VoiceMemos',
    iMovie: 'com.apple.iMovie',
    Watch: 'com.apple.Bridge',
    'Apple Store': 'com.apple.store.Jolly',
    TestFlight: 'com.apple.TestFlight',
    Keynote: 'com.apple.Keynote',
    'Keynote 讲演': 'com.apple.Keynote'
};
const external_node_assert_namespaceObject = require("node:assert");
var external_node_assert_default = /*#__PURE__*/ __webpack_require__.n(external_node_assert_namespaceObject);
const core_namespaceObject = require("@midscene/core");
const device_namespaceObject = require("@midscene/core/device");
const core_utils_namespaceObject = require("@midscene/core/utils");
const img_namespaceObject = require("@midscene/shared/img");
const webdriver_namespaceObject = require("@midscene/webdriver");
const debugIOS = (0, logger_namespaceObject.getDebug)('webdriver:ios');
const WDA_MJPEG_SCREENSHOT_QUALITY = 50;
const WDA_MJPEG_FRAMERATE = 30;
const WDA_MJPEG_SCALING_FACTOR = 50;
class IOSWebDriverClient extends webdriver_namespaceObject.WebDriverClient {
    async launchApp(bundleId) {
        this.ensureSession();
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/apps/launch`, {
                bundleId
            });
            debugIOS(`Launched app: ${bundleId}`);
        } catch (error) {
            debugIOS(`Failed to launch app ${bundleId}: ${error}`);
            throw error;
        }
    }
    async activateApp(bundleId) {
        this.ensureSession();
        await this.makeRequest('POST', `/session/${this.sessionId}/wda/apps/activate`, {
            bundleId
        });
    }
    async terminateApp(bundleId) {
        this.ensureSession();
        await this.makeRequest('POST', `/session/${this.sessionId}/wda/apps/terminate`, {
            bundleId
        });
    }
    async openUrl(url) {
        this.ensureSession();
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/url`, {
                url
            });
        } catch (error) {
            debugIOS(`Direct URL opening failed, trying Safari fallback: ${error}`);
            await this.launchApp('com.apple.mobilesafari');
            await new Promise((resolve)=>setTimeout(resolve, 2000));
            await this.makeRequest('POST', `/session/${this.sessionId}/url`, {
                url
            });
        }
    }
    async pressHomeButton() {
        this.ensureSession();
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/pressButton`, {
                name: 'home'
            });
            debugIOS('Home button pressed using hardware key');
        } catch (error) {
            debugIOS(`Failed to press home button: ${error}`);
            throw new Error(`Failed to press home button: ${error}`);
        }
    }
    async appSwitcher() {
        this.ensureSession();
        try {
            const windowSize = await this.getWindowSize();
            debugIOS('Triggering app switcher with slow swipe up gesture');
            const centerX = windowSize.width / 2;
            const startY = windowSize.height - 5;
            const endY = 0.5 * windowSize.height;
            await this.swipe(centerX, startY, centerX, endY, 1500);
            await new Promise((resolve)=>setTimeout(resolve, 800));
        } catch (error) {
            debugIOS(`App switcher failed: ${error}`);
            throw new Error(`Failed to trigger app switcher: ${error}`);
        }
    }
    async pressKey(key) {
        this.ensureSession();
        debugIOS(`Attempting to press key: ${key}`);
        if ('Enter' === key || 'Return' === key || 'return' === key) {
            debugIOS('Handling Enter/Return key for iOS');
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
                value: [
                    '\n'
                ]
            });
            debugIOS('Sent newline character for Enter key');
            await new Promise((resolve)=>setTimeout(resolve, 100));
            return;
        }
        if ('Backspace' === key || 'Delete' === key) try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
                value: [
                    '\b'
                ]
            });
            debugIOS('Sent backspace character');
            return;
        } catch (error) {
            debugIOS(`Backspace failed: ${error}`);
        }
        if ('Space' === key) try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
                value: [
                    ' '
                ]
            });
            debugIOS('Sent space character');
            return;
        } catch (error) {
            debugIOS(`Space key failed: ${error}`);
        }
        const normalizedKey = this.normalizeKeyName(key);
        const iosKeyMap = {
            Tab: '\t',
            ArrowUp: '\uE013',
            ArrowDown: '\uE015',
            ArrowLeft: '\uE012',
            ArrowRight: '\uE014',
            Home: '\uE011',
            End: '\uE010'
        };
        if (iosKeyMap[normalizedKey]) try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
                value: [
                    iosKeyMap[normalizedKey]
                ]
            });
            debugIOS(`Sent WebDriver key code for: ${key}`);
            return;
        } catch (error) {
            debugIOS(`WebDriver key failed for "${key}": ${error}`);
        }
        if (1 === key.length) try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
                value: [
                    key
                ]
            });
            debugIOS(`Sent single character: "${key}"`);
            return;
        } catch (error) {
            debugIOS(`Failed to send character "${key}": ${error}`);
        }
        debugIOS(`Warning: Key "${key}" is not supported on iOS platform`);
        throw new Error(`Key "${key}" is not supported on iOS platform`);
    }
    async getActiveElement() {
        this.ensureSession();
        debugIOS('Getting active element');
        try {
            const response = await this.makeRequest('GET', `/session/${this.sessionId}/element/active`);
            const elementId = response.value?.ELEMENT || response.value?.['element-6066-11e4-a52e-4f735466cecf'] || response.ELEMENT || response['element-6066-11e4-a52e-4f735466cecf'];
            if (elementId) {
                debugIOS(`Got active element ID: ${elementId}`);
                return elementId;
            }
            debugIOS('No active element found');
            return null;
        } catch (error) {
            debugIOS(`Failed to get active element: ${error}`);
            return null;
        }
    }
    async clearElement(elementId) {
        this.ensureSession();
        debugIOS(`Clearing element: ${elementId}`);
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/element/${elementId}/clear`);
            debugIOS('Element cleared successfully');
        } catch (error) {
            debugIOS(`Failed to clear element: ${error}`);
            throw new Error(`Failed to clear element: ${error}`);
        }
    }
    async clearActiveElement() {
        try {
            const elementId = await this.getActiveElement();
            if (!elementId) {
                debugIOS('No active element to clear');
                return false;
            }
            await this.clearElement(elementId);
            return true;
        } catch (error) {
            debugIOS(`Failed to clear active element: ${error}`);
            return false;
        }
    }
    normalizeKeyName(key) {
        return key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
    }
    async dismissKeyboard(keyNames) {
        this.ensureSession();
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keyboard/dismiss`, {
                keyNames: keyNames || [
                    'done'
                ]
            });
            debugIOS('Dismissed keyboard using WDA API');
            return true;
        } catch (error) {
            debugIOS(`Failed to dismiss keyboard: ${error}`);
            return false;
        }
    }
    async typeText(text) {
        this.ensureSession();
        try {
            const cleanText = text.trim();
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
                value: cleanText.split('')
            });
            debugIOS(`Typed text: "${text}"`);
        } catch (error) {
            debugIOS(`Failed to type text "${text}": ${error}`);
            throw new Error(`Failed to type text: ${error}`);
        }
    }
    async tap(x, y) {
        this.ensureSession();
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/wda/tap`, {
                x,
                y
            });
            debugIOS(`Tapped at coordinates (${x}, ${y})`);
        } catch (error) {
            debugIOS(`New tap endpoint failed, trying legacy endpoint: ${error}`);
            try {
                await this.makeRequest('POST', `/session/${this.sessionId}/wda/tap/0`, {
                    x,
                    y
                });
                debugIOS(`Tapped at coordinates (${x}, ${y}) using legacy endpoint`);
            } catch (fallbackError) {
                debugIOS(`Failed to tap at (${x}, ${y}): ${fallbackError}`);
                throw new Error(`Failed to tap at coordinates: ${fallbackError}`);
            }
        }
    }
    async swipe(fromX, fromY, toX, toY, duration = 500) {
        this.ensureSession();
        const actions = {
            actions: [
                {
                    type: 'pointer',
                    id: 'finger1',
                    parameters: {
                        pointerType: 'touch'
                    },
                    actions: [
                        {
                            type: 'pointerMove',
                            duration: 0,
                            x: fromX,
                            y: fromY
                        },
                        {
                            type: 'pointerDown',
                            button: 0
                        },
                        {
                            type: 'pause',
                            duration: 100
                        },
                        {
                            type: 'pointerMove',
                            duration,
                            x: toX,
                            y: toY
                        },
                        {
                            type: 'pointerUp',
                            button: 0
                        }
                    ]
                }
            ]
        };
        await this.makeRequest('POST', `/session/${this.sessionId}/actions`, actions);
        debugIOS(`Swiped using W3C Actions from (${fromX}, ${fromY}) to (${toX}, ${toY}) in ${duration}ms`);
    }
    async longPress(x, y, duration = 1000) {
        this.ensureSession();
        await this.makeRequest('POST', `/session/${this.sessionId}/wda/touchAndHold`, {
            x,
            y,
            duration: duration / 1000
        });
        debugIOS(`Long pressed at coordinates (${x}, ${y}) for ${duration}ms`);
    }
    async doubleTap(x, y) {
        this.ensureSession();
        await this.makeRequest('POST', `/session/${this.sessionId}/wda/doubleTap`, {
            x,
            y
        });
        debugIOS(`Double tapped at coordinates (${x}, ${y})`);
    }
    async tripleTap(x, y) {
        this.ensureSession();
        await this.makeRequest('POST', `/session/${this.sessionId}/wda/tapWithNumberOfTaps`, {
            x,
            y,
            numberOfTaps: 3,
            numberOfTouches: 1
        });
        debugIOS(`Triple tapped at coordinates (${x}, ${y})`);
    }
    async getScreenScale() {
        this.ensureSession();
        try {
            const screenResponse = await this.makeRequest('GET', `/session/${this.sessionId}/wda/screen`);
            if (screenResponse?.value?.scale) {
                debugIOS(`Got screen scale from WDA screen endpoint: ${screenResponse.value.scale}`);
                return screenResponse.value.scale;
            }
        } catch (error) {
            debugIOS(`Failed to get screen scale from /wda/screen: ${error}`);
        }
        try {
            debugIOS('Calculating screen scale from screenshot and window size');
            const [screenshotBase64, windowSize] = await Promise.all([
                this.takeScreenshot(),
                this.getWindowSize()
            ]);
            const { imageInfoOfBase64 } = await import("@midscene/shared/img");
            const { width: screenshotWidth, height: screenshotHeight } = await imageInfoOfBase64(screenshotBase64);
            const scale = Math.max(screenshotWidth, screenshotHeight) / Math.max(windowSize.width, windowSize.height);
            const roundedScale = Math.round(scale);
            debugIOS(`Calculated screen scale: ${roundedScale} (screenshot: ${screenshotWidth}x${screenshotHeight}, window: ${windowSize.width}x${windowSize.height})`);
            return roundedScale;
        } catch (error) {
            debugIOS(`Failed to calculate screen scale: ${error}`);
        }
        debugIOS('No screen scale found');
        return null;
    }
    async createSession(capabilities) {
        const defaultCapabilities = {
            platformName: 'iOS',
            automationName: 'XCUITest',
            shouldUseSingletonTestManager: false,
            shouldUseTestManagerForVisibilityDetection: false,
            ...capabilities
        };
        const session = await super.createSession(defaultCapabilities);
        await this.setupIOSSession();
        return session;
    }
    async setupIOSSession() {
        if (!this.sessionId) return;
        try {
            await this.makeRequest('POST', `/session/${this.sessionId}/appium/settings`, {
                snapshotMaxDepth: 50,
                elementResponseAttributes: 'type,label,name,value,rect,enabled,visible',
                mjpegServerScreenshotQuality: WDA_MJPEG_SCREENSHOT_QUALITY,
                mjpegServerFramerate: WDA_MJPEG_FRAMERATE,
                mjpegScalingFactor: WDA_MJPEG_SCALING_FACTOR
            });
            debugIOS('iOS session configuration applied (including MJPEG settings)');
        } catch (error) {
            debugIOS(`Failed to apply iOS session configuration: ${error}`);
        }
    }
    async executeRequest(method, endpoint, data) {
        return this.makeRequest(method, this.buildSessionEndpoint(endpoint), data);
    }
}
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 debugDevice = (0, logger_namespaceObject.getDebug)('ios:device');
const WDA_HTTP_METHODS = [
    'GET',
    'POST',
    'DELETE',
    'PUT'
];
const DEFAULT_WDA_MJPEG_PORT = 9100;
class device_IOSDevice {
    actionSpace() {
        const defaultActions = [
            (0, device_namespaceObject.defineActionTap)(async (param)=>{
                const element = param.locate;
                external_node_assert_default()(element, 'Element not found, cannot tap');
                await this.mouseClick(element.center[0], element.center[1]);
            }),
            (0, device_namespaceObject.defineActionDoubleClick)(async (param)=>{
                const element = param.locate;
                external_node_assert_default()(element, 'Element not found, cannot double click');
                await this.doubleTap(element.center[0], element.center[1]);
            }),
            (0, device_namespaceObject.defineAction)({
                name: 'Input',
                description: 'Input text into the input field',
                interfaceAlias: 'aiInput',
                paramSchema: core_namespaceObject.z.object({
                    value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
                    autoDismissKeyboard: core_namespaceObject.z.boolean().optional().describe('Whether to dismiss the keyboard after input. Defaults to true if not specified. Set to false to keep the keyboard visible after input.'),
                    mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
                        'replace',
                        'clear',
                        'typeOnly'
                    ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
                    locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
                }),
                call: async (param)=>{
                    const element = param.locate;
                    if ('typeOnly' !== param.mode) await this.clearInput(element);
                    if ('clear' === param.mode) return;
                    if (!param || !param.value) return;
                    const autoDismissKeyboard = param.autoDismissKeyboard ?? this.options?.autoDismissKeyboard;
                    await this.typeText(param.value, {
                        autoDismissKeyboard
                    });
                }
            }),
            (0, device_namespaceObject.defineActionScroll)(async (param)=>{
                const element = param.locate;
                const startingPoint = element ? {
                    left: element.center[0],
                    top: element.center[1]
                } : void 0;
                const scrollToEventName = param?.scrollType;
                if ('scrollToTop' === scrollToEventName) await this.scrollUntilTop(startingPoint);
                else if ('scrollToBottom' === scrollToEventName) await this.scrollUntilBottom(startingPoint);
                else if ('scrollToRight' === scrollToEventName) await this.scrollUntilRight(startingPoint);
                else if ('scrollToLeft' === scrollToEventName) await this.scrollUntilLeft(startingPoint);
                else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
                else {
                    if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await this.scrollUp(param.distance || void 0, startingPoint);
                    else if ('left' === param.direction) await this.scrollLeft(param.distance || void 0, startingPoint);
                    else if ('right' === param.direction) await this.scrollRight(param.distance || void 0, startingPoint);
                    else throw new Error(`Unknown scroll direction: ${param.direction}`);
                    else await this.scrollDown(param?.distance || void 0, startingPoint);
                    await (0, core_utils_namespaceObject.sleep)(500);
                }
            }),
            (0, device_namespaceObject.defineActionDragAndDrop)(async (param)=>{
                const from = param.from;
                const to = param.to;
                external_node_assert_default()(from, 'missing "from" param for drag and drop');
                external_node_assert_default()(to, 'missing "to" param for drag and drop');
                await this.swipe(from.center[0], from.center[1], to.center[0], to.center[1], 1000);
            }),
            (0, device_namespaceObject.defineActionSwipe)(async (param)=>{
                const { startPoint, endPoint, duration, repeatCount } = (0, device_namespaceObject.normalizeMobileSwipeParam)(param, await this.size());
                for(let i = 0; i < repeatCount; i++)await this.swipe(startPoint.x, startPoint.y, endPoint.x, endPoint.y, duration);
            }),
            (0, device_namespaceObject.defineActionKeyboardPress)(async (param)=>{
                await this.pressKey(param.keyName);
            }),
            (0, device_namespaceObject.defineActionCursorMove)(async (param)=>{
                const arrowKey = 'left' === param.direction ? 'ArrowLeft' : 'ArrowRight';
                const times = param.times ?? 1;
                for(let i = 0; i < times; i++){
                    await this.pressKey(arrowKey);
                    await (0, core_utils_namespaceObject.sleep)(100);
                }
            }),
            (0, device_namespaceObject.defineAction)({
                name: 'LongPress',
                description: 'Trigger a long press on the screen at specified element',
                paramSchema: core_namespaceObject.z.object({
                    duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
                    locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
                }),
                call: async (param)=>{
                    const element = param.locate;
                    external_node_assert_default()(element, 'LongPress requires an element to be located');
                    const [x, y] = element.center;
                    await this.longPress(x, y, param?.duration);
                }
            }),
            (0, device_namespaceObject.defineActionClearInput)(async (param)=>{
                await this.clearInput(param.locate);
            })
        ];
        const platformSpecificActions = Object.values(createPlatformActions(this));
        const customActions = this.customActions || [];
        return [
            ...defaultActions,
            ...platformSpecificActions,
            ...customActions
        ];
    }
    describe() {
        return this.description || `Device ID: ${this.deviceId}`;
    }
    async getConnectedDeviceInfo() {
        return await this.wdaBackend.getDeviceInfo();
    }
    async connect() {
        external_node_assert_default()(!this.destroyed, `IOSDevice ${this.deviceId} has been destroyed and cannot execute commands`);
        debugDevice(`Connecting to iOS device: ${this.deviceId}`);
        try {
            await this.wdaManager.start();
            await this.wdaBackend.createSession();
            const deviceInfo = await this.wdaBackend.getDeviceInfo();
            if (deviceInfo?.udid) {
                this.deviceId = deviceInfo.udid;
                debugDevice(`Updated device ID to real UDID: ${this.deviceId}`);
            }
            const size = await this.getScreenSize();
            this.description = `
UDID: ${this.deviceId}${deviceInfo ? `
Name: ${deviceInfo.name}
Model: ${deviceInfo.model}` : ''}
Type: WebDriverAgent
ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
`;
            debugDevice('iOS device connected successfully', this.description);
        } catch (e) {
            debugDevice(`Failed to connect to iOS device: ${e}`);
            throw new Error(`Unable to connect to iOS device ${this.deviceId}: ${e}`);
        }
    }
    setAppNameMapping(mapping) {
        this.appNameMapping = mapping;
    }
    resolveBundleId(appName) {
        const normalizedAppName = (0, utils_namespaceObject.normalizeForComparison)(appName);
        return this.appNameMapping[normalizedAppName];
    }
    async launch(uri) {
        this.uri = uri;
        try {
            debugDevice(`Launching app: ${uri}`);
            if (uri.startsWith('http://') || uri.startsWith('https://') || uri.includes('://')) await this.openUrl(uri);
            else {
                const resolvedUri = this.resolveBundleId(uri) ?? uri;
                await this.wdaBackend.launchApp(resolvedUri);
            }
            debugDevice(`Successfully launched: ${uri}`);
        } catch (error) {
            debugDevice(`Error launching ${uri}: ${error}`);
            throw new Error(`Failed to launch ${uri}: ${error.message}`);
        }
        return this;
    }
    async getElementsInfo() {
        return [];
    }
    async getElementsNodeTree() {
        return {
            node: null,
            children: []
        };
    }
    async initializeDevicePixelRatio() {
        if (this.devicePixelRatioInitialized) return;
        const apiScale = await this.wdaBackend.getScreenScale();
        external_node_assert_default()(apiScale && apiScale > 0, 'Failed to get device pixel ratio from WebDriverAgent API');
        debugDevice(`Got screen scale from WebDriverAgent API: ${apiScale}`);
        this.devicePixelRatio = apiScale;
        this.devicePixelRatioInitialized = true;
    }
    async getScreenSize() {
        await this.initializeDevicePixelRatio();
        const windowSize = await this.wdaBackend.getWindowSize();
        return {
            width: windowSize.width,
            height: windowSize.height,
            scale: this.devicePixelRatio
        };
    }
    async size() {
        const screenSize = await this.getScreenSize();
        return {
            width: screenSize.width,
            height: screenSize.height
        };
    }
    async screenshotBase64() {
        debugDevice('Taking screenshot via WDA');
        try {
            const base64Data = await this.wdaBackend.takeScreenshot();
            const result = (0, img_namespaceObject.createImgBase64ByFormat)('png', base64Data);
            debugDevice('Screenshot taken successfully');
            return result;
        } catch (error) {
            debugDevice(`Screenshot failed: ${error}`);
            throw new Error(`Failed to take screenshot: ${error}`);
        }
    }
    async clearInput(element) {
        if (element) {
            await this.tap(element.center[0], element.center[1]);
            await (0, core_utils_namespaceObject.sleep)(100);
        }
        debugDevice('Attempting to clear input with WebDriver Clear API');
        const cleared = await this.wdaBackend.clearActiveElement();
        cleared ? debugDevice('Successfully cleared input with WebDriver Clear API') : debugDevice('WebDriver Clear API returned false (no active element or clear failed)');
    }
    async url() {
        return '';
    }
    async tap(x, y) {
        await this.wdaBackend.tap(Math.round(x), Math.round(y));
    }
    async mouseClick(x, y) {
        debugDevice(`mouseClick at coordinates (${x}, ${y})`);
        await this.tap(x, y);
    }
    async doubleTap(x, y) {
        await this.wdaBackend.doubleTap(Math.round(x), Math.round(y));
    }
    async tripleTap(x, y) {
        await this.wdaBackend.tripleTap(Math.round(x), Math.round(y));
    }
    async longPress(x, y, duration = 1000) {
        await this.wdaBackend.longPress(Math.round(x), Math.round(y), duration);
    }
    async swipe(fromX, fromY, toX, toY, duration = 500) {
        await this.wdaBackend.swipe(Math.round(fromX), Math.round(fromY), Math.round(toX), Math.round(toY), duration);
    }
    async typeText(text, options) {
        if (!text) return;
        const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
        debugDevice(`Typing text: "${text}"`);
        try {
            await (0, core_utils_namespaceObject.sleep)(200);
            await this.wdaBackend.typeText(text);
            await (0, core_utils_namespaceObject.sleep)(300);
        } catch (error) {
            debugDevice(`Failed to type text with WDA: ${error}`);
            throw error;
        }
        if (shouldAutoDismissKeyboard) await this.hideKeyboard();
    }
    async pressKey(key) {
        await this.wdaBackend.pressKey(key);
    }
    async scrollUp(distance, startPoint) {
        const { width, height } = await this.size();
        const start = startPoint ? {
            x: Math.round(startPoint.left),
            y: Math.round(startPoint.top)
        } : {
            x: Math.round(width / 2),
            y: Math.round(height / 2)
        };
        const scrollDistance = Math.round(distance || height / 3);
        await this.swipe(start.x, start.y, start.x, start.y + scrollDistance);
    }
    async scrollDown(distance, startPoint) {
        const { width, height } = await this.size();
        const start = startPoint ? {
            x: Math.round(startPoint.left),
            y: Math.round(startPoint.top)
        } : {
            x: Math.round(width / 2),
            y: Math.round(height / 2)
        };
        const scrollDistance = Math.round(distance || height / 3);
        await this.swipe(start.x, start.y, start.x, start.y - scrollDistance);
    }
    async scrollLeft(distance, startPoint) {
        const { width, height } = await this.size();
        const start = startPoint ? {
            x: Math.round(startPoint.left),
            y: Math.round(startPoint.top)
        } : {
            x: Math.round(width / 2),
            y: Math.round(height / 2)
        };
        const scrollDistance = Math.round(distance || 0.7 * width);
        await this.swipe(start.x, start.y, start.x + scrollDistance, start.y);
    }
    async scrollRight(distance, startPoint) {
        const { width, height } = await this.size();
        const start = startPoint ? {
            x: Math.round(startPoint.left),
            y: Math.round(startPoint.top)
        } : {
            x: Math.round(width / 2),
            y: Math.round(height / 2)
        };
        const scrollDistance = Math.round(distance || 0.7 * width);
        await this.swipe(start.x, start.y, start.x - scrollDistance, start.y);
    }
    async scrollUntilTop(startPoint) {
        debugDevice('Using screenshot-based scroll detection for better reliability');
        await this.scrollUntilBoundary('up', startPoint, 1);
    }
    async scrollUntilBottom(startPoint) {
        debugDevice('Using screenshot-based scroll detection for better reliability');
        await this.scrollUntilBoundary('down', startPoint, 1);
    }
    compareScreenshots(screenshot1, screenshot2, tolerancePercent = 2) {
        if (screenshot1 === screenshot2) {
            debugDevice('Screenshots are identical');
            return true;
        }
        const len1 = screenshot1.length;
        const len2 = screenshot2.length;
        debugDevice(`Screenshots differ: length1=${len1}, length2=${len2}`);
        if (Math.abs(len1 - len2) > 0.1 * Math.min(len1, len2)) {
            debugDevice('Screenshots have significant length difference');
            return false;
        }
        if (len1 > 0 && len2 > 0) {
            const minLength = Math.min(len1, len2);
            const sampleSize = Math.min(2000, minLength);
            let diffCount = 0;
            for(let i = 0; i < sampleSize; i++)if (screenshot1[i] !== screenshot2[i]) diffCount++;
            const diffPercent = diffCount / sampleSize * 100;
            debugDevice(`Character differences: ${diffCount}/${sampleSize} (${diffPercent.toFixed(2)}%)`);
            const isSimilar = diffPercent <= tolerancePercent;
            if (isSimilar) debugDevice(`Screenshots are similar enough (${diffPercent.toFixed(2)}% <= ${tolerancePercent}%)`);
            return isSimilar;
        }
        return false;
    }
    async scrollUntilBoundary(direction, startPoint, maxUnchangedCount = 1) {
        const maxAttempts = 20;
        const { width, height } = await this.size();
        let start;
        if (startPoint) start = {
            x: Math.round(startPoint.left),
            y: Math.round(startPoint.top)
        };
        else switch(direction){
            case 'up':
                start = {
                    x: Math.round(width / 2),
                    y: Math.round(0.2 * height)
                };
                break;
            case 'down':
                start = {
                    x: Math.round(width / 2),
                    y: Math.round(0.8 * height)
                };
                break;
            case 'left':
                start = {
                    x: Math.round(0.8 * width),
                    y: Math.round(height / 2)
                };
                break;
            case 'right':
                start = {
                    x: Math.round(0.2 * width),
                    y: Math.round(height / 2)
                };
                break;
        }
        let lastScreenshot = null;
        let unchangedCount = 0;
        debugDevice(`Starting scroll to ${direction} with content detection`);
        for(let i = 0; i < maxAttempts; i++)try {
            debugDevice(`Scroll attempt ${i + 1}/${maxAttempts}`);
            await (0, core_utils_namespaceObject.sleep)(500);
            const currentScreenshot = await this.screenshotBase64();
            if (lastScreenshot && this.compareScreenshots(lastScreenshot, currentScreenshot, 10)) {
                unchangedCount++;
                debugDevice(`Screen content unchanged (${unchangedCount}/${maxUnchangedCount})`);
                if (unchangedCount >= maxUnchangedCount) {
                    debugDevice(`Reached ${direction}: screen content no longer changes`);
                    break;
                }
            } else {
                if (lastScreenshot) debugDevice(`Content changed, resetting counter (was ${unchangedCount})`);
                unchangedCount = 0;
            }
            if (i >= 15 && 0 === unchangedCount) {
                debugDevice(`Too many attempts with dynamic content, stopping scroll to ${direction}`);
                break;
            }
            lastScreenshot = currentScreenshot;
            const scrollDistance = Math.round('left' === direction || 'right' === direction ? 0.6 * width : 0.6 * height);
            debugDevice(`Performing scroll: ${direction}, distance: ${scrollDistance}`);
            switch(direction){
                case 'up':
                    await this.swipe(start.x, start.y, start.x, start.y + scrollDistance, 300);
                    break;
                case 'down':
                    await this.swipe(start.x, start.y, start.x, start.y - scrollDistance, 300);
                    break;
                case 'left':
                    await this.swipe(start.x, start.y, start.x + scrollDistance, start.y, 300);
                    break;
                case 'right':
                    await this.swipe(start.x, start.y, start.x - scrollDistance, start.y, 300);
                    break;
            }
            debugDevice('Waiting for scroll and inertia to complete...');
            await (0, core_utils_namespaceObject.sleep)(2000);
        } catch (error) {
            debugDevice(`Error during scroll attempt ${i + 1}: ${error}`);
            await (0, core_utils_namespaceObject.sleep)(300);
        }
        debugDevice(`Scroll to ${direction} completed after ${maxAttempts} attempts`);
    }
    async scrollUntilLeft(startPoint) {
        await this.scrollUntilBoundary('left', startPoint, 1);
    }
    async scrollUntilRight(startPoint) {
        await this.scrollUntilBoundary('right', startPoint, 3);
    }
    async home() {
        await this.wdaBackend.pressHomeButton();
    }
    async appSwitcher() {
        try {
            debugDevice('Triggering app switcher with slow swipe up gesture');
            const { width, height } = await this.size();
            const centerX = Math.round(width / 2);
            const startY = Math.round(height - 5);
            const endY = Math.round(0.5 * height);
            await this.wdaBackend.swipe(centerX, startY, centerX, endY, 1500);
            await (0, core_utils_namespaceObject.sleep)(800);
        } catch (error) {
            debugDevice(`App switcher failed: ${error}`);
            throw new Error(`Failed to trigger app switcher: ${error}`);
        }
    }
    async hideKeyboard(keyNames) {
        try {
            const dismissKeys = keyNames && keyNames.length > 0 ? keyNames : [
                'return',
                'done',
                'go',
                'search',
                'next',
                'send'
            ];
            debugDevice(`Attempting to dismiss keyboard using WDA API with keys: ${dismissKeys.join(', ')}`);
            try {
                await this.wdaBackend.dismissKeyboard(dismissKeys);
                debugDevice('Successfully dismissed keyboard using WDA API');
                await (0, core_utils_namespaceObject.sleep)(500);
                return true;
            } catch (wdaError) {
                debugDevice(`WDA dismissKeyboard failed, falling back to swipe gesture: ${wdaError}`);
            }
            const windowSize = await this.wdaBackend.getWindowSize();
            const centerX = Math.round(windowSize.width / 2);
            const startY = Math.round(0.9 * windowSize.height);
            const endY = Math.round(0.5 * windowSize.height);
            await this.swipe(centerX, startY, centerX, endY, 300);
            debugDevice('Dismissed keyboard with swipe up gesture from bottom of screen');
            await (0, core_utils_namespaceObject.sleep)(500);
            return true;
        } catch (error) {
            debugDevice(`Failed to hide keyboard: ${error}`);
            return false;
        }
    }
    async openUrl(url, options) {
        const opts = {
            useSafariAsBackup: true,
            waitTime: 2000,
            ...options
        };
        try {
            debugDevice(`Opening URL: ${url}`);
            await this.wdaBackend.openUrl(url);
            await (0, core_utils_namespaceObject.sleep)(opts.waitTime);
            debugDevice(`Successfully opened URL: ${url}`);
        } catch (error) {
            debugDevice(`Direct URL opening failed: ${error}`);
            if (opts.useSafariAsBackup) {
                debugDevice(`Attempting to open URL via Safari: ${url}`);
                await this.openUrlViaSafari(url);
            } else throw new Error(`Failed to open URL: ${error}`);
        }
    }
    async openUrlViaSafari(url) {
        try {
            debugDevice(`Opening URL via Safari: ${url}`);
            await this.wdaBackend.terminateApp('com.apple.mobilesafari');
            await this.wdaBackend.launchApp('com.apple.mobilesafari');
            await (0, core_utils_namespaceObject.sleep)(2000);
            await this.typeText(url);
            await (0, core_utils_namespaceObject.sleep)(500);
            await this.pressKey('Return');
            await (0, core_utils_namespaceObject.sleep)(1000);
            try {
                await (0, core_utils_namespaceObject.sleep)(2000);
                debugDevice(`URL opened via Safari: ${url}`);
            } catch (dialogError) {
                debugDevice(`No confirmation dialog or dialog handling failed: ${dialogError}`);
            }
        } catch (error) {
            debugDevice(`Failed to open URL via Safari: ${error}`);
            throw new Error(`Failed to open URL via Safari: ${error}`);
        }
    }
    async runWdaRequest(method, endpoint, data) {
        return await this.wdaBackend.executeRequest(method, endpoint, data);
    }
    async destroy() {
        if (this.destroyed) return;
        try {
            await this.wdaBackend.deleteSession();
            await this.wdaManager.stop();
        } catch (error) {
            debugDevice(`Error during cleanup: ${error}`);
        }
        this.destroyed = true;
        debugDevice(`iOS device ${this.deviceId} destroyed`);
    }
    constructor(options){
        _define_property(this, "deviceId", void 0);
        _define_property(this, "devicePixelRatio", 1);
        _define_property(this, "devicePixelRatioInitialized", false);
        _define_property(this, "destroyed", false);
        _define_property(this, "description", void 0);
        _define_property(this, "customActions", void 0);
        _define_property(this, "wdaBackend", void 0);
        _define_property(this, "wdaManager", void 0);
        _define_property(this, "mjpegStreamUrl", void 0);
        _define_property(this, "appNameMapping", {});
        _define_property(this, "interfaceType", 'ios');
        _define_property(this, "uri", void 0);
        _define_property(this, "options", void 0);
        this.deviceId = 'pending-connection';
        this.options = options;
        this.customActions = options?.customActions;
        const wdaPort = options?.wdaPort || constants_namespaceObject.DEFAULT_WDA_PORT;
        const wdaHost = options?.wdaHost || 'localhost';
        const mjpegPort = options?.wdaMjpegPort ?? DEFAULT_WDA_MJPEG_PORT;
        this.wdaBackend = new IOSWebDriverClient({
            port: wdaPort,
            host: wdaHost
        });
        this.wdaManager = webdriver_namespaceObject.WDAManager.getInstance(wdaPort, wdaHost);
        this.mjpegStreamUrl = `http://${wdaHost}:${mjpegPort}`;
    }
}
const runWdaRequestParamSchema = core_namespaceObject.z.object({
    method: core_namespaceObject.z["enum"](WDA_HTTP_METHODS).describe('HTTP method (GET, POST, DELETE, PUT)'),
    endpoint: core_namespaceObject.z.string().describe('WebDriver API endpoint'),
    data: core_namespaceObject.z.object({}).passthrough().optional().describe('Optional request body data as JSON object')
});
const launchParamSchema = core_namespaceObject.z.string().describe('App name, bundle ID, or URL to launch. Prioritize using the exact bundle ID or URL the user has provided. If none provided, use the accurate app name.');
const createPlatformActions = (device)=>({
        RunWdaRequest: (0, device_namespaceObject.defineAction)({
            name: 'RunWdaRequest',
            description: 'Execute WebDriverAgent API request directly on iOS device',
            interfaceAlias: 'runWdaRequest',
            paramSchema: runWdaRequestParamSchema,
            call: async (param)=>await device.runWdaRequest(param.method, param.endpoint, param.data)
        }),
        Launch: (0, device_namespaceObject.defineAction)({
            name: 'Launch',
            description: 'Launch an iOS app or URL',
            interfaceAlias: 'launch',
            paramSchema: launchParamSchema,
            call: async (param)=>{
                await device.launch(param);
            }
        }),
        IOSHomeButton: (0, device_namespaceObject.defineAction)({
            name: 'IOSHomeButton',
            description: 'Trigger the system "home" operation on iOS devices',
            call: async ()=>{
                await device.home();
            }
        }),
        IOSAppSwitcher: (0, device_namespaceObject.defineAction)({
            name: 'IOSAppSwitcher',
            description: 'Trigger the system "app switcher" operation on iOS devices',
            call: async ()=>{
                await device.appSwitcher();
            }
        })
    });
function agent_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;
}
(0, logger_namespaceObject.getDebug)('ios:agent');
class IOSAgent extends agent_namespaceObject.Agent {
    createActionWrapper(name) {
        const action = this.wrapActionInActionSpace(name);
        return (...args)=>action(args[0]);
    }
    constructor(device, opts){
        super(device, opts), agent_define_property(this, "launch", void 0), agent_define_property(this, "runWdaRequest", void 0), agent_define_property(this, "home", void 0), agent_define_property(this, "appSwitcher", void 0), agent_define_property(this, "appNameMapping", void 0);
        this.appNameMapping = (0, utils_namespaceObject.mergeAndNormalizeAppNameMapping)(defaultAppNameMapping, opts?.appNameMapping);
        device.setAppNameMapping(this.appNameMapping);
        this.launch = this.createActionWrapper('Launch');
        this.runWdaRequest = this.createActionWrapper('RunWdaRequest');
        this.home = this.createActionWrapper('IOSHomeButton');
        this.appSwitcher = this.createActionWrapper('IOSAppSwitcher');
    }
}
async function configureWebDriverAgent() {
    console.log('🔧 WebDriverAgent Configuration');
    console.log(`Default: localhost:${constants_namespaceObject.DEFAULT_WDA_PORT}`);
    const useDefault = await (0, prompts_namespaceObject.select)({
        message: `Use default WebDriverAgent address (localhost:${constants_namespaceObject.DEFAULT_WDA_PORT})?`,
        choices: [
            {
                name: `Yes, use localhost:${constants_namespaceObject.DEFAULT_WDA_PORT}`,
                value: true
            },
            {
                name: 'No, specify custom address',
                value: false
            }
        ]
    });
    if (useDefault) return {
        host: 'localhost',
        port: constants_namespaceObject.DEFAULT_WDA_PORT
    };
    const hostInput = await (0, prompts_namespaceObject.input)({
        message: 'WebDriverAgent host:',
        default: 'localhost'
    });
    const host = hostInput.replace(/^https?:\/\//, '');
    const portInput = await (0, prompts_namespaceObject.input)({
        message: 'WebDriverAgent port:',
        default: constants_namespaceObject.DEFAULT_WDA_PORT.toString()
    });
    const port = Number.parseInt(portInput, 10);
    if (Number.isNaN(port) || port < 1 || port > 65535) {
        console.error(`❌ Invalid port number. Using default ${constants_namespaceObject.DEFAULT_WDA_PORT}.`);
        return {
            host,
            port: constants_namespaceObject.DEFAULT_WDA_PORT
        };
    }
    return {
        host,
        port
    };
}
const staticDir = external_node_path_default().join(__dirname, '../../static');
const main = async ()=>{
    const { default: open } = await import("open");
    try {
        let wdaConfig = {
            host: 'localhost',
            port: constants_namespaceObject.DEFAULT_WDA_PORT
        };
        let connected = false;
        while(!connected)try {
            const device = new device_IOSDevice({
                wdaHost: wdaConfig.host,
                wdaPort: wdaConfig.port
            });
            console.log(`🔌 Connecting to WebDriverAgent at ${wdaConfig.host}:${wdaConfig.port}...`);
            await device.connect();
            connected = true;
            const deviceInfo = await device.getConnectedDeviceInfo();
            console.log('✅ Connected to WebDriverAgent successfully!');
            if (deviceInfo) {
                console.log(`📱 Connected to: ${deviceInfo.name} (${deviceInfo.model})`);
                console.log(`🔑 Device UDID: ${deviceInfo.udid}`);
            }
        } catch (error) {
            console.error(`❌ Failed to connect to WebDriverAgent: ${error instanceof Error ? error.message : String(error)}`);
            const action = await (0, prompts_namespaceObject.select)({
                message: 'What would you like to do?',
                choices: [
                    {
                        name: '🔧 Configure different WebDriverAgent address',
                        value: 'configure'
                    },
                    {
                        name: '📖 Show setup instructions',
                        value: 'instructions'
                    },
                    {
                        name: '🚪 Exit',
                        value: 'exit'
                    }
                ]
            });
            if ('exit' === action) {
                console.log('👋 Goodbye!');
                process.exit(0);
            } else if ('instructions' === action) console.log(`
🔧 WebDriverAgent Setup Instructions:

1. Install WebDriverAgent:
   npm install appium-webdriveragent

2. Open WebDriverAgent project in Xcode:
   node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj

3. Select your target device/simulator in Xcode

4. Build and run the WebDriverAgentRunner scheme

5. WebDriverAgent will bind to your selected device and listen on port ${constants_namespaceObject.DEFAULT_WDA_PORT}

6. Restart this playground to connect

💡 The WebDriverAgent service is already bound to the device you selected in Xcode.
💡 For more details, visit: https://github.com/appium/WebDriverAgent
`);
            else if ('configure' === action) wdaConfig = await configureWebDriverAgent();
        }
        const agentFactory = async ()=>{
            const newDevice = new device_IOSDevice({
                wdaHost: wdaConfig.host,
                wdaPort: wdaConfig.port
            });
            await newDevice.connect();
            return new IOSAgent(newDevice);
        };
        const playgroundServer = new playground_namespaceObject.PlaygroundServer(agentFactory, staticDir);
        console.log('🚀 Starting server...');
        const availablePlaygroundPort = await (0, node_namespaceObject.findAvailablePort)(constants_namespaceObject.PLAYGROUND_SERVER_PORT);
        if (availablePlaygroundPort !== constants_namespaceObject.PLAYGROUND_SERVER_PORT) console.log(`⚠️  Port ${constants_namespaceObject.PLAYGROUND_SERVER_PORT} is busy, using port ${availablePlaygroundPort} instead`);
        await playgroundServer.launch(availablePlaygroundPort);
        console.log('');
        console.log('✨ Midscene iOS Playground is ready!');
        console.log(`🎮 Playground: http://localhost:${playgroundServer.port}`);
        console.log('📱 Device: WebDriverAgent Connected');
        console.log(`🔧 WebDriverAgent: ${wdaConfig.host}:${wdaConfig.port}`);
        console.log(`🔑 Generated Server ID: ${playgroundServer.id}`);
        console.log('');
        open(`http://localhost:${playgroundServer.port}`);
    } catch (error) {
        console.error('Failed to start server:', error);
        process.exit(1);
    }
};
main();
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
Object.defineProperty(exports, '__esModule', {
    value: true
});
