libre-webui 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +204 -0
  3. package/backend/dist/db.d.ts +19 -0
  4. package/backend/dist/db.d.ts.map +1 -0
  5. package/backend/dist/db.js +355 -0
  6. package/backend/dist/db.js.map +1 -0
  7. package/backend/dist/env.d.ts +2 -0
  8. package/backend/dist/env.d.ts.map +1 -0
  9. package/backend/dist/env.js +22 -0
  10. package/backend/dist/env.js.map +1 -0
  11. package/backend/dist/index.d.ts +4 -0
  12. package/backend/dist/index.d.ts.map +1 -0
  13. package/backend/dist/index.js +751 -0
  14. package/backend/dist/index.js.map +1 -0
  15. package/backend/dist/middleware/auth.d.ts +18 -0
  16. package/backend/dist/middleware/auth.d.ts.map +1 -0
  17. package/backend/dist/middleware/auth.js +98 -0
  18. package/backend/dist/middleware/auth.js.map +1 -0
  19. package/backend/dist/middleware/index.d.ts +5 -0
  20. package/backend/dist/middleware/index.d.ts.map +1 -0
  21. package/backend/dist/middleware/index.js +62 -0
  22. package/backend/dist/middleware/index.js.map +1 -0
  23. package/backend/dist/models/personaModel.d.ts +37 -0
  24. package/backend/dist/models/personaModel.d.ts.map +1 -0
  25. package/backend/dist/models/personaModel.js +269 -0
  26. package/backend/dist/models/personaModel.js.map +1 -0
  27. package/backend/dist/models/userModel.d.ts +86 -0
  28. package/backend/dist/models/userModel.d.ts.map +1 -0
  29. package/backend/dist/models/userModel.js +212 -0
  30. package/backend/dist/models/userModel.js.map +1 -0
  31. package/backend/dist/routes/auth.d.ts +3 -0
  32. package/backend/dist/routes/auth.d.ts.map +1 -0
  33. package/backend/dist/routes/auth.js +389 -0
  34. package/backend/dist/routes/auth.js.map +1 -0
  35. package/backend/dist/routes/chat.d.ts +3 -0
  36. package/backend/dist/routes/chat.d.ts.map +1 -0
  37. package/backend/dist/routes/chat.js +767 -0
  38. package/backend/dist/routes/chat.js.map +1 -0
  39. package/backend/dist/routes/documents.d.ts +3 -0
  40. package/backend/dist/routes/documents.d.ts.map +1 -0
  41. package/backend/dist/routes/documents.js +244 -0
  42. package/backend/dist/routes/documents.js.map +1 -0
  43. package/backend/dist/routes/ollama.d.ts +3 -0
  44. package/backend/dist/routes/ollama.d.ts.map +1 -0
  45. package/backend/dist/routes/ollama.js +549 -0
  46. package/backend/dist/routes/ollama.js.map +1 -0
  47. package/backend/dist/routes/personas.d.ts +3 -0
  48. package/backend/dist/routes/personas.d.ts.map +1 -0
  49. package/backend/dist/routes/personas.js +505 -0
  50. package/backend/dist/routes/personas.js.map +1 -0
  51. package/backend/dist/routes/plugins.d.ts +3 -0
  52. package/backend/dist/routes/plugins.d.ts.map +1 -0
  53. package/backend/dist/routes/plugins.js +417 -0
  54. package/backend/dist/routes/plugins.js.map +1 -0
  55. package/backend/dist/routes/preferences.d.ts +3 -0
  56. package/backend/dist/routes/preferences.d.ts.map +1 -0
  57. package/backend/dist/routes/preferences.js +303 -0
  58. package/backend/dist/routes/preferences.js.map +1 -0
  59. package/backend/dist/routes/tts.d.ts +3 -0
  60. package/backend/dist/routes/tts.d.ts.map +1 -0
  61. package/backend/dist/routes/tts.js +304 -0
  62. package/backend/dist/routes/tts.js.map +1 -0
  63. package/backend/dist/routes/users.d.ts +3 -0
  64. package/backend/dist/routes/users.d.ts.map +1 -0
  65. package/backend/dist/routes/users.js +246 -0
  66. package/backend/dist/routes/users.js.map +1 -0
  67. package/backend/dist/services/authService.d.ts +51 -0
  68. package/backend/dist/services/authService.d.ts.map +1 -0
  69. package/backend/dist/services/authService.js +153 -0
  70. package/backend/dist/services/authService.js.map +1 -0
  71. package/backend/dist/services/chatService.d.ts +52 -0
  72. package/backend/dist/services/chatService.d.ts.map +1 -0
  73. package/backend/dist/services/chatService.js +645 -0
  74. package/backend/dist/services/chatService.js.map +1 -0
  75. package/backend/dist/services/documentService.d.ts +34 -0
  76. package/backend/dist/services/documentService.d.ts.map +1 -0
  77. package/backend/dist/services/documentService.js +428 -0
  78. package/backend/dist/services/documentService.js.map +1 -0
  79. package/backend/dist/services/encryptionService.d.ts +62 -0
  80. package/backend/dist/services/encryptionService.d.ts.map +1 -0
  81. package/backend/dist/services/encryptionService.js +284 -0
  82. package/backend/dist/services/encryptionService.js.map +1 -0
  83. package/backend/dist/services/memoryService.d.ts +140 -0
  84. package/backend/dist/services/memoryService.d.ts.map +1 -0
  85. package/backend/dist/services/memoryService.js +867 -0
  86. package/backend/dist/services/memoryService.js.map +1 -0
  87. package/backend/dist/services/mutationEngineService.d.ts +49 -0
  88. package/backend/dist/services/mutationEngineService.d.ts.map +1 -0
  89. package/backend/dist/services/mutationEngineService.js +432 -0
  90. package/backend/dist/services/mutationEngineService.js.map +1 -0
  91. package/backend/dist/services/ollamaService.d.ts +55 -0
  92. package/backend/dist/services/ollamaService.d.ts.map +1 -0
  93. package/backend/dist/services/ollamaService.js +450 -0
  94. package/backend/dist/services/ollamaService.js.map +1 -0
  95. package/backend/dist/services/personaService.d.ts +67 -0
  96. package/backend/dist/services/personaService.d.ts.map +1 -0
  97. package/backend/dist/services/personaService.js +373 -0
  98. package/backend/dist/services/personaService.js.map +1 -0
  99. package/backend/dist/services/pluginService.d.ts +42 -0
  100. package/backend/dist/services/pluginService.d.ts.map +1 -0
  101. package/backend/dist/services/pluginService.js +961 -0
  102. package/backend/dist/services/pluginService.js.map +1 -0
  103. package/backend/dist/services/preferencesService.d.ts +35 -0
  104. package/backend/dist/services/preferencesService.d.ts.map +1 -0
  105. package/backend/dist/services/preferencesService.js +255 -0
  106. package/backend/dist/services/preferencesService.js.map +1 -0
  107. package/backend/dist/services/simpleGitHubOAuth.d.ts +48 -0
  108. package/backend/dist/services/simpleGitHubOAuth.d.ts.map +1 -0
  109. package/backend/dist/services/simpleGitHubOAuth.js +203 -0
  110. package/backend/dist/services/simpleGitHubOAuth.js.map +1 -0
  111. package/backend/dist/services/simpleHuggingFaceOAuth.d.ts +43 -0
  112. package/backend/dist/services/simpleHuggingFaceOAuth.d.ts.map +1 -0
  113. package/backend/dist/services/simpleHuggingFaceOAuth.js +159 -0
  114. package/backend/dist/services/simpleHuggingFaceOAuth.js.map +1 -0
  115. package/backend/dist/services/userService.d.ts +1 -0
  116. package/backend/dist/services/userService.d.ts.map +1 -0
  117. package/backend/dist/services/userService.js +18 -0
  118. package/backend/dist/services/userService.js.map +1 -0
  119. package/backend/dist/storage.d.ts +55 -0
  120. package/backend/dist/storage.d.ts.map +1 -0
  121. package/backend/dist/storage.js +741 -0
  122. package/backend/dist/storage.js.map +1 -0
  123. package/backend/dist/test-encryption.d.ts +2 -0
  124. package/backend/dist/test-encryption.d.ts.map +1 -0
  125. package/backend/dist/test-encryption.js +64 -0
  126. package/backend/dist/test-encryption.js.map +1 -0
  127. package/backend/dist/types/index.d.ts +523 -0
  128. package/backend/dist/types/index.d.ts.map +1 -0
  129. package/backend/dist/types/index.js +31 -0
  130. package/backend/dist/types/index.js.map +1 -0
  131. package/backend/dist/utils/generationUtils.d.ts +10 -0
  132. package/backend/dist/utils/generationUtils.d.ts.map +1 -0
  133. package/backend/dist/utils/generationUtils.js +49 -0
  134. package/backend/dist/utils/generationUtils.js.map +1 -0
  135. package/backend/dist/utils/hash.d.ts +29 -0
  136. package/backend/dist/utils/hash.d.ts.map +1 -0
  137. package/backend/dist/utils/hash.js +73 -0
  138. package/backend/dist/utils/hash.js.map +1 -0
  139. package/backend/dist/utils/jwt.d.ts +37 -0
  140. package/backend/dist/utils/jwt.d.ts.map +1 -0
  141. package/backend/dist/utils/jwt.js +86 -0
  142. package/backend/dist/utils/jwt.js.map +1 -0
  143. package/bin/cli.js +150 -0
  144. package/electron/main.js +322 -0
  145. package/frontend/dist/_redirects +1 -0
  146. package/frontend/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  147. package/frontend/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  148. package/frontend/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  149. package/frontend/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  150. package/frontend/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  151. package/frontend/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  152. package/frontend/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  153. package/frontend/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  154. package/frontend/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  155. package/frontend/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  156. package/frontend/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  157. package/frontend/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  158. package/frontend/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  159. package/frontend/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  160. package/frontend/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  161. package/frontend/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  162. package/frontend/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  163. package/frontend/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  164. package/frontend/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  165. package/frontend/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  166. package/frontend/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  167. package/frontend/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  168. package/frontend/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  169. package/frontend/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  170. package/frontend/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  171. package/frontend/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  172. package/frontend/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  173. package/frontend/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  174. package/frontend/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  175. package/frontend/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  176. package/frontend/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  177. package/frontend/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  178. package/frontend/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  179. package/frontend/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  180. package/frontend/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  181. package/frontend/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  182. package/frontend/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  183. package/frontend/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  184. package/frontend/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  185. package/frontend/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  186. package/frontend/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  187. package/frontend/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  188. package/frontend/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  189. package/frontend/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  190. package/frontend/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  191. package/frontend/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  192. package/frontend/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  193. package/frontend/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  194. package/frontend/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  195. package/frontend/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  196. package/frontend/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  197. package/frontend/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  198. package/frontend/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  199. package/frontend/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  200. package/frontend/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  201. package/frontend/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  202. package/frontend/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  203. package/frontend/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  204. package/frontend/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  205. package/frontend/dist/assets/index-CRQkB7Wz.js +3 -0
  206. package/frontend/dist/css/index-B1OjddR-.css +1 -0
  207. package/frontend/dist/favicon-dark.png +0 -0
  208. package/frontend/dist/favicon-light.png +0 -0
  209. package/frontend/dist/index.html +23 -0
  210. package/frontend/dist/js/ArtifactContainer-c_oi7XMs.js +23 -0
  211. package/frontend/dist/js/ArtifactDemoPage-CdfwJVXu.js +98 -0
  212. package/frontend/dist/js/ChatPage-CyotkmS0.js +281 -0
  213. package/frontend/dist/js/ModelsPage-DNaziPHc.js +2 -0
  214. package/frontend/dist/js/PersonasPage-DcnbJf8Q.js +13 -0
  215. package/frontend/dist/js/UserManagementPage-DtTf92dS.js +1 -0
  216. package/frontend/dist/js/markdown-vendor-D-79K2xZ.js +22 -0
  217. package/frontend/dist/js/react-vendor-N--QU9DW.js +8 -0
  218. package/frontend/dist/js/router-vendor-B-t91v39.js +3 -0
  219. package/frontend/dist/js/ui-vendor-VxSCY_bv.js +177 -0
  220. package/frontend/dist/js/utils-vendor-DNzxLBGx.js +6 -0
  221. package/frontend/dist/logo-dark.png +0 -0
  222. package/frontend/dist/logo-light.png +0 -0
  223. package/frontend/dist/logo.svg +14 -0
  224. package/package.json +128 -0
  225. package/plugins/anthropic.json +25 -0
  226. package/plugins/elevenlabs.json +58 -0
  227. package/plugins/gemini.json +57 -0
  228. package/plugins/github.json +23 -0
  229. package/plugins/groq.json +25 -0
  230. package/plugins/mistral.json +73 -0
  231. package/plugins/openai-tts.json +38 -0
  232. package/plugins/openai.json +132 -0
  233. package/plugins/openrouter.json +353 -0
