speccore 5.25.2 → 5.26.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.
Files changed (62) hide show
  1. package/README.md +93 -77
  2. package/dist/cli.js +123 -45
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/ask.d.ts +4 -5
  5. package/dist/commands/ask.d.ts.map +1 -1
  6. package/dist/commands/ask.js +257 -292
  7. package/dist/commands/ask.js.map +1 -1
  8. package/dist/commands/dashboard.d.ts +12 -0
  9. package/dist/commands/dashboard.d.ts.map +1 -1
  10. package/dist/commands/dashboard.js +442 -77
  11. package/dist/commands/dashboard.js.map +1 -1
  12. package/dist/commands/dev.d.ts +2 -0
  13. package/dist/commands/dev.d.ts.map +1 -1
  14. package/dist/commands/dev.js +282 -290
  15. package/dist/commands/dev.js.map +1 -1
  16. package/dist/commands/doc2spec.d.ts +2 -0
  17. package/dist/commands/doc2spec.d.ts.map +1 -1
  18. package/dist/commands/doc2spec.js +22 -6
  19. package/dist/commands/doc2spec.js.map +1 -1
  20. package/dist/commands/help.d.ts.map +1 -1
  21. package/dist/commands/help.js +39 -0
  22. package/dist/commands/help.js.map +1 -1
  23. package/dist/commands/init.js +15 -5
  24. package/dist/commands/init.js.map +1 -1
  25. package/dist/commands/spec2doc.d.ts +11 -0
  26. package/dist/commands/spec2doc.d.ts.map +1 -0
  27. package/dist/commands/spec2doc.js +183 -0
  28. package/dist/commands/spec2doc.js.map +1 -0
  29. package/dist/commands/status-panel.d.ts +1 -0
  30. package/dist/commands/status-panel.d.ts.map +1 -1
  31. package/dist/commands/status-panel.js +97 -3
  32. package/dist/commands/status-panel.js.map +1 -1
  33. package/dist/commands/welcome.d.ts +10 -0
  34. package/dist/commands/welcome.d.ts.map +1 -1
  35. package/dist/commands/welcome.js +77 -30
  36. package/dist/commands/welcome.js.map +1 -1
  37. package/dist/core/ask-engine.d.ts +45 -0
  38. package/dist/core/ask-engine.d.ts.map +1 -0
  39. package/dist/core/ask-engine.js +405 -0
  40. package/dist/core/ask-engine.js.map +1 -0
  41. package/dist/core/ask-host-ai.d.ts +33 -0
  42. package/dist/core/ask-host-ai.d.ts.map +1 -0
  43. package/dist/core/ask-host-ai.js +156 -0
  44. package/dist/core/ask-host-ai.js.map +1 -0
  45. package/dist/core/ask-llm.d.ts +12 -0
  46. package/dist/core/ask-llm.d.ts.map +1 -0
  47. package/dist/core/ask-llm.js +166 -0
  48. package/dist/core/ask-llm.js.map +1 -0
  49. package/dist/core/dev-llm.d.ts +34 -0
  50. package/dist/core/dev-llm.d.ts.map +1 -0
  51. package/dist/core/dev-llm.js +209 -0
  52. package/dist/core/dev-llm.js.map +1 -0
  53. package/dist/core/help-panel.d.ts +1 -1
  54. package/dist/core/help-panel.d.ts.map +1 -1
  55. package/dist/core/help-panel.js +6 -5
  56. package/dist/core/help-panel.js.map +1 -1
  57. package/dist/core/intent-recognition.js +3 -3
  58. package/dist/core/intent-recognition.js.map +1 -1
  59. package/dist/utils/logger.d.ts.map +1 -1
  60. package/dist/utils/logger.js +5 -2
  61. package/dist/utils/logger.js.map +1 -1
  62. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,WAAW;CAE3B;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEpF"}
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4JH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC5E"}
@@ -1,319 +1,284 @@
1
1
  "use strict";
2
2
  /**
3
- * /ask - 智能入口命令
4
- * 自然语言意图识别引擎,自动匹配最合适的 SpecCore 命令
3
+ * ask 万能智能入口(美化版)
4
+ * 四种模式:命令解释 / 任务指引 / 意图匹配 / 复杂编排
5
+ * 终端输出使用 Unicode 框线 + 颜色码,呈现视觉化预览
5
6
  */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
6
40
  Object.defineProperty(exports, "__esModule", { value: true });
7
41
  exports.askCommand = askCommand;
8
- const intent_recognition_1 = require("../core/intent-recognition");
9
- const intent_ai_1 = require("../core/intent-ai");
10
42
  const logger_1 = require("../utils/logger");
