@becrafter/prompt-manager 0.1.2 → 0.1.9
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 +304 -121
- package/app/cli/commands/start.js +65 -4
- package/app/cli/support/argv.js +6 -0
- package/env.example +32 -0
- package/package.json +36 -7
- package/packages/server/api/admin.routes.js +409 -1
- package/packages/server/api/open.routes.js +7 -2
- package/packages/server/api/tool.routes.js +479 -0
- package/packages/server/app.js +97 -25
- package/packages/server/configs/models/built-in/bigmodel.yaml +6 -0
- package/packages/server/configs/models/providers.yaml +50 -0
- package/packages/server/configs/templates/built-in/general-iteration.yaml +60 -0
- package/packages/server/configs/templates/built-in/general-optimize.yaml +63 -0
- package/packages/server/configs/templates/built-in/output-format-optimize.yaml +95 -0
- package/packages/server/mcp/heartbeat-patch.js +73 -0
- package/packages/server/mcp/mcp.server.js +63 -314
- package/packages/server/mcp/prompt.handler.js +26 -0
- package/packages/server/mcp/thinking-toolkit.handler.js +380 -0
- package/packages/server/package.json +35 -3
- package/packages/server/server.js +114 -12
- package/packages/server/services/TerminalService.js +498 -0
- package/packages/server/services/WebSocketService.js +484 -0
- package/packages/server/services/manager.js +38 -7
- package/packages/server/services/model.service.js +473 -0
- package/packages/server/services/optimization.service.js +457 -0
- package/packages/server/services/template.service.js +333 -0
- package/packages/server/toolm/tool-description-generator-optimized.service.js +5 -2
- package/packages/server/toolm/tool-sync.service.js +47 -3
- package/packages/server/utils/config.js +8 -1
- package/packages/server/utils/port-checker.js +63 -0
- package/packages/server/utils/util.js +27 -0
- package/IFLOW.md +0 -175
- package/app/desktop/assets/app.1.png +0 -0
- package/app/desktop/assets/app.png +0 -0
- package/app/desktop/assets/icons/icon.icns +0 -0
- package/app/desktop/assets/icons/icon.ico +0 -0
- package/app/desktop/assets/icons/icon.png +0 -0
- package/app/desktop/assets/icons/tray.png +0 -0
- package/app/desktop/assets/templates/about.html +0 -147
- package/app/desktop/assets/tray.1.png +0 -0
- package/app/desktop/assets/tray.png +0 -0
- package/app/desktop/main.js +0 -241
- package/app/desktop/package-lock.json +0 -5026
- package/app/desktop/package.json +0 -100
- package/app/desktop/preload.js +0 -7
- package/app/desktop/src/core/error-handler.js +0 -108
- package/app/desktop/src/core/event-emitter.js +0 -84
- package/app/desktop/src/core/logger.js +0 -108
- package/app/desktop/src/core/state-manager.js +0 -125
- package/app/desktop/src/services/module-loader.js +0 -214
- package/app/desktop/src/services/runtime-manager.js +0 -301
- package/app/desktop/src/services/service-manager.js +0 -169
- package/app/desktop/src/services/update-manager.js +0 -267
- package/app/desktop/src/ui/about-dialog-manager.js +0 -208
- package/app/desktop/src/ui/admin-window-manager.js +0 -757
- package/app/desktop/src/ui/splash-manager.js +0 -253
- package/app/desktop/src/ui/tray-manager.js +0 -186
- package/app/desktop/src/utils/icon-manager.js +0 -133
- package/app/desktop/src/utils/path-utils.js +0 -58
- package/app/desktop/src/utils/resource-paths.js +0 -49
- package/app/desktop/src/utils/resource-sync.js +0 -260
- package/app/desktop/src/utils/runtime-sync.js +0 -241
- package/app/desktop/src/utils/template-renderer.js +0 -284
- package/app/desktop/src/utils/version-utils.js +0 -59
- package/examples/prompts/developer/code-review.yaml +0 -32
- package/examples/prompts/developer/code_refactoring.yaml +0 -31
- package/examples/prompts/developer/doc-generator.yaml +0 -36
- package/examples/prompts/developer/error-code-fixer.yaml +0 -35
- package/examples/prompts/engineer/engineer-professional.yaml +0 -92
- package/examples/prompts/engineer/laowang-engineer.yaml +0 -132
- package/examples/prompts/engineer/nekomata-engineer.yaml +0 -123
- package/examples/prompts/engineer/ojousama-engineer.yaml +0 -124
- package/examples/prompts/generator/gen_3d_edu_webpage_html.yaml +0 -117
- package/examples/prompts/generator/gen_3d_webpage_html.yaml +0 -75
- package/examples/prompts/generator/gen_bento_grid_html.yaml +0 -112
- package/examples/prompts/generator/gen_html_web_page.yaml +0 -88
- package/examples/prompts/generator/gen_knowledge_card_html.yaml +0 -83
- package/examples/prompts/generator/gen_magazine_card_html.yaml +0 -82
- package/examples/prompts/generator/gen_mimeng_headline_title.yaml +0 -71
- package/examples/prompts/generator/gen_podcast_script.yaml +0 -69
- package/examples/prompts/generator/gen_prd_prototype_html.yaml +0 -175
- package/examples/prompts/generator/gen_summarize.yaml +0 -157
- package/examples/prompts/generator/gen_title.yaml +0 -119
- package/examples/prompts/generator/others/api_documentation.yaml +0 -32
- package/examples/prompts/generator/others/build_mcp_server.yaml +0 -26
- package/examples/prompts/generator/others/project_architecture.yaml +0 -31
- package/examples/prompts/generator/others/test_case_generator.yaml +0 -30
- package/examples/prompts/generator/others/writing_assistant.yaml +0 -72
- package/examples/prompts/recommend/human_3-0_growth_diagnostic_coach_prompt.yaml +0 -105
- package/examples/prompts/workflow/sixstep-workflow.yaml +0 -192
- package/packages/admin-ui/.babelrc +0 -3
- package/packages/admin-ui/admin.html +0 -412
- package/packages/admin-ui/css/codemirror-theme_xq-light.css +0 -43
- package/packages/admin-ui/css/codemirror.css +0 -344
- package/packages/admin-ui/css/main.css +0 -2592
- package/packages/admin-ui/css/recommended-prompts.css +0 -610
- package/packages/admin-ui/package-lock.json +0 -6973
- package/packages/admin-ui/package.json +0 -36
- package/packages/admin-ui/src/codemirror.js +0 -53
- package/packages/admin-ui/src/index.js +0 -3188
- package/packages/admin-ui/webpack.config.js +0 -76
- package/packages/server/toolm/test-tools.js +0 -264
- package/scripts/build-icons.js +0 -135
- package/scripts/build.sh +0 -57
- package/scripts/postinstall.js +0 -34
- package/scripts/surge/CNAME +0 -1
- package/scripts/surge/README.md +0 -47
- package/scripts/surge/package-lock.json +0 -34
- package/scripts/surge/package.json +0 -20
- package/scripts/surge/sync-to-surge.js +0 -151
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 融合型思考工具处理器
|
|
3
|
+
*
|
|
4
|
+
* 根据场景参数自动路由到顺序思考工具或思考规划工具,
|
|
5
|
+
* 以便在 MCP 侧只暴露一个描述更精简的入口。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { handleSequentialThinking } from './sequential-thinking.handler.js';
|
|
9
|
+
import { handleThinkPlan } from './think-plan.handler.js';
|
|
10
|
+
import { logger } from '../utils/logger.js';
|
|
11
|
+
|
|
12
|
+
export const THINKING_SCENARIOS = {
|
|
13
|
+
EXPLORATORY: 'exploratory', // 探索 / 诊断类场景
|
|
14
|
+
EXECUTION: 'execution' // 执行 / 规划类场景
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 根据用户提供的场景触发不同的思考工具
|
|
19
|
+
* @param {object} args - MCP 请求参数
|
|
20
|
+
* @param {'exploratory'|'execution'} args.scenario - 用户思考场景
|
|
21
|
+
* @param {object} args.payload - 对应场景所需的参数
|
|
22
|
+
*/
|
|
23
|
+
export async function handleThinkingToolkit(args) {
|
|
24
|
+
const { scenario, payload, _meta } = args || {};
|
|
25
|
+
const resolvedScenario = scenario || _meta?.scenario;
|
|
26
|
+
|
|
27
|
+
if (!resolvedScenario) {
|
|
28
|
+
throw new Error('缺少必需参数: scenario');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const description = getScenarioDescription(resolvedScenario);
|
|
32
|
+
if (!description) {
|
|
33
|
+
throw new Error(`未找到场景 ${resolvedScenario} 对应的描述信息`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (payload === undefined || payload === null) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: description
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
logger.debug('[thinking_toolkit] dispatching scenario:', resolvedScenario);
|
|
48
|
+
|
|
49
|
+
const executor = resolvedScenario === THINKING_SCENARIOS.EXPLORATORY
|
|
50
|
+
? handleSequentialThinking
|
|
51
|
+
: resolvedScenario === THINKING_SCENARIOS.EXECUTION
|
|
52
|
+
? handleThinkPlan
|
|
53
|
+
: null;
|
|
54
|
+
|
|
55
|
+
if (!executor) {
|
|
56
|
+
throw new Error(`不支持的 scenario: ${resolvedScenario}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const normalizedPayload = normalizePayloadByScenario(resolvedScenario, payload);
|
|
60
|
+
|
|
61
|
+
const result = await executor(normalizedPayload);
|
|
62
|
+
|
|
63
|
+
if (!result || !Array.isArray(result.content)) {
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
...result,
|
|
69
|
+
content: [
|
|
70
|
+
...result.content
|
|
71
|
+
]
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function normalizePayloadByScenario(scenario, payload) {
|
|
76
|
+
if (typeof payload !== 'object' || Array.isArray(payload)) {
|
|
77
|
+
const sample = scenario === THINKING_SCENARIOS.EXPLORATORY
|
|
78
|
+
? `{"thought":"分析性能下降的可能原因","totalThoughts":5}`
|
|
79
|
+
: `{"thought":"需要上线新版本","plan":"1. 备份 2. 部署 3. 验证","action":"先执行备份脚本","thoughtNumber":"TP-001"}`;
|
|
80
|
+
throw new Error(`payload 必须是对象。例如:${sample}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const sanitizeThought = (value) => {
|
|
84
|
+
if (typeof value !== 'string') {
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
return value.trim();
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
if (scenario === THINKING_SCENARIOS.EXPLORATORY) {
|
|
91
|
+
const requiredMissing = [];
|
|
92
|
+
if (!payload.thought || sanitizeThought(payload.thought).length === 0) {
|
|
93
|
+
requiredMissing.push('thought');
|
|
94
|
+
}
|
|
95
|
+
if (requiredMissing.length > 0) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`当 scenario="exploratory" 时,需要提供 ${requiredMissing.join('、')} 字段。例如:{"thought":"分析性能下降的可能原因","totalThoughts":5}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const normalized = { ...payload };
|
|
102
|
+
if (normalized.thoughtNumber !== undefined) {
|
|
103
|
+
const numericValue = typeof normalized.thoughtNumber === 'string'
|
|
104
|
+
? Number(normalized.thoughtNumber)
|
|
105
|
+
: normalized.thoughtNumber;
|
|
106
|
+
if (Number.isNaN(numericValue)) {
|
|
107
|
+
throw new Error('exploratory 场景中 thoughtNumber 需要是数字,例如 1 或 2。');
|
|
108
|
+
}
|
|
109
|
+
normalized.thoughtNumber = numericValue;
|
|
110
|
+
}
|
|
111
|
+
return normalized;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (scenario === THINKING_SCENARIOS.EXECUTION) {
|
|
115
|
+
const requiredFields = ['thought', 'plan', 'action', 'thoughtNumber'];
|
|
116
|
+
const missing = requiredFields.filter((field) => {
|
|
117
|
+
const value = payload[field];
|
|
118
|
+
if (value === undefined || value === null) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
if (typeof value === 'string') {
|
|
122
|
+
return value.trim().length === 0;
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (missing.length > 0) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`当 scenario="execution" 时,需要提供 ${missing.join('、')} 字段。例如:{"thought":"需要上线新版本","plan":"1. 备份 2. 部署 3. 验证","action":"先执行备份脚本","thoughtNumber":"TP-001"}`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
...payload,
|
|
135
|
+
thoughtNumber: String(payload.thoughtNumber)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
throw new Error(`不支持的 scenario: ${scenario}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const SEQUENTIAL_THINKING_DESCRIPTION = `🧠 **顺序思考工具 (Sequential Thinking)** - 动态反思性思维工具
|
|
143
|
+
|
|
144
|
+
## 🎯 工具定位
|
|
145
|
+
这是一个用于**探索性、分析性、不确定性**问题的动态思考工具。支持非线性思维、修订和分支,适合需要深入分析和反复验证的场景。每个思考都可以在理解加深时,在之前获得的见解上构建、质疑或修订。
|
|
146
|
+
|
|
147
|
+
**重要说明:** 此工具支持 MCP 工具协调功能。模型会分析可用工具及其描述,智能推荐合适的工具,并由服务器跟踪和组织这些推荐。
|
|
148
|
+
|
|
149
|
+
## 🔍 场景识别 - 何时使用此工具?
|
|
150
|
+
|
|
151
|
+
**1. 探索性问题(问题不明确)**
|
|
152
|
+
- ❓ "为什么系统性能下降?" → 需要分析原因
|
|
153
|
+
- ❓ "用户流失率高的原因是什么?" → 需要诊断问题
|
|
154
|
+
- ❓ "这个bug的根本原因是什么?" → 需要深入调查
|
|
155
|
+
|
|
156
|
+
**2. 分析性任务(需要假设验证)**
|
|
157
|
+
- 📊 复杂数据分析
|
|
158
|
+
- 🔬 问题诊断和根因分析
|
|
159
|
+
- 🧪 假设生成和验证
|
|
160
|
+
- 📈 趋势分析和预测
|
|
161
|
+
|
|
162
|
+
**3. 创意性工作(需要多路径探索)**
|
|
163
|
+
- 💡 产品功能设计
|
|
164
|
+
- 🎨 方案设计
|
|
165
|
+
- 🚀 创新思路探索
|
|
166
|
+
- 🔄 需要对比多个方案
|
|
167
|
+
|
|
168
|
+
**4. 需要修订和分支的场景**
|
|
169
|
+
- 发现之前的思考有误,需要修正
|
|
170
|
+
- 需要探索多个可能的解决方案
|
|
171
|
+
- 需要回溯和重新评估
|
|
172
|
+
|
|
173
|
+
**5. 需要工具指导的场景**
|
|
174
|
+
- 不确定应该使用哪些工具
|
|
175
|
+
- 需要了解工具的执行顺序
|
|
176
|
+
- 需要工具使用的参数建议
|
|
177
|
+
- 需要工具推荐的合理性说明
|
|
178
|
+
|
|
179
|
+
## ✨ 核心特性
|
|
180
|
+
|
|
181
|
+
**1. 非线性思维**
|
|
182
|
+
- 支持分支(branch):从某个思考点探索多个方向
|
|
183
|
+
- 支持修订(revision):修正之前的思考
|
|
184
|
+
- 支持回溯:重新评估之前的步骤
|
|
185
|
+
|
|
186
|
+
**2. 动态调整**
|
|
187
|
+
- 可以调整总思考步骤数(total_thoughts)
|
|
188
|
+
- 可以中途添加更多思考
|
|
189
|
+
- 可以表达不确定性
|
|
190
|
+
- 可以探索替代方案
|
|
191
|
+
|
|
192
|
+
**3. 进度追踪**
|
|
193
|
+
- 显示思考进度(当前/总数/百分比)
|
|
194
|
+
- 自动生成最终总结
|
|
195
|
+
- 提取关键洞察和结论
|
|
196
|
+
- 跟踪已推荐的步骤和剩余步骤
|
|
197
|
+
|
|
198
|
+
**4. 灵活性强**
|
|
199
|
+
- 单一 thought 字段,内容自由
|
|
200
|
+
- 支持假设生成和验证
|
|
201
|
+
- 支持问题分解和重构
|
|
202
|
+
- 支持工具推荐和参数建议
|
|
203
|
+
|
|
204
|
+
**5. MCP 工具协调(核心特性)**
|
|
205
|
+
- 🔧 为每个步骤推荐合适的工具
|
|
206
|
+
- 📝 提供工具推荐的合理性说明
|
|
207
|
+
- 📋 建议工具执行顺序和参数
|
|
208
|
+
- 📊 跟踪之前的推荐和剩余步骤
|
|
209
|
+
- 🎯 分析可用工具并做出智能推荐
|
|
210
|
+
|
|
211
|
+
## 📋 使用指南
|
|
212
|
+
|
|
213
|
+
**参数说明:**
|
|
214
|
+
|
|
215
|
+
**基础参数:**
|
|
216
|
+
- \`thought\`(必需):当前思考步骤,可以包括:
|
|
217
|
+
* 常规分析步骤
|
|
218
|
+
* 对之前思考的修订
|
|
219
|
+
* 对之前决策的质疑
|
|
220
|
+
* 意识到需要更多分析
|
|
221
|
+
* 方法的改变
|
|
222
|
+
* 假设生成
|
|
223
|
+
* 假设验证
|
|
224
|
+
* 工具推荐和合理性说明
|
|
225
|
+
- \`thoughtNumber\`(可选):当前思考编号(可以从初始总数继续增加)
|
|
226
|
+
- \`totalThoughts\`(可选):当前估计所需思考数(可动态调整)
|
|
227
|
+
- \`nextThoughtNeeded\`(可选):是否需要继续思考(即使看似已到终点)
|
|
228
|
+
|
|
229
|
+
**修订和分支参数:**
|
|
230
|
+
- \`isRevision\`(可选):布尔值,表示此思考是否修订了之前的思考
|
|
231
|
+
- \`revisesThought\`(可选):如果 isRevision 为 true,指定要重新考虑的思考编号
|
|
232
|
+
- \`branchFromThought\`(可选):如果创建分支,指定分支起点的思考编号
|
|
233
|
+
- \`branchId\`(可选):当前分支的标识符(如果有)
|
|
234
|
+
- \`needsMoreThoughts\`(可选):如果到达终点但意识到需要更多思考
|
|
235
|
+
|
|
236
|
+
**MCP 工具协调参数:**
|
|
237
|
+
- \`available_mcp_tools\`(可选):可用 MCP 工具名称数组(例如:["mcp-omnisearch", "mcp-turso-cloud"])
|
|
238
|
+
- \`current_step\`(可选):当前步骤推荐,包括:
|
|
239
|
+
* \`step_description\`:需要做什么
|
|
240
|
+
* \`recommended_tools\`:此步骤推荐的工具
|
|
241
|
+
* \`expected_outcome\`:此步骤的预期结果
|
|
242
|
+
* \`next_step_conditions\`:下一步需要考虑的条件
|
|
243
|
+
- \`previous_steps\`(可选):已推荐的步骤
|
|
244
|
+
- \`remaining_steps\`(可选):后续步骤的高级描述
|
|
245
|
+
|
|
246
|
+
**使用流程:**
|
|
247
|
+
1. 从初始估计开始,但准备随时调整
|
|
248
|
+
2. 自由质疑和修订之前的思考
|
|
249
|
+
3. 即使到达"终点"也可以继续添加思考
|
|
250
|
+
4. 表达不确定性,探索替代方案
|
|
251
|
+
5. 标记修订和分支
|
|
252
|
+
6. 生成假设并验证
|
|
253
|
+
7. **考虑可用工具,为当前步骤推荐合适的工具**
|
|
254
|
+
8. **提供工具推荐的清晰合理性说明**
|
|
255
|
+
9. **在适当时建议具体的工具参数**
|
|
256
|
+
10. **考虑每个步骤的替代工具**
|
|
257
|
+
11. **跟踪推荐步骤的进度**
|
|
258
|
+
12. 忽略与当前步骤无关的信息
|
|
259
|
+
13. 重复直到满意
|
|
260
|
+
14. 只在真正完成且得到满意答案时设置 nextThoughtNeeded=false
|
|
261
|
+
15. 提供单一、理想情况下正确的答案作为最终输出
|
|
262
|
+
|
|
263
|
+
## 💡 典型使用示例
|
|
264
|
+
|
|
265
|
+
**示例1:问题诊断(带工具推荐)**
|
|
266
|
+
- Thought 1: "分析系统性能下降的可能原因"
|
|
267
|
+
- current_step: { step_description: "检查系统日志", recommended_tools: ["mcp-log-reader"], expected_outcome: "发现错误模式" }
|
|
268
|
+
- Thought 2: "检查数据库查询性能"
|
|
269
|
+
- current_step: { step_description: "分析慢查询", recommended_tools: ["mcp-db-profiler"], expected_outcome: "识别性能瓶颈" }
|
|
270
|
+
- Thought 3: "发现查询慢,需要进一步分析"(可能需要修订或分支)
|
|
271
|
+
|
|
272
|
+
**示例2:方案设计(带工具协调)**
|
|
273
|
+
- Thought 1: "设计用户登录功能"
|
|
274
|
+
- current_step: { step_description: "设计认证流程", recommended_tools: ["mcp-diagram-tool"], expected_outcome: "流程图" }
|
|
275
|
+
- Thought 2: "考虑安全性要求"
|
|
276
|
+
- Thought 3: "修订:需要添加双因素认证"(revision)
|
|
277
|
+
- current_step: { step_description: "实现2FA", recommended_tools: ["mcp-auth-library"], expected_outcome: "安全登录方案" }
|
|
278
|
+
|
|
279
|
+
**示例3:多方案探索(带工具推荐)**
|
|
280
|
+
- Thought 1: "评估三种架构方案"
|
|
281
|
+
- Branch A: "方案A:微服务架构"
|
|
282
|
+
- current_step: { step_description: "评估微服务方案", recommended_tools: ["mcp-architecture-analyzer"], expected_outcome: "方案A评估报告" }
|
|
283
|
+
- Branch B: "方案B:单体架构"
|
|
284
|
+
- current_step: { step_description: "评估单体方案", recommended_tools: ["mcp-architecture-analyzer"], expected_outcome: "方案B评估报告" }`;
|
|
285
|
+
|
|
286
|
+
export const THINK_AND_PLAN_DESCRIPTION = `📋 **思考规划工具 (Think & Plan)** - 结构化执行导向工具
|
|
287
|
+
|
|
288
|
+
## 🎯 工具定位
|
|
289
|
+
这是一个用于**目标明确、需要执行**的结构化规划工具。强调思考-计划-行动的三元结构,适合将复杂任务分解为可执行步骤并追踪执行过程。
|
|
290
|
+
|
|
291
|
+
## 🔍 场景识别 - 何时使用此工具?
|
|
292
|
+
|
|
293
|
+
**1. 任务执行(目标明确)**
|
|
294
|
+
- ✅ "实现用户登录功能" → 需要具体实现步骤
|
|
295
|
+
- ✅ "部署新版本到生产环境" → 需要执行计划
|
|
296
|
+
- ✅ "完成月度报告" → 需要任务分解
|
|
297
|
+
- ✅ "重构某个模块" → 需要实施步骤
|
|
298
|
+
|
|
299
|
+
**2. 项目管理(需要行动追踪)**
|
|
300
|
+
- 📝 任务分解和步骤规划
|
|
301
|
+
- 📅 项目里程碑规划
|
|
302
|
+
- ✅ 行动项追踪
|
|
303
|
+
- 🎯 目标达成路径
|
|
304
|
+
|
|
305
|
+
**3. 结构化问题(需要明确步骤)**
|
|
306
|
+
- 🔧 流程设计和实施
|
|
307
|
+
- 📊 方案执行计划
|
|
308
|
+
- 🚀 功能开发规划
|
|
309
|
+
- 🔄 系统迁移计划
|
|
310
|
+
|
|
311
|
+
**4. 需要可执行行动的场景**
|
|
312
|
+
- 每个步骤都需要明确的下一步行动
|
|
313
|
+
- 需要调用具体工具或执行具体操作
|
|
314
|
+
- 需要验证和检查点
|
|
315
|
+
|
|
316
|
+
## ✨ 核心特性
|
|
317
|
+
|
|
318
|
+
**1. 三元结构(思考-计划-行动)**
|
|
319
|
+
- 🤔 Thought(思考):分析、假设、洞见
|
|
320
|
+
- 📋 Plan(计划):分解为可执行步骤
|
|
321
|
+
- 🎯 Action(行动):具体、可执行、可验证的下一步
|
|
322
|
+
|
|
323
|
+
**2. 执行导向**
|
|
324
|
+
- 强制要求 action 字段
|
|
325
|
+
- 每个步骤都有明确的下一步
|
|
326
|
+
- 支持工具调用建议
|
|
327
|
+
|
|
328
|
+
**3. 会话隔离**
|
|
329
|
+
- 支持 sessionId 区分不同会话
|
|
330
|
+
- 多任务并行管理
|
|
331
|
+
- 独立记录和追踪
|
|
332
|
+
|
|
333
|
+
**4. 结构化强**
|
|
334
|
+
- 固定结构,使用简单
|
|
335
|
+
- 便于复盘和优化
|
|
336
|
+
- 适合团队协作
|
|
337
|
+
|
|
338
|
+
## 📋 使用指南
|
|
339
|
+
|
|
340
|
+
**参数说明:**
|
|
341
|
+
- thought(必需):当前思考内容,分析、假设、洞见、反思
|
|
342
|
+
- plan(必需):针对当前任务的计划或方案,分解为可执行步骤
|
|
343
|
+
- action(必需):下一步行动,必须具体、可执行、可验证,可以是工具调用
|
|
344
|
+
- thoughtNumber(必需):思考步骤编号,用于追踪和回溯
|
|
345
|
+
- sessionId(可选):会话标识符,默认为 'default'
|
|
346
|
+
|
|
347
|
+
**使用流程:**
|
|
348
|
+
1. 明确任务目标
|
|
349
|
+
2. 思考当前步骤的核心问题
|
|
350
|
+
3. 制定具体的执行计划
|
|
351
|
+
4. 定义明确的下一步行动(可包含工具调用)
|
|
352
|
+
5. 按编号顺序记录每个步骤
|
|
353
|
+
6. 完成后可获取摘要和回顾
|
|
354
|
+
|
|
355
|
+
## 💡 典型使用示例
|
|
356
|
+
|
|
357
|
+
**示例1:功能开发**
|
|
358
|
+
- Thought: "需要实现用户登录功能,考虑安全性和用户体验"
|
|
359
|
+
- Plan: "1. 设计登录接口 2. 实现密码加密 3. 添加验证码 4. 编写测试"
|
|
360
|
+
- Action: "调用代码生成工具创建登录接口框架"
|
|
361
|
+
|
|
362
|
+
**示例2:部署任务**
|
|
363
|
+
- Thought: "需要将新版本安全部署到生产环境"
|
|
364
|
+
- Plan: "1. 备份当前版本 2. 执行数据库迁移 3. 部署新代码 4. 验证功能"
|
|
365
|
+
- Action: "执行备份脚本,检查备份是否成功"
|
|
366
|
+
|
|
367
|
+
**示例3:报告编写**
|
|
368
|
+
- Thought: "需要完成月度业务分析报告"
|
|
369
|
+
- Plan: "1. 收集数据 2. 分析趋势 3. 编写报告 4. 审核发布"
|
|
370
|
+
- Action: "调用数据分析工具提取本月业务数据"
|
|
371
|
+
`;
|
|
372
|
+
|
|
373
|
+
const descriptionMap = {
|
|
374
|
+
exploratory: SEQUENTIAL_THINKING_DESCRIPTION,
|
|
375
|
+
execution: THINK_AND_PLAN_DESCRIPTION
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
function getScenarioDescription(scenario) {
|
|
379
|
+
return descriptionMap[scenario] || '';
|
|
380
|
+
}
|
|
@@ -2,15 +2,34 @@
|
|
|
2
2
|
"name": "@becrafter/prompt-manager-core",
|
|
3
3
|
"version": "0.0.24",
|
|
4
4
|
"description": "Core library for managing prompts with MCP protocol",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "index.js",
|
|
6
6
|
"module": "index.js",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "esbuild ./index.js --bundle --outdir=dist --format=esm --platform=node --target=node18",
|
|
10
10
|
"dev": "node --watch ./server.js",
|
|
11
|
+
"dev:clean": "node ./dev-server.js",
|
|
12
|
+
"fix:pty": "npm rebuild node-pty",
|
|
11
13
|
"start": "node ./server.js",
|
|
12
14
|
"example": "node --experimental-specifier-resolution=node ./example.js",
|
|
13
|
-
"test": "
|
|
15
|
+
"test": "vitest run tests/unit",
|
|
16
|
+
"test:watch": "vitest tests/unit",
|
|
17
|
+
"test:coverage": "vitest --coverage tests/unit",
|
|
18
|
+
"test:integration": "vitest run tests/integration",
|
|
19
|
+
"lint": "eslint . --ext .js,.mjs --fix",
|
|
20
|
+
"format": "prettier --write .",
|
|
21
|
+
"lint:check": "eslint . --ext .js,.mjs",
|
|
22
|
+
"format:check": "prettier --check .",
|
|
23
|
+
"docs": "jsdoc -c jsdoc.conf.json"
|
|
24
|
+
},
|
|
25
|
+
"lint-staged": {
|
|
26
|
+
"*.js": [
|
|
27
|
+
"eslint --fix",
|
|
28
|
+
"prettier --write"
|
|
29
|
+
],
|
|
30
|
+
"*.{json,md,yml,yaml}": [
|
|
31
|
+
"prettier --write"
|
|
32
|
+
]
|
|
14
33
|
},
|
|
15
34
|
"keywords": [
|
|
16
35
|
"mcp",
|
|
@@ -25,17 +44,30 @@
|
|
|
25
44
|
"@electron/asar": "^4.0.1",
|
|
26
45
|
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
27
46
|
"@npmcli/arborist": "^9.0.0",
|
|
47
|
+
"adm-zip": "^0.5.16",
|
|
28
48
|
"cors": "^2.8.5",
|
|
29
49
|
"dotenv": "^17.2.3",
|
|
30
50
|
"express": "^5.1.0",
|
|
31
51
|
"fs-extra": "^11.2.0",
|
|
32
52
|
"http-proxy-middleware": "^3.0.5",
|
|
33
53
|
"js-yaml": "^4.1.0",
|
|
54
|
+
"multer": "^2.0.2",
|
|
55
|
+
"ws": "^8.18.0",
|
|
34
56
|
"yaml": "^2.4.1",
|
|
35
57
|
"zod": "^3.23.8"
|
|
36
58
|
},
|
|
37
59
|
"devDependencies": {
|
|
38
|
-
"
|
|
60
|
+
"@electron/rebuild": "^4.0.2",
|
|
61
|
+
"@playwright/test": "^1.48.0",
|
|
62
|
+
"@vitest/ui": "^1.6.0",
|
|
63
|
+
"esbuild": "^0.27.0",
|
|
64
|
+
"eslint": "^8.57.1",
|
|
65
|
+
"husky": "^9.1.6",
|
|
66
|
+
"jsdoc": "^4.0.3",
|
|
67
|
+
"lint-staged": "^15.2.10",
|
|
68
|
+
"playwright": "^1.48.0",
|
|
69
|
+
"prettier": "^3.3.3",
|
|
70
|
+
"vitest": "^1.6.0"
|
|
39
71
|
},
|
|
40
72
|
"publishConfig": {
|
|
41
73
|
"access": "public"
|
|
@@ -5,6 +5,8 @@ import { logger } from './utils/logger.js';
|
|
|
5
5
|
import { util } from './utils/util.js';
|
|
6
6
|
import { syncSystemTools } from './toolm/tool-sync.service.js';
|
|
7
7
|
import { startLogCleanupTask } from './toolm/tool-logger.service.js';
|
|
8
|
+
import { webSocketService } from './services/WebSocketService.js';
|
|
9
|
+
import { checkPortAvailable, findAvailablePort } from './utils/port-checker.js';
|
|
8
10
|
|
|
9
11
|
// 动态导入 promptManager,以处理 Electron 打包后的路径问题
|
|
10
12
|
let promptManager;
|
|
@@ -27,8 +29,39 @@ export function getServerAddress() {
|
|
|
27
29
|
return `http://127.0.0.1:${config.getPort()}`;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
export function isServerRunning() {
|
|
31
|
-
|
|
32
|
+
export async function isServerRunning() {
|
|
33
|
+
if (!serverInstance) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 实际验证服务器是否在监听
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
import('http').then(http => {
|
|
40
|
+
// 设置超时以避免长时间等待
|
|
41
|
+
const req = http.request({
|
|
42
|
+
hostname: 'localhost',
|
|
43
|
+
port: config.getPort(),
|
|
44
|
+
path: '/health',
|
|
45
|
+
method: 'GET',
|
|
46
|
+
timeout: 2000
|
|
47
|
+
}, (res) => {
|
|
48
|
+
resolve(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
req.on('error', () => {
|
|
52
|
+
resolve(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
req.on('timeout', () => {
|
|
56
|
+
req.destroy();
|
|
57
|
+
resolve(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
req.end();
|
|
61
|
+
}).catch(() => {
|
|
62
|
+
resolve(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
32
65
|
}
|
|
33
66
|
|
|
34
67
|
// 封装配置处理逻辑
|
|
@@ -51,8 +84,36 @@ export async function startServer(options = {}) {
|
|
|
51
84
|
serverStartingPromise = (async () => {
|
|
52
85
|
try {
|
|
53
86
|
await _handleConfig(options);
|
|
87
|
+
|
|
88
|
+
// 检查端口可用性
|
|
89
|
+
const port = config.getPort();
|
|
90
|
+
const isPortAvailable = await checkPortAvailable(port);
|
|
91
|
+
|
|
92
|
+
if (!isPortAvailable) {
|
|
93
|
+
const errorMsg = `端口 ${port} 已被占用,请检查是否有其他服务在使用该端口,或手动指定其他端口`;
|
|
94
|
+
logger.error(errorMsg);
|
|
95
|
+
throw new Error(errorMsg);
|
|
96
|
+
}
|
|
97
|
+
|
|
54
98
|
await promptManager.loadPrompts();
|
|
55
99
|
|
|
100
|
+
// 加载优化模板和模型
|
|
101
|
+
try {
|
|
102
|
+
const { templateManager } = await import('./services/template.service.js');
|
|
103
|
+
await templateManager.loadTemplates();
|
|
104
|
+
logger.info('优化模板加载完成');
|
|
105
|
+
} catch (error) {
|
|
106
|
+
logger.warn('加载优化模板失败,继续启动服务', { error: error.message });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const { modelManager } = await import('./services/model.service.js');
|
|
111
|
+
await modelManager.loadModels();
|
|
112
|
+
logger.info('优化模型加载完成');
|
|
113
|
+
} catch (error) {
|
|
114
|
+
logger.warn('加载优化模型失败,继续启动服务', { error: error.message });
|
|
115
|
+
}
|
|
116
|
+
|
|
56
117
|
// 同步系统工具到沙箱环境
|
|
57
118
|
try {
|
|
58
119
|
await syncSystemTools();
|
|
@@ -60,28 +121,60 @@ export async function startServer(options = {}) {
|
|
|
60
121
|
logger.error('同步系统工具失败,继续启动服务', { error: error.message });
|
|
61
122
|
}
|
|
62
123
|
|
|
124
|
+
// MCP 长连接可能长时间空闲(IDE 侧保持会话),若沿用 Node 默认超时(requestTimeout 5 分钟、keepAliveTimeout 5 秒、headersTimeout 60 秒)
|
|
125
|
+
// 会导致连接被动关闭。这里将相关超时调高/关闭以避免 IDE 定期断开。
|
|
126
|
+
const MCP_LONG_TIMEOUT = 24 * 60 * 60 * 1000; // 24h
|
|
127
|
+
|
|
63
128
|
// 启动日志清理任务
|
|
64
129
|
startLogCleanupTask();
|
|
65
130
|
|
|
66
131
|
return await new Promise((resolve, reject) => {
|
|
67
|
-
const server = app.listen(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
logger.info(
|
|
71
|
-
|
|
132
|
+
const server = app.listen(port, async () => {
|
|
133
|
+
try {
|
|
134
|
+
// 服务器已经成功启动并监听端口
|
|
135
|
+
logger.info(`MCP服务启动成功 http://localhost:${port}/mcp`);
|
|
136
|
+
if (config.adminEnable) {
|
|
137
|
+
logger.info(`管理员界面可通过 http://localhost:${port}${config.adminPath} 访问`);
|
|
138
|
+
process.stderr.write('\n======================================================================================\n');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 放宽 HTTP 服务器超时,防止 MCP 流式会话被意外回收
|
|
142
|
+
server.keepAliveTimeout = MCP_LONG_TIMEOUT;
|
|
143
|
+
server.headersTimeout = MCP_LONG_TIMEOUT + 1000; // 必须大于 keepAliveTimeout
|
|
144
|
+
server.requestTimeout = 0; // 0 表示关闭 request 超时
|
|
145
|
+
server.setTimeout(0); // 兼容旧接口,关闭 socket 超时
|
|
146
|
+
logger.info(`MCP 长连接超时已放宽: keepAliveTimeout=${server.keepAliveTimeout}ms`);
|
|
147
|
+
|
|
148
|
+
// 设置服务器实例
|
|
149
|
+
serverInstance = server;
|
|
150
|
+
|
|
151
|
+
// 启动WebSocket服务
|
|
152
|
+
try {
|
|
153
|
+
await webSocketService.start();
|
|
154
|
+
logger.info(`WebSocket服务启动成功,端口: 5622`);
|
|
155
|
+
} catch (wsError) {
|
|
156
|
+
logger.error('WebSocket服务启动失败:', wsError.message);
|
|
157
|
+
// WebSocket服务失败不影响主服务器运行
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
resolve(server);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
logger.error('服务器启动后处理失败:', error.message);
|
|
163
|
+
server.close();
|
|
164
|
+
reject(error);
|
|
72
165
|
}
|
|
73
|
-
// 保存服务器实例引用,以便后续可以关闭它
|
|
74
|
-
serverInstance = server;
|
|
75
|
-
resolve(server);
|
|
76
166
|
});
|
|
77
167
|
|
|
78
168
|
server.on('error', (err) => {
|
|
79
169
|
logger.error('服务器启动失败:', err.message);
|
|
170
|
+
if (err.code === 'EADDRINUSE') {
|
|
171
|
+
logger.error(`端口 ${port} 已被占用,请检查是否有其他服务在使用该端口`);
|
|
172
|
+
}
|
|
80
173
|
reject(err);
|
|
81
174
|
});
|
|
82
175
|
});
|
|
83
176
|
} catch (error) {
|
|
84
|
-
logger.error('
|
|
177
|
+
logger.error('服务器启动失败:', error.message);
|
|
85
178
|
throw error;
|
|
86
179
|
} finally {
|
|
87
180
|
serverStartingPromise = null;
|
|
@@ -94,7 +187,8 @@ export async function startServer(options = {}) {
|
|
|
94
187
|
export async function stopServer() {
|
|
95
188
|
if (serverStartingPromise) {
|
|
96
189
|
try {
|
|
97
|
-
|
|
190
|
+
// 等待启动流程结束,避免中途关闭导致的资源悬挂
|
|
191
|
+
await serverStartingPromise;
|
|
98
192
|
} catch (error) {
|
|
99
193
|
// ignore failing start when stopping
|
|
100
194
|
}
|
|
@@ -114,6 +208,14 @@ export async function stopServer() {
|
|
|
114
208
|
logger.warn('清理MCP会话时出错:', error.message);
|
|
115
209
|
}
|
|
116
210
|
|
|
211
|
+
// 关闭WebSocket服务
|
|
212
|
+
try {
|
|
213
|
+
await webSocketService.stop();
|
|
214
|
+
logger.info('WebSocket服务已关闭');
|
|
215
|
+
} catch (error) {
|
|
216
|
+
logger.warn('关闭WebSocket服务时出错:', error.message);
|
|
217
|
+
}
|
|
218
|
+
|
|
117
219
|
await new Promise((resolve, reject) => {
|
|
118
220
|
serverInstance.close((err) => {
|
|
119
221
|
if (err) {
|