@@ -0,0 +1,322 @@
1
+ /*
2
+ * Libre WebUI - Electron Main Process
3
+ * Copyright (C) 2025 Kroonen AI, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at:
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ */
11
+
12
+ const { app, BrowserWindow, shell, Menu, dialog, nativeTheme } = require('electron');
13
+ const path = require('path');
14
+ const http = require('http');
15
+ const { spawn } = require('child_process');
16
+
17
+ // Prevent multiple instances (fixes fork bomb issue)
18
+ const gotTheLock = app.requestSingleInstanceLock();
19
+ if (!gotTheLock) {
20
+ app.quit();
21
+ process.exit(0);
22
+ }
23
+
24
+ // Keep references to prevent garbage collection
25
+ let mainWindow = null;
26
+ let splashWindow = null;
27
+ let backendProcess = null;
28
+
29
+ const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;
30
+ const BACKEND_PORT = process.env.PORT || 3001;
31
+ const FRONTEND_PORT = 5173;
32
+
33
+ // Paths
34
+ const getResourcePath = (...segments) => {
35
+ if (isDev) {
36
+ return path.join(__dirname, '..', ...segments);
37
+ }
38
+ return path.join(process.resourcesPath, ...segments);
39
+ };
40
+
41
+ // Create splash screen while loading
42
+ function createSplashWindow() {
43
+ splashWindow = new BrowserWindow({
44
+ width: 400,
45
+ height: 300,
46
+ frame: false,
47
+ transparent: true,
48
+ alwaysOnTop: true,
49
+ skipTaskbar: true,
50
+ resizable: false,
51
+ webPreferences: {
52
+ nodeIntegration: false,
53
+ contextIsolation: true,
54
+ },
55
+ });
56
+
57
+ splashWindow.loadFile(path.join(__dirname, 'splash.html'));
58
+ splashWindow.center();
59
+ }
60
+
61
+ // Create the main application window
62
+ function createMainWindow() {
63
+ mainWindow = new BrowserWindow({
64
+ width: 1400,
65
+ height: 900,
66
+ minWidth: 800,
67
+ minHeight: 600,
68
+ show: false,
69
+ titleBarStyle: 'hiddenInset',
70
+ trafficLightPosition: { x: 12, y: 12 },
71
+ backgroundColor: nativeTheme.shouldUseDarkColors ? '#1a1a1a' : '#ffffff',
72
+ webPreferences: {
73
+ nodeIntegration: false,
74
+ contextIsolation: true,
75
+ webSecurity: true,
76
+ preload: path.join(__dirname, 'preload.js'),
77
+ },
78
+ });
79
+
80
+ // Handle external links
81
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
82
+ shell.openExternal(url);
83
+ return { action: 'deny' };
84
+ });
85
+
86
+ // Show window when ready
87
+ mainWindow.once('ready-to-show', () => {
88
+ if (splashWindow) {
89
+ splashWindow.close();
90
+ splashWindow = null;
91
+ }
92
+ mainWindow.show();
93
+ mainWindow.focus();
94
+ });
95
+
96
+ mainWindow.on('closed', () => {
97
+ mainWindow = null;
98
+ });
99
+
100
+ return mainWindow;
101
+ }
102
+
103
+ // Check if backend is running
104
+ async function checkBackend() {
105
+ return new Promise((resolve) => {
106
+ const req = http.get(`http://localhost:${BACKEND_PORT}/api/health`, (res) => {
107
+ resolve(res.statusCode === 200);
108
+ });
109
+ req.on('error', () => resolve(false));
110
+ req.setTimeout(2000, () => {
111
+ req.destroy();
112
+ resolve(false);
113
+ });
114
+ });
115
+ }
116
+
117
+ // Start backend in a new Terminal window (macOS)
118
+ function startBackendInTerminal() {
119
+ const projectRoot = isDev
120
+ ? path.join(__dirname, '..')
121
+ : path.join(process.resourcesPath, '..');
122
+
123
+ // Use AppleScript to open Terminal and run the backend
124
+ const script = `
125
+ tell application "Terminal"
126
+ activate
127
+ do script "cd '${projectRoot}' && npm run dev:backend"
128
+ end tell
129
+ `;
130
+
131
+ backendProcess = spawn('osascript', ['-e', script], {
132
+ detached: true,
133
+ stdio: 'ignore',
134
+ });
135
+
136
+ backendProcess.unref();
137
+ console.log('Started backend in Terminal');
138
+ }
139
+
140
+ // Stop backend process
141
+ function stopBackend() {
142
+ if (backendProcess) {
143
+ backendProcess.kill();
144
+ backendProcess = null;
145
+ }
146
+ }
147
+
148
+ // Create application menu
149
+ function createMenu() {
150
+ const template = [
151
+ {
152
+ label: app.name,
153
+ submenu: [
154
+ { role: 'about' },
155
+ { type: 'separator' },
156
+ {
157
+ label: 'Preferences...',
158
+ accelerator: 'CmdOrCtrl+,',
159
+ click: () => {
160
+ if (mainWindow) {
161
+ mainWindow.webContents.executeJavaScript(
162
+ 'window.dispatchEvent(new CustomEvent("open-settings"))'
163
+ );
164
+ }
165
+ },
166
+ },
167
+ { type: 'separator' },
168
+ { role: 'services' },
169
+ { type: 'separator' },
170
+ { role: 'hide' },
171
+ { role: 'hideOthers' },
172
+ { role: 'unhide' },
173
+ { type: 'separator' },
174
+ { role: 'quit' },
175
+ ],
176
+ },
177
+ {
178
+ label: 'Edit',
179
+ submenu: [
180
+ { role: 'undo' },
181
+ { role: 'redo' },
182
+ { type: 'separator' },
183
+ { role: 'cut' },
184
+ { role: 'copy' },
185
+ { role: 'paste' },
186
+ { role: 'selectAll' },
187
+ ],
188
+ },
189
+ {
190
+ label: 'View',
191
+ submenu: [
192
+ { role: 'reload' },
193
+ { role: 'forceReload' },
194
+ { role: 'toggleDevTools' },
195
+ { type: 'separator' },
196
+ { role: 'resetZoom' },
197
+ { role: 'zoomIn' },
198
+ { role: 'zoomOut' },
199
+ { type: 'separator' },
200
+ { role: 'togglefullscreen' },
201
+ ],
202
+ },
203
+ {
204
+ label: 'Window',
205
+ submenu: [
206
+ { role: 'minimize' },
207
+ { role: 'zoom' },
208
+ { type: 'separator' },
209
+ { role: 'front' },
210
+ { type: 'separator' },
211
+ { role: 'window' },
212
+ ],
213
+ },
214
+ {
215
+ label: 'Help',
216
+ submenu: [
217
+ {
218
+ label: 'Documentation',
219
+ click: () => shell.openExternal('https://librewebui.org'),
220
+ },
221
+ {
222
+ label: 'GitHub',
223
+ click: () => shell.openExternal('https://github.com/libre-webui/libre-webui'),
224
+ },
225
+ { type: 'separator' },
226
+ {
227
+ label: 'Report Issue',
228
+ click: () => shell.openExternal('https://github.com/libre-webui/libre-webui/issues'),
229
+ },
230
+ ],
231
+ },
232
+ ];
233
+
234
+ const menu = Menu.buildFromTemplate(template);
235
+ Menu.setApplicationMenu(menu);
236
+ }
237
+
238
+ // Main application startup
239
+ async function main() {
240
+ createSplashWindow();
241
+ createMenu();
242
+
243
+ try {
244
+ // Check if backend is available
245
+ const backendAvailable = await checkBackend();
246
+ if (backendAvailable) {
247
+ console.log('Backend server detected on port', BACKEND_PORT);
248
+ } else {
249
+ console.log('Backend not detected - please start it manually with: npm run dev:backend');
250
+ // Disabled auto-start in Terminal for now
251
+ // startBackendInTerminal();
252
+ }
253
+
254
+ // Create main window
255
+ const window = createMainWindow();
256
+
257
+ // Load the app
258
+ if (isDev) {
259
+ // In development, load from Vite dev server
260
+ window.loadURL(`http://localhost:${FRONTEND_PORT}`);
261
+ } else {
262
+ // In production, load the built frontend
263
+ const frontendPath = getResourcePath('frontend', 'dist', 'index.html');
264
+ console.log('Loading frontend from:', frontendPath);
265
+ window.loadFile(frontendPath).catch((err) => {
266
+ console.error('Failed to load frontend:', err);
267
+ dialog.showErrorBox('Load Error', `Could not load app: ${err.message}`);
268
+ });
269
+ }
270
+
271
+ // Open DevTools in dev mode
272
+ if (isDev) {
273
+ window.webContents.openDevTools();
274
+ }
275
+ } catch (error) {
276
+ console.error('Failed to start application:', error);
277
+ dialog.showErrorBox(
278
+ 'Startup Error',
279
+ `Failed to start Libre WebUI: ${error.message}\n\nPlease check the logs and try again.`
280
+ );
281
+ app.quit();
282
+ }
283
+ }
284
+
285
+ // App lifecycle events
286
+ app.whenReady().then(main);
287
+
288
+ // Focus existing window if second instance tries to launch
289
+ app.on('second-instance', () => {
290
+ if (mainWindow) {
291
+ if (mainWindow.isMinimized()) mainWindow.restore();
292
+ mainWindow.focus();
293
+ }
294
+ });
295
+
296
+ app.on('window-all-closed', () => {
297
+ stopBackend();
298
+ if (process.platform !== 'darwin') {
299
+ app.quit();
300
+ }
301
+ });
302
+
303
+ app.on('before-quit', () => {
304
+ stopBackend();
305
+ });
306
+
307
+ app.on('activate', () => {
308
+ if (BrowserWindow.getAllWindows().length === 0) {
309
+ main();
310
+ }
311
+ });
312
+
313
+
314
+ // Handle certificate errors for localhost
315
+ app.on('certificate-error', (event, _webContents, url, _error, _certificate, callback) => {
316
+ if (url.startsWith('https://localhost')) {
317
+ event.preventDefault();
318
+ callback(true);
319
+ } else {
320
+ callback(false);
321
+ }
322
+ });
@@ -0,0 +1 @@
1
+ /* /index.html 200