mcp-osp-prompt 1.0.0 → 1.0.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/README.md +22 -78
- package/config.js +12 -17
- package/debug-env.js +7 -0
- package/dialog/browser.js +2 -2
- package/dialog/constants.js +0 -2
- package/dialog/native.js +23 -34
- package/dialog/objc.js +2 -2
- package/fetcher.js +1 -1
- package/package.json +5 -5
- package/platform-utils.js +18 -45
- package/prompt-manager.js +89 -534
- package/server.js +57 -15
- package/test.js +2 -2
- package/tools.js +14 -147
- package/resource-manager.js +0 -358
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A powerful MCP (Model Context Protocol) server that provides intelligent develop
|
|
|
8
8
|
## 🌟 Features
|
|
9
9
|
|
|
10
10
|
- **🚀 Multi-Platform Support**: GitHub, GitLab, and local directories
|
|
11
|
-
- **⚡ Auto-Detection**: Automatically detects platform from `
|
|
11
|
+
- **⚡ Auto-Detection**: Automatically detects platform from `PROMPT_PATH`
|
|
12
12
|
- **🔐 Unified Authentication**: Single `GIT_TOKEN` for both GitHub and GitLab
|
|
13
13
|
- **🎛️ Flexible Dialogs**: Native system dialogs and web-based interfaces
|
|
14
14
|
- **📦 Zero Configuration**: Works out-of-the-box with intelligent defaults
|
|
@@ -38,10 +38,10 @@ Add to your IDE's MCP configuration file (e.g., `~/.cursor/mcp.json`):
|
|
|
38
38
|
```jsonc
|
|
39
39
|
{
|
|
40
40
|
"mcpServers": {
|
|
41
|
-
"mcp-prompt
|
|
42
|
-
"command": "mcp-prompt
|
|
41
|
+
"mcp-osp-prompt": {
|
|
42
|
+
"command": "mcp-osp-prompt",
|
|
43
43
|
"env": {
|
|
44
|
-
"
|
|
44
|
+
"PROMPT_PATH": "username/repository",
|
|
45
45
|
"GIT_TOKEN": "ghp_your_github_token_here"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -53,10 +53,10 @@ Add to your IDE's MCP configuration file (e.g., `~/.cursor/mcp.json`):
|
|
|
53
53
|
```jsonc
|
|
54
54
|
{
|
|
55
55
|
"mcpServers": {
|
|
56
|
-
"mcp-prompt
|
|
57
|
-
"command": "mcp-prompt
|
|
56
|
+
"mcp-osp-prompt": {
|
|
57
|
+
"command": "mcp-osp-prompt",
|
|
58
58
|
"env": {
|
|
59
|
-
"
|
|
59
|
+
"PROMPT_PATH": "https://gitlab.com/group/project",
|
|
60
60
|
"GIT_TOKEN": "glpat-your_gitlab_token_here"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -68,27 +68,28 @@ Add to your IDE's MCP configuration file (e.g., `~/.cursor/mcp.json`):
|
|
|
68
68
|
```jsonc
|
|
69
69
|
{
|
|
70
70
|
"mcpServers": {
|
|
71
|
-
"mcp-prompt
|
|
72
|
-
"command": "mcp-prompt
|
|
71
|
+
"mcp-osp-prompt": {
|
|
72
|
+
"command": "mcp-osp-prompt",
|
|
73
73
|
"env": {
|
|
74
|
-
"
|
|
74
|
+
"PROMPT_PATH": "/path/to/your/prompts"
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
#### Local
|
|
81
|
+
#### Local Test by Source
|
|
82
82
|
```jsonc
|
|
83
83
|
{
|
|
84
|
-
"osp-prompt
|
|
84
|
+
"mcp-osp-prompt": {
|
|
85
85
|
"command": "node",
|
|
86
86
|
"args": [
|
|
87
|
-
"/
|
|
87
|
+
"/Users/penuel/workspace_script/osp-prompt/dev-mcp/server.js"
|
|
88
88
|
],
|
|
89
89
|
"env": {
|
|
90
|
-
"
|
|
91
|
-
"
|
|
90
|
+
"PROMPT_PATH": "https://gitlab.com/test-group/test-repo/-/tree/master",
|
|
91
|
+
"GIT_TOKEN": "your-actual-git-token",
|
|
92
|
+
"CACHE_TTL_SEC": "10800",
|
|
92
93
|
"AUTOMATED_MODE": "false",
|
|
93
94
|
"DEBUG_LOG": "true"
|
|
94
95
|
}
|
|
@@ -96,63 +97,6 @@ Add to your IDE's MCP configuration file (e.g., `~/.cursor/mcp.json`):
|
|
|
96
97
|
}
|
|
97
98
|
```
|
|
98
99
|
|
|
99
|
-
**本地开发配置说明:**
|
|
100
|
-
1. **克隆项目到本地:**
|
|
101
|
-
```bash
|
|
102
|
-
git clone https://gitlab.com/your-org/osp-prompt.git
|
|
103
|
-
cd osp-prompt/dev-mcp
|
|
104
|
-
npm install
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
2. **目录结构要求:**
|
|
108
|
-
```
|
|
109
|
-
osp-prompt/
|
|
110
|
-
├── osp/ # 资源根目录
|
|
111
|
-
│ ├── prompts/ # 提示词文件 (必需)
|
|
112
|
-
│ │ ├── design.prompt.md
|
|
113
|
-
│ │ ├── feature.prompt.md
|
|
114
|
-
│ │ └── ...
|
|
115
|
-
│ ├── projects/ # 项目文档 (可选)
|
|
116
|
-
│ │ ├── kiki-framework-wiki.md
|
|
117
|
-
│ │ └── ...
|
|
118
|
-
│ └── rules/ # 编码规范 (可选)
|
|
119
|
-
│ ├── java-rules.md
|
|
120
|
-
│ └── python-rules.md
|
|
121
|
-
└── dev-mcp/ # MCP 服务端
|
|
122
|
-
├── server.js
|
|
123
|
-
├── tests/ # 测试脚本
|
|
124
|
-
└── .cache/ # 本地缓存目录
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
3. **配置 Cursor MCP:**
|
|
128
|
-
- 编辑 `~/.cursor/mcp.json` 或项目的 `.cursor/mcp.json`
|
|
129
|
-
- 将上述配置中的路径替换为你的实际绝对路径
|
|
130
|
-
- 重启 Cursor
|
|
131
|
-
|
|
132
|
-
4. **运行端到端测试:**
|
|
133
|
-
```bash
|
|
134
|
-
# 测试 dev-design 完整流程
|
|
135
|
-
node tests/test-dev-design-e2e.js
|
|
136
|
-
|
|
137
|
-
# 测试 dev-feature 完整流程
|
|
138
|
-
node tests/test-dev-feature-e2e.js
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
5. **验证功能:**
|
|
142
|
-
- 在 Cursor 中打开任意项目
|
|
143
|
-
- 尝试调用 `dev-design` 或 `dev-feature` 工具
|
|
144
|
-
- 检查是否能看到:
|
|
145
|
-
* ✅ 可用的 projects 文档列表
|
|
146
|
-
* ✅ 可用的 rules 规范列表
|
|
147
|
-
* ✅ `load-resource` 工具使用说明
|
|
148
|
-
* ✅ 当前日期上下文
|
|
149
|
-
|
|
150
|
-
**重要提示:**
|
|
151
|
-
- **RESOURCE_PATH**: 本地模式下指向 `osp` 目录(包含 `prompts/`, `projects/`, `rules/` 子目录)
|
|
152
|
-
- **多目录支持**: 系统会自动扫描 `osp/projects/` 和 `osp/rules/` 目录
|
|
153
|
-
- **缓存目录**: 本地模式会将资源复制到 CACHE_DIR 进行缓存
|
|
154
|
-
- **AUTOMATED_MODE**: 设为 `false` 启用交互式确认,`true` 为全自动模式
|
|
155
|
-
|
|
156
100
|
### 2️⃣ Universal URL Parser - Handle Any Complex URL!
|
|
157
101
|
|
|
158
102
|
Our advanced URL parser supports **any complex** GitLab and GitHub repository structure:
|
|
@@ -173,7 +117,7 @@ Our advanced URL parser supports **any complex** GitLab and GitHub repository st
|
|
|
173
117
|
|
|
174
118
|
#### Auto-Detection Results:
|
|
175
119
|
|
|
176
|
-
|
|
|
120
|
+
| PROMPT_PATH Format | Platform | Parsed As |
|
|
177
121
|
|--------------------|----------|-----------|
|
|
178
122
|
| `user/repo` | GitHub | `user/repo@main:dev-arch` |
|
|
179
123
|
| `https://github.com/owner/repo/tree/branch/path/to/files` | GitHub | `owner/repo@branch:path/to/files` |
|
|
@@ -216,7 +160,7 @@ dev-bugfix: Debug intermittent session loss during user login
|
|
|
216
160
|
|
|
217
161
|
| Variable | Default | Description |
|
|
218
162
|
|----------|---------|-------------|
|
|
219
|
-
| `
|
|
163
|
+
| `PROMPT_PATH` | *(required)* | Platform will be auto-detected from this path |
|
|
220
164
|
| `GIT_TOKEN` | *(required for remote)* | GitHub (`ghp_...`) or GitLab (`glpat-...`) token |
|
|
221
165
|
| `DIALOG_MODE` | `auto` | Dialog mode: `auto`\|`native`\|`browser` |
|
|
222
166
|
| `AUTOMATED_MODE` | `true` | `false`=interactive confirmation, `true`=auto-execute |
|
|
@@ -229,13 +173,13 @@ dev-bugfix: Debug intermittent session loss during user login
|
|
|
229
173
|
### Verify Installation
|
|
230
174
|
```bash
|
|
231
175
|
# Test local mode
|
|
232
|
-
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' |
|
|
176
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | PROMPT_PATH="./dev-arch" mcp-prompt-fetcher
|
|
233
177
|
|
|
234
178
|
# Test GitHub mode
|
|
235
|
-
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' |
|
|
179
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | PROMPT_PATH="user/repo" GIT_TOKEN="your_token" mcp-prompt-fetcher
|
|
236
180
|
|
|
237
181
|
# Test GitLab mode
|
|
238
|
-
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' |
|
|
182
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | PROMPT_PATH="https://gitlab.com/group/project" GIT_TOKEN="your_token" mcp-prompt-fetcher
|
|
239
183
|
```
|
|
240
184
|
|
|
241
185
|
### Run Test Suite
|
|
@@ -255,7 +199,7 @@ npm run audit:security
|
|
|
255
199
|
<!-- 发布包 -->
|
|
256
200
|
npm publish --access public
|
|
257
201
|
<!-- 查看结果 -->
|
|
258
|
-
npm info mcp-prompt
|
|
202
|
+
npm info mcp-osp-prompt
|
|
259
203
|
```
|
|
260
204
|
|
|
261
205
|
## 📁 Directory Structure
|
package/config.js
CHANGED
|
@@ -29,9 +29,9 @@ function parseNativeDialogWidth() {
|
|
|
29
29
|
// 🔧 系统配置
|
|
30
30
|
export const CFG = {
|
|
31
31
|
debug: process.env.DEBUG_LOG === 'true',
|
|
32
|
-
automatedMode: process.env.AUTOMATED_MODE
|
|
32
|
+
automatedMode: process.env.AUTOMATED_MODE === 'true', // 默认false,需要显式设置true才启用自动模式
|
|
33
33
|
dialogMode: process.env.DIALOG_MODE || 'native',
|
|
34
|
-
defaultAuto:
|
|
34
|
+
defaultAuto: false, // 默认关闭自动模式,启用分步确认
|
|
35
35
|
force: force,
|
|
36
36
|
cacheDir: process.env.CACHE_DIR || path.join(process.env.HOME || '.', '.cache', 'prompts'),
|
|
37
37
|
ttl: parseInt(process.env.CACHE_TTL_SEC || '10800', 10), // 3小时默认TTL
|
|
@@ -53,10 +53,6 @@ export const CFG = {
|
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
// 🟢 GREEN: 统一资源配置 - 所有工具都加载完整的projects和rules列表
|
|
57
|
-
// AI将根据具体需求自行选择使用哪些resources
|
|
58
|
-
export const UNIFIED_RESOURCES = ['projects', 'rules'];
|
|
59
|
-
|
|
60
56
|
// 🟢 GREEN: Task 1.1 - 实现目录扫描功能(支持本地和远程)
|
|
61
57
|
export async function scanPromptFiles(devArchPath) {
|
|
62
58
|
try {
|
|
@@ -81,27 +77,27 @@ export async function scanPromptFiles(devArchPath) {
|
|
|
81
77
|
// 🟢 GREEN: Task 1.2 - 实现自动配置生成功能(简化版)
|
|
82
78
|
export async function generateAutoPromptTools() {
|
|
83
79
|
try {
|
|
84
|
-
const
|
|
85
|
-
if (!
|
|
80
|
+
const promptPath = process.env.PROMPT_PATH;
|
|
81
|
+
if (!promptPath) {
|
|
86
82
|
return getBasicPromptTools();
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
const platform = detectPlatformFromPath(
|
|
85
|
+
const platform = detectPlatformFromPath(promptPath);
|
|
90
86
|
let scannedFiles;
|
|
91
87
|
|
|
92
88
|
if (platform === 'local') {
|
|
93
89
|
// 本地模式:扫描配置的本地目录
|
|
94
|
-
console.log(`[Config] Using local
|
|
95
|
-
scannedFiles = await scanPromptFiles(
|
|
90
|
+
console.log(`[Config] Using local prompt path: ${promptPath}`);
|
|
91
|
+
scannedFiles = await scanPromptFiles(promptPath);
|
|
96
92
|
|
|
97
93
|
// 如果本地扫描失败或没有找到文件,回退到基础工具
|
|
98
94
|
if (scannedFiles.length === 0) {
|
|
99
|
-
console.warn(`Warning: No prompt files found in ${
|
|
95
|
+
console.warn(`Warning: No prompt files found in ${promptPath}, falling back to basic tools`);
|
|
100
96
|
return getBasicPromptTools();
|
|
101
97
|
}
|
|
102
98
|
} else {
|
|
103
99
|
// 远程模式:从GitHub或GitLab获取prompt文件列表
|
|
104
|
-
console.log(`[Config] Using remote ${platform} prompt files from: ${
|
|
100
|
+
console.log(`[Config] Using remote ${platform} prompt files from: ${promptPath}`);
|
|
105
101
|
scannedFiles = await scanRemotePromptFiles();
|
|
106
102
|
|
|
107
103
|
// 如果远程扫描失败或没有找到文件,回退到基础工具
|
|
@@ -233,8 +229,7 @@ async function scanRemoteGitLabFiles(pathInfo) {
|
|
|
233
229
|
async function scanRemotePromptFiles() {
|
|
234
230
|
validatePlatformConfiguration();
|
|
235
231
|
|
|
236
|
-
const
|
|
237
|
-
const platform = detectPlatformFromPath(resourcePath);
|
|
232
|
+
const platform = detectPlatformFromPath(process.env.PROMPT_PATH);
|
|
238
233
|
|
|
239
234
|
if (platform === 'local') {
|
|
240
235
|
throw new Error('scanRemotePromptFiles called for local path');
|
|
@@ -267,9 +262,9 @@ async function scanRemotePromptFiles() {
|
|
|
267
262
|
let scannedFiles = [];
|
|
268
263
|
|
|
269
264
|
if (platform === 'github') {
|
|
270
|
-
scannedFiles = await scanRemoteGitHubFiles(parseRemotePath(
|
|
265
|
+
scannedFiles = await scanRemoteGitHubFiles(parseRemotePath(process.env.PROMPT_PATH));
|
|
271
266
|
} else if (platform === 'gitlab') {
|
|
272
|
-
scannedFiles = await scanRemoteGitLabFiles(parseRemotePath(
|
|
267
|
+
scannedFiles = await scanRemoteGitLabFiles(parseRemotePath(process.env.PROMPT_PATH));
|
|
273
268
|
}
|
|
274
269
|
|
|
275
270
|
// 缓存结果
|
package/debug-env.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
console.log('=== 环境变量调试 ===');
|
|
2
|
+
console.log('PROMPT_PATH:', process.env.PROMPT_PATH || 'NOT SET');
|
|
3
|
+
console.log('GIT_TOKEN:', process.env.GIT_TOKEN ? 'SET (' + process.env.GIT_TOKEN.substring(0,20) + '...)' : 'NOT SET');
|
|
4
|
+
console.log('DEBUG_LOG:', process.env.DEBUG_LOG || 'NOT SET');
|
|
5
|
+
console.log('NODE_ENV:', process.env.NODE_ENV || 'NOT SET');
|
|
6
|
+
console.log('所有环境变量数量:', Object.keys(process.env).length);
|
|
7
|
+
console.log('完整环境变量列表:', Object.keys(process.env).slice(0,10).join(', '), '...');
|
package/dialog/browser.js
CHANGED
|
@@ -137,7 +137,7 @@ export async function showConfirmDialog(opts) {
|
|
|
137
137
|
|
|
138
138
|
// ✅ UNIFIED: 使用统一的按钮管理系统
|
|
139
139
|
const finalButtons = getSafeButtons(buttons);
|
|
140
|
-
console.log
|
|
140
|
+
// Removed: console.log with array output (causes JSON parse errors in MCP client)
|
|
141
141
|
|
|
142
142
|
// Handle automated testing mode
|
|
143
143
|
if (process.env.AUTOMATED_MODE === 'true') {
|
|
@@ -244,7 +244,7 @@ export async function showPlanAdjustmentDialog(opts) {
|
|
|
244
244
|
|
|
245
245
|
// ✅ UNIFIED: 使用统一的按钮管理系统
|
|
246
246
|
const finalOptions = getSafeButtons(options);
|
|
247
|
-
console.log
|
|
247
|
+
// Removed: console.log with array output (causes JSON parse errors in MCP client)
|
|
248
248
|
|
|
249
249
|
// Handle automated mode
|
|
250
250
|
if (process.env.AUTOMATED_MODE === 'true') {
|
package/dialog/constants.js
CHANGED
|
@@ -30,8 +30,6 @@ export const STANDARD_DIALOG_BUTTONS = {
|
|
|
30
30
|
* @returns {Array} 标准按钮数组,始终包含"修改计划"
|
|
31
31
|
*/
|
|
32
32
|
export function getStandardButtons(options = []) {
|
|
33
|
-
console.log(`🔧 [BUTTON-GENERATION] 输入options:`, options);
|
|
34
|
-
|
|
35
33
|
if (options && Array.isArray(options) && options.length > 0) {
|
|
36
34
|
// 📋 自定义按钮模式:有用户提供的选项
|
|
37
35
|
return STANDARD_DIALOG_BUTTONS.select(options);
|
package/dialog/native.js
CHANGED
|
@@ -35,7 +35,6 @@ export async function showInputDialog({ title = '输入', message = '请输入
|
|
|
35
35
|
|
|
36
36
|
// 验证行数
|
|
37
37
|
const actualLines = expandedDefaultText.split('\n').length;
|
|
38
|
-
console.log(`[Native Dialog] 📏 REAL 20-line input box: ${actualLines} lines created (target: 20 lines, CFG.nativeDialogWidth=${CFG.nativeDialogWidth}px)`);
|
|
39
38
|
|
|
40
39
|
try {
|
|
41
40
|
let command, args;
|
|
@@ -64,14 +63,18 @@ export async function showInputDialog({ title = '输入', message = '请输入
|
|
|
64
63
|
end if
|
|
65
64
|
`;
|
|
66
65
|
|
|
66
|
+
// 🆕 添加保活机制
|
|
67
|
+
const keepAliveInterval = setInterval(() => {
|
|
68
|
+
console.error('[Dialog-KeepAlive] Waiting for user input in textarea...');
|
|
69
|
+
}, 15000);
|
|
70
|
+
|
|
67
71
|
try {
|
|
68
|
-
console.log(`[Native Dialog] 🔄 Executing AppleScript for textarea...`);
|
|
69
72
|
const result = execSync(`osascript -e '${applescript}'`, {
|
|
70
73
|
encoding: 'utf8',
|
|
71
74
|
timeout: 1800000 // 30 minutes timeout (用户要求增加timeout)
|
|
72
75
|
}).trim();
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
clearInterval(keepAliveInterval); // 清理定时器
|
|
75
78
|
|
|
76
79
|
// Clean up the result - remove the placeholder text we added
|
|
77
80
|
let cleanedResult = result;
|
|
@@ -82,12 +85,7 @@ export async function showInputDialog({ title = '输入', message = '请输入
|
|
|
82
85
|
return cleanedResult;
|
|
83
86
|
|
|
84
87
|
} catch (error) {
|
|
85
|
-
|
|
86
|
-
message: error.message,
|
|
87
|
-
status: error.status,
|
|
88
|
-
signal: error.signal
|
|
89
|
-
});
|
|
90
|
-
|
|
88
|
+
clearInterval(keepAliveInterval); // 出错时也要清理定时器
|
|
91
89
|
// 更精确的用户取消检测
|
|
92
90
|
const isUserCancelled =
|
|
93
91
|
error.message && (
|
|
@@ -99,11 +97,11 @@ export async function showInputDialog({ title = '输入', message = '请输入
|
|
|
99
97
|
);
|
|
100
98
|
|
|
101
99
|
if (isUserCancelled) {
|
|
102
|
-
console.
|
|
100
|
+
console.error(`[Native Dialog] 👤 User cancelled textarea dialog`);
|
|
103
101
|
return defaultValue;
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
console.
|
|
104
|
+
console.error(`[Native Dialog] 💥 Textarea system error: ${error.message}`);
|
|
107
105
|
return defaultValue;
|
|
108
106
|
}
|
|
109
107
|
|
|
@@ -149,8 +147,6 @@ export async function showInputDialog({ title = '输入', message = '请输入
|
|
|
149
147
|
export async function showConfirmDialog({ title = '确认', message = '请选择:', buttons }) {
|
|
150
148
|
// ✅ UNIFIED: 使用统一的按钮管理系统
|
|
151
149
|
buttons = getSafeButtons(buttons);
|
|
152
|
-
console.log('🔧 [BUTTON-UNIFIED] Native dialog using unified button management:', buttons);
|
|
153
|
-
|
|
154
150
|
// Handle automated testing mode
|
|
155
151
|
if (process.env.AUTOMATED_MODE === 'true') {
|
|
156
152
|
// ✅ UNIFIED: 验证按钮包含"修改计划"选项,确保统一标准
|
|
@@ -163,7 +159,10 @@ export async function showConfirmDialog({ title = '确认', message = '请选择
|
|
|
163
159
|
|
|
164
160
|
const platform = os.platform();
|
|
165
161
|
|
|
166
|
-
|
|
162
|
+
// 🆕 添加保活机制
|
|
163
|
+
const keepAliveInterval = setInterval(() => {
|
|
164
|
+
console.error('[Dialog-KeepAlive] Waiting for user to select button...');
|
|
165
|
+
}, 15000);
|
|
167
166
|
|
|
168
167
|
try {
|
|
169
168
|
let command, args;
|
|
@@ -174,23 +173,17 @@ export async function showConfirmDialog({ title = '确认', message = '请选择
|
|
|
174
173
|
|
|
175
174
|
// Clean button text and ensure they're safe for AppleScript
|
|
176
175
|
const safeButtons = buttons.map(b => {
|
|
177
|
-
// Remove emojis from buttons but keep meaningful text
|
|
178
|
-
|
|
176
|
+
// Remove emojis from buttons but keep meaningful text, then escape
|
|
177
|
+
const cleanButton = b
|
|
179
178
|
.replace(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/gu, '')
|
|
180
179
|
.trim();
|
|
181
|
-
// 🔥 关键修复:在调用escapeAppleScriptString之前,先移除逗号(全角和半角)
|
|
182
|
-
// 因为escapeAppleScriptString会将全角逗号转为半角逗号,而半角逗号会破坏AppleScript按钮语法
|
|
183
|
-
cleanButton = cleanButton.replace(/[,,]/g, ' '); // 移除全角和半角逗号,替换为空格
|
|
184
180
|
return escapeAppleScriptString(cleanButton) || '确定';
|
|
185
181
|
});
|
|
186
182
|
|
|
187
183
|
const buttonsList = safeButtons.map(b => `"${b}"`).join(', ');
|
|
188
184
|
const script = `set selectedButton to button returned of (display dialog "${safeMessage}" with title "${safeTitle}" buttons {${buttonsList}} default button "${safeButtons[0]}")`;
|
|
189
185
|
|
|
190
|
-
|
|
191
|
-
console.log('🔧 [DEBUG] Safe title:', safeTitle);
|
|
192
|
-
console.log('🔧 [DEBUG] Safe buttons:', safeButtons);
|
|
193
|
-
console.log('🔧 [DEBUG] Script length:', script.length);
|
|
186
|
+
// Removed: DEBUG logs with array/object output (causes JSON parse errors in MCP client)
|
|
194
187
|
|
|
195
188
|
const result = execSync(`osascript -e '${script}'`, {
|
|
196
189
|
encoding: 'utf8',
|
|
@@ -198,8 +191,9 @@ export async function showConfirmDialog({ title = '确认', message = '请选择
|
|
|
198
191
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
199
192
|
});
|
|
200
193
|
|
|
194
|
+
clearInterval(keepAliveInterval); // 清理定时器
|
|
195
|
+
|
|
201
196
|
const selectedButton = result.trim();
|
|
202
|
-
console.log('✅ [USER SELECTED]:', selectedButton);
|
|
203
197
|
|
|
204
198
|
// Map safe button back to original button
|
|
205
199
|
const safeIndex = safeButtons.indexOf(selectedButton);
|
|
@@ -212,13 +206,12 @@ export async function showConfirmDialog({ title = '确认', message = '请选择
|
|
|
212
206
|
encoding: 'utf8',
|
|
213
207
|
timeout: 300000
|
|
214
208
|
});
|
|
215
|
-
|
|
209
|
+
clearInterval(keepAliveInterval); // 清理定时器
|
|
216
210
|
return result.trim() || buttons[0];
|
|
217
211
|
}
|
|
218
212
|
} catch (error) {
|
|
213
|
+
clearInterval(keepAliveInterval); // 出错时也要清理
|
|
219
214
|
console.error('❌ [DIALOG ERROR]:', error.message);
|
|
220
|
-
console.log('⚠️ Dialog failed to display - this may indicate a system issue');
|
|
221
|
-
|
|
222
215
|
// Throw a specific error that indicates dialog system failure
|
|
223
216
|
throw new Error(`DIALOG_SYSTEM_FAILURE: ${error.message}`);
|
|
224
217
|
}
|
|
@@ -231,7 +224,7 @@ export async function showPlanAdjustmentDialog({ title = '', message = '', curre
|
|
|
231
224
|
|
|
232
225
|
// ✅ UNIFIED: 使用统一的按钮管理系统
|
|
233
226
|
options = getSafeButtons(options);
|
|
234
|
-
console.log
|
|
227
|
+
// Removed: console.log with array output (causes JSON parse errors in MCP client)
|
|
235
228
|
|
|
236
229
|
// Handle automated mode
|
|
237
230
|
if (process.env.AUTOMATED_MODE === 'true') {
|
|
@@ -259,12 +252,10 @@ export async function showPlanAdjustmentDialog({ title = '', message = '', curre
|
|
|
259
252
|
const safeTitle = escapeAppleScriptString(title).trim() || 'Dialog';
|
|
260
253
|
const safeMessage = escapeAppleScriptString(fullMessage);
|
|
261
254
|
const safeOptions = options.map(b => {
|
|
262
|
-
// Remove emojis from options but keep meaningful text
|
|
263
|
-
|
|
255
|
+
// Remove emojis from options but keep meaningful text, then escape
|
|
256
|
+
const cleanOption = b
|
|
264
257
|
.replace(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/gu, '')
|
|
265
258
|
.trim();
|
|
266
|
-
// 🔥 关键修复:在调用escapeAppleScriptString之前,先移除逗号(全角和半角)
|
|
267
|
-
cleanOption = cleanOption.replace(/[,,]/g, ' '); // 移除全角和半角逗号,替换为空格
|
|
268
259
|
return escapeAppleScriptString(cleanOption) || '继续';
|
|
269
260
|
});
|
|
270
261
|
|
|
@@ -278,7 +269,6 @@ export async function showPlanAdjustmentDialog({ title = '', message = '', curre
|
|
|
278
269
|
];
|
|
279
270
|
|
|
280
271
|
const script = scriptParts.join(' ');
|
|
281
|
-
console.log('🔧 [DEBUG] Plan adjustment script length:', script.length);
|
|
282
272
|
result = execSync(`osascript -e '${script}'`, { encoding: 'utf8', timeout: 30000 }).trim();
|
|
283
273
|
|
|
284
274
|
// If "修改计划" is selected, show input dialog using improved showInputDialog
|
|
@@ -327,7 +317,6 @@ export async function showSelectDialog({ title = '选择', message = '请选择'
|
|
|
327
317
|
const safeTitle = escapeAppleScriptString(title);
|
|
328
318
|
const safeMessage = escapeAppleScriptString(message);
|
|
329
319
|
const script = `set theChoice to choose from list {${safeItems}} with title \"${safeTitle}\" with prompt \"${safeMessage}\"`;
|
|
330
|
-
console.log('🔧 [DEBUG] Select dialog script length:', script.length);
|
|
331
320
|
const result = execSync(`osascript -e "${script}"`, { encoding: 'utf8', timeout: 30000 });
|
|
332
321
|
return result.trim();
|
|
333
322
|
|
package/dialog/objc.js
CHANGED
|
@@ -124,7 +124,7 @@ return resultText`;
|
|
|
124
124
|
export async function showConfirmDialog({ title = '确认', message = '请选择:', buttons }) {
|
|
125
125
|
// ✅ UNIFIED: 使用统一的按钮管理系统
|
|
126
126
|
buttons = getSafeButtons(buttons);
|
|
127
|
-
console.log
|
|
127
|
+
// Removed: console.log with array output (causes JSON parse errors in MCP client)
|
|
128
128
|
|
|
129
129
|
if (process.env.AUTOMATED_MODE === 'true') {
|
|
130
130
|
// ✅ UNIFIED: 验证按钮包含"修改计划"选项,确保统一标准
|
|
@@ -237,7 +237,7 @@ export async function showPlanAdjustmentDialog({ title = '', message = '', curre
|
|
|
237
237
|
|
|
238
238
|
// ✅ UNIFIED: 使用统一的按钮管理系统
|
|
239
239
|
options = getSafeButtons(options);
|
|
240
|
-
console.log
|
|
240
|
+
// Removed: console.log with array output (causes JSON parse errors in MCP client)
|
|
241
241
|
|
|
242
242
|
if (process.env.AUTOMATED_MODE === 'true') {
|
|
243
243
|
// ✅ UNIFIED: 验证选项包含"修改计划"选项,确保统一标准
|
package/fetcher.js
CHANGED
|
@@ -48,7 +48,7 @@ export function getPlatformInfo() {
|
|
|
48
48
|
// 验证当前配置
|
|
49
49
|
export function validateCurrentConfiguration() {
|
|
50
50
|
try {
|
|
51
|
-
const platform = validatePlatformConfiguration(process.env.
|
|
51
|
+
const platform = validatePlatformConfiguration(process.env.PROMPT_PATH, process.env.GIT_TOKEN);
|
|
52
52
|
return { valid: true, platform };
|
|
53
53
|
} catch (error) {
|
|
54
54
|
return { valid: false, error: error.message };
|
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-osp-prompt",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "MCP server for fetching and caching prompt templates from GitHub, GitLab, or local directories",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mcp-prompt-fetcher": "./server.js"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
|
-
"author": "OSP Team",
|
|
10
|
+
"author": "OSP Development Team",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/mcp-
|
|
14
|
+
"url": "https://github.com/mcp-community/prompt-fetcher.git"
|
|
15
15
|
},
|
|
16
|
-
"homepage": "https://github.com/mcp-
|
|
16
|
+
"homepage": "https://github.com/mcp-community/prompt-fetcher#readme",
|
|
17
17
|
"bugs": {
|
|
18
|
-
"url": "https://github.com/mcp-
|
|
18
|
+
"url": "https://github.com/mcp-community/prompt-fetcher/issues"
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
21
|
"mcp",
|