@becrafter/prompt-manager 0.0.16 → 0.0.19

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 (60) hide show
  1. package/IFLOW.md +175 -0
  2. package/README.md +66 -80
  3. package/app/desktop/assets/icons/icon.icns +0 -0
  4. package/app/desktop/assets/icons/icon.ico +0 -0
  5. package/app/desktop/assets/icons/icon_1024x1024.png +0 -0
  6. package/app/desktop/assets/icons/icon_128x128.png +0 -0
  7. package/app/desktop/assets/icons/icon_16x16.png +0 -0
  8. package/app/desktop/assets/icons/icon_24x24.png +0 -0
  9. package/app/desktop/assets/icons/icon_256x256.png +0 -0
  10. package/app/desktop/assets/icons/icon_32x32.png +0 -0
  11. package/app/desktop/assets/icons/icon_48x48.png +0 -0
  12. package/app/desktop/assets/icons/icon_512x512.png +0 -0
  13. package/app/desktop/assets/icons/icon_64x64.png +0 -0
  14. package/app/desktop/assets/icons/icon_96x96.png +0 -0
  15. package/app/desktop/assets/templates/about.html +147 -0
  16. package/app/desktop/main.js +178 -460
  17. package/app/desktop/package-lock.json +1150 -412
  18. package/app/desktop/package.json +54 -11
  19. package/app/desktop/preload.js +7 -0
  20. package/app/desktop/src/core/error-handler.js +108 -0
  21. package/app/desktop/src/core/event-emitter.js +84 -0
  22. package/app/desktop/src/core/logger.js +108 -0
  23. package/app/desktop/src/core/state-manager.js +125 -0
  24. package/app/desktop/src/services/module-loader.js +193 -0
  25. package/app/desktop/src/services/runtime-manager.js +152 -0
  26. package/app/desktop/src/services/service-manager.js +169 -0
  27. package/app/desktop/src/services/update-manager.js +268 -0
  28. package/app/desktop/src/ui/about-dialog-manager.js +208 -0
  29. package/app/desktop/src/ui/tray-manager.js +202 -0
  30. package/app/desktop/src/utils/icon-manager.js +141 -0
  31. package/app/desktop/src/utils/path-utils.js +58 -0
  32. package/app/desktop/src/utils/resource-paths.js +72 -0
  33. package/app/desktop/src/utils/template-renderer.js +284 -0
  34. package/app/desktop/src/utils/version-utils.js +59 -0
  35. package/examples/prompts/engineer/engineer-professional.yaml +92 -0
  36. package/examples/prompts/engineer/laowang-engineer.yaml +132 -0
  37. package/examples/prompts/engineer/nekomata-engineer.yaml +123 -0
  38. package/examples/prompts/engineer/ojousama-engineer.yaml +124 -0
  39. package/examples/prompts/workflow/sixstep-workflow.yaml +192 -0
  40. package/package.json +10 -3
  41. package/packages/admin-ui/admin.html +2 -2
  42. package/packages/resources/tools/filesystem/filesystem.tool.js +184 -0
  43. package/packages/resources/tools/index.js +16 -0
  44. package/packages/server/api/admin.routes.js +450 -0
  45. package/packages/server/api/open.routes.js +89 -0
  46. package/packages/server/app.js +163 -0
  47. package/packages/server/mcp/mcp.handler.js +265 -0
  48. package/packages/server/mcp/mcp.server.js +181 -0
  49. package/packages/server/mcp/toolx.handler.js +131 -0
  50. package/packages/server/middlewares/auth.middleware.js +34 -0
  51. package/packages/server/server.js +42 -908
  52. package/packages/server/{manager.js → services/manager.js} +13 -5
  53. package/packages/server/{config.js → utils/config.js} +27 -27
  54. package/packages/server/utils/util.js +356 -0
  55. package/scripts/build-icons.js +105 -0
  56. package/scripts/icns-builder/package.json +12 -0
  57. package/packages/server/mcp.js +0 -234
  58. package/packages/server/mcpManager.js +0 -205
  59. /package/app/desktop/assets/{icon.png → icons/icon.png} +0 -0
  60. /package/packages/server/{logger.js → utils/logger.js} +0 -0
