@becrafter/prompt-manager 0.1.17 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/env.example +1 -1
  2. package/package.json +19 -7
  3. package/packages/server/server.js +2 -1
  4. package/packages/server/services/TerminalService.js +247 -13
  5. package/packages/server/toolm/tool-sync.service.js +8 -0
  6. package/packages/server/utils/config.js +1 -1
  7. package/packages/web/css/{main.3b61356b384d2f11f47f.css → main.196f434e6a88cd448158.css} +10 -0
  8. package/packages/web/index.html +1 -1
  9. package/packages/web/{main.77c2c4b553ca3fac223b.js → main.b427a9e6f77a32a2f87f.js} +2 -2
  10. package/app/desktop/assets/app.1.png +0 -0
  11. package/app/desktop/assets/app.png +0 -0
  12. package/app/desktop/assets/icons/icon.icns +0 -0
  13. package/app/desktop/assets/icons/icon.ico +0 -0
  14. package/app/desktop/assets/icons/icon.png +0 -0
  15. package/app/desktop/assets/icons/tray.png +0 -0
  16. package/app/desktop/assets/templates/about.html +0 -147
  17. package/app/desktop/assets/tray.1.png +0 -0
  18. package/app/desktop/assets/tray.png +0 -0
  19. package/app/desktop/docs/ASSETS_PLANNING.md +0 -351
  20. package/app/desktop/docs/REFACTORING_SUMMARY.md +0 -205
  21. package/app/desktop/main.js +0 -340
  22. package/app/desktop/package-lock.json +0 -6912
  23. package/app/desktop/package.json +0 -119
  24. package/app/desktop/preload.js +0 -7
  25. package/app/desktop/src/core/error-handler.js +0 -108
  26. package/app/desktop/src/core/event-emitter.js +0 -84
  27. package/app/desktop/src/core/logger.js +0 -130
  28. package/app/desktop/src/core/state-manager.js +0 -125
  29. package/app/desktop/src/services/module-loader.js +0 -330
  30. package/app/desktop/src/services/runtime-manager.js +0 -398
  31. package/app/desktop/src/services/service-manager.js +0 -210
  32. package/app/desktop/src/services/update-manager.js +0 -267
  33. package/app/desktop/src/ui/about-dialog-manager.js +0 -208
  34. package/app/desktop/src/ui/admin-window-manager.js +0 -757
  35. package/app/desktop/src/ui/splash-manager.js +0 -253
  36. package/app/desktop/src/ui/tray-manager.js +0 -186
  37. package/app/desktop/src/utils/icon-manager.js +0 -133
  38. package/app/desktop/src/utils/path-utils.js +0 -58
  39. package/app/desktop/src/utils/resource-paths.js +0 -49
  40. package/app/desktop/src/utils/resource-sync.js +0 -260
  41. package/app/desktop/src/utils/runtime-sync.js +0 -241
  42. package/app/desktop/src/utils/self-check.js +0 -288
  43. package/app/desktop/src/utils/template-renderer.js +0 -284
  44. package/app/desktop/src/utils/version-utils.js +0 -59
  45. package/packages/server/.eslintrc.js +0 -70
  46. package/packages/server/.husky/pre-commit +0 -8
  47. package/packages/server/.husky/pre-push +0 -8
  48. package/packages/server/.prettierrc +0 -14
  49. package/packages/server/dev-server.js +0 -90
  50. package/packages/server/jsdoc.conf.json +0 -39
  51. package/packages/server/package.json +0 -85
  52. package/packages/server/playwright.config.js +0 -62
  53. package/packages/server/scripts/generate-docs.js +0 -300
  54. package/packages/server/tests/e2e/terminal-e2e.test.js +0 -315
  55. package/packages/server/tests/integration/terminal-websocket.test.js +0 -372
  56. package/packages/server/tests/integration/tools.test.js +0 -264
  57. package/packages/server/tests/setup.js +0 -45
  58. package/packages/server/tests/unit/TerminalService.test.js +0 -410
  59. package/packages/server/tests/unit/WebSocketService.test.js +0 -403
  60. package/packages/server/tests/unit/core.test.js +0 -94
  61. package/packages/server/typedoc.json +0 -52
  62. package/packages/server/vitest.config.js +0 -74
  63. /package/packages/web/{main.77c2c4b553ca3fac223b.js.LICENSE.txt → main.b427a9e6f77a32a2f87f.js.LICENSE.txt} +0 -0
