mirror of
https://github.com/open-webui/desktop
synced 2025-06-26 18:15:59 +00:00
refac
This commit is contained in:
parent
58edd82696
commit
8f499475fd
@ -11,7 +11,7 @@ const config: ForgeConfig = {
|
||||
packagerConfig: {
|
||||
asar: true,
|
||||
icon: 'public/assets/icon.png',
|
||||
extraResource: ['public/assets', 'resources/python.tar.gz']
|
||||
extraResource: ['public/assets', 'resources']
|
||||
},
|
||||
rebuildConfig: {},
|
||||
makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})],
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
"lint": "eslint --ext .ts,.tsx .",
|
||||
"format": "prettier --plugin-search-dir --write \"**/*.{js,ts,svelte,css,md,html,json}\"",
|
||||
"create:conda-lock": "cd resources && rimraf conda-lock.yml && conda-lock -f environment.yml && cd -",
|
||||
"create:python-tar": "rimraf ./resources/python.tar.gz && conda-lock install --prefix ./resources/python ./resources/conda-lock.yml && conda pack -p ./resources/python -o ./resources/python.tar.gz"
|
||||
"create:python-tar": "rimraf ./resources/python.tar.gz && conda-lock install --prefix ./resources/python ./resources/conda-lock.yml && conda pack -p ./resources/python -o ./resources/python.tar.gz && rimraf ./resources/python"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^7.6.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { installStatus, serverStatus } from './lib/stores';
|
||||
import { installStatus, serverStatus, serverStartedAt } from './lib/stores';
|
||||
|
||||
import Main from './lib/components/Main.svelte';
|
||||
|
||||
@ -28,6 +28,9 @@
|
||||
console.log('Server status:', event.data.data);
|
||||
serverStatus.set(event.data.data);
|
||||
|
||||
if ($serverStatus) {
|
||||
serverStartedAt.set(Date.now());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
|
||||
import { installStatus, serverStatus } from '../stores';
|
||||
import { installStatus, serverStatus, serverStartedAt } from '../stores';
|
||||
|
||||
import Spinner from './common/Spinner.svelte';
|
||||
import ArrowRightCircle from './icons/ArrowRightCircle.svelte';
|
||||
|
||||
import backgroundImage from '../assets/images/green.jpg';
|
||||
|
||||
let currentTime = Date.now();
|
||||
|
||||
let installing = false;
|
||||
const continueHandler = async () => {
|
||||
if (window?.electronAPI) {
|
||||
@ -16,6 +18,16 @@
|
||||
installing = true;
|
||||
}
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
const interval = setInterval(() => {
|
||||
currentTime = Date.now();
|
||||
}, 1000); // Update every second
|
||||
|
||||
return () => {
|
||||
clearInterval(interval); // Cleanup interval on destroy
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $installStatus === null}
|
||||
@ -107,10 +119,22 @@
|
||||
{:else if $installStatus === true}
|
||||
<div class="flex-1 w-full flex justify-center relative">
|
||||
<div class="m-auto">
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-col gap-3 text-center">
|
||||
<Spinner className="size-5" />
|
||||
|
||||
<div class=" font-secondary">Launching Open WebUI...</div>
|
||||
|
||||
{#if $serverStartedAt}
|
||||
{#if currentTime - $serverStartedAt > 10000}
|
||||
<div
|
||||
class=" font-default text-xs"
|
||||
in:fly={{ duration: 500, y: 10 }}
|
||||
>
|
||||
If it's your first time, it might take a few minutes to
|
||||
start.
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -2,3 +2,5 @@ import { writable } from 'svelte/store';
|
||||
|
||||
export const installStatus = writable(null);
|
||||
export const serverStatus = writable(null);
|
||||
|
||||
export const serverStartedAt = writable(null);
|
||||
|
||||
@ -192,8 +192,13 @@ export function createAdHocSignCommand(envPath: string): string {
|
||||
return `cd ${envPath} && codesign -s - -o 0x2 -f ${signList.join(' ')} && cd -`;
|
||||
}
|
||||
|
||||
export async function installOpenWebUI(installationPath: string, version?: string) {
|
||||
export async function installOpenWebUI(
|
||||
installationPath: string,
|
||||
version?: string
|
||||
): Promise<boolean> {
|
||||
console.log(installationPath);
|
||||
|
||||
// Build the appropriate unpack command based on the platform
|
||||
let unpackCommand =
|
||||
process.platform === 'win32'
|
||||
? `${installationPath}\\Scripts\\activate.bat && pip install open-webui${version ? `==${version}` : ' -U'}`
|
||||
@ -204,32 +209,47 @@ export async function installOpenWebUI(installationPath: string, version?: strin
|
||||
// unpackCommand = `${createAdHocSignCommand(installationPath)}\n${unpackCommand}`;
|
||||
// }
|
||||
|
||||
const commandProcess = exec(unpackCommand, {
|
||||
shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash'
|
||||
});
|
||||
// Wrap the logic in a Promise to properly handle async execution and return a boolean
|
||||
return new Promise((resolve, reject) => {
|
||||
const commandProcess = exec(unpackCommand, {
|
||||
shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash'
|
||||
});
|
||||
|
||||
const onLog = (data) => {
|
||||
console.log(data);
|
||||
logEmitter.emit('log', data);
|
||||
};
|
||||
// Function to handle logging output
|
||||
const onLog = (data: any) => {
|
||||
console.log(data);
|
||||
logEmitter.emit('log', data);
|
||||
};
|
||||
|
||||
commandProcess.stdout?.on('data', onLog);
|
||||
commandProcess.stderr?.on('data', onLog);
|
||||
// Listen to stdout and stderr for logging
|
||||
commandProcess.stdout?.on('data', onLog);
|
||||
commandProcess.stderr?.on('data', onLog);
|
||||
|
||||
commandProcess.on('exit', (code) => {
|
||||
console.log(`Child exited with code ${code}`);
|
||||
logEmitter.emit('log', `Child exited with code ${code}`);
|
||||
// Handle the exit event
|
||||
commandProcess.on('exit', (code) => {
|
||||
console.log(`Child exited with code ${code}`);
|
||||
logEmitter.emit('log', `Child exited with code ${code}`);
|
||||
|
||||
if (code !== 0) {
|
||||
log.error(`Failed to install open-webui: ${code}`);
|
||||
logEmitter.emit('log', `Failed to install open-webui: ${code}`);
|
||||
} else {
|
||||
logEmitter.emit('log', 'open-webui installed successfully');
|
||||
}
|
||||
if (code !== 0) {
|
||||
log.error(`Failed to install open-webui: ${code}`);
|
||||
logEmitter.emit('log', `Failed to install open-webui: ${code}`);
|
||||
resolve(false); // Resolve the Promise with `false` if the command fails
|
||||
} else {
|
||||
logEmitter.emit('log', 'open-webui installed successfully');
|
||||
resolve(true); // Resolve the Promise with `true` if the command succeeds
|
||||
}
|
||||
});
|
||||
|
||||
// Handle errors during execution
|
||||
commandProcess.on('error', (error) => {
|
||||
log.error(`Error occurred while installing open-webui: ${error.message}`);
|
||||
logEmitter.emit('log', `Error occurred while installing open-webui: ${error.message}`);
|
||||
reject(error); // Reject the Promise if an unexpected error occurs
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function installBundledPython(installationPath?: string) {
|
||||
export async function installBundledPython(installationPath?: string): Promise<boolean> {
|
||||
installationPath = installationPath || getBundledPythonInstallationPath();
|
||||
|
||||
const pythonTarPath = getBundledPythonTarPath();
|
||||
@ -241,7 +261,7 @@ export async function installBundledPython(installationPath?: string) {
|
||||
if (!fs.existsSync(pythonTarPath)) {
|
||||
log.error('Python tarball not found');
|
||||
logEmitter.emit('log', 'Python tarball not found'); // Emit log
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
@ -253,6 +273,7 @@ export async function installBundledPython(installationPath?: string) {
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
logEmitter.emit('log', error); // Emit log
|
||||
return false; // Return false to indicate failure
|
||||
}
|
||||
|
||||
// Get the path to the installed Python binary
|
||||
@ -261,7 +282,7 @@ export async function installBundledPython(installationPath?: string) {
|
||||
if (!fs.existsSync(bundledPythonPath)) {
|
||||
log.error('Python binary not found in install path');
|
||||
logEmitter.emit('log', 'Python binary not found in install path'); // Emit log
|
||||
return;
|
||||
return false; // Return false to indicate failure
|
||||
}
|
||||
|
||||
try {
|
||||
@ -271,12 +292,17 @@ export async function installBundledPython(installationPath?: string) {
|
||||
});
|
||||
console.log('Installed Python Version:', pythonVersion.trim());
|
||||
logEmitter.emit('log', `Installed Python Version: ${pythonVersion.trim()}`); // Emit log
|
||||
|
||||
return true; // Return true to indicate success
|
||||
} catch (error) {
|
||||
log.error('Failed to execute Python binary', error);
|
||||
|
||||
return false; // Return false to indicate failure
|
||||
}
|
||||
}
|
||||
|
||||
export async function installPackage(installationPath?: string) {
|
||||
export async function installPackage(installationPath?: string): Promise<boolean> {
|
||||
// Resolve the installation path or use the default bundled Python installation path
|
||||
installationPath = installationPath || getBundledPythonInstallationPath();
|
||||
|
||||
// if (!isBundledPythonInstalled()) {
|
||||
@ -288,24 +314,35 @@ export async function installPackage(installationPath?: string) {
|
||||
// }
|
||||
// }
|
||||
|
||||
console.log('Installing python...');
|
||||
// Log the status for installation steps
|
||||
console.log('Installing Python...');
|
||||
|
||||
try {
|
||||
await installBundledPython(installationPath);
|
||||
// Install the bundled Python
|
||||
const res = await installBundledPython(installationPath);
|
||||
if (!res) {
|
||||
throw new Error('Failed to install bundled Python');
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('Failed to install bundled Python', error);
|
||||
|
||||
throw new Error('Failed to install bundled Python');
|
||||
}
|
||||
|
||||
console.log('Installing open-webui...');
|
||||
try {
|
||||
await installOpenWebUI(installationPath);
|
||||
// Install the Open-WebUI package
|
||||
const success = await installOpenWebUI(installationPath);
|
||||
if (!success) {
|
||||
// Handle a scenario where `installOpenWebUI` returns `false`
|
||||
log.error('Failed to install open-webui');
|
||||
throw new Error('Failed to install open-webui');
|
||||
}
|
||||
} catch (error) {
|
||||
// Log and throw an error if the Open-WebUI installation fails
|
||||
log.error('Failed to install open-webui', error);
|
||||
throw new Error('Failed to install open-webui');
|
||||
}
|
||||
|
||||
// Return true if all installations are successful
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user