Files
zn-ai/dist-electron/main/main.js.bak
2026-04-12 22:12:57 +08:00

5 lines
42 KiB
JavaScript

"use strict";var we=Object.create;var re=Object.defineProperty;var Ae=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var Se=Object.getPrototypeOf,Ee=Object.prototype.hasOwnProperty;var ve=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ye(e))!Ee.call(n,s)&&s!==t&&re(n,s,{get:()=>e[s],enumerable:!(i=Ae(e,s))||i.enumerable});return n};var Ce=(n,e,t)=>(t=n!=null?we(Se(n)):{},ve(e||!n||!n.__esModule?re(t,"default",{value:n,enumerable:!0}):t,n));const o=require("electron"),De=require("openai"),K=require("util"),d=require("electron-log"),y=require("path"),A=require("fs"),de=require("js-base64"),N=require("node:path"),Ie=require("crypto"),Me=require("electron-squirrel-startup"),Re=require("net"),Oe=require("http"),X=require("child_process"),be=require("events");require("bytenode");const C=require("electron-updater");function ue(n){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const i=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(e,t,i.get?i:{enumerable:!0,get:()=>n[t]})}}return e.default=n,Object.freeze(e)}const W=ue(y),I=ue(A);var c=(n=>(n.EXTERNAL_OPEN="external-open",n.WINDOW_MINIMIZE="window-minimize",n.WINDOW_MAXIMIZE="window-maximize",n.WINDOW_CLOSE="window-close",n.IS_WINDOW_MAXIMIZED="is-window-maximized",n.APP_SET_FRAMELESS="app:set-frameless",n.APP_LOAD_PAGE="app:load-page",n.TAB_CREATE="tab:create",n.TAB_LIST="tab:list",n.TAB_NAVIGATE="tab:navigate",n.TAB_RELOAD="tab:reload",n.TAB_BACK="tab:back",n.TAB_FORWARD="tab:forward",n.TAB_SWITCH="tab:switch",n.TAB_CLOSE="tab:close",n.LOG_TO_MAIN="log-to-main",n.READ_FILE="read-file",n.INVOKE="ipc:invoke",n.INVOKE_ASYNC="ipc:invokeAsync",n.APP_MINIMIZE="app:minimize",n.APP_MAXIMIZE="app:maximize",n.APP_QUIT="app:quit",n.FILE_READ="file:read",n.FILE_WRITE="file:write",n.GET_WINDOW_ID="get-window-id",n.CUSTOM_EVENT="custom:event",n.TIME_UPDATE="time:update",n.RENDERER_IS_READY="renderer-ready",n.SHOW_CONTEXT_MENU="show-context-menu",n.START_A_DIALOGUE="start-a-dialogue",n.OPEN_WINDOW="open-window",n.LOG_DEBUG="log-debug",n.LOG_INFO="log-info",n.LOG_WARN="log-warn",n.LOG_ERROR="log-error",n.CONFIG_UPDATED="config-updated",n.SET_CONFIG="set-config",n.GET_CONFIG="get-config",n.UPDATE_CONFIG="update-config",n.SET_THEME_MODE="set-theme-mode",n.GET_THEME_MODE="get-theme-mode",n.IS_DARK_THEME="is-dark-theme",n.THEME_MODE_UPDATED="theme-mode-updated",n.EXECUTE_SCRIPT="execute-script",n.OPEN_CHANNEL="open-channel",n.SCRIPT_LIST="script:list",n.SCRIPT_GET="script:get",n.SCRIPT_SAVE="script:save",n.SCRIPT_DELETE="script:delete",n.SCRIPT_TOGGLE="script:toggle",n.SCRIPT_RUN="script:run",n.SCRIPT_RECORD_START="script:record-start",n.SCRIPT_RECORD_STOP="script:record-stop",n.SCRIPT_CODEGEN="script:codegen",n.UPDATE_CHECK="update:check",n.UPDATE_DOWNLOAD="update:download",n.UPDATE_INSTALL="update:install",n.UPDATE_VERSION="update:version",n.UPDATE_STATUS_CHANGED="update:status-changed",n))(c||{});const pe={width:1440,height:900,minWidth:1440,minHeight:900};var E=(n=>(n.MAIN="main",n.SETTING="setting",n.DIALOG="dialog",n.LOADING="loading",n))(E||{}),_=(n=>(n.THEME_MODE="themeMode",n.PRIMARY_COLOR="primaryColor",n.LANGUAGE="language",n.FONT_SIZE="fontSize",n.MINIMIZE_TO_TRAY="minimizeToTray",n.PROVIDER="provider",n.DEFAULT_MODEL="defaultModel",n.AUTO_CHECK_UPDATE="autoCheckUpdate",n.AUTO_DOWNLOAD_UPDATE="autoDownloadUpdate",n))(_||{}),D=(n=>(n.CONVERSATION_ITEM="conversation-item",n.CONVERSATION_LIST="conversation-list",n.MESSAGE_ITEM="message-item",n))(D||{}),O=(n=>(n.PIN="pin",n.RENAME="rename",n.DEL="del",n))(O||{}),w=(n=>(n.NEW_CONVERSATION="newConversation",n.SORT_BY="sortBy",n.SORT_BY_CREATE_TIME="sortByCreateTime",n.SORT_BY_UPDATE_TIME="sortByUpdateTime",n.SORT_BY_NAME="sortByName",n.SORT_BY_MODEL="sortByModel",n.SORT_ASCENDING="sortAscending",n.SORT_DESCENDING="sortDescending",n.BATCH_OPERATIONS="batchOperations",n))(w||{}),b=(n=>(n.COPY="copy",n.DELETE="delete",n.SELECT="select",n))(b||{});class Ne{}const Le=K.promisify(I.readdir),Pe=K.promisify(I.stat),We=K.promisify(I.unlink);class J{static _instance;LOG_RETENTION_DAYS=7;CLEANUP_INTERVAL_MS=1440*60*1e3;constructor(){const e=W.join(o.app.getPath("userData"),"logs");try{I.existsSync(e)||I.mkdirSync(e,{recursive:!0})}catch(t){this.error("Failed to create log directory:",t)}d.transports.file.resolvePathFn=()=>{const t=new Date,i=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`;return W.join(e,`${i}.log`)},d.transports.file.format="[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}",d.transports.file.maxSize=10*1024*1024,d.transports.console.level=process.env.NODE_ENV==="development"?"debug":"info",d.transports.file.level="debug",this._setupIpcEvents(),this._rewriteConsole(),this.info("LogService initialized successfully."),this._cleanupOldLogs(),setInterval(()=>this._cleanupOldLogs(),this.CLEANUP_INTERVAL_MS)}_setupIpcEvents(){o.ipcMain.on(c.LOG_DEBUG,(e,t,...i)=>this.debug(t,...i)),o.ipcMain.on(c.LOG_INFO,(e,t,...i)=>this.info(t,...i)),o.ipcMain.on(c.LOG_WARN,(e,t,...i)=>this.warn(t,...i)),o.ipcMain.on(c.LOG_ERROR,(e,t,...i)=>this.error(t,...i))}_rewriteConsole(){console.debug=d.debug,console.log=d.info,console.info=d.info,console.warn=d.warn,console.error=d.error}async _cleanupOldLogs(){try{const e=W.join(o.app.getPath("userData"),"logs");if(!I.existsSync(e))return;const t=new Date,i=new Date(t.getTime()-this.LOG_RETENTION_DAYS*24*60*60*1e3),s=await Le(e);let r=0;for(const a of s){if(!a.endsWith(".log"))continue;const l=W.join(e,a);try{const g=await Pe(l);g.isFile()&&g.birthtime<i&&(await We(l),r++)}catch(g){this.error(`Failed to delete old log file ${l}:`,g)}}r>0&&this.info(`Successfully cleaned up ${r} old log files.`)}catch(e){this.error("Failed to cleanup old logs:",e)}}static getInstance(){return this._instance||(this._instance=new J),this._instance}debug(e,...t){d.debug(e,...t)}info(e,...t){d.info(e,...t)}warn(e,...t){d.warn(e,...t)}error(e,...t){d.error(e,...t)}logApiRequest(e,t={},i="POST"){this.info(`API Request: ${e}, Method: ${i}, Request: ${JSON.stringify(t)}`)}logApiResponse(e,t={},i=200,s=0){i>=400?this.error(`API Error Response: ${e}, Status: ${i}, Response Time: ${s}ms, Response: ${JSON.stringify(t)}`):this.debug(`API Response: ${e}, Status: ${i}, Response Time: ${s}ms, Response: ${JSON.stringify(t)}`)}logUserOperation(e,t="unknown",i={}){this.info(`User Operation: ${e} by ${t}, Details: ${JSON.stringify(i)}`)}}const h=J.getInstance();function Ue(n){const e=n.choices[0];return{isEnd:e?.finish_reason==="stop",result:e?.delta?.content??""}}class ke extends Ne{client;constructor(e,t){super(),this.client=new De({apiKey:e,baseURL:t})}async chat(e,t){const i=Date.now(),s=e[e.length-1];h.logApiRequest("chat.completions.create",{model:t,lastMessage:s?.content?.substring(0,100)+(s?.content?.length>100?"...":""),messageCount:e.length},"POST");try{const r=await this.client.chat.completions.create({model:t,messages:e,stream:!0}),a=Date.now()-i;return h.logApiResponse("chat.completions.create",{success:!0},200,a),{async*[Symbol.asyncIterator](){for await(const l of r)yield Ue(l)}}}catch(r){const a=Date.now()-i;throw h.logApiResponse("chat.completions.create",{error:r instanceof Error?r.message:String(r)},500,a),r}}}function he(n,e){let t=null;return function(...i){t&&clearTimeout(t),t=setTimeout(()=>{n.apply(this,i)},e)}}function Z(n){if(n===null||typeof n!="object")return n;if(Array.isArray(n))return n.map(t=>Z(t));const e=Object.assign({},n);for(const t in e)Object.prototype.hasOwnProperty.call(e,t)&&(e[t]=Z(e[t]));return e}function xe(n){try{return JSON.parse(JSON.stringify(n))}catch(e){return console.error("simpleCloneDeep failed:",e),n}}function Be(n){try{return JSON.parse(de.decode(n))}catch(e){return console.error("parseOpenAISetting failed:",e),{}}}const Ge={[_.THEME_MODE]:"system",[_.PRIMARY_COLOR]:"#BB5BE7",[_.LANGUAGE]:"zh",[_.FONT_SIZE]:14,[_.MINIMIZE_TO_TRAY]:!1,[_.PROVIDER]:"",[_.DEFAULT_MODEL]:null};class Q{static _instance;_config;_configPath;_defaultConfig=Ge;_listeners=[];constructor(){this._configPath=W.join(o.app.getPath("userData"),"config.json"),this._config=this._loadConfig(),this._setupIpcEvents(),h.info("ConfigService initialized successfully.")}_setupIpcEvents(){const t=he(i=>this.update(i),200);o.ipcMain.handle(c.GET_CONFIG,(i,s)=>this.get(s)),o.ipcMain.on(c.SET_CONFIG,(i,s,r)=>this.set(s,r)),o.ipcMain.on(c.UPDATE_CONFIG,(i,s)=>t(s))}static getInstance(){return this._instance||(this._instance=new Q),this._instance}_loadConfig(){try{if(I.existsSync(this._configPath)){const e=I.readFileSync(this._configPath,"utf-8"),t={...this._defaultConfig,...JSON.parse(e)};return h.info("Config loaded successfully from:",this._configPath),t}}catch(e){h.error("Failed to load config:",e)}return{...this._defaultConfig}}_saveConfig(){try{I.mkdirSync(W.dirname(this._configPath),{recursive:!0}),I.writeFileSync(this._configPath,JSON.stringify(this._config,null,2),"utf-8"),this._notifyListeners(),h.info("Config saved successfully to:",this._configPath)}catch(e){h.error("Failed to save config:",e)}}_notifyListeners(){o.BrowserWindow.getAllWindows().forEach(e=>e.webContents.send(c.CONFIG_UPDATED,this._config)),this._listeners.forEach(e=>e({...this._config}))}getConfig(){return xe(this._config)}get(e){return this._config[e]}set(e,t,i=!0){!(e in this._config)||this._config[e]===t||(this._config[e]=t,h.debug(`Config set: ${e} = ${t}`),i&&this._saveConfig())}update(e,t=!0){this._config={...this._config,...e},t&&this._saveConfig()}resetToDefault(){this._config={...this._defaultConfig},h.info("Config reset to default."),this._saveConfig()}onConfigChange(e){return this._listeners.push(e),()=>this._listeners=this._listeners.filter(t=>t!==e)}}const v=Q.getInstance();process.env.BIGMODEL_API_KEY,new Date().getTime(),new Date().getTime(),process.env.DEEPSEEK_API_KEY,new Date().getTime(),new Date().getTime(),process.env.SILICONFLOW_API_KEY,new Date().getTime(),new Date().getTime(),process.env.QIANFAN_API_KEY,new Date().getTime(),new Date().getTime();const $e=()=>{let n=[],e=!1;const t=v.get(_.PROVIDER),i=s=>({...s,openAISetting:typeof s.openAISetting=="string"?Be(s.openAISetting??""):s.openAISetting});try{n=JSON.parse(de.decode(t)),e=!0}catch(s){h.error(`parse base64 provider failed: ${s}`)}if(!e)try{n=JSON.parse(t)}catch(s){h.error(`parse provider failed: ${s}`)}if(n.length)return n.map(i)},He=()=>{try{return $e()}catch(n){return h.error(`get provider config failed: ${n}`),null}};function Fe(n){const e=He();if(!e)throw new Error("provider config not found");for(const t of e)if(t.name===n){if(!t.openAISetting?.apiKey||!t.openAISetting?.baseURL)throw new Error("apiKey or baseURL not found");return new ke(t.openAISetting.apiKey,t.openAISetting.baseURL)}}const ze={minimize:"Minimize",maximize:"Maximize",restore:"Restore",close:"Close"},je={welcome:{helloMessage:"Hello, I'm Diona"},conversation:{placeholder:"Type a message...",newConversation:"New Conversation",selectModel:"Please select model",createConversation:"Create Conversation",searchPlaceholder:"Search conversations...",goSettings:"Go to",settings:"Settings Window",addModel:"to add a model",dialog:{title:"Confirm Deletion",content:"Are you sure you want to delete this conversation?",content_1:"Are you sure you want to delete the selected conversations? This action cannot be undone."},operations:{pin:"Pin Selected",del:"Delete Selected",selectAll:"Select All",cancel:"Cancel"}},sidebar:{conversations:"Conversations",settings:"Settings",help:"Help"},message:{dialog:{title:"Confirm Deletion",messageDelete:"Are you sure you want to delete this message?",batchDelete:"Are you sure you want to delete the selected messages?",copySuccess:"Copied successfully"},batchActions:{deleteSelected:"Delete Selected"},rendering:"Thinking...",stoppedGeneration:"(Stopped generating)",sending:"Sending",stopGeneration:"Stop generating",send:"Send"}},qe={cancel:"Cancel",confirm:"Confirm"},Ye={title:"Settings",base:"Basic Settings",provider:{modelConfig:"Model Configuration"},theme:{label:"Theme Settings",dark:"Dark Theme",light:"Light Theme",system:"System Theme",primaryColor:"Primary Color"},appearance:{fontSize:"Font Size",fontSizeOptions:{10:"Tiny (10px)",12:"Small (12px)",14:"Normal (14px)",16:"Medium (16px)",18:"Large (18px)",20:"Larger (20px)",24:"Extra Large (24px)"}},behavior:{minimizeToTray:"Minimize to tray when closed"},language:{label:"Language"},providers:{defaultModel:"Default Model",apiKey:"API Key",apiUrl:"API URL"}},Xe={conversation:{newConversation:"New Conversation",sortBy:"Sort By",sortByCreateTime:"Sort by Creation Time",sortByUpdateTime:"Sort by Update Time",sortByName:"Sort by Name",sortByModel:"Sort by Model",sortAscending:"Ascending",sortDescending:"Descending",pinConversation:"Pin Conversation",unpinConversation:"Unpin Conversation",renameConversation:"Rename Conversation",delConversation:"Delete Conversation",batchOperations:"Batch Operations"},message:{copyMessage:"Copy Message",deleteMessage:"Delete Message",selectMessage:"Select Message"}},Ze={tooltip:"Diona Application",showWindow:"Show Window",exit:"Exit"},Ke={justNow:"Just now",minutes:"{count} minutes ago",hours:"{count} hours ago",days:"{count} days ago",months:"{count} months ago",years:"{count} years ago",weekday:{sun:"Sunday",mon:"Monday",tue:"Tuesday",wed:"Wednesday",thu:"Thursday",fri:"Friday",sat:"Saturday"}},Je={title:"Diona Application"},Qe={window:ze,main:je,dialog:qe,settings:Ye,menu:Xe,tray:Ze,timeAgo:Ke,app:Je},Ve={minimize:"最小化",maximize:"最大化",restore:"还原",close:"关闭"},et={welcome:{helloMessage:"你好,我是迪奥娜"},conversation:{placeholder:"输入消息...",newConversation:"新对话",selectModel:"请选择模型",createConversation:"创建对话",searchPlaceholder:"搜索对话...",goSettings:"快去",settings:"设置窗口",addModel:"添加模型",dialog:{title:"确认删除",content:"确定要删除这个对话吗?",content_1:"确定要删除选中的对话吗?此操作不可撤销。"},operations:{pin:"置顶所选",del:"删除所选",selectAll:"全选",cancel:"取消"}},sidebar:{conversations:"对话",settings:"设置",help:"帮助"},message:{dialog:{title:"确认删除",messageDelete:"确认删除该条消息?",batchDelete:"确认删除选中的消息?",copySuccess:"复制成功"},batchActions:{deleteSelected:"删除选中项"},rendering:"思考中...",stoppedGeneration:"(已停止生成)",sending:"发送中",stopGeneration:"停止生成",send:"发送"}},tt={cancel:"取消",confirm:"确认"},nt={title:"设置",base:"基础设置",provider:{modelConfig:"模型配置"},providers:{defaultModel:"默认模型",apiKey:"API密钥",apiUrl:"API地址"},theme:{label:"主题设置",dark:"深色主题",light:"浅色主题",system:"跟随系统",primaryColor:"主题颜色"},appearance:{fontSize:"字体大小",fontSizeOptions:{10:"极小 (10px)",12:"小 (12px)",14:"正常 (14px)",16:"中 (16px)",18:"大 (18px)",20:"较大 (20px)",24:"超大 (24px)"}},behavior:{minimizeToTray:"关闭时最小化到托盘"},language:{label:"语言设置"}},it={conversation:{newConversation:"新建对话",sortBy:"排序方式",sortByCreateTime:"按创建时间排序",sortByUpdateTime:"按更新时间排序",sortByName:"按名称排序",sortByModel:"按模型排序",sortAscending:"递增",sortDescending:"递减",pinConversation:"置顶对话",unpinConversation:"取消置顶",renameConversation:"重命名对话",delConversation:"删除对话",batchOperations:"批量操作"},message:{copyMessage:"复制消息",deleteMessage:"删除消息",selectMessage:"选择消息"}},st={tooltip:"迪奥娜",showWindow:"显示窗口",exit:"退出"},rt={justNow:"刚刚",minutes:"{count}分钟前",hours:"{count}小时前",days:"{count}天前",months:"{count}个月前",years:"{count}年前",weekday:{sun:"星期日",mon:"星期一",tue:"星期二",wed:"星期三",thu:"星期四",fri:"星期五",sat:"星期六"}},ot={title:"迪奥娜"},at={window:Ve,main:et,dialog:tt,settings:nt,menu:it,tray:st,timeAgo:rt,app:ot},ct={en:Qe,zh:at};function H(){return n=>{if(n)try{const e=n?.split(".");let t=ct[v.get(_.LANGUAGE)];for(const i of e)t=t[i];return t}catch(e){return h.error("failed to translate key:",n,e),n}}}let G;function ge(){if(G!=null)return G;const n=o.app.getAppPath();return G=N.join(n,"resources","icons","icon.ico"),G}class V{static _instance;_isDark=o.nativeTheme.shouldUseDarkColors;constructor(){const e=v.get(_.THEME_MODE);e&&(o.nativeTheme.themeSource=e,this._isDark=o.nativeTheme.shouldUseDarkColors),this._setupIpcEvent(),h.info("ThemeService initialized successfully.")}_setupIpcEvent(){o.ipcMain.handle(c.SET_THEME_MODE,(e,t)=>(o.nativeTheme.themeSource=t,v.set(_.THEME_MODE,t),o.nativeTheme.shouldUseDarkColors)),o.ipcMain.handle(c.GET_THEME_MODE,()=>o.nativeTheme.themeSource),o.ipcMain.handle(c.IS_DARK_THEME,()=>o.nativeTheme.shouldUseDarkColors),o.nativeTheme.on("updated",()=>{this._isDark=o.nativeTheme.shouldUseDarkColors,o.BrowserWindow.getAllWindows().forEach(e=>e.webContents.send(c.THEME_MODE_UPDATED,this._isDark))})}static getInstance(){return this._instance||(this._instance=new V),this._instance}get isDark(){return this._isDark}get themeMode(){return o.nativeTheme.themeSource}}const oe=V.getInstance(),lt={frame:!1,titleBarStyle:"hidden",trafficLightPosition:{x:-100,y:-100},show:!1,title:"NIANXX",darkTheme:oe.isDark,backgroundColor:oe.isDark?"#2C2C2C":"#FFFFFF",webPreferences:{nodeIntegration:!1,contextIsolation:!0,sandbox:!0,backgroundThrottling:!1,preload:MAIN_WINDOW_VITE_DEV_SERVER_URL?N.join(process.cwd(),"dist-electron/preload/preload.js"):N.join(__dirname,"preload.js")}};class ee{static _instance;_logo=ge();isDev=!!MAIN_WINDOW_VITE_DEV_SERVER_URL;_winStates={main:{instance:void 0,isHidden:!1,onCreate:[],onClosed:[]},setting:{instance:void 0,isHidden:!1,onCreate:[],onClosed:[]},dialog:{instance:void 0,isHidden:!1,onCreate:[],onClosed:[]},login:{instance:void 0,isHidden:!1,onCreate:[],onClosed:[]},loading:{instance:void 0,isHidden:!1,onCreate:[],onClosed:[]}};constructor(){this._setupIpcEvents(),h.info("WindowService initialized successfully.")}_isReallyClose(e){return e===E.MAIN?v.get(_.MINIMIZE_TO_TRAY)===!1:e!==E.SETTING}_setupIpcEvents(){const e=r=>{const a=o.BrowserWindow.fromWebContents(r.sender),l=this.getName(a);this.close(a,this._isReallyClose(l))},t=r=>{o.BrowserWindow.fromWebContents(r.sender)?.minimize()},i=r=>{this.toggleMax(o.BrowserWindow.fromWebContents(r.sender))},s=r=>o.BrowserWindow.fromWebContents(r.sender)?.isMaximized()??!1;o.ipcMain.on(c.WINDOW_CLOSE,e),o.ipcMain.on(c.WINDOW_MINIMIZE,t),o.ipcMain.on(c.WINDOW_MAXIMIZE,i),o.ipcMain.handle(c.IS_WINDOW_MAXIMIZED,s),o.ipcMain.handle(c.APP_LOAD_PAGE,(r,a)=>{const l=o.BrowserWindow.fromWebContents(r.sender);l&&this._loadPage(l,a)})}static getInstance(){return this._instance||(this._instance=new ee),this._instance}create(e,t,i){if(this.get(e))return;const s=this._isHiddenWin(e);let r=this._createWinInstance(e,{...t,...i});return this.isDev&&r.webContents.openDevTools(),!s&&this._setupWinLifecycle(r,e)._loadWindowTemplate(r,e),this._listenWinReady({win:r,isHiddenWin:s,size:t}),s||(this._winStates[e].instance=r,this._winStates[e].onCreate.forEach(a=>a(r))),s&&(this._winStates[e].isHidden=!1,h.info(`Hidden window show: ${e}`)),r}_setupWinLifecycle(e,t){const i=he(()=>!e?.isDestroyed()&&e?.webContents?.send(c.WINDOW_MAXIMIZE+"back",e?.isMaximized()),80);return e.once("closed",()=>{this._winStates[t].onClosed.forEach(s=>s(e)),e?.destroy(),e?.removeListener("resize",i),this._winStates[t].instance=void 0,this._winStates[t].isHidden=!1,h.info(`Window closed: ${t}`)}),e.on("resize",i),this}_listenWinReady(e){const t=()=>{e.win?.once("show",()=>setTimeout(()=>this._applySizeConstraints(e.win,e.size),2)),e.win?.show()};e.isHiddenWin?t():this._addLoadingView(e.win,e.size)?.(t)}_addLoadingView(e,t){let i=!1;const s=r=>{r.sender!==e?.webContents||i||(i=!0,o.ipcMain.removeListener(c.RENDERER_IS_READY,s))};return o.ipcMain.on(c.RENDERER_IS_READY,s),r=>{r()}}_applySizeConstraints(e,t){t.maxHeight&&t.maxWidth&&e.setMaximumSize(t.maxWidth,t.maxHeight),t.minHeight&&t.minWidth&&e.setMinimumSize(t.minWidth,t.minHeight)}_loadPage(e,t){if(MAIN_WINDOW_VITE_DEV_SERVER_URL)return e.loadURL(`${MAIN_WINDOW_VITE_DEV_SERVER_URL}/${t}.html`);e.loadFile(N.join(app.getAppPath(),"dist",`${t}.html`))}_loadWindowTemplate(e,t){this._loadPage(e,"index")}_handleCloseWindowState(e,t){const i=this.getName(e);i&&(t?this._winStates[i].instance=void 0:this._winStates[i].isHidden=!0),setTimeout(()=>{e[t?"close":"hide"]?.(),this._checkAndCloseAllWinodws()},210)}_checkAndCloseAllWinodws(){if(!this._winStates[E.MAIN].instance||this._winStates[E.MAIN].instance?.isDestroyed())return Object.values(this._winStates).forEach(t=>t?.instance?.close());if(!v.get(_.MINIMIZE_TO_TRAY)&&!this.get(E.MAIN)?.isVisible())return Object.values(this._winStates).forEach(t=>!t?.instance?.isVisible()&&t?.instance?.close())}_isHiddenWin(e){return this._winStates[e]&&this._winStates[e].isHidden}_createWinInstance(e,t){return this._isHiddenWin(e)?this._winStates[e].instance:new o.BrowserWindow({...lt,icon:this._logo,...t})}focus(e){if(!e)return;const t=this.getName(e);e?.isMaximized()?(e?.restore(),h.debug(`Window ${t} restored and focused`)):h.debug(`Window ${t} focused`),e?.focus()}close(e,t=!0){if(!e)return;const i=this.getName(e);h.info(`Close window: ${i}, really: ${t}`),this._handleCloseWindowState(e,t)}toggleMax(e){e&&(e.isMaximized()?e.unmaximize():e.maximize())}getName(e){if(e){for(const[t,i]of Object.entries(this._winStates))if(i?.instance===e)return t}}get(e){if(!this._winStates[e].isHidden)return this._winStates[e].instance}onWindowCreate(e,t){this._winStates[e].onCreate.push(t)}onWindowClosed(e,t){this._winStates[e].onClosed.push(t)}}const B=ee.getInstance();let F=H();class te{static _instance;_menuTemplates=new Map;_currentMenu=void 0;constructor(){this._setupIpcListener(),this._setupLanguageChangeListener(),h.info("MenuService initialized successfully.")}_setupIpcListener(){o.ipcMain.handle(c.SHOW_CONTEXT_MENU,(e,t,i)=>new Promise(s=>this.showMenu(t,()=>s(!0),i)))}_setupLanguageChangeListener(){v.onConfigChange(e=>{e[_.LANGUAGE]&&(F=H())})}static getInstance(){return this._instance||(this._instance=new te),this._instance}register(e,t){return this._menuTemplates.set(e,t),e}showMenu(e,t,i){if(this._currentMenu)return;const s=Z(this._menuTemplates.get(e));if(!s){h.warn(`Menu ${e} not found.`),t?.();return}let r=[];try{r=Array.isArray(i)?i:JSON.parse(i??"[]")}catch(u){h.error(`Failed to parse dynamicOptions for menu ${e}: ${u}`)}const a=u=>u.submenu?{...u,label:F(u?.label)??void 0,submenu:u.submenu?.map(f=>a(f))}:{...u,label:F(u?.label)??void 0},l=s.map(u=>{if(!Array.isArray(r)||!r.length)return a(u);const f=r.find(m=>m.id===u.id);if(f){const m={...u,...f};return a(m)}return u.submenu?a({...u,submenu:u.submenu?.map(m=>{const T=r.find(p=>p.id===m.id);return{...m,...T}})}):a(u)}),g=o.Menu.buildFromTemplate(l);this._currentMenu=g,g.popup({callback:()=>{this._currentMenu=void 0,t?.()}})}destroyMenu(e){this._menuTemplates.delete(e)}destroyed(){this._menuTemplates.clear(),this._currentMenu=void 0}}const z=te.getInstance();let x=H();class ne{static _instance;_tray=null;_removeLanguageListener;_setupLanguageChangeListener(){this._removeLanguageListener=v.onConfigChange(e=>{e[_.LANGUAGE]&&(x=H(),this._tray&&this._updateTray())})}_updateTray(){this._tray||(this._tray=new o.Tray(ge()));const e=()=>{const t=B.get(E.MAIN);if(t&&!t?.isDestroyed()&&t?.isVisible()&&!t?.isFocused())return t.focus();if(t?.isMinimized())return t?.restore();t?.isVisible()&&t?.isFocused()||B.create(E.MAIN,pe)};this._tray.setToolTip(x("tray.tooltip")??"Diona Application"),this._tray.setContextMenu(o.Menu.buildFromTemplate([{label:x("tray.showWindow"),accelerator:"CmdOrCtrl+N",click:e},{type:"separator"},{label:x("settings.title"),click:()=>o.ipcMain.emit(`${c.OPEN_WINDOW}:${E.SETTING}`)},{role:"quit",label:x("tray.exit")}])),this._tray.removeAllListeners("click"),this._tray.on("click",e)}constructor(){this._setupLanguageChangeListener(),h.info("TrayService initialized successfully.")}static getInstance(){return this._instance||(this._instance=new ne),this._instance}create(){this._tray||(this._updateTray(),o.app.on("quit",()=>{this.destroy()}))}destroy(){this._tray?.destroy(),this._tray=null,this._removeLanguageListener&&(this._removeLanguageListener(),this._removeLanguageListener=void 0)}}const ae=ne.getInstance();class dt{win;views=new Map;activeId=null;skipNextNavigate=new Map;enabled=!1;constructor(e){this.win=e,this.win.on("resize",()=>this.updateActiveBounds()),this._setupIpcEvents()}_setupIpcEvents(){o.ipcMain.handle(c.TAB_CREATE,(e,t)=>this.create(t)),o.ipcMain.handle(c.TAB_LIST,()=>this.list()),o.ipcMain.handle(c.TAB_NAVIGATE,(e,{tabId:t,url:i})=>{this.navigate(t,i)}),o.ipcMain.handle(c.TAB_RELOAD,(e,t)=>{this.reload(t)}),o.ipcMain.handle(c.TAB_BACK,(e,t)=>{this.goBack(t)}),o.ipcMain.handle(c.TAB_FORWARD,(e,t)=>{this.goForward(t)}),o.ipcMain.handle(c.TAB_SWITCH,(e,t)=>{this.switch(t)}),o.ipcMain.handle(c.TAB_CLOSE,(e,t)=>{this.close(t)})}enable(){this.enabled=!0,this.updateActiveBounds(),this.activeId&&this.attach(this.activeId)}disable(){this.enabled=!1;const e=this.activeId?this.views.get(this.activeId):null;e&&this.win.removeBrowserView(e)}destroy(){this.disable(),this.views.forEach(e=>{e.webContents.destroy()}),this.views.clear(),o.ipcMain.removeHandler(c.TAB_CREATE),o.ipcMain.removeHandler(c.TAB_LIST),o.ipcMain.removeHandler(c.TAB_NAVIGATE),o.ipcMain.removeHandler(c.TAB_RELOAD),o.ipcMain.removeHandler(c.TAB_BACK),o.ipcMain.removeHandler(c.TAB_FORWARD),o.ipcMain.removeHandler(c.TAB_SWITCH),o.ipcMain.removeHandler(c.TAB_CLOSE)}list(){return Array.from(this.views.entries()).map(([e,t])=>this.info(e,t))}create(e,t=!0){const i=Ie.randomUUID(),s=new o.BrowserView({webPreferences:{nodeIntegration:!1,contextIsolation:!0,sandbox:!0,preload:MAIN_WINDOW_VITE_DEV_SERVER_URL?N.join(process.cwd(),"dist-electron/preload/preload.js"):N.join(__dirname,"preload.js")}});this.views.set(i,s),this.enabled&&t&&this.attach(i);const r=e&&e.length>0?e:"about:blank";s.webContents.loadURL(r),this.bindEvents(i,s);const a=this.info(i,s);return this.win.webContents.send("tab-created",a),a}switch(e){this.views.has(e)&&(this.enabled&&this.attach(e),this.win.webContents.send("tab-switched",{tabId:e}))}close(e){const t=this.views.get(e);if(!t)return;this.activeId===e&&(this.win.removeBrowserView(t),this.activeId=null),t.webContents.destroy(),this.views.delete(e),this.win.webContents.send("tab-closed",{tabId:e});const i=this.views.keys().next().value;i&&this.switch(i)}navigate(e,t){const i=this.views.get(e);i&&(this.skipNextNavigate.set(e,!0),i.webContents.loadURL(t))}reload(e){const t=this.views.get(e);t&&t.webContents.reload()}goBack(e){const t=this.views.get(e);t&&t.webContents.canGoBack()&&t.webContents.goBack()}goForward(e){const t=this.views.get(e);t&&t.webContents.canGoForward()&&t.webContents.goForward()}attach(e){if(!this.enabled)return;const t=this.views.get(e);if(t){if(this.activeId&&this.views.get(this.activeId)){const i=this.views.get(this.activeId);this.win.removeBrowserView(i)}this.activeId=e,this.win.addBrowserView(t),this.updateActiveBounds()}}updateActiveBounds(){if(!this.enabled||!this.activeId)return;const e=this.views.get(this.activeId);if(!e)return;const[t,i]=this.win.getContentSize(),s=88,r=8,a=488,l=r,g=s+r,u=t-a-r,f=i-s-r*2;e.setBounds({x:l,y:g,width:Math.max(0,u),height:Math.max(0,f)})}bindEvents(e,t){const i=()=>this.win.webContents.send("tab-updated",this.info(e,t));t.webContents.on("did-start-loading",i),t.webContents.on("did-stop-loading",i),t.webContents.on("did-finish-load",i),t.webContents.on("page-title-updated",i),t.webContents.on("did-navigate",i),t.webContents.on("did-navigate-in-page",i),t.webContents.on("will-navigate",(s,r)=>{if(this.skipNextNavigate.get(e)){this.skipNextNavigate.set(e,!1);return}s.preventDefault(),this.create(r)}),t.webContents.setWindowOpenHandler(({url:s})=>(this.create(s),{action:"deny"}))}info(e,t){const i=t.webContents;return{id:e,url:i.getURL(),title:i.getTitle(),isLoading:i.isLoading(),canGoBack:i.canGoBack(),canGoForward:i.canGoForward()}}}const ce=n=>{if(n){ae.create();return}ae.destroy()},ut=n=>{const e=s=>{h.logUserOperation(`${c.SHOW_CONTEXT_MENU}:${D.CONVERSATION_ITEM}-${s}`),n.webContents.send(`${c.SHOW_CONTEXT_MENU}:${D.CONVERSATION_ITEM}`,s)};z.register(D.CONVERSATION_ITEM,[{id:O.PIN,label:"menu.conversation.pinConversation",click:()=>e(O.PIN)},{id:O.RENAME,label:"menu.conversation.renameConversation",click:()=>e(O.RENAME)},{id:O.DEL,label:"menu.conversation.delConversation",click:()=>e(O.DEL)}]);const t=s=>{h.logUserOperation(`${c.SHOW_CONTEXT_MENU}:${D.CONVERSATION_LIST}-${s}`),n.webContents.send(`${c.SHOW_CONTEXT_MENU}:${D.CONVERSATION_LIST}`,s)};z.register(D.CONVERSATION_LIST,[{id:w.NEW_CONVERSATION,label:"menu.conversation.newConversation",click:()=>t(w.NEW_CONVERSATION)},{type:"separator"},{id:w.SORT_BY,label:"menu.conversation.sortBy",submenu:[{id:w.SORT_BY_CREATE_TIME,label:"menu.conversation.sortByCreateTime",type:"radio",checked:!1,click:()=>t(w.SORT_BY_CREATE_TIME)},{id:w.SORT_BY_UPDATE_TIME,label:"menu.conversation.sortByUpdateTime",type:"radio",checked:!1,click:()=>t(w.SORT_BY_UPDATE_TIME)},{id:w.SORT_BY_NAME,label:"menu.conversation.sortByName",type:"radio",checked:!1,click:()=>t(w.SORT_BY_NAME)},{id:w.SORT_BY_MODEL,label:"menu.conversation.sortByModel",type:"radio",checked:!1,click:()=>t(w.SORT_BY_MODEL)},{type:"separator"},{id:w.SORT_ASCENDING,label:"menu.conversation.sortAscending",type:"radio",checked:!1,click:()=>t(w.SORT_ASCENDING)},{id:w.SORT_DESCENDING,label:"menu.conversation.sortDescending",type:"radio",checked:!1,click:()=>t(w.SORT_DESCENDING)}]},{id:w.BATCH_OPERATIONS,label:"menu.conversation.batchOperations",click:()=>t(w.BATCH_OPERATIONS)}]);const i=s=>{h.logUserOperation(`${c.SHOW_CONTEXT_MENU}:${D.MESSAGE_ITEM}-${s}`),n.webContents.send(`${c.SHOW_CONTEXT_MENU}:${D.MESSAGE_ITEM}`,s)};z.register(D.MESSAGE_ITEM,[{id:b.COPY,label:"menu.message.copyMessage",click:()=>i(b.COPY)},{id:b.SELECT,label:"menu.message.selectMessage",click:()=>i(b.SELECT)},{type:"separator"},{id:b.DELETE,label:"menu.message.deleteMessage",click:()=>i(b.DELETE)}])};function fe(){B.onWindowCreate(E.MAIN,n=>{let e=v.get(_.MINIMIZE_TO_TRAY);v.onConfigChange(i=>{e!==i[_.MINIMIZE_TO_TRAY]&&(e=i[_.MINIMIZE_TO_TRAY],ce(e))}),ce(e),ut(n);const t=new dt(n);t.enable(),n.on("closed",()=>{t.destroy()})}),B.create(E.MAIN,pe),o.ipcMain.on(c.START_A_DIALOGUE,async(n,e)=>{const{providerName:t,messages:i,messageId:s,selectedModel:r}=e,a=B.get(E.MAIN);if(!a)throw new Error("mainWindow not found");try{const g=await Fe(t)?.chat(i,r);if(!g)throw new Error("chunks or stream not found");for await(const u of g){const f={messageId:s,data:u};a.webContents.send(c.START_A_DIALOGUE+"back"+s,f)}}catch(l){const g={messageId:s,data:{isEnd:!0,isError:!0,result:l instanceof Error?l.message:String(l)}};a.webContents.send(c.START_A_DIALOGUE+"back"+s,g)}})}function pt(){if(process.platform==="win32")return"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";if(process.platform==="darwin")return"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";if(process.platform==="linux")return"google-chrome"}function ht(n){return N.join(o.app.getPath("userData"),"profiles",n)}function gt(n){return new Promise(e=>{const t=Re.createServer();t.once("error",i=>e(!0)),t.once("listening",()=>{t.close(),e(!1)}),t.listen(n)})}async function ft(){try{return new Promise(n=>{const e=Oe.get("http://127.0.0.1:9222/json/version",t=>{n(t.statusCode===200)});e.on("error",()=>n(!1)),e.setTimeout(1e3,()=>{e.destroy(),n(!1)})})}catch{return!1}}async function _t(){const n=pt(),e=ht("default");if(d.info(`Launching Chrome with user data dir: ${e}`),await gt(9222)){d.info("Chrome already running on port 9222, skip launching.");return}if(await ft()){d.info("Chrome already running, skip launching.");return}return new Promise((i,s)=>{X.spawn(n,["--remote-debugging-port=9222","--window-size=1920,1080","--window-position=0,0","--no-first-run",`--user-data-dir=${e}`,"--no-default-browser-check","about:blank"],{detached:!0,stdio:"ignore"}).on("error",s),setTimeout(()=>{i(0)},1e3)})}class _e extends be.EventEmitter{async executeScript(e,t){const s=(r,a)=>{const l=r+a;return l.length>32768?l.slice(l.length-32768):l};return await new Promise(r=>{try{const a=t?.roomType??"",l=t?.startTime??"",g=t?.endTime??"",u=t?.operation??"",f=t?.tabIndex??"",m=t?.channels??"",T=t?.startTabIndex??"",p=o.utilityProcess.fork(e,[],{env:{...process.env,ROOM_TYPE:String(a),START_DATE:String(l),END_DATE:String(g),OPERATION:String(u),TAB_INDEX:String(f),CHANNELS:typeof m=="string"?m:JSON.stringify(m),START_TAB_INDEX:String(T)},stdio:"pipe"});let M="",k="";p.stdout&&p.stdout.on("data",S=>{const R=S.toString();M=s(M,R),d.info(`stdout: ${R}`)}),p.stderr&&p.stderr.on("data",S=>{const R=S.toString();k=s(k,R),d.info(`stderr: ${R}`)}),p.on("exit",S=>{d.info(`子进程退出,退出码 ${S}`),r({success:S===0,exitCode:S,stdoutTail:M,stderrTail:k,...S===0?{}:{error:`Script exited with code ${S}`}})})}catch(a){r({success:!1,exitCode:null,stdoutTail:"",stderrTail:"",error:a?.message||"运行 Node 脚本时出错"})}})}}const mt="scripts.meta.json";function L(){return o.app.isPackaged?y.join(__dirname,"scripts"):y.join(process.cwd(),"electron/scripts")}function me(){const n=L();A.existsSync(n)||A.mkdirSync(n,{recursive:!0})}function ie(){return y.join(L(),mt)}function P(){const n=ie();if(!A.existsSync(n))return{scripts:[]};try{const e=A.readFileSync(n,"utf-8"),t=JSON.parse(e);if(t&&Array.isArray(t.scripts))return t}catch(e){d.warn("[script-store-service] Failed to read meta:",e)}return{scripts:[]}}function U(n){me();const e=ie();A.writeFileSync(e,JSON.stringify(n,null,2),"utf-8")}function Tt(n){return n.toLowerCase().replace(/[^a-z0-9\u4e00-\u9fa5]+/g,"-").replace(/^-+|-+$/g,"")||"script"}function wt(n,e){const t=Tt(n);let i=`${t}.mjs`,s=1;for(;e.has(i);)i=`${t}-${s}.mjs`,s++;return i}function At(){const n=L(),e=ie();if(A.existsSync(e))return;if(!A.existsSync(n)){d.info("[script-store-service] Scripts directory does not exist, skipping seed.");return}const t={scripts:[]},i=A.readdirSync(n).filter(s=>s.endsWith(".mjs"));for(const s of i)try{const r=s.replace(/\.mjs$/,""),a=new Date().toISOString();t.scripts.push({id:`seed-${r}`,name:r,description:"",filename:s,enabled:!0,channel:"",createdAt:a,updatedAt:a})}catch(r){d.warn("[script-store-service] Failed to seed script",s,r)}U(t),d.info("[script-store-service] Seeded scripts:",t.scripts.length)}function yt(){me(),At()}function St(){return P().scripts.map(e=>$(e)).sort((e,t)=>new Date(t.updatedAt).getTime()-new Date(e.updatedAt).getTime())}function j(n){const t=P().scripts.find(i=>i.id===n);return t?$(t):null}function Et(n){const t=P().scripts.find(i=>i.id===n);return t?y.join(L(),t.filename):null}function le(n){const e=P(),t=L(),i=new Set(e.scripts.map(u=>u.filename)),s=new Date().toISOString();if(n.id){const u=e.scripts.findIndex(f=>f.id===n.id);if(u>=0){const f=e.scripts[u],m=y.join(t,f.filename);return A.writeFileSync(m,n.code,"utf-8"),e.scripts[u]={...f,name:n.name,description:n.description,channel:n.channel,enabled:n.enabled,updatedAt:s},U(e),$(e.scripts[u])}}const r=wt(n.name,i),a=y.join(t,r);A.writeFileSync(a,n.code,"utf-8");const g={id:`script-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,name:n.name,description:n.description,filename:r,enabled:n.enabled,channel:n.channel,createdAt:s,updatedAt:s};return e.scripts.push(g),U(e),$(g)}function vt(n){const e=P(),t=e.scripts.findIndex(r=>r.id===n);if(t===-1)return!1;const i=e.scripts[t],s=y.join(L(),i.filename);if(A.existsSync(s))try{A.unlinkSync(s)}catch(r){d.warn("[script-store-service] Failed to delete script file:",r)}return e.scripts.splice(t,1),U(e),!0}function Ct(n,e){const t=P(),i=t.scripts.findIndex(s=>s.id===n);return i===-1?!1:(t.scripts[i].enabled=e,t.scripts[i].updatedAt=new Date().toISOString(),U(t),!0)}function Dt(n,e){const t=P(),i=t.scripts.findIndex(s=>s.id===n);return i===-1?!1:(t.scripts[i].lastRun=e,t.scripts[i].updatedAt=new Date().toISOString(),U(t),!0)}function $(n){const e=L(),t=y.join(e,n.filename);let i="";try{A.existsSync(t)&&(i=A.readFileSync(t,"utf-8"))}catch(s){d.warn("[script-store-service] Failed to read script file:",s)}return{...n,code:i}}const It=new _e;async function Mt(n,e){const t=Et(n);if(!t)return{success:!1,exitCode:null,stdoutTail:"",stderrTail:"",error:"Script not found"};const i=await It.executeScript(t,{SCRIPT_ID:n,CHANNEL:e||""});return Dt(n,{time:new Date().toISOString(),success:i.success,error:i.error}),i}const q=new Map;function Y(){return o.app.isPackaged?y.join(__dirname,"scripts"):y.join(process.cwd(),"electron/scripts")}function Rt(){const n=new _e,e=y.dirname(require.resolve("playwright-core")),t=y.join(e,"cli.js");let i=null;o.ipcMain.handle(c.SCRIPT_LIST,async()=>{try{return St()}catch(s){throw d.error("[SCRIPT_LIST] error:",s),s}}),o.ipcMain.handle(c.SCRIPT_GET,async(s,r)=>{try{return j(r)}catch(a){throw d.error("[SCRIPT_GET] error:",a),a}}),o.ipcMain.handle(c.SCRIPT_SAVE,async(s,r)=>{try{return le(r)}catch(a){throw d.error("[SCRIPT_SAVE] error:",a),a}}),o.ipcMain.handle(c.SCRIPT_DELETE,async(s,r)=>{try{return vt(r)}catch(a){throw d.error("[SCRIPT_DELETE] error:",a),a}}),o.ipcMain.handle(c.SCRIPT_TOGGLE,async(s,r,a)=>{try{return Ct(r,a)}catch(l){throw d.error("[SCRIPT_TOGGLE] error:",l),l}}),o.ipcMain.handle(c.SCRIPT_RUN,async(s,r)=>{try{const a=j(r);return await Mt(r,a?.channel)}catch(a){return d.error("[SCRIPT_RUN] error:",a),{success:!1,exitCode:null,stdoutTail:"",stderrTail:"",error:a?.message||"Run failed"}}}),o.ipcMain.handle(c.SCRIPT_RECORD_START,async(s,r)=>{try{i&&(i.kill("SIGINT"),i=null);const a=r||"about:blank";return i=X.spawn(process.execPath,[t,"codegen","--target","javascript","--viewport-size","1920,1080","--color-scheme","light",a],{env:{...process.env,ELECTRON_RUN_AS_NODE:"1"},stdio:"pipe"}),i.on("error",l=>{d.error("[SCRIPT_RECORD_START] Failed to start codegen process:",l)}),i.stdout?.on("data",l=>{d.info(`[SCRIPT_RECORD_START] stdout: ${l.toString()}`)}),i.stderr?.on("data",l=>{d.error(`[SCRIPT_RECORD_START] stderr: ${l.toString()}`)}),{success:!0}}catch(a){return d.error("[SCRIPT_RECORD_START] error:",a),{success:!1,error:a?.message||"Recording start failed"}}}),o.ipcMain.handle(c.SCRIPT_RECORD_STOP,async()=>{try{return i&&(i.kill("SIGINT"),i=null),{success:!0,code:""}}catch(s){return d.error("[SCRIPT_RECORD_STOP] error:",s),{success:!1,error:s?.message||"Recording stop failed"}}}),o.ipcMain.handle(c.SCRIPT_CODEGEN,async(s,r,a)=>{try{const l=j(r);if(!l)return{success:!1,error:"Script not found"};const g=Y(),u=y.join(g,l.filename),f=a||"about:blank";return d.info(`[SCRIPT_CODEGEN] Starting codegen for script ${r} at ${u} with url ${f}`),await new Promise(m=>{const T=X.spawn(process.execPath,[t,"codegen","--target","javascript","-o",u,f],{env:{...process.env,ELECTRON_RUN_AS_NODE:"1"},stdio:"pipe"});T.on("exit",()=>{try{let p=A.readFileSync(u,"utf-8");p.includes("require('playwright')")&&!p.includes("createRequire")&&(p=`import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
${p}`),A.writeFileSync(u,p,"utf-8"),le({id:r,name:l.name,description:l.description,code:p,channel:l.channel,enabled:l.enabled}),m({success:!0,code:p})}catch(p){d.error("[SCRIPT_CODEGEN] Failed to process generated code:",p),m({success:!1,error:p?.message||"Failed to process generated code"})}}),T.on("error",p=>{d.error("[SCRIPT_CODEGEN] Failed to start codegen:",p),m({success:!1,error:p.message})})})}catch(l){return d.error("[SCRIPT_CODEGEN] error:",l),{success:!1,error:l?.message||"Codegen failed"}}}),o.ipcMain.handle(c.OPEN_CHANNEL,async(s,r)=>{try{await _t();const a=Y(),l=y.join(a,"open_all_channel.js");if(q.clear(),Array.isArray(r))for(let u=0;u<r.length;u++){const f=r[u]?.channelName;f&&q.set(String(f),u)}return{success:!0,result:await n.executeScript(l,{channels:r})}}catch(a){return{success:!1,error:a?.message||"open channel failed"}}}),o.ipcMain.handle(c.EXECUTE_SCRIPT,async(s,r)=>{try{const a=r.roomList.find(T=>T.id===r.roomType),g=[["fzName","fg_trace.js"],["mtName","mt_trace.js"],["dyHotelName","dy_hotel_trace.js"],["dyHotSpringName","dy_hot_spring_trace.js"]].filter(([T])=>a?.[T]),u=Y(),f=g.map(([T,p])=>{const M=y.join(u,p);if(!A.existsSync(M))throw new Error(`Script not found for channel ${T}: ${M}`);return{channel:T,scriptPath:M}}),m=[];for(let T=0;T<f.length;T++){const p=f[T],M={fzName:"fliggy",mtName:"meituan",dyHotelName:"douyin",dyHotSpringName:"douyin"},k={fliggy:0,meituan:1,douyin:2},S=M[p.channel],R=S?q.get(S)??k[S]??T:T;d.info(`Launching script for channel ${p.channel}: ${p.scriptPath} (tabIndex: ${R})`);const Te=await n.executeScript(p.scriptPath,{roomType:a[p.channel],startTime:r.startTime,endTime:r.endTime,operation:r.operation,tabIndex:R});m.push({channel:p.channel,scriptPath:p.scriptPath,...Te})}return{success:!0,result:m}}catch(a){return{success:!1,error:a.message}}})}class se{mainWindow=null;static _instance;_initialized=!1;constructor(){C.autoUpdater.autoDownload=!1}init(){this._initialized||(this._initialized=!0,this.setupListeners(),this.registerHandlers())}static getInstance(){return this._instance||(this._instance=new se),this._instance}setMainWindow(e){this.mainWindow=e}setupListeners(){C.autoUpdater.on("checking-for-update",()=>this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"checking"})),C.autoUpdater.on("update-available",e=>this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"available",info:e})),C.autoUpdater.on("update-not-available",()=>this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"not-available"})),C.autoUpdater.on("download-progress",e=>this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"downloading",progress:e})),C.autoUpdater.on("update-downloaded",e=>this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"downloaded",info:e})),C.autoUpdater.on("error",e=>this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"error",error:e.message}))}sendToRenderer(e,t){o.BrowserWindow.getAllWindows().forEach(i=>{i.isDestroyed()||i.webContents.send(e,t)})}registerHandlers(){o.ipcMain.handle(c.UPDATE_CHECK,()=>o.app.isPackaged?C.autoUpdater.checkForUpdates():(this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"checking"}),setTimeout(()=>{this.sendToRenderer(c.UPDATE_STATUS_CHANGED,{status:"not-available"})},1500),null)),o.ipcMain.handle(c.UPDATE_DOWNLOAD,()=>o.app.isPackaged?C.autoUpdater.downloadUpdate():null),o.ipcMain.handle(c.UPDATE_INSTALL,()=>o.app.isPackaged?C.autoUpdater.quitAndInstall():null),o.ipcMain.handle(c.UPDATE_VERSION,()=>o.app.getVersion())}}const Ot=se.getInstance();Ot.init();Me&&o.app.quit();o.app.whenReady().then(()=>{fe(),yt(),Rt()});o.app.on("window-all-closed",()=>{process.platform!=="darwin"&&!v.get(_.MINIMIZE_TO_TRAY)&&(d.info("app closing due to all windows being closed"),o.app.quit())});o.app.on("activate",()=>{o.BrowserWindow.getAllWindows().length===0&&fe()});