11
- const context_1 = require("../core/context");
43
+ const ask_engine_1 = require("../core/ask-engine");
44
+ const COLORS = {
45
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
46
+ cyan: '\x1b[36m', green: '\x1b[32m', yellow: '\x1b[33m',
47
+ red: '\x1b[31m', blue: '\x1b[34m', magenta: '\x1b[35m',
48
+ gray: '\x1b[90m', bg: '\x1b[48;5;236m', border: '\x1b[38;5;39m',
49
+ };
50
+ const BOX = {
51
+ tl: '╭', tr: '╮', bl: '╰', br: '╯',
52
+ h: '─', v: '│', tee: '├', cross: '┼',
53
+ arrow: '→', down: '↓', up: '↑', branch: '├─', end: '└─',
54
+ bar: '│', thick: '┃', dashed: '╴',
55
+ };
56
+ function box(width, content) {
57
+ const lines = [];
58
+ const top = `${COLORS.border}${BOX.tl}${BOX.h.repeat(width - 2)}${BOX.tr}${COLORS.reset}`;
59
+ const bot = `${COLORS.border}${BOX.bl}${BOX.h.repeat(width - 2)}${BOX.br}${COLORS.reset}`;
60
+ lines.push(top);
61
+ for (const line of content) {
62
+ // 计算实际长度(去掉 ANSI 颜色码)
63
+ const clean = line.replace(/\x1b\[[0-9;]*m/g, '');
64
+ const pad = Math.max(0, width - 2 - clean.length);
65
+ lines.push(`${COLORS.border}${BOX.v}${COLORS.reset}${line}${' '.repeat(pad)}${COLORS.border}${BOX.v}${COLORS.reset}`);
66
+ }
67
+ lines.push(bot);
68
+ return lines.join('\n');
69
+ }
70
+ function section(title, body, width = 60) {
71
+ const lines = [];
72
+ lines.push(`${COLORS.cyan}${BOX.tl}${'─'.repeat(2)} ${title} ${'─'.repeat(width - 5 - title.length)}${BOX.tr}${COLORS.reset}`);
73
+ for (const line of body) {
74
+ lines.push(`${COLORS.cyan}${BOX.v}${COLORS.reset} ${line}`);
75
+ }
76
+ lines.push(`${COLORS.cyan}${BOX.bl}${'─'.repeat(width - 2)}${BOX.br}${COLORS.reset}`);
77
+ return lines.join('\n');
78
+ }
79
+ function header(title, subtitle) {
80
+ return [
81
+ '',
82
+ `${COLORS.cyan}${BOX.tl}━${'━'.repeat(56)}━${BOX.tr}${COLORS.reset}`,
83
+ `${COLORS.cyan}${BOX.v}${COLORS.reset} ${COLORS.bold}${COLORS.cyan}${title.padEnd(56)}${COLORS.reset}${COLORS.cyan}${BOX.v}${COLORS.reset}`,
84
+ `${COLORS.cyan}${BOX.v}${COLORS.reset} ${COLORS.gray}${subtitle.padEnd(56)}${COLORS.reset}${COLORS.cyan}${BOX.v}${COLORS.reset}`,
85
+ `${COLORS.cyan}${BOX.bl}━${'━'.repeat(56)}━${BOX.br}${COLORS.reset}`,
86
+ ].join('\n');
87
+ }
88
+ function modeBadge(mode) {
89
+ const map = {
90
+ explain: { emoji: '📖', color: COLORS.cyan },
91
+ guide: { emoji: '🗺️', color: COLORS.yellow },
92
+ match: { emoji: '🎯', color: COLORS.green },
93
+ pipeline: { emoji: '⚡', color: COLORS.magenta },
94
+ };
95
+ const info = map[mode] || { emoji: '🔍', color: COLORS.gray };
96
+ return `${info.color}${info.emoji} ${mode.toUpperCase()}${COLORS.reset}`;
97
+ }
98
+ function renderExplain(result) {
99
+ const lines = [];
100
+ const [name, ...rest] = result.detail.split('\n');
101
+ lines.push(section(`📖 命令详解: ${name.replace('📖', '').trim()}`, rest.slice(0, rest.length - 1)));
102
+ return lines.join('\n');
103
+ }
104
+ function renderGuide(result) {
105
+ const lines = [];
106
+ lines.push(section('🗺️ 任务指引', [
107
+ `${COLORS.bold}${result.summary}${COLORS.reset}`,
108
+ '',
109
+ ...result.detail.split('\n').slice(1),
110
+ ]));
111
+ return lines.join('\n');
112
+ }
113
+ function renderMatch(result) {
114
+ const lines = [];
115
+ lines.push(section('🎯 意图匹配', [
116
+ `${COLORS.bold}${result.summary}${COLORS.reset}`,
117
+ '',
118
+ ...result.detail.split('\n').slice(1),
119
+ ]));
120
+ return lines.join('\n');
121
+ }
122
+ function renderPipeline(result, plan) {
123
+ const lines = [];
124
+ lines.push(header('⚡ 多步执行计划', `来源: "${plan.input}"`));
125
+ lines.push('');
126
+ // 流程拓扑
127
+ const steps = plan.steps;
128
+ const stepWidth = 22;
129
+ const flowTop = steps.map((_, i) => `${COLORS.magenta}${'─'.repeat(stepWidth - 6)}▶${COLORS.reset}`).join(`${COLORS.gray}┐${COLORS.reset}\n${COLORS.gray}│${COLORS.reset}\n${COLORS.gray}┘${COLORS.reset}\n${COLORS.gray}│${COLORS.reset}\n`);
130
+ // 简单版:横向并排流程
131
+ const cols = steps.map((s, i) => {
132
+ const num = `${COLORS.cyan}${COLORS.bold}${s.order}.${COLORS.reset}`;
133
+ const cmd = `${COLORS.cyan}${s.command}${COLORS.reset}`;
134
+ return [
135
+ `${num} ${COLORS.bold}${cmd}${COLORS.reset}`,
136
+ `${COLORS.gray}${(s.args || '').slice(0, stepWidth - 2)}${COLORS.reset}`,
137
+ ];
138
+ });
139
+ // 渲染两行
140
+ const row1 = steps.map((s, i) => {
141
+ const n = `${COLORS.cyan}${COLORS.bold}#${s.order}${COLORS.reset}`;
142
+ return `${n} ${COLORS.bold}${s.command}${COLORS.reset}` + ' '.repeat(Math.max(0, 18 - s.command.length - 3));
143
+ }).join(`${COLORS.gray} ▶ ${COLORS.reset}`);
144
+ const row2 = steps.map((s, i) => {
145
+ return `${COLORS.gray}${(s.args || '').padEnd(18).slice(0, 18)}${COLORS.reset}`;
146
+ }).join(' '.repeat(4));
147
+ // 流程卡片:先输出所有顶部,再 body,再箭头
148
+ const topBorder = steps.map(() => `${COLORS.cyan} ${BOX.tl}${'─'.repeat(20)}${BOX.tr}${COLORS.reset}`).join(` ${COLORS.gray}───────${COLORS.reset} `);
149
+ lines.push(topBorder);
150
+ const line1 = steps.map(s => `${COLORS.cyan} ${BOX.v}${COLORS.reset} ${COLORS.bold}#${s.order} ${(s.command + ' ').slice(0, 12)}${COLORS.reset}${COLORS.cyan} ${BOX.v}${COLORS.reset}`).join(` ${COLORS.gray}───────${COLORS.reset} `);
151
+ const line2 = steps.map(s => `${COLORS.cyan} ${BOX.v}${COLORS.reset} ${COLORS.gray}${(s.args || '').padEnd(14).slice(0, 14)}${COLORS.reset}${COLORS.cyan} ${BOX.v}${COLORS.reset}`).join(` ${COLORS.gray}───────${COLORS.reset} `);
152
+ const bottomBorder = steps.map(() => `${COLORS.cyan} ${BOX.bl}${'─'.repeat(20)}${BOX.br}${COLORS.reset}`).join(` ${COLORS.gray}───────${COLORS.reset} `);
153
+ lines.push(line1);
154
+ lines.push(line2);
155
+ lines.push(bottomBorder);
156
+ // 箭头
157
+ const arrows = steps.map((_, i) => i < steps.length - 1 ? ` ${COLORS.magenta}▼${COLORS.reset}` : ' ').join(` `);
158
+ lines.push(arrows);
159
+ lines.push('');
160
+ lines.push('');
161
+ // 详细步骤
162
+ lines.push(section('📋 详细步骤', [
163
+ ...steps.map(s => {
164
+ const dep = s.dependsOn ? ` ${COLORS.gray}← 依赖 #${s.dependsOn}${COLORS.reset}` : '';
165
+ return `${COLORS.cyan} #${s.order}${COLORS.reset} ${COLORS.bold}${COLORS.green}speccore ${s.command}${COLORS.reset} ${COLORS.yellow}${s.args || ''}${COLORS.reset}${dep}`;
166
+ }),
167
+ '',
168
+ `${COLORS.gray} ── 解析说明 ──${COLORS.reset}`,
169
+ ...steps.map(s => ` ${COLORS.gray}#${s.order}: ${s.explanation}${COLORS.reset}`),
170
+ ]));
171
+ lines.push('');
172
+ // 确认按钮
173
+ lines.push(`${COLORS.magenta}${'═'.repeat(58)}${COLORS.reset}`);
174
+ lines.push(`${COLORS.magenta} ⚠️ 请确认后执行。输入 ${COLORS.bold}y${COLORS.reset}${COLORS.magenta} 确认,或 ${COLORS.bold}n${COLORS.reset}${COLORS.magenta} 取消${COLORS.reset}`);
175
+ lines.push(`${COLORS.magenta}${'═'.repeat(58)}${COLORS.reset}`);
176
+ return lines.join('\n');
177
+ }
12
178
  async function askCommand(input, _options) {
179
+ // 如果不是 TTY(AI 调用),输出 HTML 页面
180
+ if (!process.stdout.isTTY) {
181
+ await askHtml(input);
182
+ return;
183
+ }
13
184
  if (!input || !input.trim()) {
14
- logger_1.logger.info('🔍 SpecCore 智能入口');
185
+ logger_1.logger.info('🔍 SpecCore 万能 AI 入口');
15
186
  logger_1.logger.info('');
16
- logger_1.logger.info('用法: speccore ask "<自然语言描述>"');
187
+ logger_1.logger.info('用法: speccore ask "<自然语言>"');
17
188
  logger_1.logger.info('');
18
- logger_1.logger.info('示例:');
19
- logger_1.logger.info(' speccore ask "做一个用户登录功能,支持手机号+密码"');
20
- logger_1.logger.info(' speccore ask "修复登录超时问题"');
21
- logger_1.logger.info(' speccore ask "查看进度"');
22
- logger_1.logger.info(' speccore ask "开始干活"');
23
- logger_1.logger.info(' speccore ask "把登录改成验证码登录"');
24
- logger_1.logger.info(' speccore ask "审查一下"');
189
+ logger_1.logger.info('四种模式自动识别:');
190
+ logger_1.logger.info(' 📖 命令解释: speccore ask "dashboard 怎么用"');
191
+ logger_1.logger.info(' 🗺️ 任务指引: speccore ask "我想做一个登录功能"');
192
+ logger_1.logger.info(' 🎯 意图匹配: speccore ask "查看项目进度"');
193
+ logger_1.logger.info(' ⚡ 复杂编排: speccore ask "计划所有任务,晚8点分批执行"');
25
194
  return;
26
195
  }
27
- logger_1.logger.info(`🔍 正在理解你的意图...`);
28
- logger_1.logger.info('');
29
- const iteration = await (0, context_1.getDefaultIteration)();
30
- const assignee = await (0, context_1.getDefaultAssignee)();
31
- let results = [];
196
+ logger_1.logger.info(`🔍 正在分析: "${input}"`);
32
197
  try {
33
- results = await (0, intent_recognition_1.recognizeIntent)(input);
198
+ const result = await (0, ask_engine_1.askEngine)(input);
199
+ logger_1.logger.info('');
200
+ logger_1.logger.info(`${modeBadge(result.mode)}`);
201
+ logger_1.logger.info('');
202
+ if (result.mode === 'pipeline' && result.pipeline) {
203
+ logger_1.logger.info(renderPipeline(result, result.pipeline));
204
+ }
205
+ else if (result.mode === 'explain') {
206
+ logger_1.logger.info(renderExplain(result));
207
+ }
208
+ else if (result.mode === 'guide') {
209
+ logger_1.logger.info(renderGuide(result));
210
+ }
211
+ else {
212
+ logger_1.logger.info(renderMatch(result));
213
+ }
34
214
  }
35
215
  catch (e) {
36
- logger_1.logger.error(`意图识别失败: ${e.message || e}`);
216
+ logger_1.logger.error(`分析失败: ${e.message || e}`);
37
217
  logger_1.logger.info('💡 请使用 speccore help 查看可用命令');
38
- return;
39
- }
40
- // AI 增强:置信度不足时自动调用
41
- if (results.length === 0) {
42
- // 低置信度:无法识别
43
- logger_1.logger.warn('🤔 我没有完全理解你的意图,请补充说明。');
44
- logger_1.logger.info('');
45
- logger_1.logger.info('你可以这样说:');
46
- logger_1.logger.info(' - "查看项目进度"');
47
- logger_1.logger.info(' - "帮我创建一个登录功能"');
48
- logger_1.logger.info(' - "审查一下当前任务"');
49
- logger_1.logger.info(' - "开始开发"');
50
- logger_1.logger.info(' - "把登录改成验证码登录"');
51
- return;
52
- }
53
- let aiBest = null;
54
- try {
55
- const aiResult = await (0, intent_ai_1.recognizeWithAi)(input, results);
56
- aiBest = aiResult.final;
57
- }
58
- catch { /* AI 增强失败,使用规则匹配 */ }
59
- const best = aiBest || results[0];
60
- const level = (0, intent_recognition_1.getConfidenceLevel)(best.confidence);
61
- // 显示上下文信息
62
- if (iteration) {
63
- logger_1.logger.info(`📍 当前期次: ${iteration}`);
64
- }
65
- if (assignee && assignee !== 'unknown') {
66
- logger_1.logger.info(`👤 当前用户: ${assignee}`);
67
- }
68
- logger_1.logger.info('');
69
- if (level === 'high') {
70
- // 高置信度 (>=80%):展示预览
71
- await showHighConfidenceResult(best, iteration);
72
- }
73
- else if (level === 'medium') {
74
- // 中置信度 (50-80%):展示候选列表
75
- showMediumConfidenceResults(results.slice(0, 3), iteration);
76
- }
77
- else {
78
- // 低置信度 (<50%):引导澄清
79
- showLowConfidenceGuidance(results.slice(0, 2), input);
80
218
  }
81
219
  }
82
- async function showHighConfidenceResult(result, iteration) {
83
- // ── 1. 明确告知用户理解了什么 ──
84
- logger_1.logger.info('━'.repeat(55));
85
- logger_1.logger.info(`✅ 我理解了:你想 **${getIntentLabel(result.intent)}**`);
86
- logger_1.logger.info(` 匹配: speccore ${result.command} (置信度 ${result.confidence}%)`);
87
- logger_1.logger.info(''.repeat(55));
88
- logger_1.logger.info('');
89
- const params = result.extractedParams;
90
- // ── 2. 用自然语言重述用户意图 ──
91
- const paraphrase = buildParaphrase(result.intent, result.command, params, iteration);
92
- if (paraphrase) {
93
- logger_1.logger.info(`💬 你是说:${paraphrase}`);
94
- logger_1.logger.info('');
95
- }
96
- // ── 3. 展示将要执行的命令 + 参数说明 ──
97
- logger_1.logger.info('📋 将要执行的命令:');
98
- let cmdPreview = `speccore ${result.command}`;
99
- if (params.name)
100
- cmdPreview += ` -n "${params.name}"`;
101
- if (params.desc)
102
- cmdPreview += ` -d "${params.desc}"`;
103
- if (params.task)
104
- cmdPreview += ` -t "${params.task}"`;
105
- if (iteration && !params.iteration)
106
- cmdPreview += ` -i "${iteration}"`;
107
- if (params.iteration)
108
- cmdPreview += ` -i "${params.iteration}"`;
109
- logger_1.logger.info(` $ ${cmdPreview}`);
110
- logger_1.logger.info('');
111
- // ── 4. 展示后续步骤(如果有关联流程)─
112
- const nextSteps = getNextStepsForIntent(result.intent, result.command, params, iteration);
113
- if (nextSteps.length > 0) {
114
- logger_1.logger.info('📌 建议的完整流程:');
115
- let stepNum = 1;
116
- for (const step of nextSteps) {
117
- logger_1.logger.info(` ${stepNum}. ${step}`);
118
- stepNum++;
119
- }
120
- logger_1.logger.info('');
121
- }
122
- // ── 5. 提示可以马上执行 ──
123
- logger_1.logger.info('💡 直接运行上述命令即可开始,或输入更多细节调整参数。');
220
+ /**
221
+ * AI 模式:生成 HTML 页面(非 TTY 环境自动使用)
222
+ */
223
+ async function askHtml(input) {
224
+ const { askEngine } = await Promise.resolve().then(() => __importStar(require('../core/ask-engine')));
225
+ const result = await askEngine(input || '');
226
+ const html = renderAskHtml(result, input);
227
+ const path = require('path');
228
+ const fs = require('fs');
229
+ const file = path.join(process.cwd(), 'speccore-ask-result.html');
230
+ fs.writeFileSync(file, html);
231
+ logger_1.logger.info(`✅ 已生成: ${file}`);
124
232
  }
125
- function showMediumConfidenceResults(results, iteration) {
126
- logger_1.logger.info('🔍 你的输入可能有以下含义,请选择:');
127
- logger_1.logger.info('');
128
- // ── 命令→详细步骤映射 ──
129
- const stepMap = {
130
- init: ['1. speccore init # 初始化项目,生成 .speccore/'],
131
- 'iteration create': [
132
- '1. speccore iteration create -n Q1 --owner=张三 # 创建期次',
133
- '2. speccore analyze -I Q1 # AI 分析需求',
134
- '3. speccore iteration split -i Q1 --interactive # 智能拆分',
135
- ],
136
- 'task new': [
137
- '1. speccore task new -n "功能名" # 创建开发任务',
138
- '2. speccore analyze -t Task-001 # AI 分析需求',
139
- '3. speccore execute -t Task-001 --force # 执行开发',
140
- ],
141
- analyze: [
142
- '1. speccore analyze -I Q1 # 期次分析',
143
- '2. speccore analyze --scope global --src xxx,xxx # 全局分析',
144
- '3. speccore analyze --scope global --src xxx --depth deep # 深度分析',
145
- ],
146
- execute: [
147
- '1. speccore execute -t Task-001 --force # 直接执行',
148
- '2. speccore execute -i Q1 --all # 执行全部任务',
149
- ],
150
- 'iteration split': [
151
- '1. speccore iteration split -i Q1 --interactive # 交互拆分',
152
- '2. speccore iteration split -i Q1 --strict # 逐项确认',
153
- ],
154
- 'status-panel': [
155
- '1. speccore status-panel # 终端查看',
156
- '2. speccore status-panel --export=html # 导出仪表盘',
157
- ],
158
- pr: [
159
- '1. speccore pr --task=Task-001 # 创建PR',
160
- ],
161
- done: [
162
- '1. speccore done --task=Task-001 # 单任务归档',
163
- '2. speccore done --all -i Q1 # 批量归档',
164
- ],
165
- dev: [
166
- '1. speccore dev # 检测下一步',
167
- '2. speccore dev --auto # 全自动流水线',
168
- ],
169
- };
170
- for (let i = 0; i < results.length; i++) {
171
- const r = results[i];
172
- logger_1.logger.info(` ${i + 1}. ${getIntentLabel(r.intent)} (${r.confidence}%) → speccore ${r.command}`);
173
- const steps = stepMap[r.command];
174
- if (steps)
175
- for (const step of steps)
176
- logger_1.logger.info(` ${step}`);
177
- logger_1.logger.info('');
233
+ function renderAskHtml(result, input) {
234
+ switch (result.mode) {
235
+ case 'explain': return renderExplainHtml(result, input);
236
+ case 'guide': return renderGuideHtml(result, input);
237
+ case 'pipeline': return renderPipelineHtml(result, input);
238
+ default: return renderMatchHtml(result, input);
178
239
  }
179
- logger_1.logger.info('💡 输入序号选择(默认 1),或 q 取消');
180
- // 读取用户选择
181
- const rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
182
- rl.question('> ', async (answer) => {
183
- rl.close();
184
- if (answer === 'q' || answer === 'Q') {
185
- logger_1.logger.info('已取消');
186
- return;
187
- }
188
- const idx = parseInt(answer) - 1;
189
- const selected = (idx >= 0 && idx < results.length) ? results[idx] : results[0];
190
- const params = selected.extractedParams;
191
- let cmd = `speccore ${selected.command}`;
192
- if (params.name)
193
- cmd += ` -n "${params.name}"`;
194
- if (iteration && !params.iteration)
195
- cmd += ` -i "${iteration}"`;
196
- if (params.iteration)
197
- cmd += ` -i "${params.iteration}"`;
198
- logger_1.logger.info(`\n⚡ 执行: ${cmd}\n`);
199
- // 实际执行命令
200
- const { execSync } = require('child_process');
201
- try {
202
- execSync(cmd, { stdio: 'inherit' });
203
- }
204
- catch (e) {
205
- logger_1.logger.warn(` ⚠️ 命令执行失败: ${e.message}`);
206
- }
207
- });
208
240
  }
209
- function showLowConfidenceGuidance(results, input) {
210
- logger_1.logger.warn(`🤔 对"${input}"不太确定,以下是可能的匹配:`);
211
- logger_1.logger.info('');
212
- if (results.length > 0) {
213
- for (let i = 0; i < results.length; i++) {
214
- const r = results[i];
215
- logger_1.logger.info(` ${i + 1}. ${getIntentLabel(r.intent)} → speccore ${r.command}`);
216
- }
217
- logger_1.logger.info('');
241
+ function renderExplainHtml(result, input) {
242
+ const lines = result.detail.split('\n').filter((l) => l.trim());
243
+ let desc = '', usage = '', examples = [], related = '';
244
+ for (const l of lines) {
245
+ if (l.includes('描述:'))
246
+ desc = l.replace(/.*描述:\s*/, '');
247
+ else if (l.includes('用法:'))
248
+ usage = l.replace(/.*用法:\s*/, '');
249
+ else if (l.startsWith('$'))
250
+ examples.push(l.replace('$ ', ''));
251
+ else if (l.includes('关联命令:'))
252
+ related = l.replace(/.*关联命令:\s*/, '');
218
253
  }
219
- // 引导性提问
220
- logger_1.logger.info('你可以换个方式说,比如:');
221
- logger_1.logger.info(' "我要开始开发了" → 自动匹配 execute');
222
- logger_1.logger.info(' "帮我看看项目进度" → 自动匹配 status-panel');
223
- logger_1.logger.info(' "创建一个用户登录功能" → 自动匹配 task new');
224
- logger_1.logger.info(' "批量导入这些bug" → 自动匹配 bugfix');
225
- logger_1.logger.info(' "把刚才的需求拆成任务" → 自动匹配 iteration split');
226
- logger_1.logger.info('');
227
- logger_1.logger.info('或者直接输入: speccore help 查看所有命令');
254
+ const body = `<div class="explain-box"><div class="explain-desc">${desc}</div><div class="explain-usage"><span class="label">用法</span><code>${usage}</code></div>${examples.length > 0 ? `<div class="explain-examples"><span class="label">示例</span>${examples.map(e => `<code>${e}</code>`).join('')}</div>` : ''}${related ? `<div class="explain-related"><span class="label">关联</span>${related.split(',').map((r) => `<span class="tag">${r.trim()}</span>`).join(' ')}</div>` : ''}</div>`;
255
+ return buildPage('📖 命令解释', body, input, '#14b8a6');
228
256
  }
229
- function getIntentLabel(intent) {
230
- const labels = {
231
- change: '🔄 需求变更',
232
- execute: ' 执行开发',
233
- create: '✨ 创建功能/任务',
234
- iteration_create: '📅 创建期次',
235
- analyze: '🧠 AI 需求分析',
236
- split: '📦 智能拆分',
237
- pr: '🔀 提交PR',
238
- done: '✅ 完成任务',
239
- bugfix: '🐛 Bug 修复',
240
- review: '✅ 审查产出',
241
- plan: '📐 智能调度',
242
- reference: '📚 查找参考',
243
- archive: '📦 归档任务',
244
- query_progress: '📊 查看进度',
245
- handover: '📤 生成交接文档',
246
- health: '🏥 查看健康度',
247
- config: '⚙️ 配置管理',
248
- help: '📖 查看帮助',
249
- demo: '🎮 快速体验',
250
- welcome: '👋 新手引导',
251
- init: '🏗️ 项目初始化',
252
- import: '📥 导入项目',
253
- research: '🔬 技术调研',
254
- sync: '🔄 反向同步',
255
- retro: '📝 期次回顾',
256
- template_add: '📄 添加模板',
257
- };
258
- return labels[intent] || intent;
257
+ function renderGuideHtml(result, input) {
258
+ const steps = result.pipeline?.steps || [];
259
+ const body = `<div class="guide-title">${result.summary}</div><div class="guide-steps">${steps.map((s) => `<div class="guide-step"><div class="step-num">${s.order}</div><div class="step-body"><div class="step-cmd">speccore ${s.command}${s.args ? ' ' + s.args : ''}</div><div class="step-desc">${s.explanation}</div></div></div>`).join('')}</div>`;
260
+ return buildPage('🗺️ 任务指引', body, input, '#f97316');
259
261
  }
260
- // ── 自然语言重述 ──
261
- function buildParaphrase(intent, cmd, params, iteration) {
262
- const name = params.name || '';
263
- const desc = params.desc || '';
264
- const task = params.task || '';
265
- const templates = {
266
- 'task new': (p) => `创建一个新任务"${p.name || ''}"${p.desc ? ',描述:' + p.desc : ''}`,
267
- 'iteration create': (p) => `创建一个新期次"${p.name || ''}"`,
268
- execute: (p) => p.task ? `执行任务 "${p.task}"` : '执行开发任务',
269
- bugfix: (p) => p.name ? `修复 Bug:"${p.name}"` : p.desc ? `修复问题:${p.desc}` : '修复一个 Bug',
270
- change: (p) => p.desc ? `把需求改为:${p.desc}` : '',
271
- import: () => '导入一个存量项目',
272
- 'iteration split': () => '把当前需求拆分成开发任务',
273
- 'status-panel': () => '查看项目进度和状态',
274
- pr: (p) => p.task ? `为任务 ${p.task} 创建 Pull Request` : '',
275
- done: (p) => p.task ? `完成任务 ${p.task}` : '',
276
- analyze: () => '分析需求文档',
277
- dev: () => '检测项目当前阶段并继续推进',
278
- validate: () => '检查项目规范性',
279
- };
280
- const fn = templates[cmd];
281
- return fn ? fn(params, iteration) : '';
262
+ function renderMatchHtml(result, input) {
263
+ const body = `<div class="match-result"><div class="match-summary">${result.summary}</div><div class="match-detail">${result.detail.replace(/\n/g, '<br>').replace(/speccore\s+(\S+)/g, '<code>$&</code>')}</div></div>`;
264
+ return buildPage('🎯 意图匹配', body, input, '#0ea5e9');
282
265
  }
283
- // ── 关联后续步骤 ──
284
- function getNextStepsForIntent(intent, cmd, params, iteration) {
285
- const iter = iteration || 'Q1';
286
- const task = params.task || 'Task-001';
287
- const flows = {
288
- 'iteration create': [
289
- `speccore doc2spec -f PRD.docx -p backend -i ${iter} # 导入需求文档`,
290
- `speccore analyze -i ${iter} # AI 分析需求`,
291
- `speccore iteration split -i ${iter} # 拆分为 Task`,
292
- ],
293
- 'task new': [
294
- `speccore analyze -t ${task} -i ${iter} --auto # AI 分析`,
295
- `speccore execute -t ${task} --force --verify # 开发 + 验证`,
296
- `speccore pr --task=${task} # 提 PR`,
297
- `speccore done --task=${task} # 完成归档`,
298
- ],
299
- execute: [
300
- `speccore pr -t ${task} # 代码提 PR`,
301
- `speccore done -t ${task} # 标记完成`,
302
- ],
303
- bugfix: [
304
- `speccore execute -t ${task} --force --verify # 修复 + 验证`,
305
- `speccore pr -t ${task} # 提 PR`,
306
- ],
307
- 'iteration split': [
308
- `speccore plan -i ${iter} # 生成执行计划`,
309
- `speccore execute --all --force --verify -i ${iter} # 批量执行`,
310
- ],
311
- import: [
312
- `在 AI IDE 中触发 /spec-import-analyze # AI 反工程分析`,
313
- `speccore analyze -i ${iter} # 完善需求`,
314
- `speccore iteration split -i ${iter} # 拆分为 Task`,
315
- ],
316
- };
317
- return flows[cmd] || [];
266
+ function renderPipelineHtml(result, input) {
267
+ const steps = result.pipeline?.steps || [];
268
+ const body = `<div class="pipeline-title">📋 ${steps.length} 步执行计划</div><div class="pipeline-steps">${steps.map((s) => `<div class="pipe-step"><div class="pipe-num">#${s.order}</div><div class="pipe-body"><div class="pipe-cmd">speccore ${s.command} <span class="pipe-args">${s.args || ''}</span></div><div class="pipe-desc">${s.explanation}</div>${s.dependsOn ? `<div class="pipe-dep">🔗 依赖 #${s.dependsOn}</div>` : ''}</div></div>`).join('')}</div><div class="confirm-bar">⚠️ 确认后执行 · 输入 y / n</div>`;
269
+ return buildPage('⚡ 复杂编排', body, input, '#6366f1');
270
+ }
271
+ function buildPage(title, body, input, accent) {
272
+ const ver = require('../../package.json').version;
273
+ return `<!DOCTYPE html><html lang="zh-CN" data-theme="ocean"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>SpecCore · ${input.slice(0, 20)}</title><style>@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700;900&family=JetBrains+Mono:wght@400;600;700&display=swap');[data-theme="ocean"]{--cyan:#0ea5e9;--bg:#0b1929;--card:rgba(13,31,56,.95);--border:rgba(14,165,233,.15);--text:#bae6fd;--muted:#5b7fa5;--green:#14b8a6;--orange:#f97316;--purple:#6366f1}*{margin:0;padding:0;box-sizing:border-box}body{font-family:'JetBrains Mono',monospace;background:var(--bg);color:var(--text);min-height:100vh;padding:40px 20px}.scanlines{position:fixed;inset:0;pointer-events:none;z-index:99;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,240,255,.01) 2px,rgba(0,240,255,.01) 4px)}.card{max-width:680px;margin:0 auto;background:var(--card);border:1px solid var(--border);border-radius:16px;padding:36px;position:relative;overflow:hidden}.card::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--cyan),transparent);animation:scanX 3s linear infinite}.card::after{content:'';position:absolute;bottom:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--cyan),transparent);animation:scanX-rev 3s linear infinite}@keyframes scanX{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}@keyframes scanX-rev{0%{transform:translateX(100%)}100%{transform:translateX(-100%)}}@keyframes scanY{0%{transform:translateY(-100%)}100%{transform:translateY(100%)}}@keyframes scanY-rev{0%{transform:translateY(100%)}100%{transform:translateY(-100%)}}.vline{position:absolute;top:0;width:1px;bottom:0;pointer-events:none}.vline.l{left:0;background:linear-gradient(180deg,transparent,var(--cyan),transparent);animation:scanY-rev 3s linear infinite}.vline.r{right:0;background:linear-gradient(180deg,transparent,var(--cyan),transparent);animation:scanY 3s linear infinite}h1{font-family:'Orbitron',sans-serif;font-size:24px;font-weight:900;background:linear-gradient(135deg,var(--cyan),var(--purple));-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:2px}.query{color:var(--muted);font-size:12px;margin:8px 0 16px}.badge{display:inline-block;padding:4px 14px;border-radius:20px;font-size:11px;font-weight:600;background:${accent}22;color:${accent};border:1px solid ${accent}44;margin-bottom:20px}code{background:rgba(14,165,233,.1);padding:2px 8px;border-radius:4px;color:var(--cyan);font-size:12px;display:inline-block;margin:4px 4px 4px 0}.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:10px;background:rgba(20,184,166,.1);color:var(--green);margin:2px}
274
+ /* Explain */
275
+ .explain-box{padding:10px 0}.explain-desc{font-size:13px;margin-bottom:16px}.explain-usage,.explain-examples,.explain-related{margin:10px 0}.label{font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:1px;margin-right:8px}
276
+ /* Guide */
277
+ .guide-title{font-weight:600;margin-bottom:16px}.guide-steps{display:flex;flex-direction:column;gap:8px}.guide-step{display:flex;gap:14px;padding:12px 14px;background:rgba(249,115,22,.04);border-left:2px solid var(--orange);border-radius:0 8px 8px 0}.guide-step .step-num{font-family:Orbitron;font-size:20px;font-weight:900;color:var(--orange);min-width:30px}.guide-step .step-cmd{font-weight:600;color:var(--text)}.guide-step .step-desc{color:var(--muted);font-size:10px;margin-top:4px}
278
+ /* Match */
279
+ .match-result{padding:10px 0}.match-summary{font-weight:600;font-size:14px;margin-bottom:12px}.match-detail{color:var(--muted);font-size:12px;line-height:1.6}
280
+ /* Pipeline */
281
+ .pipeline-title{font-weight:600;margin-bottom:16px}.pipeline-steps{display:flex;flex-direction:column;gap:10px}.pipe-step{display:flex;gap:14px;padding:12px 14px;background:rgba(99,102,241,.04);border-left:2px solid var(--purple);border-radius:0 8px 8px 0}.pipe-step .pipe-num{font-family:Orbitron;font-size:20px;font-weight:900;color:var(--purple);min-width:36px}.pipe-step .pipe-cmd{font-weight:600;color:var(--green)}.pipe-step .pipe-args{color:var(--muted);font-size:11px}.pipe-step .pipe-desc{color:var(--muted);font-size:10px;margin-top:4px}.pipe-step .pipe-dep{font-size:9px;color:var(--orange);margin-top:4px}.confirm-bar{text-align:center;padding:14px;margin-top:16px;background:rgba(99,102,241,.08);border:1px dashed rgba(99,102,241,.2);border-radius:8px;color:var(--purple);font-size:12px}
282
+ .footer{text-align:center;color:var(--muted);font-size:10px;margin-top:24px;padding-top:16px;border-top:1px solid rgba(255,255,255,.04)}</style></head><body><div class="scanlines"></div><div class="card"><div class="vline l"></div><div class="vline r"></div><h1>SPECCORE ASK</h1><div class="query">"${input}"</div><div class="badge">${title}</div>${body}<div class="footer">由 SpecCore 驱动 v${ver} · ${new Date().toISOString().split('T')[0]}</div></div></body></html>`;
318
283
  }
319
284
  //# sourceMappingURL=ask.js.map