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.
- package/LICENSE +201 -0
- package/README.md +204 -0
- package/backend/dist/db.d.ts +19 -0
- package/backend/dist/db.d.ts.map +1 -0
- package/backend/dist/db.js +355 -0
- package/backend/dist/db.js.map +1 -0
- package/backend/dist/env.d.ts +2 -0
- package/backend/dist/env.d.ts.map +1 -0
- package/backend/dist/env.js +22 -0
- package/backend/dist/env.js.map +1 -0
- package/backend/dist/index.d.ts +4 -0
- package/backend/dist/index.d.ts.map +1 -0
- package/backend/dist/index.js +751 -0
- package/backend/dist/index.js.map +1 -0
- package/backend/dist/middleware/auth.d.ts +18 -0
- package/backend/dist/middleware/auth.d.ts.map +1 -0
- package/backend/dist/middleware/auth.js +98 -0
- package/backend/dist/middleware/auth.js.map +1 -0
- package/backend/dist/middleware/index.d.ts +5 -0
- package/backend/dist/middleware/index.d.ts.map +1 -0
- package/backend/dist/middleware/index.js +62 -0
- package/backend/dist/middleware/index.js.map +1 -0
- package/backend/dist/models/personaModel.d.ts +37 -0
- package/backend/dist/models/personaModel.d.ts.map +1 -0
- package/backend/dist/models/personaModel.js +269 -0
- package/backend/dist/models/personaModel.js.map +1 -0
- package/backend/dist/models/userModel.d.ts +86 -0
- package/backend/dist/models/userModel.d.ts.map +1 -0
- package/backend/dist/models/userModel.js +212 -0
- package/backend/dist/models/userModel.js.map +1 -0
- package/backend/dist/routes/auth.d.ts +3 -0
- package/backend/dist/routes/auth.d.ts.map +1 -0
- package/backend/dist/routes/auth.js +389 -0
- package/backend/dist/routes/auth.js.map +1 -0
- package/backend/dist/routes/chat.d.ts +3 -0
- package/backend/dist/routes/chat.d.ts.map +1 -0
- package/backend/dist/routes/chat.js +767 -0
- package/backend/dist/routes/chat.js.map +1 -0
- package/backend/dist/routes/documents.d.ts +3 -0
- package/backend/dist/routes/documents.d.ts.map +1 -0
- package/backend/dist/routes/documents.js +244 -0
- package/backend/dist/routes/documents.js.map +1 -0
- package/backend/dist/routes/ollama.d.ts +3 -0
- package/backend/dist/routes/ollama.d.ts.map +1 -0
- package/backend/dist/routes/ollama.js +549 -0
- package/backend/dist/routes/ollama.js.map +1 -0
- package/backend/dist/routes/personas.d.ts +3 -0
- package/backend/dist/routes/personas.d.ts.map +1 -0
- package/backend/dist/routes/personas.js +505 -0
- package/backend/dist/routes/personas.js.map +1 -0
- package/backend/dist/routes/plugins.d.ts +3 -0
- package/backend/dist/routes/plugins.d.ts.map +1 -0
- package/backend/dist/routes/plugins.js +417 -0
- package/backend/dist/routes/plugins.js.map +1 -0
- package/backend/dist/routes/preferences.d.ts +3 -0
- package/backend/dist/routes/preferences.d.ts.map +1 -0
- package/backend/dist/routes/preferences.js +303 -0
- package/backend/dist/routes/preferences.js.map +1 -0
- package/backend/dist/routes/tts.d.ts +3 -0
- package/backend/dist/routes/tts.d.ts.map +1 -0
- package/backend/dist/routes/tts.js +304 -0
- package/backend/dist/routes/tts.js.map +1 -0
- package/backend/dist/routes/users.d.ts +3 -0
- package/backend/dist/routes/users.d.ts.map +1 -0
- package/backend/dist/routes/users.js +246 -0
- package/backend/dist/routes/users.js.map +1 -0
- package/backend/dist/services/authService.d.ts +51 -0
- package/backend/dist/services/authService.d.ts.map +1 -0
- package/backend/dist/services/authService.js +153 -0
- package/backend/dist/services/authService.js.map +1 -0
- package/backend/dist/services/chatService.d.ts +52 -0
- package/backend/dist/services/chatService.d.ts.map +1 -0
- package/backend/dist/services/chatService.js +645 -0
- package/backend/dist/services/chatService.js.map +1 -0
- package/backend/dist/services/documentService.d.ts +34 -0
- package/backend/dist/services/documentService.d.ts.map +1 -0
- package/backend/dist/services/documentService.js +428 -0
- package/backend/dist/services/documentService.js.map +1 -0
- package/backend/dist/services/encryptionService.d.ts +62 -0
- package/backend/dist/services/encryptionService.d.ts.map +1 -0
- package/backend/dist/services/encryptionService.js +284 -0
- package/backend/dist/services/encryptionService.js.map +1 -0
- package/backend/dist/services/memoryService.d.ts +140 -0
- package/backend/dist/services/memoryService.d.ts.map +1 -0
- package/backend/dist/services/memoryService.js +867 -0
- package/backend/dist/services/memoryService.js.map +1 -0
- package/backend/dist/services/mutationEngineService.d.ts +49 -0
- package/backend/dist/services/mutationEngineService.d.ts.map +1 -0
- package/backend/dist/services/mutationEngineService.js +432 -0
- package/backend/dist/services/mutationEngineService.js.map +1 -0
- package/backend/dist/services/ollamaService.d.ts +55 -0
- package/backend/dist/services/ollamaService.d.ts.map +1 -0
- package/backend/dist/services/ollamaService.js +450 -0
- package/backend/dist/services/ollamaService.js.map +1 -0
- package/backend/dist/services/personaService.d.ts +67 -0
- package/backend/dist/services/personaService.d.ts.map +1 -0
- package/backend/dist/services/personaService.js +373 -0
- package/backend/dist/services/personaService.js.map +1 -0
- package/backend/dist/services/pluginService.d.ts +42 -0
- package/backend/dist/services/pluginService.d.ts.map +1 -0
- package/backend/dist/services/pluginService.js +961 -0
- package/backend/dist/services/pluginService.js.map +1 -0
- package/backend/dist/services/preferencesService.d.ts +35 -0
- package/backend/dist/services/preferencesService.d.ts.map +1 -0
- package/backend/dist/services/preferencesService.js +255 -0
- package/backend/dist/services/preferencesService.js.map +1 -0
- package/backend/dist/services/simpleGitHubOAuth.d.ts +48 -0
- package/backend/dist/services/simpleGitHubOAuth.d.ts.map +1 -0
- package/backend/dist/services/simpleGitHubOAuth.js +203 -0
- package/backend/dist/services/simpleGitHubOAuth.js.map +1 -0
- package/backend/dist/services/simpleHuggingFaceOAuth.d.ts +43 -0
- package/backend/dist/services/simpleHuggingFaceOAuth.d.ts.map +1 -0
- package/backend/dist/services/simpleHuggingFaceOAuth.js +159 -0
- package/backend/dist/services/simpleHuggingFaceOAuth.js.map +1 -0
- package/backend/dist/services/userService.d.ts +1 -0
- package/backend/dist/services/userService.d.ts.map +1 -0
- package/backend/dist/services/userService.js +18 -0
- package/backend/dist/services/userService.js.map +1 -0
- package/backend/dist/storage.d.ts +55 -0
- package/backend/dist/storage.d.ts.map +1 -0
- package/backend/dist/storage.js +741 -0
- package/backend/dist/storage.js.map +1 -0
- package/backend/dist/test-encryption.d.ts +2 -0
- package/backend/dist/test-encryption.d.ts.map +1 -0
- package/backend/dist/test-encryption.js +64 -0
- package/backend/dist/test-encryption.js.map +1 -0
- package/backend/dist/types/index.d.ts +523 -0
- package/backend/dist/types/index.d.ts.map +1 -0
- package/backend/dist/types/index.js +31 -0
- package/backend/dist/types/index.js.map +1 -0
- package/backend/dist/utils/generationUtils.d.ts +10 -0
- package/backend/dist/utils/generationUtils.d.ts.map +1 -0
- package/backend/dist/utils/generationUtils.js +49 -0
- package/backend/dist/utils/generationUtils.js.map +1 -0
- package/backend/dist/utils/hash.d.ts +29 -0
- package/backend/dist/utils/hash.d.ts.map +1 -0
- package/backend/dist/utils/hash.js +73 -0
- package/backend/dist/utils/hash.js.map +1 -0
- package/backend/dist/utils/jwt.d.ts +37 -0
- package/backend/dist/utils/jwt.d.ts.map +1 -0
- package/backend/dist/utils/jwt.js +86 -0
- package/backend/dist/utils/jwt.js.map +1 -0
- package/bin/cli.js +150 -0
- package/electron/main.js +322 -0
- package/frontend/dist/_redirects +1 -0
- package/frontend/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/frontend/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/frontend/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/frontend/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/frontend/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/frontend/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/frontend/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/frontend/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/frontend/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/frontend/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/frontend/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/frontend/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/frontend/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/frontend/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/frontend/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/frontend/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/frontend/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/frontend/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/frontend/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/frontend/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/frontend/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/frontend/dist/assets/index-CRQkB7Wz.js +3 -0
- package/frontend/dist/css/index-B1OjddR-.css +1 -0
- package/frontend/dist/favicon-dark.png +0 -0
- package/frontend/dist/favicon-light.png +0 -0
- package/frontend/dist/index.html +23 -0
- package/frontend/dist/js/ArtifactContainer-c_oi7XMs.js +23 -0
- package/frontend/dist/js/ArtifactDemoPage-CdfwJVXu.js +98 -0
- package/frontend/dist/js/ChatPage-CyotkmS0.js +281 -0
- package/frontend/dist/js/ModelsPage-DNaziPHc.js +2 -0
- package/frontend/dist/js/PersonasPage-DcnbJf8Q.js +13 -0
- package/frontend/dist/js/UserManagementPage-DtTf92dS.js +1 -0
- package/frontend/dist/js/markdown-vendor-D-79K2xZ.js +22 -0
- package/frontend/dist/js/react-vendor-N--QU9DW.js +8 -0
- package/frontend/dist/js/router-vendor-B-t91v39.js +3 -0
- package/frontend/dist/js/ui-vendor-VxSCY_bv.js +177 -0
- package/frontend/dist/js/utils-vendor-DNzxLBGx.js +6 -0
- package/frontend/dist/logo-dark.png +0 -0
- package/frontend/dist/logo-light.png +0 -0
- package/frontend/dist/logo.svg +14 -0
- package/package.json +128 -0
- package/plugins/anthropic.json +25 -0
- package/plugins/elevenlabs.json +58 -0
- package/plugins/gemini.json +57 -0
- package/plugins/github.json +23 -0
- package/plugins/groq.json +25 -0
- package/plugins/mistral.json +73 -0
- package/plugins/openai-tts.json +38 -0
- package/plugins/openai.json +132 -0
- package/plugins/openrouter.json +353 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Libre WebUI
|
|
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
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
// Helper function to extract error message from unknown error
|
|
18
|
+
export const getErrorMessage = (error, fallback) => {
|
|
19
|
+
if (error && typeof error === 'object' && 'response' in error) {
|
|
20
|
+
const response = error;
|
|
21
|
+
if (response.response?.data?.error) {
|
|
22
|
+
return response.response.data.error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (error instanceof Error) {
|
|
26
|
+
return error.message;
|
|
27
|
+
}
|
|
28
|
+
return fallback;
|
|
29
|
+
};
|
|
30
|
+
// Note: Legacy interfaces have been merged into the main Persona interface with optional advanced features
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAkdH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAc,EAAE,QAAgB,EAAU,EAAE;IAC1E,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,IAAI,KAAK,EAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,KAAqD,CAAC;QACvE,IAAI,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YACnC,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;QACtC,CAAC;IACH,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AA8JF,2GAA2G"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { GenerationOptions, GenerationStatistics, OllamaChatResponse } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Merges user preferences with request options, giving precedence to request options
|
|
4
|
+
*/
|
|
5
|
+
export declare const mergeGenerationOptions: (userOptions: Partial<GenerationOptions>, requestOptions?: Partial<GenerationOptions>) => GenerationOptions;
|
|
6
|
+
/**
|
|
7
|
+
* Extracts generation statistics from Ollama response
|
|
8
|
+
*/
|
|
9
|
+
export declare const extractStatistics: (response: OllamaChatResponse) => GenerationStatistics;
|
|
10
|
+
//# sourceMappingURL=generationUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generationUtils.d.ts","sourceRoot":"","sources":["../../src/utils/generationUtils.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,aAAa,OAAO,CAAC,iBAAiB,CAAC,EACvC,iBAAiB,OAAO,CAAC,iBAAiB,CAAC,KAC1C,iBAKF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,kBAAkB,KAC3B,oBAqBF,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Libre WebUI
|
|
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
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Merges user preferences with request options, giving precedence to request options
|
|
19
|
+
*/
|
|
20
|
+
export const mergeGenerationOptions = (userOptions, requestOptions) => {
|
|
21
|
+
return {
|
|
22
|
+
...userOptions,
|
|
23
|
+
...requestOptions,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Extracts generation statistics from Ollama response
|
|
28
|
+
*/
|
|
29
|
+
export const extractStatistics = (response) => {
|
|
30
|
+
const stats = {
|
|
31
|
+
total_duration: response.total_duration,
|
|
32
|
+
load_duration: response.load_duration,
|
|
33
|
+
prompt_eval_count: response.prompt_eval_count,
|
|
34
|
+
prompt_eval_duration: response.prompt_eval_duration,
|
|
35
|
+
eval_count: response.eval_count,
|
|
36
|
+
eval_duration: response.eval_duration,
|
|
37
|
+
created_at: response.created_at,
|
|
38
|
+
model: response.model,
|
|
39
|
+
};
|
|
40
|
+
// Calculate tokens per second if we have the necessary data
|
|
41
|
+
if (response.eval_count && response.eval_duration) {
|
|
42
|
+
// Convert nanoseconds to seconds and calculate tokens/second
|
|
43
|
+
stats.tokens_per_second =
|
|
44
|
+
Math.round((response.eval_count / (response.eval_duration / 1e9)) * 100) /
|
|
45
|
+
100;
|
|
46
|
+
}
|
|
47
|
+
return stats;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=generationUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generationUtils.js","sourceRoot":"","sources":["../../src/utils/generationUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,WAAuC,EACvC,cAA2C,EACxB,EAAE;IACrB,OAAO;QACL,GAAG,WAAW;QACd,GAAG,cAAc;KAClB,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAA4B,EACN,EAAE;IACxB,MAAM,KAAK,GAAyB;QAClC,cAAc,EAAE,QAAQ,CAAC,cAAc;QACvC,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;QAC7C,oBAAoB,EAAE,QAAQ,CAAC,oBAAoB;QACnD,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;IAEF,4DAA4D;IAC5D,IAAI,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClD,6DAA6D;QAC7D,KAAK,CAAC,iBAAiB;YACrB,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,QAAQ,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;gBACxE,GAAG,CAAC;IACR,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hash a password using bcrypt
|
|
3
|
+
* @param password - The plain text password to hash
|
|
4
|
+
* @returns Promise<string> - The hashed password
|
|
5
|
+
*/
|
|
6
|
+
export declare function hashPassword(password: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Compare a plain text password with a hashed password
|
|
9
|
+
* @param password - The plain text password
|
|
10
|
+
* @param hash - The hashed password to compare against
|
|
11
|
+
* @returns Promise<boolean> - True if passwords match, false otherwise
|
|
12
|
+
*/
|
|
13
|
+
export declare function comparePassword(password: string, hash: string): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Generate a random password
|
|
16
|
+
* @param length - Length of the password (default: 12)
|
|
17
|
+
* @returns string - Random password
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateRandomPassword(length?: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* Validate password strength
|
|
22
|
+
* @param password - The password to validate
|
|
23
|
+
* @returns object - Validation result with isValid and errors
|
|
24
|
+
*/
|
|
25
|
+
export declare function validatePasswordStrength(password: string): {
|
|
26
|
+
isValid: boolean;
|
|
27
|
+
errors: string[];
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpE;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAElB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAUlE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAuBA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Libre WebUI
|
|
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
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import bcrypt from 'bcrypt';
|
|
18
|
+
/**
|
|
19
|
+
* Hash a password using bcrypt
|
|
20
|
+
* @param password - The plain text password to hash
|
|
21
|
+
* @returns Promise<string> - The hashed password
|
|
22
|
+
*/
|
|
23
|
+
export async function hashPassword(password) {
|
|
24
|
+
const saltRounds = 12; // Higher salt rounds for better security
|
|
25
|
+
return await bcrypt.hash(password, saltRounds);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compare a plain text password with a hashed password
|
|
29
|
+
* @param password - The plain text password
|
|
30
|
+
* @param hash - The hashed password to compare against
|
|
31
|
+
* @returns Promise<boolean> - True if passwords match, false otherwise
|
|
32
|
+
*/
|
|
33
|
+
export async function comparePassword(password, hash) {
|
|
34
|
+
return await bcrypt.compare(password, hash);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate a random password
|
|
38
|
+
* @param length - Length of the password (default: 12)
|
|
39
|
+
* @returns string - Random password
|
|
40
|
+
*/
|
|
41
|
+
export function generateRandomPassword(length = 12) {
|
|
42
|
+
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
|
|
43
|
+
let password = '';
|
|
44
|
+
for (let i = 0; i < length; i++) {
|
|
45
|
+
password += charset.charAt(Math.floor(Math.random() * charset.length));
|
|
46
|
+
}
|
|
47
|
+
return password;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validate password strength
|
|
51
|
+
* @param password - The password to validate
|
|
52
|
+
* @returns object - Validation result with isValid and errors
|
|
53
|
+
*/
|
|
54
|
+
export function validatePasswordStrength(password) {
|
|
55
|
+
const errors = [];
|
|
56
|
+
if (password.length < 6) {
|
|
57
|
+
errors.push('Password must be at least 6 characters long');
|
|
58
|
+
}
|
|
59
|
+
if (!/[A-Z]/.test(password)) {
|
|
60
|
+
errors.push('Password must contain at least one uppercase letter');
|
|
61
|
+
}
|
|
62
|
+
if (!/[a-z]/.test(password)) {
|
|
63
|
+
errors.push('Password must contain at least one lowercase letter');
|
|
64
|
+
}
|
|
65
|
+
if (!/[0-9]/.test(password)) {
|
|
66
|
+
errors.push('Password must contain at least one number');
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
isValid: errors.length === 0,
|
|
70
|
+
errors,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,yCAAyC;IAChE,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,IAAY;IAEZ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE;IACxD,MAAM,OAAO,GACX,wEAAwE,CAAC;IAC3E,IAAI,QAAQ,GAAG,EAAE,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IAIvD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC5B,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { User } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* JWT payload interface
|
|
4
|
+
*/
|
|
5
|
+
export interface JWTPayload {
|
|
6
|
+
userId: string;
|
|
7
|
+
username: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
role: string;
|
|
10
|
+
iat?: number;
|
|
11
|
+
exp?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Generate a JWT token for a user
|
|
15
|
+
* @param user - User object
|
|
16
|
+
* @returns string - JWT token
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateToken(user: User): string;
|
|
19
|
+
/**
|
|
20
|
+
* Verify and decode a JWT token
|
|
21
|
+
* @param token - JWT token string
|
|
22
|
+
* @returns JWTPayload - Decoded payload
|
|
23
|
+
*/
|
|
24
|
+
export declare function verifyToken(token: string): JWTPayload;
|
|
25
|
+
/**
|
|
26
|
+
* Generate a refresh token (longer expiry)
|
|
27
|
+
* @param user - User object
|
|
28
|
+
* @returns string - Refresh token
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateRefreshToken(user: User): string;
|
|
31
|
+
/**
|
|
32
|
+
* Extract token from Authorization header
|
|
33
|
+
* @param authHeader - Authorization header value
|
|
34
|
+
* @returns string | null - Token or null if not found
|
|
35
|
+
*/
|
|
36
|
+
export declare function extractTokenFromHeader(authHeader: string | undefined): string | null;
|
|
37
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAWhD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAarD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAUvD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,GAAG,IAAI,CAWf"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Libre WebUI
|
|
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
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import jwt from 'jsonwebtoken';
|
|
18
|
+
import { JWT_SECRET } from '../services/authService.js';
|
|
19
|
+
/**
|
|
20
|
+
* Generate a JWT token for a user
|
|
21
|
+
* @param user - User object
|
|
22
|
+
* @returns string - JWT token
|
|
23
|
+
*/
|
|
24
|
+
export function generateToken(user) {
|
|
25
|
+
const payload = {
|
|
26
|
+
userId: user.id,
|
|
27
|
+
username: user.username,
|
|
28
|
+
email: user.email,
|
|
29
|
+
role: user.role,
|
|
30
|
+
};
|
|
31
|
+
const expiresIn = process.env.JWT_EXPIRES_IN || '7d';
|
|
32
|
+
return jwt.sign(payload, JWT_SECRET, { expiresIn });
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verify and decode a JWT token
|
|
36
|
+
* @param token - JWT token string
|
|
37
|
+
* @returns JWTPayload - Decoded payload
|
|
38
|
+
*/
|
|
39
|
+
export function verifyToken(token) {
|
|
40
|
+
try {
|
|
41
|
+
const decoded = jwt.verify(token, JWT_SECRET);
|
|
42
|
+
return decoded;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof jwt.TokenExpiredError) {
|
|
46
|
+
throw new Error('Token has expired');
|
|
47
|
+
}
|
|
48
|
+
else if (error instanceof jwt.JsonWebTokenError) {
|
|
49
|
+
throw new Error('Invalid token');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
throw new Error('Token verification failed');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generate a refresh token (longer expiry)
|
|
58
|
+
* @param user - User object
|
|
59
|
+
* @returns string - Refresh token
|
|
60
|
+
*/
|
|
61
|
+
export function generateRefreshToken(user) {
|
|
62
|
+
const payload = {
|
|
63
|
+
userId: user.id,
|
|
64
|
+
username: user.username,
|
|
65
|
+
email: user.email,
|
|
66
|
+
role: user.role,
|
|
67
|
+
};
|
|
68
|
+
// Refresh tokens have longer expiry (30 days)
|
|
69
|
+
return jwt.sign(payload, JWT_SECRET, { expiresIn: '30d' });
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract token from Authorization header
|
|
73
|
+
* @param authHeader - Authorization header value
|
|
74
|
+
* @returns string | null - Token or null if not found
|
|
75
|
+
*/
|
|
76
|
+
export function extractTokenFromHeader(authHeader) {
|
|
77
|
+
if (!authHeader) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const parts = authHeader.split(' ');
|
|
81
|
+
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return parts[1];
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,GAAG,MAAM,cAAc,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAcxD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,MAAM,OAAO,GAAe;QAC1B,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC;IAErD,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,SAAS,EAAqB,CAAC,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAe,CAAC;QAC5D,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,KAAK,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAU;IAC7C,MAAM,OAAO,GAAe;QAC1B,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;IAEF,8CAA8C;IAC9C,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,KAAK,EAAqB,CAAC,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAA8B;IAE9B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Libre WebUI
|
|
5
|
+
* Copyright (C) 2025 Kroonen AI, Inc.
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at:
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const { spawn } = require('child_process');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
|
|
24
|
+
// Parse command line arguments
|
|
25
|
+
const args = process.argv.slice(2);
|
|
26
|
+
const helpFlags = ['-h', '--help'];
|
|
27
|
+
const versionFlags = ['-v', '--version'];
|
|
28
|
+
|
|
29
|
+
if (args.some(arg => helpFlags.includes(arg))) {
|
|
30
|
+
console.log(`
|
|
31
|
+
Libre WebUI - Privacy-First AI Chat Interface
|
|
32
|
+
|
|
33
|
+
Usage: npx libre-webui [options]
|
|
34
|
+
|
|
35
|
+
Options:
|
|
36
|
+
-h, --help Show this help message
|
|
37
|
+
-v, --version Show version number
|
|
38
|
+
-p, --port Set the port (default: 8080)
|
|
39
|
+
|
|
40
|
+
Environment Variables:
|
|
41
|
+
PORT Server port (default: 8080)
|
|
42
|
+
OLLAMA_BASE_URL Ollama API URL (default: http://localhost:11434)
|
|
43
|
+
OPENAI_API_KEY OpenAI API key (optional)
|
|
44
|
+
ANTHROPIC_API_KEY Anthropic API key (optional)
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
npx libre-webui
|
|
48
|
+
npx libre-webui --port 3000
|
|
49
|
+
PORT=3000 npx libre-webui
|
|
50
|
+
|
|
51
|
+
Documentation: https://docs.librewebui.org
|
|
52
|
+
`);
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (args.some(arg => versionFlags.includes(arg))) {
|
|
57
|
+
const packageJson = require('../package.json');
|
|
58
|
+
console.log(`libre-webui v${packageJson.version}`);
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Handle --port argument
|
|
63
|
+
const portArgIndex = args.findIndex(arg => arg === '-p' || arg === '--port');
|
|
64
|
+
if (portArgIndex !== -1 && args[portArgIndex + 1]) {
|
|
65
|
+
process.env.PORT = args[portArgIndex + 1];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Find the backend entry point
|
|
69
|
+
const possibleBackendPaths = [
|
|
70
|
+
path.join(__dirname, '../backend/dist/index.js'),
|
|
71
|
+
path.join(__dirname, '../dist/backend/index.js'),
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
let backendPath = '';
|
|
75
|
+
for (const p of possibleBackendPaths) {
|
|
76
|
+
if (fs.existsSync(p)) {
|
|
77
|
+
backendPath = p;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!backendPath) {
|
|
83
|
+
console.error('Error: Backend not found. The package may be corrupted.');
|
|
84
|
+
console.error('Please try reinstalling: npm install -g libre-webui');
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Check if frontend exists
|
|
89
|
+
const possibleFrontendPaths = [
|
|
90
|
+
path.join(__dirname, '../frontend/dist/index.html'),
|
|
91
|
+
path.join(__dirname, '../dist/frontend/index.html'),
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
let frontendExists = false;
|
|
95
|
+
for (const p of possibleFrontendPaths) {
|
|
96
|
+
if (fs.existsSync(p)) {
|
|
97
|
+
frontendExists = true;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!frontendExists) {
|
|
103
|
+
console.error('Error: Frontend not found. The package may be corrupted.');
|
|
104
|
+
console.error('Please try reinstalling: npm install -g libre-webui');
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Set production environment
|
|
109
|
+
const env = {
|
|
110
|
+
...process.env,
|
|
111
|
+
NODE_ENV: 'production',
|
|
112
|
+
SERVE_FRONTEND: 'true',
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const port = env.PORT || '8080';
|
|
116
|
+
|
|
117
|
+
console.log(`
|
|
118
|
+
╭─────────────────────────────────────────────────╮
|
|
119
|
+
│ │
|
|
120
|
+
│ Libre WebUI │
|
|
121
|
+
│ Privacy-First AI Chat Interface │
|
|
122
|
+
│ │
|
|
123
|
+
╰─────────────────────────────────────────────────╯
|
|
124
|
+
|
|
125
|
+
Starting server...
|
|
126
|
+
`);
|
|
127
|
+
|
|
128
|
+
// Start the backend server
|
|
129
|
+
const server = spawn('node', [backendPath], {
|
|
130
|
+
stdio: 'inherit',
|
|
131
|
+
env,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
server.on('error', err => {
|
|
135
|
+
console.error('Failed to start server:', err.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
server.on('close', code => {
|
|
140
|
+
process.exit(code || 0);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Handle graceful shutdown
|
|
144
|
+
process.on('SIGINT', () => {
|
|
145
|
+
server.kill('SIGINT');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
process.on('SIGTERM', () => {
|
|
149
|
+
server.kill('SIGTERM');
|
|
150
|
+
});
|