@@ -1,234 +0,0 @@
1
- // 导入自定义模块
2
- import { config } from './config.js';
3
- import { logger } from './logger.js';
4
-
5
- // 处理 get_prompt 工具调用
6
- export async function handleGetPrompt(args, promptManager) {
7
- // 注意:这里为了兼容性,我们同时支持prompt_id和name参数
8
- const promptId = args.prompt_id || args.name;
9
-
10
- if (!promptId) {
11
- throw new Error("缺少必需参数: prompt_id 或 name");
12
- }
13
-
14
- const prompt = promptManager.getPrompt(promptId);
15
- if (!prompt) {
16
- throw new Error(`未找到ID为 "${promptId}" 的prompt`);
17
- }
18
-
19
- // 返回完整的prompt信息
20
- const promptInfo = {
21
- id: prompt.uniqueId, // 使用基于文件路径的唯一ID
22
- name: prompt.name,
23
- description: prompt.description || `Prompt: ${prompt.name}`,
24
- messages: prompt.messages || [],
25
- arguments: prompt.arguments || [],
26
- filePath: prompt.relativePath, // 添加文件路径信息
27
- };
28
-
29
- if (config.getLogLevel() === 'debug') {
30
- promptInfo.metadata = {
31
- uniqueId: prompt.uniqueId,
32
- fileName: prompt.fileName,
33
- fullPath: prompt.filePath,
34
- };
35
- }
36
-
37
- return convertToText({
38
- success: true,
39
- prompt: promptInfo
40
- });
41
- }
42
-
43
- // 处理 search_prompts 工具调用
44
- export async function handleSearchPrompts(args, promptManager) {
45
- // 注意:这里为了兼容性,我们同时支持title和name参数
46
- const searchTerm = args.title || args.name;
47
-
48
- const logLevel = config.getLogLevel();
49
- const allPrompts = promptManager.getPrompts();
50
-
51
- // 如果搜索词为空,则返回所有提示词
52
- if (!searchTerm) {
53
- let simplifiedPrompts = formatResults(allPrompts);
54
-
55
- return convertToText({
56
- success: true,
57
- query: searchTerm || '',
58
- count: simplifiedPrompts.length,
59
- results: simplifiedPrompts
60
- });
61
- }
62
-
63
- // 实现相似度匹配算法
64
- const searchResults = allPrompts.map(prompt => {
65
- prompt.description = prompt.description || `Prompt: ${prompt.name}`;
66
- prompt.arguments = prompt.arguments || [];
67
- prompt.hasArguments = prompt.arguments && prompt.arguments.length > 0;
68
- return {
69
- prompt: prompt,
70
- score: calculateSimilarityScore(searchTerm, prompt),
71
- };
72
- })
73
- .filter(result => result.score > 0) // 只返回有匹配的结果
74
- .sort((a, b) => b.score - a.score); // 按相似度得分降序排列
75
-
76
-
77
- let result = {
78
- success: true,
79
- query: searchTerm || '',
80
- count: searchResults.length,
81
- results: formatResults(searchResults),
82
- }
83
-
84
- if (logLevel === 'debug') {
85
- result.debug = {
86
- scores: searchResults.map(result => ({
87
- id: result.prompt.id,
88
- name: result.prompt.name,
89
- score: result.score,
90
- fullPath: result.prompt.filePath,
91
- }))
92
- }
93
- }
94
-
95
- return convertToText(result);
96
- }
97
-
98
- /**
99
- * 处理 reload_prompts 工具调用
100
- */
101
- export async function handleReloadPrompts(promptManager) {
102
- logger.info('重新加载prompts...');
103
-
104
- const result = await promptManager.reloadPrompts();
105
-
106
- return {
107
- content: [
108
- {
109
- type: "text",
110
- text: JSON.stringify({
111
- success: true,
112
- message: `重新加载完成: 成功 ${result.success} 个, 失败 ${result.errorCount} 个`,
113
- result: formatResults(result.prompts)
114
- }, null, 2)
115
- }
116
- ]
117
- };
118
- }
119
-
120
- /**
121
- * 格式化搜索结果
122
- * @param {*} results
123
- * @returns
124
- */
125
- function formatResults(results = []) {
126
- if (!Array.isArray(results)) return [];
127
-
128
- // console.log(results);
129
-
130
- return results.map(result => {
131
- const prompt = result.prompt ? result.prompt : result;
132
- const baseItem = {
133
- id: prompt.id || prompt.uniqueId || '',
134
- name: prompt.name || 'Unnamed Prompt',
135
- description: prompt.description || `Prompt: ${prompt.name || 'Unnamed'}`
136
- };
137
-
138
- if (config.getLogLevel() === 'debug') {
139
- return {
140
- ...baseItem,
141
- metadata: {
142
- fullPath: prompt.filePath || ''
143
- }
144
- };
145
- }
146
- return baseItem;
147
- });
148
- }
149
-
150
- /**
151
- * 将对象转换为text类型
152
- * @param {*} object
153
- * @returns
154
- */
155
- function convertToText(result) {
156
- return {
157
- content: [
158
- {
159
- type: "text",
160
- text: JSON.stringify(result, null, 2)
161
- }
162
- ]
163
- };
164
- }
165
-
166
- /**
167
- * 计算搜索关键词与prompt的相似度得分
168
- * @param {string} searchTerm - 搜索关键词
169
- * @param {Object} prompt - prompt对象
170
- * @returns {number} 相似度得分 (0-100)
171
- */
172
- function calculateSimilarityScore(searchTerm, prompt) {
173
- let totalScore = 0;
174
- const searchLower = searchTerm ? searchTerm.toLowerCase() : '';
175
-
176
- // 搜索字段权重配置(专注于内容搜索,不包含ID检索)
177
- const fieldWeights = {
178
- name: 60, // 名称权重高,是主要匹配字段
179
- description: 40 // 描述权重适中,是辅助匹配字段
180
- };
181
-
182
- // 计算name匹配得分
183
- if (prompt && prompt.name && typeof prompt.name === 'string') {
184
- const nameScore = getStringMatchScore(searchLower, prompt.name.toLowerCase());
185
- totalScore += nameScore * fieldWeights.name;
186
- }
187
-
188
- // 计算description匹配得分
189
- if (prompt.description) {
190
- const descScore = getStringMatchScore(searchLower, prompt.description.toLowerCase());
191
- totalScore += descScore * fieldWeights.description;
192
- }
193
-
194
- // 标准化得分到0-100范围
195
- const maxPossibleScore = Object.values(fieldWeights).reduce((sum, weight) => sum + weight, 0);
196
- return Math.round((totalScore / maxPossibleScore) * 100);
197
- }
198
-
199
- /**
200
- * 计算两个字符串的匹配得分
201
- * @param {string} search - 搜索词 (已转小写)
202
- * @param {string} target - 目标字符串 (已转小写)
203
- * @returns {number} 匹配得分 (0-1)
204
- */
205
- function getStringMatchScore(search, target) {
206
- if (!search || !target) return 0;
207
-
208
- // 完全匹配得分最高
209
- if (target === search) return 1.0;
210
-
211
- // 完全包含得分较高
212
- if (target.includes(search)) return 0.8;
213
-
214
- // 部分词匹配
215
- const searchWords = search.split(/\s+/).filter(word => word.length > 0);
216
- const targetWords = target.split(/\s+/).filter(word => word.length > 0);
217
-
218
- let matchedWords = 0;
219
- for (const searchWord of searchWords) {
220
- for (const targetWord of targetWords) {
221
- if (targetWord.includes(searchWord) || searchWord.includes(targetWord)) {
222
- matchedWords++;
223
- break;
224
- }
225
- }
226
- }
227
-
228
- if (searchWords.length > 0) {
229
- const wordMatchRatio = matchedWords / searchWords.length;
230
- return wordMatchRatio * 0.6; // 部分词匹配得分
231
- }
232
-
233
- return 0;
234
- }
@@ -1,205 +0,0 @@
1
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
5
- import { logger } from './logger.js';
6
- import { config } from './config.js';
7
- import { PromptManager } from './manager.js';
8
- import { handleSearchPrompts, handleGetPrompt, handleReloadPrompts } from './mcp.js';
9
-
10
- /**
11
- * MCP服务器管理类
12
- */
13
- export class MCPManager {
14
- constructor() {
15
- this.server = null;
16
- this.stdioTransport = null;
17
- this.httpTransport = null;
18
- this.promptManager = null;
19
- this.isInitialized = false;
20
- }
21
-
22
- /**
23
- * 初始化MCP服务器
24
- */
25
- async initialize() {
26
- if (this.isInitialized) {
27
- return;
28
- }
29
-
30
- try {
31
- // 初始化prompt管理器
32
- this.promptManager = new PromptManager(config.getPromptsDir());
33
- await this.promptManager.loadPrompts();
34
-
35
- // 创建MCP服务器
36
- this.server = new Server({
37
- name: 'Prompt Server MCP',
38
- version: config.serverVersion,
39
- }, {
40
- capabilities: {
41
- tools: {}
42
- }
43
- });
44
-
45
- // 注册工具处理器
46
- this.registerToolHandlers();
47
-
48
- // 启动Stdio传输
49
- this.stdioTransport = new StdioServerTransport();
50
- await this.server.connect(this.stdioTransport);
51
-
52
- this.isInitialized = true;
53
- logger.info('MCP服务器初始化完成');
54
- } catch (error) {
55
- logger.error('MCP服务器初始化失败:', error.message);
56
- throw error;
57
- }
58
- }
59
-
60
- /**
61
- * 注册工具处理器
62
- */
63
- registerToolHandlers() {
64
- // 注册工具列表处理器
65
- this.server.setRequestHandler(ListToolsRequestSchema, async () => {
66
- return {
67
- tools: [
68
- {
69
- name: 'search_prompts',
70
- description: 'For keyword search matching, retrieve or return all prompts. When a corresponding prompt word is matched, utilize the prompt ID to invoke the get_prompt tool to query the complete content of the prompt word.',
71
- inputSchema: {
72
- type: 'object',
73
- properties: {
74
- name: {
75
- type: 'string',
76
- description: 'Optional name filter for prompts'
77
- }
78
- }
79
- }
80
- },
81
- {
82
- name: 'get_prompt',
83
- description: 'Retrieve the complete content of a specific prompt by its ID, including all messages, arguments, and metadata.',
84
- inputSchema: {
85
- type: 'object',
86
- properties: {
87
- prompt_id: {
88
- type: 'string',
89
- description: 'The unique identifier of the prompt to retrieve'
90
- }
91
- },
92
- required: ['prompt_id']
93
- }
94
- },
95
- {
96
- name: 'reload_prompts',
97
- description: 'Force a reload of all preset prompts to overwrite the cache.',
98
- inputSchema: {
99
- type: 'object',
100
- properties: {}
101
- }
102
- }
103
- ]
104
- };
105
- });
106
-
107
- // 注册工具调用处理器
108
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
109
- const { name, arguments: args } = request.params;
110
-
111
- try {
112
- switch (name) {
113
- case 'search_prompts':
114
- return await handleSearchPrompts(args, this.promptManager);
115
- case 'get_prompt':
116
- return await handleGetPrompt(args, this.promptManager);
117
- case 'reload_prompts':
118
- // 重新加载prompts
119
- return await handleReloadPrompts(this.promptManager);
120
- default:
121
- throw new Error(`Unknown tool: ${name}`);
122
- }
123
- } catch (error) {
124
- logger.error(`执行工具 ${name} 时发生错误:`, error.message);
125
- return {
126
- content: [{ type: 'text', text: `Error: ${error.message}` }],
127
- isError: true
128
- };
129
- }
130
- });
131
- }
132
-
133
- /**
134
- * 处理HTTP请求
135
- */
136
- async handleHTTPRequest(req, res) {
137
- try {
138
- // 如果HTTP传输不存在,创建一个新的
139
- if (!this.httpTransport) {
140
- this.httpTransport = new StreamableHTTPServerTransport({
141
- sessionIdGenerator: undefined,
142
- enableJsonResponse: true
143
- });
144
-
145
- // 连接服务器到HTTP传输
146
- await this.server.connect(this.httpTransport);
147
- }
148
-
149
- // 处理请求
150
- await this.httpTransport.handleRequest(req, res, req.body);
151
- } catch (error) {
152
- logger.error('MCP HTTP请求处理失败:', error.message);
153
- if (!res.headersSent) {
154
- res.status(500).json({
155
- jsonrpc: '2.0',
156
- error: {
157
- code: -32603,
158
- message: 'Internal error'
159
- }
160
- });
161
- }
162
- }
163
- }
164
-
165
- /**
166
- * 关闭MCP服务器
167
- */
168
- async close() {
169
- try {
170
- if (this.httpTransport) {
171
- this.httpTransport.close();
172
- this.httpTransport = null;
173
- }
174
-
175
- if (this.server) {
176
- this.server.close();
177
- this.server = null;
178
- }
179
-
180
- this.isInitialized = false;
181
- logger.info('MCP服务器已关闭');
182
- } catch (error) {
183
- logger.error('关闭MCP服务器时发生错误:', error.message);
184
- }
185
- }
186
-
187
- /**
188
- * 重新加载prompts
189
- */
190
- async reloadPrompts() {
191
- if (this.promptManager) {
192
- return await this.promptManager.reloadPrompts();
193
- }
194
- }
195
-
196
- /**
197
- * 获取prompt管理器
198
- */
199
- getPromptManager() {
200
- return this.promptManager;
201
- }
202
- }
203
-
204
- // 导出单例实例
205
- export const mcpManager = new MCPManager();
File without changes
File without changes