mcp-osp-prompt 1.0.0 → 1.0.2

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.
@@ -1,358 +0,0 @@
1
- /**
2
- * 资源管理器模块
3
- *
4
- * 提供统一的资源访问API,用于获取projects和rules内容
5
- * Task 2.1 - 资源访问接口层
6
- */
7
-
8
- import fs from 'fs/promises';
9
- import path from 'path';
10
- import { CFG } from './config.js';
11
-
12
- /**
13
- * 读取资源缓存
14
- * @returns {Object|null} 缓存的资源对象
15
- */
16
- export async function readResourceCache() {
17
- const cacheFile = path.join(CFG.cacheDir, 'resource-cache.json');
18
-
19
- try {
20
- const data = await fs.readFile(cacheFile, 'utf8');
21
- const resources = JSON.parse(data);
22
-
23
- if (resources && resources.prompts && resources.projects && resources.rules) {
24
- return resources;
25
- }
26
-
27
- return null;
28
- } catch (error) {
29
- console.warn(`[ResourceManager] No resource cache found: ${error.message}`);
30
- return null;
31
- }
32
- }
33
-
34
- /**
35
- * 获取项目列表
36
- * @returns {Array} 项目文档列表
37
- */
38
- export async function getProjectsList() {
39
- try {
40
- const cache = await readResourceCache();
41
-
42
- if (!cache || !cache.projects) {
43
- console.warn('[ResourceManager] No projects found in cache');
44
- return [];
45
- }
46
-
47
- console.log(`[ResourceManager] Found ${cache.projects.length} projects`);
48
- return cache.projects;
49
- } catch (error) {
50
- console.error(`[ResourceManager] Failed to get projects list: ${error.message}`);
51
- return [];
52
- }
53
- }
54
-
55
- /**
56
- * 获取项目文档内容
57
- * @param {String} projectName - 项目文件名 (如 'kiki-framework-wiki.md')
58
- * @returns {String|null} 项目文档内容
59
- */
60
- export async function getProjectContent(projectName) {
61
- try {
62
- // 项目文档缓存在 projects 子目录
63
- const cacheFile = path.join(CFG.cacheDir, 'projects', projectName);
64
-
65
- const content = await fs.readFile(cacheFile, 'utf8');
66
- console.log(`[ResourceManager] Loaded project: ${projectName} (${content.length} bytes)`);
67
-
68
- return content;
69
- } catch (error) {
70
- console.warn(`[ResourceManager] Failed to load project ${projectName}: ${error.message}`);
71
-
72
- // 尝试从远程拉取(TODO: 在后续优化中实现)
73
- return null;
74
- }
75
- }
76
-
77
- /**
78
- * 根据语言获取规则文件信息
79
- * @param {String} language - 语言名称 (如 'java', 'python')
80
- * @returns {Object|null} 规则文件信息
81
- */
82
- export async function getRulesByLanguage(language) {
83
- try {
84
- const cache = await readResourceCache();
85
-
86
- if (!cache || !cache.rules) {
87
- console.warn('[ResourceManager] No rules found in cache');
88
- return null;
89
- }
90
-
91
- // 查找匹配的规则文件
92
- const rule = cache.rules.find(r => r.language === language);
93
-
94
- if (rule) {
95
- console.log(`[ResourceManager] Found rule for language: ${language}`);
96
- return rule;
97
- }
98
-
99
- console.warn(`[ResourceManager] No rule found for language: ${language}`);
100
- return null;
101
- } catch (error) {
102
- console.error(`[ResourceManager] Failed to get rules for ${language}: ${error.message}`);
103
- return null;
104
- }
105
- }
106
-
107
- /**
108
- * 获取规则文档内容
109
- * @param {String} ruleFilename - 规则文件名 (如 'java-code-rules.md')
110
- * @returns {String|null} 规则文档内容
111
- */
112
- export async function getRuleContent(ruleFilename) {
113
- try {
114
- // 规则文档缓存在 rules 子目录
115
- const cacheFile = path.join(CFG.cacheDir, 'rules', ruleFilename);
116
-
117
- const content = await fs.readFile(cacheFile, 'utf8');
118
- console.log(`[ResourceManager] Loaded rule: ${ruleFilename} (${content.length} bytes)`);
119
-
120
- return content;
121
- } catch (error) {
122
- console.warn(`[ResourceManager] Failed to load rule ${ruleFilename}: ${error.message}`);
123
-
124
- // 尝试从远程拉取(TODO: 在后续优化中实现)
125
- return null;
126
- }
127
- }
128
-
129
- /**
130
- * 根据语言获取规则内容(便捷函数)
131
- * @param {String} language - 语言名称
132
- * @returns {String|null} 规则内容
133
- */
134
- export async function getRuleContentByLanguage(language) {
135
- try {
136
- const ruleInfo = await getRulesByLanguage(language);
137
-
138
- if (!ruleInfo) {
139
- return null;
140
- }
141
-
142
- return await getRuleContent(ruleInfo.filename);
143
- } catch (error) {
144
- console.error(`[ResourceManager] Failed to get rule content for ${language}: ${error.message}`);
145
- return null;
146
- }
147
- }
148
-
149
- /**
150
- * 获取所有可用的规则语言列表
151
- * @returns {Array} 语言名称数组
152
- */
153
- export async function getAvailableLanguages() {
154
- try {
155
- const cache = await readResourceCache();
156
-
157
- if (!cache || !cache.rules) {
158
- return [];
159
- }
160
-
161
- const languages = cache.rules
162
- .map(r => r.language)
163
- .filter(Boolean);
164
-
165
- console.log(`[ResourceManager] Available languages: ${languages.join(', ')}`);
166
- return languages;
167
- } catch (error) {
168
- console.error(`[ResourceManager] Failed to get available languages: ${error.message}`);
169
- return [];
170
- }
171
- }
172
-
173
- /**
174
- * 检查资源是否已同步
175
- * @returns {Boolean} true表示资源已同步
176
- */
177
- export async function isResourcesSynced() {
178
- try {
179
- const cache = await readResourceCache();
180
- return cache !== null;
181
- } catch (error) {
182
- return false;
183
- }
184
- }
185
-
186
- /**
187
- * 获取资源同步时间
188
- * @returns {String|null} ISO时间字符串
189
- */
190
- export async function getLastSyncTime() {
191
- try {
192
- const cache = await readResourceCache();
193
- return cache ? cache.lastSync : null;
194
- } catch (error) {
195
- return null;
196
- }
197
- }
198
-
199
- /**
200
- * 🟢 GREEN: 读取文件的前几行作为摘要
201
- * @param {string} filePath - 文件路径
202
- * @param {number} maxLines - 最多读取的行数
203
- * @returns {string} 摘要内容
204
- */
205
- async function readFileSummary(filePath, maxLines = 2) {
206
- try {
207
- const content = await fs.readFile(filePath, 'utf-8');
208
- const allLines = content.split('\n');
209
-
210
- // 去掉markdown标题符号和空行,获取前N行有效内容
211
- const validLines = allLines
212
- .map(line => line.replace(/^#+\s*/, '').trim())
213
- .filter(line => line.length > 0)
214
- .slice(0, maxLines); // 取前N行有效内容
215
-
216
- // 每行限制120字符,用换行符连接
217
- const summary = validLines
218
- .map(line => line.substring(0, 120))
219
- .join('\n '); // 第二行缩进以便区分
220
-
221
- return summary || 'No description available';
222
- } catch (error) {
223
- return 'Description not available';
224
- }
225
- }
226
-
227
- /**
228
- * 🟢 GREEN: 格式化resources列表为轻量级文本(供prompt使用)
229
- * @param {Array<string>} resourceTypes - 需要的resource类型 ['projects', 'rules']
230
- * @returns {string} 格式化的文本
231
- */
232
- export async function formatResourcesList(resourceTypes = ['projects', 'rules']) {
233
- try {
234
- const cache = await readResourceCache();
235
- if (!cache) {
236
- return '# Available Resources\n\n(No resources cached yet)\n';
237
- }
238
-
239
- let text = '# Available Resources\n\n';
240
-
241
- // 格式化projects
242
- if (resourceTypes.includes('projects') && cache.projects && cache.projects.length > 0) {
243
- text += '## Projects Documentation\n';
244
- for (const project of cache.projects) {
245
- // 尝试读取文件摘要
246
- const projectPath = path.join(CFG.cacheDir, 'projects', project.filename);
247
- const summary = await readFileSummary(projectPath);
248
- text += `- **${project.filename}**: ${summary}\n`;
249
- }
250
- text += '\n';
251
- }
252
-
253
- // 格式化rules
254
- if (resourceTypes.includes('rules') && cache.rules && cache.rules.length > 0) {
255
- text += '## Rules & Standards\n';
256
- for (const rule of cache.rules) {
257
- // 尝试读取文件摘要
258
- const rulePath = path.join(CFG.cacheDir, 'rules', rule.filename);
259
- const summary = await readFileSummary(rulePath);
260
- text += `- **${rule.filename}**: ${summary}\n`;
261
- }
262
- text += '\n';
263
- }
264
-
265
- text += '---\n\n';
266
- text += '*To load full content of a resource, use the `load-resource` tool when needed.*\n\n';
267
-
268
- return text;
269
- } catch (error) {
270
- console.error('[ResourceManager] Failed to format resources list:', error.message);
271
- return '# Available Resources\n\n(Error loading resources)\n';
272
- }
273
- }
274
-
275
- /**
276
- * 🟢 GREEN: 加载resource的完整内容
277
- * @param {string} resourceName - 资源名称(不含路径,如 "java-rules.md")
278
- * @returns {Object} { success: boolean, content: string, error?: string }
279
- */
280
- export async function loadResourceContent(resourceName) {
281
- try {
282
- const cache = await readResourceCache();
283
- if (!cache) {
284
- return { success: false, error: 'No resources cached' };
285
- }
286
-
287
- // 查找resource在哪个类型中
288
- let resourcePath = null;
289
- let resourceType = null;
290
-
291
- // 检查projects
292
- if (cache.projects.some(p => p.filename === resourceName)) {
293
- resourcePath = path.join(CFG.cacheDir, 'projects', resourceName);
294
- resourceType = 'project';
295
- }
296
- // 检查rules
297
- else if (cache.rules.some(r => r.filename === resourceName)) {
298
- resourcePath = path.join(CFG.cacheDir, 'rules', resourceName);
299
- resourceType = 'rule';
300
- }
301
-
302
- if (!resourcePath) {
303
- return { success: false, error: `Resource "${resourceName}" not found in cache` };
304
- }
305
-
306
- // 读取文件内容
307
- const content = await fs.readFile(resourcePath, 'utf-8');
308
- return {
309
- success: true,
310
- content: content,
311
- type: resourceType,
312
- filename: resourceName
313
- };
314
- } catch (error) {
315
- return { success: false, error: error.message };
316
- }
317
- }
318
-
319
- /**
320
- * 获取资源统计信息
321
- * @returns {Object} 统计信息
322
- */
323
- export async function getResourceStats() {
324
- try {
325
- const cache = await readResourceCache();
326
-
327
- if (!cache) {
328
- return {
329
- synced: false,
330
- prompts: 0,
331
- projects: 0,
332
- rules: 0,
333
- total: 0,
334
- lastSync: null
335
- };
336
- }
337
-
338
- return {
339
- synced: true,
340
- prompts: cache.prompts?.length || 0,
341
- projects: cache.projects?.length || 0,
342
- rules: cache.rules?.length || 0,
343
- total: (cache.prompts?.length || 0) + (cache.projects?.length || 0) + (cache.rules?.length || 0),
344
- lastSync: cache.lastSync
345
- };
346
- } catch (error) {
347
- console.error(`[ResourceManager] Failed to get resource stats: ${error.message}`);
348
- return {
349
- synced: false,
350
- prompts: 0,
351
- projects: 0,
352
- rules: 0,
353
- total: 0,
354
- lastSync: null
355
- };
356
- }
357
- }
358
-