diff --git a/modules/model/init.ts b/modules/model/init.ts index 6d9c74c7..b71588eb 100644 --- a/modules/model/init.ts +++ b/modules/model/init.ts @@ -74,8 +74,8 @@ const allProviders: ProviderConfigType[] = [ yi ]; -export const initModels = async () => { - await initModelAvatars(); +export const initModels = async (reboot: boolean = false) => { + if (!reboot) await initModelAvatars(); modelsBuffer.data = allProviders .map((item) => { diff --git a/modules/tool/loadToolDev.ts b/modules/tool/loadToolDev.ts index 581abaf8..83b660df 100644 --- a/modules/tool/loadToolDev.ts +++ b/modules/tool/loadToolDev.ts @@ -31,27 +31,29 @@ export const LoadToolsDev = async (filename: string): Promise => { const readmeFile = join(toolPath, 'README.md'); // Upload logo files if found - for (const logoPath of logoFiles) { - try { - const logoFilename = logoPath.split('/').pop()!; - const logoNameWithoutExt = logoFilename.split('.').slice(0, -1).join('.'); - await publicS3Server.uploadFileAdvanced({ - path: logoPath, - defaultFilename: logoNameWithoutExt, - prefix: UploadToolsS3Path + '/' + filename, - keepRawFilename: true, - contentType: mimeMap[parse(logoPath).ext] - }); - addLog.debug( - `📦 Uploaded tool logo file: ${filename} -> ${UploadToolsS3Path}/${filename}/${logoNameWithoutExt}` - ); - } catch (error) { - addLog.warn(`Failed to upload logo file ${logoPath}: ${error}`); + if (!global.isReboot) { + for (const logoPath of logoFiles) { + try { + const logoFilename = logoPath.split('/').pop()!; + const logoNameWithoutExt = logoFilename.split('.').slice(0, -1).join('.'); + await publicS3Server.uploadFileAdvanced({ + path: logoPath, + defaultFilename: logoNameWithoutExt, + prefix: UploadToolsS3Path + '/' + filename, + keepRawFilename: true, + contentType: mimeMap[parse(logoPath).ext] + }); + addLog.debug( + `📦 Uploaded tool logo file: ${filename} -> ${UploadToolsS3Path}/${filename}/${logoNameWithoutExt}` + ); + } catch (error) { + addLog.warn(`Failed to upload logo file ${logoPath}: ${error}`); + } } } // Upload README.md if it exists - if (existsSync(readmeFile)) { + if (existsSync(readmeFile) && !global.isReboot) { try { await publicS3Server.uploadFileAdvanced({ path: readmeFile, @@ -102,7 +104,7 @@ export const LoadToolsDev = async (filename: string): Promise => { // Find logo files using glob pattern for child tool const childLogoFiles = await glob(`${childPath}/logo.*`); - if (childLogoFiles.length > 0) { + if (childLogoFiles.length > 0 && !global.isReboot) { // Child has its own logo, upload it for (const logoPath of childLogoFiles) { try { @@ -125,7 +127,7 @@ export const LoadToolsDev = async (filename: string): Promise => { } else { // Child doesn't have logo, use parent's logo const parentLogoFiles = await glob(`${toolPath}/logo.*`); - if (parentLogoFiles.length > 0) { + if (parentLogoFiles.length > 0 && !global.isReboot) { for (const parentLogoPath of parentLogoFiles) { try { const logoFilename = parentLogoPath.split('/').pop()!; @@ -188,3 +190,7 @@ export const LoadToolsDev = async (filename: string): Promise => { tools.forEach((tool) => devToolIds.add(tool.toolId)); return tools; }; + +declare global { + var isReboot: boolean; +} diff --git a/runtime/dev/devServer.ts b/runtime/dev/devServer.ts index a34e7606..b04a8c32 100644 --- a/runtime/dev/devServer.ts +++ b/runtime/dev/devServer.ts @@ -10,6 +10,7 @@ export class DevServer { private serverProcess: Subprocess | null = null; private isRestarting = false; private debounceTimer: Timer | null = null; + private isFirstStart = true; // 启动开发环境 async start() { @@ -35,12 +36,18 @@ export class DevServer { await this.stopServer(); } + const cmd = this.isFirstStart + ? ['bun', 'run', path.join(__dirname, '..', 'index.ts')] + : ['bun', 'run', path.join(__dirname, '..', 'index.ts'), '--reboot']; + this.serverProcess = spawn({ - cmd: ['bun', 'run', path.join(__dirname, '..', 'index.ts')], + cmd, stdout: 'inherit', stderr: 'inherit', stdin: 'inherit' }); + + this.isFirstStart = false; } // 停止服务器进程 diff --git a/runtime/index.ts b/runtime/index.ts index 6a171bc7..a51cbff6 100644 --- a/runtime/index.ts +++ b/runtime/index.ts @@ -18,61 +18,75 @@ import { setupGlobalErrorHandling } from './utils/error'; const requestSizeLimit = `${Number(process.env.MAX_API_SIZE || 10)}mb`; -const app = express().use( - express.json({ limit: requestSizeLimit }), - express.urlencoded({ extended: true, limit: requestSizeLimit }), - express.static(isProd ? 'public' : join(basePath, 'dist', 'public'), { - maxAge: isProd ? '1d' : '0', - etag: true, - lastModified: true - }) -); +async function main(reboot: boolean = false) { + const app = express().use( + express.json({ limit: requestSizeLimit }), + express.urlencoded({ extended: true, limit: requestSizeLimit }), + express.static(isProd ? 'public' : join(basePath, 'dist', 'public'), { + maxAge: isProd ? '1d' : '0', + etag: true, + lastModified: true + }) + ); -connectSignoz(); + connectSignoz(); -// System -initOpenAPI(app); -initRouter(app); -setupProxy(); + // System + initOpenAPI(app); + initRouter(app); + setupProxy(); -// DB -try { - await connectMongo(connectionMongo, MONGO_URL); -} catch (error) { - addLog.error('Failed to initialize services:', error); - process.exit(1); -} + // DB + try { + await connectMongo(connectionMongo, MONGO_URL); + } catch (error) { + addLog.error('Failed to initialize services:', error); + process.exit(1); + } -await initializeS3(); + await initializeS3(); -// Modules -await refreshDir(tempDir); // upload pkg files, unpkg, temp dir -await ensureDir(tempToolsDir); // ensure the unpkged tools temp dir + // Modules + await refreshDir(tempDir); // upload pkg files, unpkg, temp dir + await ensureDir(tempToolsDir); // ensure the unpkged tools temp dir -await Promise.all([ - getCachedData(SystemCacheKeyEnum.systemTool), // init system tool - initModels(), - initWorkflowTemplates() -]); + await Promise.all([ + getCachedData(SystemCacheKeyEnum.systemTool), // init system tool + initModels(reboot), + initWorkflowTemplates() + ]); -const PORT = parseInt(process.env.PORT || '3000'); -const server = app.listen(PORT, (error?: Error) => { - if (error) { - console.error(error); - process.exit(1); - } - addLog.info(`FastGPT Plugin Service is listening at http://localhost:${PORT}`); -}); + const PORT = parseInt(process.env.PORT || '3000'); + const server = app.listen(PORT, (error?: Error) => { + if (error) { + console.error(error); + process.exit(1); + } + addLog.info(`FastGPT Plugin Service is listening at http://localhost:${PORT}`); + }); -['SIGTERM', 'SIGINT'].forEach((signal) => - process.on(signal, () => { - addLog.debug(`${signal} signal received: closing HTTP server`); - server.close(() => { - addLog.info('HTTP server closed'); - process.exit(0); - }); - }) -); + ['SIGTERM', 'SIGINT'].forEach((signal) => + process.on(signal, () => { + addLog.debug(`${signal} signal received: closing HTTP server`); + server.close(() => { + addLog.info('HTTP server closed'); + process.exit(0); + }); + }) + ); -// 全局错误处理设置 -setupGlobalErrorHandling(app); + // 全局错误处理设置 + setupGlobalErrorHandling(app); +} + +if (import.meta.main) { + // get the arguments from the command line + const args = process.argv.slice(2); + const reboot = args.includes('--reboot'); + global.isReboot = reboot; + await main(reboot); +} + +declare global { + var isReboot: boolean; +}