@@ -1,253 +0,0 @@
1
- const { BrowserWindow, nativeImage } = require('electron');
2
- const path = require('path');
3
-
4
- class SplashManager {
5
- constructor(logger, iconManager) {
6
- this.logger = logger;
7
- this.iconManager = iconManager;
8
- this.splashWindow = null;
9
- }
10
-
11
- /**
12
- * 创建并显示启动画面
13
- */
14
- async showSplash() {
15
- this.logger.info('Showing splash screen');
16
-
17
- // 如果启动画面已存在,直接返回
18
- if (this.splashWindow) {
19
- return;
20
- }
21
-
22
- try {
23
- // 创建启动窗口
24
- this.splashWindow = this.createSplashWindow();
25
-
26
- // 加载启动画面内容
27
- const htmlContent = this.generateSplashHTML();
28
- this.splashWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(htmlContent)}`);
29
-
30
- // 设置窗口事件
31
- this.setupWindowEvents();
32
-
33
- this.logger.info('Splash screen shown successfully');
34
-
35
- } catch (error) {
36
- this.logger.error('Failed to show splash screen', error);
37
- // 如果启动画面失败,不阻塞主流程
38
- }
39
- }
40
-
41
- /**
42
- * 创建启动窗口
43
- */
44
- createSplashWindow() {
45
- return new BrowserWindow({
46
- width: 400,
47
- height: 100,
48
- transparent: true,
49
- frame: false,
50
- resizable: false,
51
- movable: false,
52
- fullscreenable: false,
53
- hasShadow: false,
54
- alwaysOnTop: true,
55
- show: false,
56
- webPreferences: {
57
- contextIsolation: true,
58
- nodeIntegration: false,
59
- sandbox: false
60
- }
61
- });
62
- }
63
-
64
- /**
65
- * 生成启动画面HTML内容
66
- */
67
- generateSplashHTML() {
68
- return `<!DOCTYPE html>
69
- <html>
70
- <head>
71
- <meta charset="UTF-8">
72
- <title>Prompt Manager - Loading</title>
73
- <style>
74
- body {
75
- margin: 0;
76
- padding: 0;
77
- background: transparent;
78
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
79
- display: flex;
80
- align-items: center;
81
- justify-content: center;
82
- height: 100vh;
83
- overflow: hidden;
84
- }
85
-
86
- .container {
87
- width: 360px;
88
- padding: 20px;
89
- background: white;
90
- border: 2px solid #1a1a1a;
91
- border-radius: 8px;
92
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
93
- text-align: center;
94
- }
95
-
96
- .title {
97
- font-size: 20px;
98
- font-weight: 580;
99
- color: #666;
100
- margin: 0 0 16px 0;
101
- letter-spacing: -0.02em;
102
- font-family: "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
103
- position: relative;
104
- }
105
-
106
- .title::after {
107
- content: '';
108
- position: absolute;
109
- bottom: -8px;
110
- left: 50%;
111
- transform: translateX(-50%);
112
- width: 40px;
113
- height: 1px;
114
- background: linear-gradient(to right, transparent, #ccc, transparent);
115
- }
116
-
117
- .loading-container {
118
- display: flex;
119
- align-items: center;
120
- justify-content: center;
121
- gap: 12px;
122
- }
123
-
124
- .loading-text {
125
- font-size: 14px;
126
- color: #999;
127
- }
128
-
129
- .dots {
130
- display: flex;
131
- gap: 4px;
132
- }
133
-
134
- .dot {
135
- width: 6px;
136
- height: 6px;
137
- background: #aaa;
138
- border-radius: 50%;
139
- animation: pulse 1.5s infinite ease-in-out;
140
- }
141
-
142
- .dot:nth-child(1) { animation-delay: -0.32s; }
143
- .dot:nth-child(2) { animation-delay: -0.16s; }
144
-
145
- @keyframes pulse {
146
- 0%, 80%, 100% {
147
- transform: scale(0);
148
- opacity: 0.5;
149
- }
150
- 40% {
151
- transform: scale(1);
152
- opacity: 1;
153
- }
154
- }
155
- </style>
156
- </head>
157
- <body>
158
- <div class="container">
159
- <div class="title">Prompt Manager</div>
160
- <div class="loading-container">
161
- <div class="loading-text">正在启动</div>
162
- <div class="dots">
163
- <div class="dot"></div>
164
- <div class="dot"></div>
165
- <div class="dot"></div>
166
- </div>
167
- </div>
168
- </div>
169
-
170
- <script>
171
- // 简单的动画效果增强
172
- let dotIndex = 0;
173
- const dots = document.querySelectorAll('.dot');
174
-
175
- setInterval(() => {
176
- // 重置所有点
177
- dots.forEach(dot => {
178
- dot.style.animation = 'none';
179
- setTimeout(() => {
180
- dot.style.animation = 'pulse 1.5s infinite ease-in-out';
181
- }, 10);
182
- });
183
-
184
- // 依次激活点
185
- dotIndex = (dotIndex + 1) % dots.length;
186
- }, 1500);
187
- </script>
188
- </body>
189
- </html>`;
190
- }
191
-
192
- /**
193
- * 更新启动状态
194
- * @param {string} message - 状态消息
195
- * @param {number} progress - 进度百分比 (0-100)
196
- */
197
- updateStatus(message, progress) {
198
- if (!this.splashWindow || this.splashWindow.isDestroyed()) {
199
- return;
200
- }
201
-
202
- try {
203
- this.splashWindow.webContents.executeJavaScript(`
204
- (function() {
205
- const statusElement = document.getElementById('status');
206
- const progressElement = document.getElementById('progress');
207
- if (statusElement) statusElement.textContent = "${message}";
208
- if (progressElement && ${progress} >= 0) {
209
- progressElement.style.width = "${progress}%";
210
- }
211
- })();
212
- `);
213
- } catch (error) {
214
- this.logger.warn('Failed to update splash status', error);
215
- }
216
- }
217
-
218
- /**
219
- * 设置窗口事件
220
- */
221
- setupWindowEvents() {
222
- if (!this.splashWindow) return;
223
-
224
- this.splashWindow.once('ready-to-show', () => {
225
- if (this.splashWindow) {
226
- this.splashWindow.show();
227
- }
228
- });
229
-
230
- this.splashWindow.on('closed', () => {
231
- this.splashWindow = null;
232
- this.logger.info('Splash screen closed');
233
- });
234
- }
235
-
236
- /**
237
- * 关闭启动画面
238
- */
239
- async closeSplash() {
240
- this.logger.info('Closing splash screen');
241
-
242
- if (this.splashWindow) {
243
- try {
244
- this.splashWindow.close();
245
- this.splashWindow = null;
246
- } catch (error) {
247
- this.logger.warn('Failed to close splash window', error);
248
- }
249
- }
250
- }
251
- }
252
-
253
- module.exports = SplashManager;
@@ -1,186 +0,0 @@
1
- const { Tray, Menu, clipboard, nativeImage, dialog, shell } = require('electron');
2
- const fs = require('fs');
3
- const path = require('path');
4
- const EventEmitter = require('../core/event-emitter');
5
- const AdminWindowManager = require('./admin-window-manager');
6
-
7
- class TrayManager extends EventEmitter {
8
- constructor(logger, errorHandler, iconManager) {
9
- super();
10
- this.logger = logger;
11
- this.errorHandler = errorHandler;
12
- this.iconManager = iconManager;
13
- this.tray = null;
14
- this.menuTemplate = [];
15
- this.iconPaths = [];
16
- this.currentState = null;
17
- this.adminWindowManager = new AdminWindowManager(logger, iconManager);
18
- }
19
-
20
- async initialize(stateManager) {
21
- this.currentState = stateManager;
22
-
23
- await this.createTray();
24
- this.updateMenu();
25
-
26
- return this.tray;
27
- }
28
-
29
- async createTray() {
30
- this.logger.info('Creating system tray');
31
-
32
- try {
33
- const icon = await this.loadTrayIcon();
34
- this.tray = new Tray(icon);
35
- this.tray.setToolTip('Prompt Manager');
36
-
37
- this.logger.info('System tray created successfully');
38
- } catch (error) {
39
- this.logger.error('Failed to create tray icon', error);
40
-
41
- // 降级处理:使用空图标
42
- try {
43
- this.tray = new Tray(nativeImage.createEmpty());
44
- this.tray.setToolTip('Prompt Manager - Icon Missing');
45
- this.logger.warn('Created tray with empty icon as fallback');
46
- } catch (fallbackError) {
47
- this.errorHandler.handleIconLoadError(fallbackError);
48
- throw fallbackError;
49
- }
50
- }
51
- }
52
-
53
- async loadTrayIcon() {
54
- const icon = this.iconManager.getTrayIcon();
55
-
56
- if (!icon) {
57
- throw new Error('Failed to load tray icon from icon manager');
58
- }
59
-
60
- this.logger.info('Tray icon loaded successfully', {
61
- isEmpty: icon.isEmpty(),
62
- size: icon.getSize()
63
- });
64
-
65
- return icon;
66
- }
67
-
68
- updateMenu() {
69
- if (!this.tray || !this.currentState) return;
70
-
71
- const menu = Menu.buildFromTemplate(this.buildMenuTemplate());
72
- this.tray.setContextMenu(menu);
73
-
74
- this.logger.debug('Tray menu updated');
75
- }
76
-
77
- buildMenuTemplate() {
78
- const state = this.currentState.get();
79
- const serviceStatus = this.currentState.getServiceStatus();
80
- const isRunning = this.currentState.isServiceRunning();
81
- const serverAddress = state.server?.address || 'http://127.0.0.1:5621';
82
- const adminUrl = state.server?.adminPath ?
83
- `${serverAddress}${state.server.adminPath}` :
84
- `${serverAddress}/admin`;
85
-
86
- return [
87
- {
88
- label: `状态:${serviceStatus}`,
89
- enabled: false
90
- },
91
- { type: 'separator' },
92
- {
93
- label: isRunning ? '停止服务' : '启动服务',
94
- click: () => this.handleServiceToggle()
95
- },
96
- {
97
- label: '复制服务地址',
98
- enabled: isRunning,
99
- click: () => this.copyServiceAddress(serverAddress)
100
- },
101
- {
102
- label: '打开管理后台',
103
- enabled: isRunning,
104
- click: () => this.openAdminWindow(adminUrl)
105
- },
106
- { type: 'separator' },
107
- {
108
- label: '检查更新',
109
- click: () => this.checkForUpdates()
110
- },
111
- {
112
- label: '关于服务',
113
- click: () => this.showAboutDialog()
114
- },
115
- { type: 'separator' },
116
- {
117
- label: '退出服务',
118
- click: () => this.quitApplication()
119
- }
120
- ];
121
- }
122
-
123
- handleServiceToggle() {
124
- const isRunning = this.currentState.isServiceRunning();
125
-
126
- if (isRunning) {
127
- this.logger.info('User requested to stop service');
128
- this.emit('service-stop-requested');
129
- } else {
130
- this.logger.info('User requested to start service');
131
- this.emit('service-start-requested');
132
- }
133
- }
134
-
135
- copyServiceAddress(address) {
136
- try {
137
- const serviceUrl = `${address}/mcp`;
138
- clipboard.writeText(serviceUrl);
139
- this.logger.info('Service address copied to clipboard', { address: serviceUrl });
140
- } catch (error) {
141
- this.logger.error('Failed to copy service address', error);
142
- }
143
- }
144
-
145
- openAdminWindow(adminUrl) {
146
- if (this.adminWindowManager.hasWindow()) {
147
- this.adminWindowManager.getWindow().focus();
148
- return;
149
- }
150
-
151
- try {
152
- this.adminWindowManager.openAdminWindow(adminUrl);
153
- } catch (error) {
154
- this.logger.error('Failed to open admin window', error);
155
- }
156
- }
157
-
158
- checkForUpdates() {
159
- this.logger.info('User requested to check for updates');
160
- this.emit('update-check-requested');
161
- }
162
-
163
- showAboutDialog() {
164
- this.logger.info('User requested to show about dialog');
165
- this.emit('about-dialog-requested');
166
- }
167
-
168
- quitApplication() {
169
- this.logger.info('User requested to quit application');
170
- this.emit('quit-requested');
171
- }
172
-
173
- destroy() {
174
- if (this.tray) {
175
- this.tray.destroy();
176
- this.tray = null;
177
- this.logger.info('Tray destroyed');
178
- }
179
-
180
- if (this.adminWindowManager) {
181
- this.adminWindowManager.closeAdminWindow();
182
- }
183
- }
184
- }
185
-
186
- module.exports = TrayManager;
@@ -1,133 +0,0 @@
1
- /**
2
- * 图标管理器
3
- * 负责管理和提供应用程序图标
4
- */
5
-
6
- const { nativeImage } = require('electron');
7
- const path = require('path');
8
- const fs = require('fs');
9
-
10
- class IconManager {
11
- constructor() {
12
- this.iconCache = new Map();
13
- this.iconPaths = this.getIconPaths();
14
- }
15
-
16
- /**
17
- * 获取图标路径配置
18
- */
19
- getIconPaths() {
20
- const basePath = path.join(__dirname, '..', '..', 'assets', 'icons');
21
-
22
- return {
23
- 'icns': path.join(basePath, 'icon.icns'),
24
- 'ico': path.join(basePath, 'icon.ico'),
25
- 'png': path.join(basePath, 'icon.png'),
26
- 'tray': path.join(basePath, 'tray.png'),
27
- };
28
- }
29
-
30
- /**
31
- * 获取应用程序图标
32
- * @returns {nativeImage|null} - 图标对象
33
- */
34
- getAppIcon() {
35
- const platform = process.platform;
36
- if (platform === 'darwin') {
37
- const iconPath = this.iconPaths['icns'];
38
- return fs.existsSync(iconPath) ? nativeImage.createFromPath(iconPath) : null;
39
- } else if (platform === 'win32') {
40
- const iconPath = this.iconPaths['ico'];
41
- return fs.existsSync(iconPath) ? nativeImage.createFromPath(iconPath) : null;
42
- }
43
- const iconPath = this.iconPaths['png'];
44
- return fs.existsSync(iconPath) ? nativeImage.createFromPath(iconPath) : null;
45
- }
46
-
47
- /**
48
- * 获取指定尺寸的托盘图标
49
- * @param {string|number} size - 图标尺寸
50
- * @returns {nativeImage|null} - 图标对象
51
- */
52
- getTrayIconBySize(size) {
53
- const sizeKey = String(size);
54
-
55
- if (this.iconCache.has(`tray-${sizeKey}`)) {
56
- return this.iconCache.get(`tray-${sizeKey}`);
57
- }
58
-
59
- const iconPath = this.iconPaths['tray'];
60
- if (!iconPath || !fs.existsSync(iconPath)) {
61
- console.warn(`Tray icon not found for size ${sizeKey}`);
62
- return null;
63
- }
64
-
65
- try {
66
- const icon = nativeImage.createFromPath(iconPath);
67
- icon.resize({ width: size, height: size });
68
-
69
- if (icon.isEmpty()) {
70
- console.warn(`Failed to load tray icon from ${iconPath}`);
71
- return null;
72
- }
73
-
74
- this.iconCache.set(`tray-${sizeKey}`, icon);
75
- return icon;
76
- } catch (error) {
77
- console.error(`Error loading tray icon ${iconPath}:`, error);
78
- return null;
79
- }
80
- }
81
-
82
- /**
83
- * 获取托盘图标(根据平台自动选择合适尺寸)
84
- */
85
- getTrayIcon() {
86
- const platform = process.platform;
87
- let iconSize;
88
-
89
- switch (platform) {
90
- case 'darwin':
91
- iconSize = '18'; // macOS 推荐 18x18
92
- break;
93
- case 'win32':
94
- iconSize = '16'; // Windows 推荐 16x16
95
- break;
96
- default:
97
- iconSize = '24'; // Linux 推荐 24x24
98
- }
99
-
100
- let icon = this.getTrayIconBySize(iconSize);
101
-
102
- // macOS 特殊处理
103
- if (platform === 'darwin' && icon) {
104
- try {
105
- icon = icon.resize({ width: 18, height: 18 });
106
- icon.setTemplateImage(true);
107
- } catch (error) {
108
- console.warn('Failed to resize icon for macOS:', error);
109
- }
110
- }
111
-
112
- return icon;
113
- }
114
-
115
- /**
116
- * 获取关于对话框图标
117
- */
118
- getAboutDialogIcon() {
119
- // 优先使用应用图标,如果没有则使用较大的托盘图标
120
- const iconPath = this.iconPaths['png'];
121
- let icon = nativeImage.createFromPath(iconPath)
122
- return icon.resize({ width: 64, height: 64 });
123
- }
124
-
125
- /**
126
- * 清除图标缓存
127
- */
128
- clearCache() {
129
- this.iconCache.clear();
130
- }
131
- }
132
-
133
- module.exports = IconManager;
@@ -1,58 +0,0 @@
1
- const fs = require('fs').promises;
2
- const path = require('path');
3
- const { constants } = require('fs');
4
-
5
- /**
6
- * 路径工具类 - 提供文件系统相关工具方法
7
- * 专注于文件系统操作和路径处理
8
- */
9
- class PathUtils {
10
- /**
11
- * 检查路径是否存在
12
- */
13
- static async pathExists(targetPath) {
14
- try {
15
- await fs.access(targetPath, constants.F_OK);
16
- return true;
17
- } catch (error) {
18
- return false;
19
- }
20
- }
21
-
22
- /**
23
- * 安全地删除目录
24
- */
25
- static async safeRemoveDir(dirPath) {
26
- try {
27
- await fs.rm(dirPath, { recursive: true, force: true });
28
- } catch (error) {
29
- console.warn(`Failed to remove directory ${dirPath}:`, error.message);
30
- }
31
- }
32
-
33
- /**
34
- * 确保目录存在
35
- */
36
- static async ensureDir(dirPath) {
37
- try {
38
- await fs.mkdir(dirPath, { recursive: true });
39
- } catch (error) {
40
- if (error.code !== 'EEXIST') {
41
- throw error;
42
- }
43
- }
44
- }
45
-
46
- /**
47
- * 复制目录
48
- */
49
- static async copyDir(src, dest) {
50
- try {
51
- await fs.cp(src, dest, { recursive: true });
52
- } catch (error) {
53
- throw new Error(`Failed to copy directory from ${src} to ${dest}: ${error.message}`);
54
- }
55
- }
56
- }
57
-
58
- module.exports = PathUtils;
@@ -1,49 +0,0 @@
1
- /**
2
- * 资源路径管理器
3
- * 集中管理所有资源文件路径
4
- */
5
-
6
- const path = require('path');
7
-
8
- class ResourcePaths {
9
- constructor() {
10
- this.basePath = path.join(__dirname, '..', '..');
11
- this.assetsPath = path.join(this.basePath, 'assets');
12
- }
13
-
14
- /**
15
- * 模板路径
16
- */
17
- static get templates() {
18
- const templatesPath = path.join(__dirname, '..', '..', 'assets', 'templates');
19
- return {
20
- base: templatesPath,
21
- about: path.join(templatesPath, 'about.html'),
22
- update: path.join(templatesPath, 'update.html'),
23
- error: path.join(templatesPath, 'error.html')
24
- };
25
- }
26
-
27
- /**
28
- * 预加载脚本路径
29
- */
30
- static get preload() {
31
- return path.join(__dirname, '..', '..', 'preload.js');
32
- }
33
-
34
- /**
35
- * 主入口路径
36
- */
37
- static get main() {
38
- return path.join(__dirname, '..', '..', 'main.js');
39
- }
40
-
41
- /**
42
- * 包信息路径
43
- */
44
- static get packageJson() {
45
- return path.join(__dirname, '..', '..', '..', '..', 'package.json');
46
- }
47
- }
48
-
49
- module.exports = ResourcePaths;