@becrafter/prompt-manager 0.0.19 → 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.
Files changed (103) hide show
  1. package/README.md +145 -234
  2. package/app/desktop/assets/app.1.png +0 -0
  3. package/app/desktop/assets/app.png +0 -0
  4. package/app/desktop/assets/icons/icon.icns +0 -0
  5. package/app/desktop/assets/icons/icon.ico +0 -0
  6. package/app/desktop/assets/icons/icon.png +0 -0
  7. package/app/desktop/assets/icons/tray.png +0 -0
  8. package/app/desktop/assets/tray.1.png +0 -0
  9. package/app/desktop/assets/tray.png +0 -0
  10. package/app/desktop/main.js +27 -0
  11. package/app/desktop/package-lock.json +216 -48
  12. package/app/desktop/package.json +23 -29
  13. package/app/desktop/src/services/module-loader.js +43 -22
  14. package/app/desktop/src/services/runtime-manager.js +172 -23
  15. package/app/desktop/src/ui/admin-window-manager.js +757 -0
  16. package/app/desktop/src/ui/splash-manager.js +253 -0
  17. package/app/desktop/src/ui/tray-manager.js +8 -24
  18. package/app/desktop/src/utils/icon-manager.js +39 -47
  19. package/app/desktop/src/utils/resource-paths.js +0 -23
  20. package/app/desktop/src/utils/resource-sync.js +260 -0
  21. package/app/desktop/src/utils/runtime-sync.js +241 -0
  22. package/examples/prompts/recommend/human_3-0_growth_diagnostic_coach_prompt.yaml +105 -0
  23. package/package.json +16 -13
  24. package/packages/admin-ui/.babelrc +3 -0
  25. package/packages/admin-ui/admin.html +237 -4784
  26. package/packages/admin-ui/css/main.css +2592 -0
  27. package/packages/admin-ui/css/recommended-prompts.css +610 -0
  28. package/packages/admin-ui/package-lock.json +6981 -0
  29. package/packages/admin-ui/package.json +36 -0
  30. package/packages/admin-ui/src/codemirror.js +53 -0
  31. package/packages/admin-ui/src/index.js +3188 -0
  32. package/packages/admin-ui/webpack.config.js +76 -0
  33. package/packages/resources/tools/chrome-devtools/README.md +310 -0
  34. package/packages/resources/tools/chrome-devtools/chrome-devtools.tool.js +1703 -0
  35. package/packages/resources/tools/file-reader/README.md +289 -0
  36. package/packages/resources/tools/file-reader/file-reader.tool.js +1545 -0
  37. package/packages/resources/tools/filesystem/README.md +359 -0
  38. package/packages/resources/tools/filesystem/filesystem.tool.js +514 -160
  39. package/packages/resources/tools/ollama-remote/README.md +192 -0
  40. package/packages/resources/tools/ollama-remote/ollama-remote.tool.js +421 -0
  41. package/packages/resources/tools/pdf-reader/README.md +236 -0
  42. package/packages/resources/tools/pdf-reader/pdf-reader.tool.js +565 -0
  43. package/packages/resources/tools/playwright/README.md +306 -0
  44. package/packages/resources/tools/playwright/playwright.tool.js +1186 -0
  45. package/packages/resources/tools/todolist/README.md +394 -0
  46. package/packages/resources/tools/todolist/todolist.tool.js +1312 -0
  47. package/packages/server/README.md +142 -0
  48. package/packages/server/api/admin.routes.js +42 -11
  49. package/packages/server/api/surge.routes.js +43 -0
  50. package/packages/server/app.js +119 -14
  51. package/packages/server/index.js +39 -0
  52. package/packages/server/mcp/mcp.server.js +324 -105
  53. package/packages/server/mcp/sequential-thinking.handler.js +318 -0
  54. package/packages/server/mcp/think-plan.handler.js +274 -0
  55. package/packages/server/middlewares/auth.middleware.js +6 -0
  56. package/packages/server/package.json +51 -0
  57. package/packages/server/server.js +37 -1
  58. package/packages/server/toolm/index.js +9 -0
  59. package/packages/server/toolm/package-installer.service.js +267 -0
  60. package/packages/server/toolm/test-tools.js +264 -0
  61. package/packages/server/toolm/tool-context.service.js +334 -0
  62. package/packages/server/toolm/tool-dependency.service.js +168 -0
  63. package/packages/server/toolm/tool-description-generator-optimized.service.js +375 -0
  64. package/packages/server/toolm/tool-description-generator.service.js +312 -0
  65. package/packages/server/toolm/tool-environment.service.js +200 -0
  66. package/packages/server/toolm/tool-execution.service.js +277 -0
  67. package/packages/server/toolm/tool-loader.service.js +219 -0
  68. package/packages/server/toolm/tool-logger.service.js +223 -0
  69. package/packages/server/toolm/tool-manager.handler.js +65 -0
  70. package/packages/server/toolm/tool-manual-generator.service.js +389 -0
  71. package/packages/server/toolm/tool-mode-handlers.service.js +224 -0
  72. package/packages/server/toolm/tool-storage.service.js +111 -0
  73. package/packages/server/toolm/tool-sync.service.js +138 -0
  74. package/packages/server/toolm/tool-utils.js +20 -0
  75. package/packages/server/toolm/tool-yaml-parser.service.js +81 -0
  76. package/packages/server/toolm/validate-system.js +421 -0
  77. package/packages/server/utils/config.js +49 -5
  78. package/packages/server/utils/util.js +65 -10
  79. package/scripts/build-icons.js +99 -69
  80. package/scripts/build.sh +57 -0
  81. package/scripts/surge/CNAME +1 -0
  82. package/scripts/surge/README.md +47 -0
  83. package/scripts/surge/package-lock.json +34 -0
  84. package/scripts/surge/package.json +20 -0
  85. package/scripts/surge/sync-to-surge.js +151 -0
  86. package/app/desktop/assets/icons/icon_1024x1024.png +0 -0
  87. package/app/desktop/assets/icons/icon_128x128.png +0 -0
  88. package/app/desktop/assets/icons/icon_16x16.png +0 -0
  89. package/app/desktop/assets/icons/icon_24x24.png +0 -0
  90. package/app/desktop/assets/icons/icon_256x256.png +0 -0
  91. package/app/desktop/assets/icons/icon_32x32.png +0 -0
  92. package/app/desktop/assets/icons/icon_48x48.png +0 -0
  93. package/app/desktop/assets/icons/icon_512x512.png +0 -0
  94. package/app/desktop/assets/icons/icon_64x64.png +0 -0
  95. package/app/desktop/assets/icons/icon_96x96.png +0 -0
  96. package/packages/admin-ui/js/closebrackets.min.js +0 -8
  97. package/packages/admin-ui/js/codemirror.min.js +0 -8
  98. package/packages/admin-ui/js/js-yaml.min.js +0 -2
  99. package/packages/admin-ui/js/markdown.min.js +0 -8
  100. package/packages/resources/tools/index.js +0 -16
  101. package/packages/server/mcp/toolx.handler.js +0 -131
  102. package/scripts/icns-builder/package.json +0 -12
  103. /package/packages/server/mcp/{mcp.handler.js → prompt.handler.js} +0 -0
