@becrafter/prompt-manager 0.0.18 → 0.1.1
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/IFLOW.md +175 -0
- package/README.md +145 -234
- package/app/desktop/assets/app.1.png +0 -0
- package/app/desktop/assets/app.png +0 -0
- package/app/desktop/assets/icons/icon.icns +0 -0
- package/app/desktop/assets/icons/icon.ico +0 -0
- package/app/desktop/assets/icons/icon.png +0 -0
- package/app/desktop/assets/icons/tray.png +0 -0
- package/app/desktop/assets/templates/about.html +147 -0
- package/app/desktop/assets/tray.png +0 -0
- package/app/desktop/main.js +187 -732
- package/app/desktop/package-lock.json +723 -522
- package/app/desktop/package.json +54 -25
- package/app/desktop/preload.js +7 -0
- package/app/desktop/src/core/error-handler.js +108 -0
- package/app/desktop/src/core/event-emitter.js +84 -0
- package/app/desktop/src/core/logger.js +108 -0
- package/app/desktop/src/core/state-manager.js +125 -0
- package/app/desktop/src/services/module-loader.js +214 -0
- package/app/desktop/src/services/runtime-manager.js +301 -0
- package/app/desktop/src/services/service-manager.js +169 -0
- package/app/desktop/src/services/update-manager.js +268 -0
- package/app/desktop/src/ui/about-dialog-manager.js +208 -0
- package/app/desktop/src/ui/admin-window-manager.js +757 -0
- package/app/desktop/src/ui/splash-manager.js +253 -0
- package/app/desktop/src/ui/tray-manager.js +186 -0
- package/app/desktop/src/utils/icon-manager.js +133 -0
- package/app/desktop/src/utils/path-utils.js +58 -0
- package/app/desktop/src/utils/resource-paths.js +49 -0
- package/app/desktop/src/utils/resource-sync.js +260 -0
- package/app/desktop/src/utils/runtime-sync.js +241 -0
- package/app/desktop/src/utils/template-renderer.js +284 -0
- package/app/desktop/src/utils/version-utils.js +59 -0
- package/examples/prompts/engineer/engineer-professional.yaml +92 -0
- package/examples/prompts/engineer/laowang-engineer.yaml +132 -0
- package/examples/prompts/engineer/nekomata-engineer.yaml +123 -0
- package/examples/prompts/engineer/ojousama-engineer.yaml +124 -0
- package/examples/prompts/recommend/human_3-0_growth_diagnostic_coach_prompt.yaml +105 -0
- package/examples/prompts/workflow/sixstep-workflow.yaml +192 -0
- package/package.json +18 -9
- package/packages/admin-ui/.babelrc +3 -0
- package/packages/admin-ui/admin.html +237 -4784
- package/packages/admin-ui/css/main.css +2592 -0
- package/packages/admin-ui/css/recommended-prompts.css +610 -0
- package/packages/admin-ui/package-lock.json +6981 -0
- package/packages/admin-ui/package.json +36 -0
- package/packages/admin-ui/src/codemirror.js +53 -0
- package/packages/admin-ui/src/index.js +3188 -0
- package/packages/admin-ui/webpack.config.js +76 -0
- package/packages/resources/tools/chrome-devtools/README.md +310 -0
- package/packages/resources/tools/chrome-devtools/chrome-devtools.tool.js +1703 -0
- package/packages/resources/tools/file-reader/README.md +289 -0
- package/packages/resources/tools/file-reader/file-reader.tool.js +1545 -0
- package/packages/resources/tools/filesystem/README.md +359 -0
- package/packages/resources/tools/filesystem/filesystem.tool.js +538 -0
- package/packages/resources/tools/ollama-remote/README.md +192 -0
- package/packages/resources/tools/ollama-remote/ollama-remote.tool.js +421 -0
- package/packages/resources/tools/pdf-reader/README.md +236 -0
- package/packages/resources/tools/pdf-reader/pdf-reader.tool.js +565 -0
- package/packages/resources/tools/playwright/README.md +306 -0
- package/packages/resources/tools/playwright/playwright.tool.js +1186 -0
- package/packages/resources/tools/todolist/README.md +394 -0
- package/packages/resources/tools/todolist/todolist.tool.js +1312 -0
- package/packages/server/README.md +142 -0
- package/packages/server/api/admin.routes.js +42 -11
- package/packages/server/api/surge.routes.js +43 -0
- package/packages/server/app.js +119 -14
- package/packages/server/index.js +39 -0
- package/packages/server/mcp/mcp.server.js +346 -28
- package/packages/server/mcp/{mcp.handler.js → prompt.handler.js} +108 -9
- package/packages/server/mcp/sequential-thinking.handler.js +318 -0
- package/packages/server/mcp/think-plan.handler.js +274 -0
- package/packages/server/middlewares/auth.middleware.js +6 -0
- package/packages/server/package.json +51 -0
- package/packages/server/server.js +37 -1
- package/packages/server/toolm/index.js +9 -0
- package/packages/server/toolm/package-installer.service.js +267 -0
- package/packages/server/toolm/test-tools.js +264 -0
- package/packages/server/toolm/tool-context.service.js +334 -0
- package/packages/server/toolm/tool-dependency.service.js +168 -0
- package/packages/server/toolm/tool-description-generator-optimized.service.js +375 -0
- package/packages/server/toolm/tool-description-generator.service.js +312 -0
- package/packages/server/toolm/tool-environment.service.js +200 -0
- package/packages/server/toolm/tool-execution.service.js +277 -0
- package/packages/server/toolm/tool-loader.service.js +219 -0
- package/packages/server/toolm/tool-logger.service.js +223 -0
- package/packages/server/toolm/tool-manager.handler.js +65 -0
- package/packages/server/toolm/tool-manual-generator.service.js +389 -0
- package/packages/server/toolm/tool-mode-handlers.service.js +224 -0
- package/packages/server/toolm/tool-storage.service.js +111 -0
- package/packages/server/toolm/tool-sync.service.js +138 -0
- package/packages/server/toolm/tool-utils.js +20 -0
- package/packages/server/toolm/tool-yaml-parser.service.js +81 -0
- package/packages/server/toolm/validate-system.js +421 -0
- package/packages/server/utils/config.js +49 -5
- package/packages/server/utils/util.js +65 -10
- package/scripts/build-icons.js +135 -0
- package/scripts/build.sh +57 -0
- package/scripts/surge/CNAME +1 -0
- package/scripts/surge/README.md +47 -0
- package/scripts/surge/package-lock.json +34 -0
- package/scripts/surge/package.json +20 -0
- package/scripts/surge/sync-to-surge.js +151 -0
- package/packages/admin-ui/js/closebrackets.min.js +0 -8
- package/packages/admin-ui/js/codemirror.min.js +0 -8
- package/packages/admin-ui/js/js-yaml.min.js +0 -2
- package/packages/admin-ui/js/markdown.min.js +0 -8
- /package/app/desktop/assets/{icon.png → tray.1.png} +0 -0
package/app/desktop/main.js
CHANGED
|
@@ -1,786 +1,241 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const { pathToFileURL } = require('url');
|
|
7
|
-
const tar = require('tar');
|
|
8
|
-
const { spawn } = require('child_process');
|
|
9
|
-
|
|
10
|
-
// 设置日志文件
|
|
11
|
-
const logFilePath = path.join(app.getPath('userData'), 'prompt-manager-desktop.log');
|
|
12
|
-
let logStream;
|
|
13
|
-
|
|
14
|
-
// 初始化日志流
|
|
15
|
-
function initLogStream() {
|
|
16
|
-
try {
|
|
17
|
-
// 确保日志目录存在
|
|
18
|
-
const logDir = path.dirname(logFilePath);
|
|
19
|
-
if (!fs.existsSync(logDir)) {
|
|
20
|
-
fs.mkdirSync(logDir, { recursive: true });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// 创建或追加到日志文件
|
|
24
|
-
logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
|
|
25
|
-
console.log = function(...args) {
|
|
26
|
-
const message = `[${new Date().toISOString()}] [INFO] ${args.join(' ')}\n`;
|
|
27
|
-
process.stdout.write(message);
|
|
28
|
-
if (logStream) {
|
|
29
|
-
logStream.write(message);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
console.error = function(...args) {
|
|
34
|
-
const message = `[${new Date().toISOString()}] [ERROR] ${args.join(' ')}\n`;
|
|
35
|
-
process.stderr.write(message);
|
|
36
|
-
if (logStream) {
|
|
37
|
-
logStream.write(message);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
console.warn = function(...args) {
|
|
42
|
-
const message = `[${new Date().toISOString()}] [WARN] ${args.join(' ')}\n`;
|
|
43
|
-
process.stdout.write(message);
|
|
44
|
-
if (logStream) {
|
|
45
|
-
logStream.write(message);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
console.debug = function(...args) {
|
|
50
|
-
const message = `[${new Date().toISOString()}] [DEBUG] ${args.join(' ')}\n`;
|
|
51
|
-
process.stdout.write(message);
|
|
52
|
-
if (logStream) {
|
|
53
|
-
logStream.write(message);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
console.log(`Logging initialized. Log file: ${logFilePath}`);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error('Failed to initialize logging:', error);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 应用主入口
|
|
3
|
+
* 重构后的主程序,遵循SRP、KISS、DRY、YAGNI原则
|
|
4
|
+
*/
|
|
62
5
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
let serviceState = 'stopped';
|
|
66
|
-
let currentServerState = null;
|
|
67
|
-
let serverModule = null;
|
|
68
|
-
let serverModuleVersion = 0;
|
|
69
|
-
let serverModuleLoading = null;
|
|
70
|
-
let isQuitting = false;
|
|
71
|
-
let runtimeServerRoot = null;
|
|
72
|
-
let startFailureCount = 0;
|
|
73
|
-
|
|
74
|
-
const desktopPackageJson = JSON.parse(
|
|
75
|
-
fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8')
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
function resolveBaseServerRoot() {
|
|
79
|
-
return path.resolve(__dirname, '..', '..');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async function ensureRuntimeServerRoot() {
|
|
83
|
-
if (runtimeServerRoot) {
|
|
84
|
-
console.log('Using cached runtimeServerRoot:', runtimeServerRoot);
|
|
85
|
-
return runtimeServerRoot;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (!app.isPackaged) {
|
|
89
|
-
console.log('App is not packaged, using development server root');
|
|
90
|
-
runtimeServerRoot = resolveBaseServerRoot();
|
|
91
|
-
console.log('Development server root:', runtimeServerRoot);
|
|
92
|
-
return runtimeServerRoot;
|
|
93
|
-
}
|
|
6
|
+
const { app, BrowserWindow, ipcMain } = require('electron');
|
|
7
|
+
const path = require('path');
|
|
94
8
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
9
|
+
// 导入管理器模块
|
|
10
|
+
const AppState = require('./src/core/state-manager');
|
|
11
|
+
const Logger = require('./src/core/logger');
|
|
12
|
+
const ErrorHandler = require('./src/core/error-handler');
|
|
13
|
+
const RuntimeManager = require('./src/services/runtime-manager');
|
|
14
|
+
const ModuleLoader = require('./src/services/module-loader');
|
|
15
|
+
const ServiceManager = require('./src/services/service-manager');
|
|
16
|
+
const TrayManager = require('./src/ui/tray-manager');
|
|
17
|
+
const UpdateManager = require('./src/services/update-manager');
|
|
18
|
+
const AboutDialogManager = require('./src/ui/about-dialog-manager');
|
|
19
|
+
const SplashManager = require('./src/ui/splash-manager');
|
|
20
|
+
const IconManager = require('./src/utils/icon-manager');
|
|
21
|
+
const RuntimeSync = require('./src/utils/runtime-sync');
|
|
22
|
+
|
|
23
|
+
class PromptManagerApp {
|
|
24
|
+
constructor() {
|
|
25
|
+
this.stateManager = new AppState();
|
|
26
|
+
this.logger = new Logger({ debugEnabled: false });
|
|
27
|
+
this.errorHandler = new ErrorHandler(this.logger);
|
|
28
|
+
this.runtimeManager = new RuntimeManager(this.logger, this.errorHandler);
|
|
29
|
+
this.moduleLoader = new ModuleLoader(this.logger, this.errorHandler);
|
|
30
|
+
this.iconManager = new IconManager();
|
|
31
|
+
this.serviceManager = new ServiceManager(this.logger, this.errorHandler, this.moduleLoader);
|
|
32
|
+
this.updateManager = new UpdateManager(this.logger, this.errorHandler, this.runtimeManager);
|
|
33
|
+
this.aboutDialogManager = new AboutDialogManager(this.logger, this.runtimeManager, this.iconManager);
|
|
34
|
+
this.trayManager = new TrayManager(this.logger, this.errorHandler, this.iconManager);
|
|
35
|
+
this.splashManager = new SplashManager(this.logger, this.iconManager);
|
|
36
|
+
|
|
37
|
+
this.isInitialized = false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async initialize() {
|
|
41
|
+
if (this.isInitialized) return;
|
|
104
42
|
|
|
105
|
-
try {
|
|
106
|
-
// 检查打包的资源目录是否存在
|
|
107
43
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
44
|
+
this.logger.info('Initializing Prompt Manager Desktop Application');
|
|
45
|
+
|
|
46
|
+
// 显示启动画面
|
|
47
|
+
await this.splashManager.showSplash();
|
|
48
|
+
this.splashManager.updateStatus('正在初始化...', 20);
|
|
49
|
+
|
|
50
|
+
// 同步环境配置
|
|
51
|
+
await RuntimeSync.syncRuntime();
|
|
52
|
+
this.splashManager.updateStatus('正在同步工具箱...', 35);
|
|
53
|
+
|
|
54
|
+
// 初始化日志系统
|
|
55
|
+
await this.logger.initialize();
|
|
56
|
+
|
|
57
|
+
// 设置应用菜单
|
|
58
|
+
this.setupApplicationMenu();
|
|
59
|
+
|
|
60
|
+
// 初始化系统托盘
|
|
61
|
+
this.splashManager.updateStatus('正在启动托盘服务...', 60);
|
|
62
|
+
await this.trayManager.initialize(this.stateManager);
|
|
63
|
+
|
|
64
|
+
// 设置事件监听
|
|
65
|
+
this.setupEventListeners();
|
|
66
|
+
|
|
67
|
+
// 确保运行时环境
|
|
68
|
+
this.splashManager.updateStatus('正在准备运行时环境...', 70);
|
|
69
|
+
const serverRoot = await this.runtimeManager.ensureRuntimeEnvironment();
|
|
70
|
+
this.stateManager.set('runtimeRoot', serverRoot);
|
|
71
|
+
|
|
72
|
+
// 启动服务
|
|
73
|
+
this.splashManager.updateStatus('正在启动核心服务...', 80);
|
|
74
|
+
await this.startService();
|
|
75
|
+
|
|
76
|
+
this.isInitialized = true;
|
|
77
|
+
this.logger.info('Application initialized successfully');
|
|
78
|
+
|
|
79
|
+
// 关闭启动画面
|
|
80
|
+
this.splashManager.updateStatus('准备就绪...', 100);
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
this.splashManager.closeSplash();
|
|
83
|
+
}, 500); // 短暂延迟以显示完成状态
|
|
120
84
|
|
|
121
|
-
// 检查是否需要安装依赖
|
|
122
|
-
try {
|
|
123
|
-
await fs.promises.access(path.join(runtimeRoot, 'node_modules'), fs.constants.F_OK);
|
|
124
|
-
console.log('node_modules already exists in runtime root');
|
|
125
|
-
} catch (error) {
|
|
126
|
-
console.log('node_modules not found in runtime root, will install dependencies');
|
|
127
|
-
needsInstall = true;
|
|
128
|
-
}
|
|
129
85
|
} catch (error) {
|
|
130
|
-
|
|
131
|
-
await fs.promises.mkdir(runtimeRoot, { recursive: true });
|
|
132
|
-
console.log('Created runtime root directory');
|
|
86
|
+
this.logger.error('Application initialization failed', error);
|
|
133
87
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (needsInstall) {
|
|
143
|
-
console.log('Installing dependencies in runtime root');
|
|
144
|
-
try {
|
|
145
|
-
await installServerDependencies(runtimeRoot);
|
|
146
|
-
console.log('Dependencies installed successfully');
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error('Failed to install dependencies:', error);
|
|
149
|
-
dialog.showErrorBox('依赖安装失败', `无法安装服务器依赖: ${error.message}\n\n请查看日志文件: ${logFilePath}`);
|
|
150
|
-
throw error;
|
|
151
|
-
}
|
|
88
|
+
// 关闭启动画面
|
|
89
|
+
this.splashManager.closeSplash();
|
|
90
|
+
|
|
91
|
+
this.errorHandler.handleError('APP_INIT_FAILED', error, {
|
|
92
|
+
logFilePath: this.logger.getLogFilePath()
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
throw error;
|
|
152
96
|
}
|
|
153
|
-
} catch (error) {
|
|
154
|
-
console.error('Error in ensureRuntimeServerRoot:', error);
|
|
155
|
-
dialog.showErrorBox('服务器初始化失败', `无法设置服务器运行环境: ${error.message}\n\n请查看日志文件: ${logFilePath}`);
|
|
156
|
-
throw error;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
runtimeServerRoot = runtimeRoot;
|
|
160
|
-
console.log('Final runtimeServerRoot:', runtimeServerRoot);
|
|
161
|
-
return runtimeServerRoot;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async function loadServerModule(options = {}) {
|
|
165
|
-
console.log('loadServerModule called with options:', options);
|
|
166
|
-
console.log('Current serviceState:', serviceState);
|
|
167
|
-
console.log('serverModule exists:', !!serverModule);
|
|
168
|
-
console.log('serverModuleLoading exists:', !!serverModuleLoading);
|
|
169
|
-
|
|
170
|
-
// 如果强制重新加载或服务状态异常,则清理缓存
|
|
171
|
-
if (options.forceReload || serviceState === 'error') {
|
|
172
|
-
console.log('Forcing module reload, clearing cache');
|
|
173
|
-
serverModule = null;
|
|
174
|
-
serverModuleVersion += 1;
|
|
175
|
-
serverModuleLoading = null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (serverModule) {
|
|
179
|
-
console.log('Returning cached server module');
|
|
180
|
-
return serverModule;
|
|
181
97
|
}
|
|
182
98
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
try {
|
|
189
|
-
const serverRoot = await ensureRuntimeServerRoot();
|
|
190
|
-
console.log('Server root resolved to:', serverRoot);
|
|
191
|
-
|
|
192
|
-
const serverEntry = path.join(serverRoot, 'packages', 'server', 'server.js');
|
|
193
|
-
console.log('Server entry file:', serverEntry);
|
|
194
|
-
|
|
195
|
-
// 检查入口文件是否存在
|
|
196
|
-
try {
|
|
197
|
-
await fs.promises.access(serverEntry, fs.constants.F_OK);
|
|
198
|
-
console.log('Server entry file exists');
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.error('Server entry file does not exist:', serverEntry);
|
|
201
|
-
throw new Error(`Server entry file not found: ${serverEntry}`);
|
|
99
|
+
setupApplicationMenu() {
|
|
100
|
+
if (process.platform === 'darwin') {
|
|
101
|
+
app.dock.hide();
|
|
202
102
|
}
|
|
203
103
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
serverModuleLoading = import(entryUrl.href)
|
|
209
|
-
.then((mod) => {
|
|
210
|
-
console.log('Module loaded successfully');
|
|
211
|
-
serverModule = mod;
|
|
212
|
-
return mod;
|
|
213
|
-
})
|
|
214
|
-
.catch((error) => {
|
|
215
|
-
console.error('Module loading failed:', error);
|
|
216
|
-
// 清理加载状态,以便下次重试
|
|
217
|
-
serverModuleLoading = null;
|
|
218
|
-
serverModule = null;
|
|
219
|
-
throw new Error(`Failed to load server module: ${error.message}`);
|
|
220
|
-
})
|
|
221
|
-
.finally(() => {
|
|
222
|
-
serverModuleLoading = null;
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
return serverModuleLoading;
|
|
226
|
-
} catch (error) {
|
|
227
|
-
console.error('Error in loadServerModule:', error);
|
|
228
|
-
dialog.showErrorBox('模块加载失败', error.message);
|
|
229
|
-
throw error;
|
|
104
|
+
// 隐藏默认应用菜单
|
|
105
|
+
const { Menu } = require('electron');
|
|
106
|
+
Menu.setApplicationMenu(null);
|
|
230
107
|
}
|
|
231
|
-
}
|
|
232
108
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return '停止中';
|
|
241
|
-
case 'error':
|
|
242
|
-
return '启动失败';
|
|
243
|
-
default:
|
|
244
|
-
return '已停止';
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
async function startService() {
|
|
249
|
-
console.log('startService called');
|
|
250
|
-
// 如果正在运行或正在启动,直接返回
|
|
251
|
-
if (serviceState === 'running' || serviceState === 'starting') {
|
|
252
|
-
console.log('Service is already running or starting, returning');
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
serviceState = 'starting';
|
|
257
|
-
console.log('Service state set to starting');
|
|
258
|
-
refreshTrayMenu();
|
|
259
|
-
|
|
260
|
-
try {
|
|
261
|
-
console.log('Loading server module with force reload');
|
|
262
|
-
// 强制重新加载模块以确保获取最新状态
|
|
263
|
-
const module = await loadServerModule({ forceReload: true });
|
|
264
|
-
console.log('Server module loaded, starting server');
|
|
109
|
+
setupEventListeners() {
|
|
110
|
+
// 托盘事件
|
|
111
|
+
this.trayManager.on('service-start-requested', () => this.startService());
|
|
112
|
+
this.trayManager.on('service-stop-requested', () => this.stopService());
|
|
113
|
+
this.trayManager.on('update-check-requested', () => this.checkForUpdates());
|
|
114
|
+
this.trayManager.on('about-dialog-requested', () => this.showAboutDialog());
|
|
115
|
+
this.trayManager.on('quit-requested', () => this.quitApplication());
|
|
265
116
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
117
|
+
// 服务管理器事件
|
|
118
|
+
this.serviceManager.on('status-update', () => this.trayManager.updateMenu());
|
|
119
|
+
this.serviceManager.on('restart-requested', () => this.restartApplication());
|
|
269
120
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
startFailureCount = 0; // 重置失败计数
|
|
275
|
-
console.log('Service state set to running');
|
|
276
|
-
} catch (error) {
|
|
277
|
-
serviceState = 'error';
|
|
278
|
-
currentServerState = null;
|
|
279
|
-
startFailureCount++;
|
|
121
|
+
// IPC事件
|
|
122
|
+
ipcMain.on('about-window-click', (event, data) => {
|
|
123
|
+
this.aboutDialogManager.handleAboutWindowClick(data);
|
|
124
|
+
});
|
|
280
125
|
|
|
281
|
-
|
|
282
|
-
|
|
126
|
+
// 应用事件
|
|
127
|
+
app.on('window-all-closed', (event) => {
|
|
128
|
+
event.preventDefault(); // 防止应用退出
|
|
129
|
+
});
|
|
283
130
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
} finally {
|
|
292
|
-
console.log('Refreshing tray menu');
|
|
293
|
-
refreshTrayMenu();
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async function stopService() {
|
|
298
|
-
// 如果服务未运行或正在停止,直接返回
|
|
299
|
-
if (serviceState !== 'running' && serviceState !== 'error') {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
serviceState = 'stopping';
|
|
304
|
-
refreshTrayMenu();
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
const module = await loadServerModule();
|
|
308
|
-
if (module && typeof module.stopServer === 'function') {
|
|
309
|
-
await module.stopServer();
|
|
310
|
-
}
|
|
311
|
-
currentServerState = null;
|
|
312
|
-
serviceState = 'stopped';
|
|
131
|
+
app.on('before-quit', async (event) => {
|
|
132
|
+
if (this.stateManager.get('isQuitting')) return;
|
|
133
|
+
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
await this.quitApplication();
|
|
136
|
+
});
|
|
313
137
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
serviceState = 'error';
|
|
320
|
-
} finally {
|
|
321
|
-
refreshTrayMenu();
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function ensureTray() {
|
|
326
|
-
if (tray) {
|
|
327
|
-
return tray;
|
|
138
|
+
app.on('activate', () => {
|
|
139
|
+
if (!this.trayManager.tray) {
|
|
140
|
+
this.trayManager.initialize(this.stateManager);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
328
143
|
}
|
|
329
144
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
];
|
|
336
|
-
|
|
337
|
-
let iconPath = null;
|
|
338
|
-
let icon = null;
|
|
339
|
-
|
|
340
|
-
console.log('App is packaged:', app.isPackaged);
|
|
341
|
-
console.log('__dirname:', __dirname);
|
|
342
|
-
console.log('process.resourcesPath:', process.resourcesPath);
|
|
343
|
-
|
|
344
|
-
for (const possiblePath of possiblePaths) {
|
|
345
|
-
console.log('Checking icon path:', possiblePath);
|
|
346
|
-
console.log('File exists:', fs.existsSync(possiblePath));
|
|
347
|
-
if (fs.existsSync(possiblePath)) {
|
|
348
|
-
iconPath = possiblePath;
|
|
349
|
-
break;
|
|
145
|
+
async startService() {
|
|
146
|
+
const serverRoot = this.stateManager.get('runtimeRoot');
|
|
147
|
+
if (!serverRoot) {
|
|
148
|
+
this.logger.error('Cannot start service: runtime root not set');
|
|
149
|
+
return false;
|
|
350
150
|
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (!iconPath) {
|
|
354
|
-
console.error('Icon file not found in any of the expected locations');
|
|
355
|
-
// 创建一个简单的文本托盘作为后备
|
|
356
|
-
tray = new Tray(nativeImage.createEmpty());
|
|
357
|
-
tray.setToolTip('Prompt Server - Icon Missing');
|
|
358
|
-
refreshTrayMenu();
|
|
359
|
-
return tray;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
console.log('Attempting to load icon from:', iconPath);
|
|
363
|
-
|
|
364
|
-
try {
|
|
365
|
-
icon = nativeImage.createFromPath(iconPath);
|
|
366
|
-
console.log('Icon loaded successfully');
|
|
367
|
-
console.log('Icon is empty:', icon.isEmpty());
|
|
368
|
-
console.log('Icon size:', icon.getSize());
|
|
369
151
|
|
|
370
|
-
|
|
371
|
-
icon = icon.resize({ width: 18, height: 18 });
|
|
372
|
-
icon.setTemplateImage(true);
|
|
373
|
-
console.log('Icon resized and set as template image');
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
tray = new Tray(icon);
|
|
377
|
-
tray.setToolTip('Prompt Server');
|
|
378
|
-
console.log('Tray created successfully');
|
|
379
|
-
refreshTrayMenu();
|
|
380
|
-
return tray;
|
|
381
|
-
} catch (error) {
|
|
382
|
-
console.error('Failed to create tray:', error);
|
|
383
|
-
// 创建一个简单的文本托盘作为后备
|
|
384
|
-
tray = new Tray(nativeImage.createEmpty());
|
|
385
|
-
tray.setToolTip('Prompt Server - Error');
|
|
386
|
-
refreshTrayMenu();
|
|
387
|
-
return tray;
|
|
152
|
+
return await this.serviceManager.startService(serverRoot, this.stateManager);
|
|
388
153
|
}
|
|
389
|
-
}
|
|
390
154
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
return;
|
|
155
|
+
async stopService() {
|
|
156
|
+
return await this.serviceManager.stopService(this.stateManager);
|
|
394
157
|
}
|
|
395
158
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
{ type: 'separator' },
|
|
402
|
-
{
|
|
403
|
-
label: serviceState === 'running' ? '停止服务' : '启动服务',
|
|
404
|
-
click: () => (serviceState === 'running' ? stopService() : startService())
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
label: '复制服务地址',
|
|
408
|
-
enabled: serviceState === 'running',
|
|
409
|
-
click: () => clipboard.writeText(`${address}/mcp`)
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
label: '打开管理后台',
|
|
413
|
-
enabled: serviceState === 'running',
|
|
414
|
-
click: () => openAdminWindow(adminUrl)
|
|
415
|
-
},
|
|
416
|
-
{ type: 'separator' },
|
|
417
|
-
{
|
|
418
|
-
label: '查看日志文件',
|
|
419
|
-
click: () => {
|
|
420
|
-
try {
|
|
421
|
-
shell.openPath(logFilePath);
|
|
422
|
-
} catch (error) {
|
|
423
|
-
dialog.showErrorBox('打开日志文件失败', error.message);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
label: '检查更新',
|
|
429
|
-
click: () => checkForUpdates()
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
label: '关于服务',
|
|
433
|
-
click: () => showAboutDialog()
|
|
434
|
-
},
|
|
435
|
-
{ type: 'separator' },
|
|
436
|
-
{
|
|
437
|
-
label: '退出服务',
|
|
438
|
-
click: async () => {
|
|
439
|
-
isQuitting = true;
|
|
440
|
-
await stopService();
|
|
441
|
-
if (logStream) {
|
|
442
|
-
logStream.end();
|
|
443
|
-
}
|
|
444
|
-
app.quit();
|
|
445
|
-
}
|
|
159
|
+
async checkForUpdates() {
|
|
160
|
+
try {
|
|
161
|
+
await this.updateManager.checkForUpdates();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.logger.error('Update check failed', error);
|
|
446
164
|
}
|
|
447
|
-
];
|
|
448
|
-
|
|
449
|
-
const menu = Menu.buildFromTemplate(template);
|
|
450
|
-
tray.setContextMenu(menu);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
function openAdminWindow(url) {
|
|
454
|
-
if (adminWindow) {
|
|
455
|
-
adminWindow.focus();
|
|
456
|
-
return;
|
|
457
165
|
}
|
|
458
166
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
height: 800,
|
|
462
|
-
title: 'Prompt Server 管理后台',
|
|
463
|
-
webPreferences: {
|
|
464
|
-
contextIsolation: true,
|
|
465
|
-
preload: undefined
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
adminWindow.loadURL(url);
|
|
470
|
-
adminWindow.on('closed', () => {
|
|
471
|
-
adminWindow = null;
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
async function getCurrentServiceVersion() {
|
|
476
|
-
try {
|
|
477
|
-
const serverRoot = await ensureRuntimeServerRoot();
|
|
478
|
-
const pkgRaw = await fs.promises.readFile(path.join(serverRoot, 'package.json'), 'utf8');
|
|
479
|
-
const pkg = JSON.parse(pkgRaw);
|
|
480
|
-
return pkg.version;
|
|
481
|
-
} catch (error) {
|
|
482
|
-
return 'unknown';
|
|
167
|
+
showAboutDialog() {
|
|
168
|
+
this.aboutDialogManager.showAboutDialog();
|
|
483
169
|
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
function compareVersions(a, b) {
|
|
487
|
-
const toNumbers = (value = '') => value.split('.').map((part) => parseInt(part, 10) || 0);
|
|
488
|
-
const [a1, a2, a3] = toNumbers(a);
|
|
489
|
-
const [b1, b2, b3] = toNumbers(b);
|
|
490
|
-
if (a1 !== b1) return a1 - b1;
|
|
491
|
-
if (a2 !== b2) return a2 - b2;
|
|
492
|
-
return a3 - b3;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
async function checkForUpdates() {
|
|
496
|
-
try {
|
|
497
|
-
const currentVersion = await getCurrentServiceVersion();
|
|
498
|
-
|
|
499
|
-
const response = await fetch('https://registry.npmjs.org/@becrafter/prompt-manager');
|
|
500
|
-
if (!response.ok) {
|
|
501
|
-
throw new Error('无法获取最新版本信息');
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const metadata = await response.json();
|
|
505
|
-
const latestVersion = metadata?.['dist-tags']?.latest;
|
|
506
|
-
|
|
507
|
-
if (!latestVersion) {
|
|
508
|
-
throw new Error('未能解析最新版本号');
|
|
509
|
-
}
|
|
510
170
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
message: '已是最新版本',
|
|
515
|
-
detail: `服务当前版本:${currentVersion}`
|
|
516
|
-
});
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
const { response: action } = await dialog.showMessageBox({
|
|
521
|
-
type: 'question',
|
|
522
|
-
buttons: ['立即升级', '打开发布页', '取消'],
|
|
523
|
-
defaultId: 0,
|
|
524
|
-
cancelId: 2,
|
|
525
|
-
message: `发现新版本 ${latestVersion}`,
|
|
526
|
-
detail: '升级期间服务会短暂停止,是否继续?'
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
if (action === 1) {
|
|
530
|
-
shell.openExternal('https://github.com/BeCrafter/prompt-manager/releases/latest');
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
if (action !== 0) {
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
const wasRunning = serviceState === 'running';
|
|
539
|
-
if (wasRunning) {
|
|
540
|
-
await stopService();
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
await performInPlaceUpgrade(latestVersion);
|
|
544
|
-
|
|
545
|
-
await dialog.showMessageBox({
|
|
546
|
-
type: 'info',
|
|
547
|
-
message: '升级成功',
|
|
548
|
-
detail: `服务已升级到 ${latestVersion}`
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
if (wasRunning) {
|
|
552
|
-
await startService();
|
|
553
|
-
}
|
|
554
|
-
} catch (error) {
|
|
555
|
-
dialog.showErrorBox('检查更新失败', error?.message || String(error));
|
|
171
|
+
handleAboutWindowClick(data) {
|
|
172
|
+
// 委托给AboutDialogManager处理
|
|
173
|
+
this.aboutDialogManager.handleAboutWindowClick(data);
|
|
556
174
|
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
async function performInPlaceUpgrade(version) {
|
|
560
|
-
console.log('Performing in-place upgrade to version:', version);
|
|
561
|
-
const tarballUrl = `https://registry.npmjs.org/@becrafter/prompt-manager/-/@becrafter/prompt-manager-${version}.tgz`;
|
|
562
|
-
const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'prompt-manager-upgrade-'));
|
|
563
|
-
const tarballPath = path.join(tmpDir, `${version}.tgz`);
|
|
564
|
-
|
|
565
|
-
console.log('Temporary directory:', tmpDir);
|
|
566
|
-
|
|
567
|
-
try {
|
|
568
|
-
console.log('Downloading tarball from:', tarballUrl);
|
|
569
|
-
const response = await fetch(tarballUrl);
|
|
570
|
-
if (!response.ok) {
|
|
571
|
-
throw new Error(`Failed to download tarball: ${response.status} ${response.statusText}`);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
const buffer = Buffer.from(await response.arrayBuffer());
|
|
575
|
-
await fs.promises.writeFile(tarballPath, buffer);
|
|
576
|
-
console.log('Tarball downloaded to:', tarballPath);
|
|
577
|
-
|
|
578
|
-
await tar.x({ file: tarballPath, cwd: tmpDir });
|
|
579
|
-
const extractedPath = path.join(tmpDir, 'package');
|
|
580
|
-
console.log('Tarball extracted to:', extractedPath);
|
|
581
|
-
|
|
582
|
-
const serverRoot = await ensureRuntimeServerRoot();
|
|
583
|
-
const examplesDir = path.join(serverRoot, 'examples', 'prompts');
|
|
584
|
-
const examplesBackup = path.join(tmpDir, 'examples-prompts');
|
|
585
|
-
|
|
586
|
-
if (await pathExists(examplesDir)) {
|
|
587
|
-
console.log('Backing up examples directory');
|
|
588
|
-
await fs.promises.cp(examplesDir, examplesBackup, { recursive: true });
|
|
589
|
-
}
|
|
590
175
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
await fs.promises.mkdir(serverRoot, { recursive: true });
|
|
176
|
+
async restartApplication() {
|
|
177
|
+
this.logger.info('Restarting application');
|
|
594
178
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
await fs.promises.mkdir(path.dirname(targetExamples), { recursive: true });
|
|
602
|
-
await fs.promises.cp(examplesBackup, targetExamples, { recursive: true });
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
console.log('Installing server dependencies');
|
|
606
|
-
await installServerDependencies(serverRoot);
|
|
607
|
-
|
|
608
|
-
console.log('Reloading server module');
|
|
609
|
-
await loadServerModule({ forceReload: true });
|
|
610
|
-
|
|
611
|
-
console.log('Upgrade completed successfully');
|
|
612
|
-
} catch (error) {
|
|
613
|
-
console.error('Upgrade failed:', error);
|
|
614
|
-
throw error;
|
|
615
|
-
} finally {
|
|
616
|
-
console.log('Cleaning up temporary directory');
|
|
617
|
-
await fs.promises.rm(tmpDir, { recursive: true, force: true });
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
async function pathExists(targetPath) {
|
|
622
|
-
try {
|
|
623
|
-
await fs.promises.access(targetPath, fs.constants.F_OK);
|
|
624
|
-
return true;
|
|
625
|
-
} catch (error) {
|
|
626
|
-
return false;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
async function installServerDependencies(targetDir) {
|
|
631
|
-
console.log('Installing server dependencies in:', targetDir);
|
|
632
|
-
|
|
633
|
-
// 检查 targetDir 是否存在 package.json
|
|
634
|
-
const pkgPath = path.join(targetDir, 'package.json');
|
|
635
|
-
try {
|
|
636
|
-
await fs.promises.access(pkgPath, fs.constants.F_OK);
|
|
637
|
-
console.log('package.json found in target directory');
|
|
638
|
-
} catch (error) {
|
|
639
|
-
console.error('package.json not found in target directory:', pkgPath);
|
|
640
|
-
throw new Error(`package.json not found in ${targetDir}`);
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// 检查 @modelcontextprotocol/sdk 是否在 dependencies 中
|
|
644
|
-
try {
|
|
645
|
-
const pkgContent = await fs.promises.readFile(pkgPath, 'utf8');
|
|
646
|
-
const pkg = JSON.parse(pkgContent);
|
|
647
|
-
if (!pkg.dependencies || !pkg.dependencies['@modelcontextprotocol/sdk']) {
|
|
648
|
-
console.warn('@modelcontextprotocol/sdk not found in dependencies, adding it');
|
|
649
|
-
pkg.dependencies = pkg.dependencies || {};
|
|
650
|
-
pkg.dependencies['@modelcontextprotocol/sdk'] = '^1.20.2';
|
|
651
|
-
await fs.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2), 'utf8');
|
|
179
|
+
try {
|
|
180
|
+
await this.stopService();
|
|
181
|
+
app.relaunch();
|
|
182
|
+
app.exit(0);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
this.logger.error('Failed to restart application', error);
|
|
652
185
|
}
|
|
653
|
-
} catch (error) {
|
|
654
|
-
console.error('Error checking/adding @modelcontextprotocol/sdk to package.json:', error);
|
|
655
186
|
}
|
|
656
|
-
|
|
657
|
-
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
658
|
-
const args = ['install', '--omit=dev', '--no-audit', '--no-fund'];
|
|
659
|
-
|
|
660
|
-
console.log('Running npm install with args:', args);
|
|
661
|
-
|
|
662
|
-
await new Promise((resolve, reject) => {
|
|
663
|
-
const child = spawn(npmCommand, args, {
|
|
664
|
-
cwd: targetDir,
|
|
665
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
666
|
-
});
|
|
667
187
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
child.stdout.on('data', (data) => {
|
|
672
|
-
const output = data.toString().trim();
|
|
673
|
-
stdout += output;
|
|
674
|
-
console.log(`[npm stdout] ${output}`);
|
|
675
|
-
});
|
|
188
|
+
async quitApplication() {
|
|
189
|
+
this.logger.info('Quitting application');
|
|
676
190
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
});
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
async function promptForRestart() {
|
|
703
|
-
const { response } = await dialog.showMessageBox({
|
|
704
|
-
type: 'error',
|
|
705
|
-
buttons: ['重启应用', '取消'],
|
|
706
|
-
defaultId: 0,
|
|
707
|
-
cancelId: 1,
|
|
708
|
-
message: '服务启动失败',
|
|
709
|
-
detail: '多次尝试启动服务均失败,建议重启应用以恢复正常状态。'
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
if (response === 0) {
|
|
713
|
-
app.relaunch();
|
|
714
|
-
app.exit(0);
|
|
191
|
+
try {
|
|
192
|
+
this.stateManager.set('isQuitting', true);
|
|
193
|
+
|
|
194
|
+
// 关闭启动画面
|
|
195
|
+
await this.splashManager.closeSplash();
|
|
196
|
+
|
|
197
|
+
// 停止服务
|
|
198
|
+
await this.stopService();
|
|
199
|
+
|
|
200
|
+
// 清理资源
|
|
201
|
+
await this.aboutDialogManager.closeAboutDialog();
|
|
202
|
+
|
|
203
|
+
this.trayManager.destroy();
|
|
204
|
+
await this.logger.close();
|
|
205
|
+
await this.runtimeManager.cleanup();
|
|
206
|
+
|
|
207
|
+
app.quit();
|
|
208
|
+
} catch (error) {
|
|
209
|
+
this.logger.error('Error during application shutdown', error);
|
|
210
|
+
app.quit(); // 强制退出
|
|
211
|
+
}
|
|
715
212
|
}
|
|
716
213
|
}
|
|
717
214
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
const lines = [
|
|
721
|
-
// `桌面应用版本:${desktopPackageJson.version}`,
|
|
722
|
-
`服务版本:${serviceVersion}`,
|
|
723
|
-
`Electron:${process.versions.electron}`,
|
|
724
|
-
// `Chromium:${process.versions.chrome}`,
|
|
725
|
-
`Node.js:${process.versions.node}`
|
|
726
|
-
];
|
|
727
|
-
|
|
728
|
-
await dialog.showMessageBox({
|
|
729
|
-
type: 'info',
|
|
730
|
-
title: '关于 Prompt Server',
|
|
731
|
-
message: '组件版本信息',
|
|
732
|
-
detail: lines.join('\n')
|
|
733
|
-
});
|
|
734
|
-
}
|
|
215
|
+
// 应用启动
|
|
216
|
+
const promptManagerApp = new PromptManagerApp();
|
|
735
217
|
|
|
736
218
|
app.whenReady().then(async () => {
|
|
737
|
-
// 初始化日志
|
|
738
|
-
initLogStream();
|
|
739
|
-
console.log('App is packaged:', app.isPackaged);
|
|
740
|
-
console.log('App data path:', app.getPath('userData'));
|
|
741
|
-
console.log('Resources path:', process.resourcesPath);
|
|
742
|
-
console.log('__dirname:', __dirname);
|
|
743
|
-
console.log('Process platform:', process.platform);
|
|
744
|
-
console.log('Process version:', process.version);
|
|
745
|
-
console.log('Electron version:', process.versions.electron);
|
|
746
|
-
|
|
747
|
-
Menu.setApplicationMenu(null);
|
|
748
|
-
if (process.platform === 'darwin') {
|
|
749
|
-
app.dock.hide();
|
|
750
|
-
}
|
|
751
|
-
|
|
752
219
|
try {
|
|
753
|
-
await
|
|
754
|
-
console.log('Runtime server root ensured successfully');
|
|
755
|
-
ensureTray();
|
|
756
|
-
console.log('System tray ensured successfully');
|
|
757
|
-
await startService();
|
|
758
|
-
console.log('Service started successfully');
|
|
220
|
+
await promptManagerApp.initialize();
|
|
759
221
|
} catch (error) {
|
|
760
|
-
console.error('
|
|
761
|
-
|
|
222
|
+
console.error('Failed to start application:', error);
|
|
223
|
+
app.quit();
|
|
762
224
|
}
|
|
763
225
|
});
|
|
764
226
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
if (isQuitting) {
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
event.preventDefault();
|
|
774
|
-
isQuitting = true;
|
|
775
|
-
await stopService();
|
|
776
|
-
if (logStream) {
|
|
777
|
-
logStream.end();
|
|
227
|
+
// 异常处理
|
|
228
|
+
process.on('uncaughtException', (error) => {
|
|
229
|
+
console.error('Uncaught Exception:', error);
|
|
230
|
+
if (promptManagerApp.logger) {
|
|
231
|
+
promptManagerApp.logger.error('Uncaught Exception', error);
|
|
778
232
|
}
|
|
779
233
|
app.quit();
|
|
780
234
|
});
|
|
781
235
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
236
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
237
|
+
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
238
|
+
if (promptManagerApp.logger) {
|
|
239
|
+
promptManagerApp.logger.error('Unhandled Rejection', reason);
|
|
785
240
|
}
|
|
786
|
-
});
|
|
241
|
+
});
|