@@ -0,0 +1,142 @@
1
+ # @becrafter/prompt-manager-core
2
+
3
+ Core library for managing prompts with MCP (Model Context Protocol) support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @becrafter/prompt-manager-core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Usage
14
+
15
+ ```javascript
16
+ import { startServer, stopServer, config } from '@becrafter/prompt-manager-core';
17
+
18
+ // Start the server with default configuration
19
+ const server = await startServer();
20
+
21
+ console.log('Server is running!');
22
+ ```
23
+
24
+ ### Advanced Usage with Configuration
25
+
26
+ ```javascript
27
+ import { startServer, stopServer, config } from '@becrafter/prompt-manager-core';
28
+
29
+ // Start the server with custom configuration
30
+ const server = await startServer({
31
+ configOverrides: {
32
+ promptsDir: './my-prompts',
33
+ port: 3000,
34
+ adminEnable: true,
35
+ adminRequireAuth: false
36
+ }
37
+ });
38
+
39
+ // Stop the server when needed
40
+ // await stopServer();
41
+ ```
42
+
43
+ ### Using the Express App Instance
44
+
45
+ ```javascript
46
+ import { app, config } from '@becrafter/prompt-manager-core';
47
+
48
+ // You can use the app instance to add custom routes
49
+ app.get('/custom-endpoint', (req, res) => {
50
+ res.json({ message: 'Hello from custom endpoint!' });
51
+ });
52
+
53
+ // Then start the server
54
+ import { startServer } from '@becrafter/prompt-manager-core';
55
+ await startServer();
56
+ ```
57
+
58
+ ### Accessing Prompt Manager
59
+
60
+ ```javascript
61
+ import { promptManager, util } from '@becrafter/prompt-manager-core';
62
+
63
+ // Load prompts
64
+ await promptManager.loadPrompts();
65
+
66
+ // Get all prompts
67
+ const prompts = promptManager.getPrompts();
68
+ console.log('Loaded prompts:', prompts);
69
+
70
+ // Get a specific prompt by ID
71
+ const prompt = promptManager.getPrompt('prompt-id');
72
+ console.log('Prompt:', prompt);
73
+
74
+ // Search prompts
75
+ const searchTerm = 'search term';
76
+ const searchResults = prompts.filter(prompt =>
77
+ prompt.name.includes(searchTerm) ||
78
+ (prompt.description && prompt.description.includes(searchTerm))
79
+ );
80
+ ```
81
+
82
+ ## API Reference
83
+
84
+ ### Functions
85
+
86
+ - `startServer(options = {})` - Starts the prompt manager server
87
+ - `stopServer()` - Stops the prompt manager server
88
+ - `getServerState()` - Gets the current server state
89
+ - `getServerAddress()` - Gets the server address
90
+ - `isServerRunning()` - Checks if the server is running
91
+
92
+ ### Objects
93
+
94
+ - `app` - Express application instance
95
+ - `config` - Configuration object
96
+ - `logger` - Logger instance
97
+ - `util` - Utility functions
98
+ - `promptManager` - Prompt manager instance
99
+
100
+ ### MCP Related
101
+
102
+ - `getMcpServer()` - Gets the MCP server instance
103
+ - `handleGetPrompt`, `handleSearchPrompts`, `handleReloadPrompts` - MCP handlers
104
+
105
+ ### Routes
106
+
107
+ - `adminRouter` - Admin API routes
108
+ - `openRouter` - Open API routes
109
+
110
+ ### Middleware
111
+
112
+ - `adminAuthMiddleware` - Admin authentication middleware
113
+
114
+ ## Configuration Options
115
+
116
+ You can override default configuration using the `configOverrides` option:
117
+
118
+ ```javascript
119
+ {
120
+ promptsDir: './prompts', // Directory for prompt files
121
+ port: 5621, // Server port
122
+ serverName: 'prompt-manager', // Server name
123
+ serverVersion: '0.0.19', // Server version
124
+ logLevel: 'info', // Log level
125
+ maxPrompts: 1000, // Max prompt count
126
+ recursiveScan: true, // Recursive scan for prompts
127
+ adminEnable: true, // Enable admin functionality
128
+ adminPath: '/admin', // Admin path
129
+ adminRequireAuth: true, // Require admin authentication
130
+ admins: [ // Admin accounts
131
+ {
132
+ username: 'admin',
133
+ password: 'admin',
134
+ token: '...'
135
+ }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ ## License
141
+
142
+ MIT
@@ -17,6 +17,20 @@ const router = express.Router();
17
17
 
18
18
  // 获取prompts目录路径(在启动时可能被覆盖)
19
19
  let promptsDir = config.getPromptsDir();
20
+ const PROMPT_NAME_REGEX = /^(?![.]{1,2}$)[^\\/:*?"<>|\r\n]{1,64}$/;
21
+
22
+ // 获取服务器配置端点
23
+ router.get('/config', (req, res) => {
24
+ // 检查是否启用了管理员功能
25
+ if (!config.adminEnable) {
26
+ return res.status(404).json({ error: 'Admin功能未启用' });
27
+ }
28
+
29
+ res.json({
30
+ requireAuth: config.adminRequireAuth,
31
+ adminEnable: config.adminEnable
32
+ });
33
+ });
20
34
 
21
35
  // 登录端点
22
36
  router.post('/login', (req, res) => {
@@ -25,6 +39,11 @@ router.post('/login', (req, res) => {
25
39
  return res.status(404).json({ error: 'Admin功能未启用' });
26
40
  }
27
41
 
42
+ // 如果不需要认证,返回默认token
43
+ if (!config.adminRequireAuth) {
44
+ return res.json({ token: config.admins[0].token });
45
+ }
46
+
28
47
  const { username, password } = req.body;
29
48
 
30
49
  if (!username || !password) {
@@ -129,14 +148,15 @@ router.get('/prompts/:name', adminAuthMiddleware, (req, res) => {
129
148
  router.post('/prompts', adminAuthMiddleware, (req, res) => {
130
149
  try {
131
150
  const { name, group, yaml: yamlContent, relativePath: originalRelativePath } = req.body;
151
+ const trimmedName = (name || '').trim();
132
152
 
133
- if (!name || !yamlContent) {
153
+ if (!trimmedName || !yamlContent) {
134
154
  return res.status(400).json({ error: '名称和YAML内容是必需的' });
135
155
  }
136
156
 
137
157
  // 验证名称格式
138
- if (!/^[a-zA-Z0-9-_]{1,64}$/.test(name)) {
139
- return res.status(400).json({ error: '名称格式无效' });
158
+ if (!PROMPT_NAME_REGEX.test(trimmedName)) {
159
+ return res.status(400).json({ error: '名称格式无效,不能包含 / \\ : * ? \" < > | 或换行,长度需在1-64字符' });
140
160
  }
141
161
 
142
162
  // 计算目标路径
@@ -148,7 +168,7 @@ router.post('/prompts', adminAuthMiddleware, (req, res) => {
148
168
  targetSegments.push(groupName);
149
169
  }
150
170
 
151
- const finalFileName = `${name}.yaml`;
171
+ const finalFileName = `${trimmedName}.yaml`;
152
172
  targetSegments.push(finalFileName);
153
173
 
154
174
  const targetRelativePath = path.posix.join(...targetSegments);
@@ -160,7 +180,7 @@ router.post('/prompts', adminAuthMiddleware, (req, res) => {
160
180
  // 检查是否重名(同目录下)
161
181
  const prompts = util.getPromptsFromFiles();
162
182
  const existingPrompt = prompts.find(p => {
163
- if (p.name !== name) return false;
183
+ if (p.name !== trimmedName) return false;
164
184
  const isOriginalFile = normalizedOriginalPath && p.relativePath === normalizedOriginalPath;
165
185
  if (isOriginalFile) return false;
166
186
  const sameRelativePath = p.relativePath === targetRelativePath;
@@ -193,7 +213,7 @@ router.post('/prompts', adminAuthMiddleware, (req, res) => {
193
213
  // 创建新分组目录
194
214
  router.post('/groups', adminAuthMiddleware, (req, res) => {
195
215
  try {
196
- const { name } = req.body;
216
+ const { name, parent } = req.body;
197
217
 
198
218
  if (!name) {
199
219
  return res.status(400).json({ error: '分组名称是必需的' });
@@ -201,18 +221,29 @@ router.post('/groups', adminAuthMiddleware, (req, res) => {
201
221
 
202
222
  // 验证名称格式
203
223
  if (!util.isValidGroupName(name)) {
204
- return res.status(400).json({ error: '名称格式无效,只能包含字母、数字、中划线、下划线和中文' });
224
+ return res.status(400).json({ error: '名称格式无效,不能包含 / \\ : * ? \" < > | 或换行,长度需在1-64字符' });
205
225
  }
206
226
 
207
- const groupDir = path.join(promptsDir, name);
227
+ // 构建目标目录路径
228
+ let targetPath;
229
+ if (parent) {
230
+ // 验证父级目录路径
231
+ const resolvedParent = util.resolveGroupDir(parent);
232
+ if (!resolvedParent) {
233
+ return res.status(400).json({ error: '无效的父级目录路径' });
234
+ }
235
+ targetPath = path.join(resolvedParent.dir, name);
236
+ } else {
237
+ targetPath = path.join(promptsDir, name);
238
+ }
208
239
 
209
240
  // 检查目录是否已存在
210
- if (fs.existsSync(groupDir)) {
241
+ if (fs.existsSync(targetPath)) {
211
242
  return res.status(400).json({ error: '分组已存在' });
212
243
  }
213
244
 
214
245
  // 创建目录
215
- fs.mkdirSync(groupDir, { recursive: true });
246
+ fs.mkdirSync(targetPath, { recursive: true });
216
247
 
217
248
  res.json({ message: '分组创建成功' });
218
249
  } catch (error) {
@@ -228,7 +259,7 @@ router.patch('/groups/rename', adminAuthMiddleware, (req, res) => {
228
259
  return res.status(400).json({ error: '分组路径和新名称是必需的' });
229
260
  }
230
261
  if (!util.isValidGroupName(newName)) {
231
- return res.status(400).json({ error: '名称格式无效,只能包含字母、数字、中划线、下划线和中文' });
262
+ return res.status(400).json({ error: '名称格式无效,不能包含 / \\ : * ? \" < > | 或换行,长度需在1-64字符' });
232
263
  }
233
264
  if (groupPath === 'default') {
234
265
  return res.status(400).json({ error: '默认分组不允许重命名' });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Surge 静态资源代理接口
3
+ * 代理所有 /surge/* 请求到指定的 Surge 静态资源地址
4
+ */
5
+
6
+ import express from 'express';
7
+ import { createProxyMiddleware } from 'http-proxy-middleware';
8
+ import { config } from '../utils/config.js';
9
+
10
+ const router = express.Router();
11
+
12
+ // 从配置中获取 Surge 目标地址,默认为 https://becrafter.surge.sh
13
+ const surgeTarget = config.surgeTarget || 'https://becrafter.surge.sh';
14
+
15
+ // 创建代理中间件
16
+ const surgeProxy = createProxyMiddleware({
17
+ target: surgeTarget,
18
+ changeOrigin: true,
19
+ // 当路由已经去除了 /surge 前缀后,路径变为 /test_prompts.json
20
+ // 我们需要将其重写为 /assets/test_prompts.json
21
+ pathRewrite: {
22
+ '^/': '/assets/', // 将 / 开头的路径重写为 /assets/ 开头
23
+ },
24
+ // 设置代理请求头
25
+ onProxyReq: (proxyReq, req, res) => {
26
+ // 可以在这里添加自定义逻辑,如设置请求头等
27
+ console.log(`代理请求: ${req.method} ${req.url} -> ${surgeTarget}${req.url.replace(/^\/(.*)/, '/assets/$1')}`);
28
+ },
29
+ onProxyRes: (proxyRes, req, res) => {
30
+ // 可以在这里添加自定义逻辑,如修改响应头等
31
+ proxyRes.headers['surge-proxy'] = 'enabled';
32
+ },
33
+ onError: (err, req, res) => {
34
+ console.error('Surge 代理错误:', err);
35
+ res.status(500).send('代理错误');
36
+ }
37
+ });
38
+
39
+ // 使用代理中间件处理所有请求
40
+ // 由于在 app.js 中已经使用了 /surge 路径前缀,这里直接处理所有请求
41
+ router.use(surgeProxy);
42
+
43
+ export const surgeRouter = router;
@@ -1,12 +1,14 @@
1
1
  import express from 'express';
2
2
  import cors from 'cors';
3
3
  import path from 'path';
4
+ import fs from 'fs';
4
5
  import { randomUUID } from 'node:crypto';
5
6
  import { util } from './utils/util.js';
6
7
  import { config } from './utils/config.js';
7
8
  import { logger } from './utils/logger.js';
8
9
  import { adminRouter } from './api/admin.routes.js';
9
10
  import { openRouter } from './api/open.routes.js';
11
+ import { surgeRouter } from './api/surge.routes.js';
10
12
  import { getMcpServer } from './mcp/mcp.server.js';
11
13
  import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
12
14
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
@@ -14,7 +16,60 @@ import { InMemoryEventStore } from '@modelcontextprotocol/sdk/examples/shared/in
14
16
 
15
17
 
16
18
  const app = express();
17
- const adminUiRoot = util.getAdminUiRoot();
19
+ const adminUiRoot = util.getWebUiRoot();
20
+
21
+ // 自定义中间件,用于处理 ASAR 包中的静态文件
22
+ function serveAsarStatic(root) {
23
+ return async (req, res, next) => {
24
+ // 检查 root 是否是 ASAR 包中的路径
25
+ if (root.includes('.asar')) {
26
+ try {
27
+ // 动态导入 asar 模块(在 ES 模块环境中)
28
+ const { default: asar } = await import('@electron/asar');
29
+
30
+ // 从 root 中提取 asar 文件路径和相对路径
31
+ const asarPathMatch = root.match(/^(.*?\.asar)(\/.*)?$/);
32
+ const asarFilePath = asarPathMatch ? asarPathMatch[1] : root.replace(/\/.*$/, '.asar');
33
+ const relativePathInAsar = asarPathMatch && asarPathMatch[2] ? asarPathMatch[2].substring(1) : 'web';
34
+
35
+ const filePath = path.posix.join(relativePathInAsar, req.path).replace(/^\//, '');
36
+ const stat = asar.statFile(asarFilePath, filePath);
37
+
38
+ if (stat) {
39
+ const fileContent = asar.extractFile(asarFilePath, filePath);
40
+
41
+ // 设置适当的 Content-Type
42
+ const ext = path.extname(filePath).toLowerCase();
43
+ const mimeTypes = {
44
+ '.html': 'text/html',
45
+ '.js': 'application/javascript',
46
+ '.css': 'text/css',
47
+ '.json': 'application/json',
48
+ '.png': 'image/png',
49
+ '.jpg': 'image/jpeg',
50
+ '.gif': 'image/gif',
51
+ '.svg': 'image/svg+xml',
52
+ '.ico': 'image/x-icon'
53
+ };
54
+
55
+ if (mimeTypes[ext]) {
56
+ res.setHeader('Content-Type', mimeTypes[ext]);
57
+ }
58
+
59
+ res.send(fileContent);
60
+ } else {
61
+ next();
62
+ }
63
+ } catch (error) {
64
+ // 文件不存在或 asar 模块无法导入,继续到下一个中间件
65
+ next();
66
+ }
67
+ } else {
68
+ // 不是 ASAR 包中的路径,使用默认的静态文件服务
69
+ express.static(root)(req, res, next);
70
+ }
71
+ };
72
+ }
18
73
 
19
74
  // 全局中间件
20
75
  app.use(cors());
@@ -23,17 +78,50 @@ app.use(express.urlencoded({ extended: true }));
23
78
 
24
79
 
25
80
  // 为管理员界面提供静态文件服务 - 根路径
26
- app.use(config.adminPath, express.static(adminUiRoot));
81
+ // 检查是否需要使用 ASAR 处理(需要验证 .asar 文件实际上存在)
82
+ const isAsarPath = adminUiRoot.includes('.asar') && fs.existsSync(adminUiRoot.replace(/\/.*$/, '.asar'));
83
+ if (isAsarPath) {
84
+ app.use(config.adminPath, serveAsarStatic(adminUiRoot));
85
+ } else {
86
+ app.use(config.adminPath, express.static(adminUiRoot));
87
+ }
27
88
 
28
- // 为管理员界面提供根路径访问(当用户访问 /admin 时显示 admin.html
29
- app.get(config.adminPath, (req, res) => {
30
- res.sendFile(path.join(adminUiRoot, 'admin.html'));
31
- });
89
+ // 统一处理 index.html 请求的辅助函数
90
+ async function sendIndexHtml(req, res) {
91
+ if (isAsarPath) {
92
+ try {
93
+ // 动态导入 asar 模块(在 ES 模块环境中)
94
+ const { default: asar } = await import('@electron/asar');
95
+
96
+ // 从 adminUiRoot 中提取 asar 文件路径和相对路径
97
+ const asarPathMatch = adminUiRoot.match(/^(.*?\.asar)(\/.*)?$/);
98
+ const asarFilePath = asarPathMatch ? asarPathMatch[1] : adminUiRoot.replace(/\/.*$/, '.asar');
99
+ const relativePathInAsar = asarPathMatch && asarPathMatch[2] ? asarPathMatch[2].substring(1) : 'web';
100
+ const indexPath = path.posix.join(relativePathInAsar, 'index.html');
101
+
102
+ // 检查文件是否存在
103
+ const stat = asar.statFile(asarFilePath, indexPath);
104
+ if (stat) {
105
+ // 读取 index.html 文件内容
106
+ const fileContent = asar.extractFile(asarFilePath, indexPath);
107
+ res.setHeader('Content-Type', 'text/html');
108
+ res.send(fileContent);
109
+ } else {
110
+ res.status(500).send('Internal Server Error');
111
+ }
112
+ } catch (error) {
113
+ res.status(500).send('Internal Server Error');
114
+ }
115
+ } else {
116
+ res.sendFile(path.join(adminUiRoot, 'index.html'));
117
+ }
118
+ }
32
119
 
33
- // 为管理员界面提供根路径访问(当用户访问 /admin/ 时显示 admin.html)
34
- app.get(config.adminPath + '/', (req, res) => {
35
- res.sendFile(path.join(adminUiRoot, 'admin.html'));
36
- });
120
+ // 为管理员界面提供根路径访问(当用户访问 /admin 时显示 index.html)
121
+ app.get(config.adminPath, sendIndexHtml);
122
+
123
+ // 为管理员界面提供根路径访问(当用户访问 /admin/ 时显示 index.html)
124
+ app.get(config.adminPath + '/', sendIndexHtml);
37
125
 
38
126
 
39
127
  // 注册后台API
@@ -42,6 +130,9 @@ app.use('/adminapi', adminRouter);
42
130
  // 注册开放API
43
131
  app.use('/openapi', openRouter);
44
132
 
133
+ // 注册 Surge 静态资源代理 API
134
+ app.use('/surge', surgeRouter);
135
+
45
136
 
46
137
  const transports = {};
47
138
  const mcpServers = {}; // 存储每个会话的MCP服务器实例
@@ -72,17 +163,31 @@ app.all('/mcp', (req, res) => {
72
163
  }
73
164
  } else if (!sessionId && req.method === 'POST' && isInitializeRequest(req.body)) {
74
165
  const eventStore = new InMemoryEventStore();
166
+
167
+ // 预先创建 MCP 服务器实例,避免异步时序问题
168
+ let mcpServerPromise = null;
169
+ let serverReady = false;
170
+
75
171
  transport = new StreamableHTTPServerTransport({
76
172
  sessionIdGenerator: () => randomUUID(),
77
173
  eventStore, // Enable resumability
78
- onsessioninitialized: sessionId => {
174
+ onsessioninitialized: async sessionId => {
79
175
  // Store the transport by session ID when session is initialized
80
176
  console.log(`StreamableHTTP session initialized with ID: ${sessionId}`);
81
177
  transports[sessionId] = transport;
82
178
 
83
- // 为新会话创建MCP服务器实例
84
- mcpServers[sessionId] = getMcpServer();
85
- mcpServers[sessionId].connect(transport);
179
+ try {
180
+ // 为新会话创建MCP服务器实例(同步等待完成)
181
+ const server = await getMcpServer();
182
+ mcpServers[sessionId] = server;
183
+ server.connect(transport);
184
+ serverReady = true;
185
+ console.log(`MCP server connected for session ${sessionId}`);
186
+ } catch (error) {
187
+ console.error('创建MCP服务器失败:', error);
188
+ // 即使失败也标记为ready,避免阻塞
189
+ serverReady = true;
190
+ }
86
191
  }
87
192
  });
88
193
 
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Prompt Manager Core Library
3
+ *
4
+ * This is the main entry point for the Prompt Manager core library.
5
+ * It exports the main server functionality and utility functions.
6
+ */
7
+
8
+ // Export the main server functionality
9
+ export { startServer, stopServer, getServerState, getServerAddress, isServerRunning } from './server.js';
10
+
11
+ // Export the application instance
12
+ export { default as app } from './app.js';
13
+
14
+ // Export utility functions
15
+ export { config } from './utils/config.js';
16
+ export { logger } from './utils/logger.js';
17
+ export { util } from './utils/util.js';
18
+
19
+ // Export services
20
+ export { promptManager } from './services/manager.js';
21
+
22
+ // Export MCP functionality
23
+ export { getMcpServer } from './mcp/mcp.server.js';
24
+ export {
25
+ handleGetPrompt,
26
+ handleSearchPrompts,
27
+ handleReloadPrompts
28
+ } from './mcp/prompt.handler.js';
29
+ export { handleSequentialThinking } from './mcp/sequential-thinking.handler.js';
30
+ export { handleThinkPlan } from './mcp/think-plan.handler.js';
31
+ export { handleToolM } from './toolm/index.js';
32
+
33
+ // Export API routes
34
+ export { adminRouter } from './api/admin.routes.js';
35
+ export { openRouter } from './api/open.routes.js';
36
+ export { surgeRouter } from './api/surge.routes.js';
37
+
38
+ // Export middlewares
39
+ export { adminAuthMiddleware } from './middlewares/auth.middleware.js';