@nick848/sf-cli 1.0.19 → 1.0.20
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/dist/cli/index.js +111 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +111 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +111 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -229,23 +229,38 @@ ${resource.analysis}`;
|
|
|
229
229
|
lines.push("");
|
|
230
230
|
lines.push(chalk9.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
231
231
|
lines.push("");
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
activeSession.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
|
|
233
|
+
loader.start();
|
|
234
|
+
try {
|
|
235
|
+
activeSession.specItems = await generateSpecItemsWithAI(
|
|
236
|
+
activeSession.refinedRequirement,
|
|
237
|
+
activeSession.context,
|
|
238
|
+
activeSession.bddScenarios,
|
|
239
|
+
activeSession.clarificationQuestions,
|
|
240
|
+
activeSession.referenceResources,
|
|
241
|
+
ctx
|
|
242
|
+
);
|
|
243
|
+
loader.stop();
|
|
244
|
+
} catch {
|
|
245
|
+
loader.stop(chalk9.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840\u89C4\u683C\u62C6\u5206"));
|
|
246
|
+
activeSession.specItems = generateSpecItems(
|
|
247
|
+
activeSession.refinedRequirement,
|
|
248
|
+
activeSession.context,
|
|
249
|
+
activeSession.bddScenarios,
|
|
250
|
+
activeSession.clarificationQuestions,
|
|
251
|
+
activeSession.referenceResources
|
|
252
|
+
);
|
|
253
|
+
}
|
|
239
254
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
240
255
|
lines.push(chalk9.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
241
256
|
lines.push(chalk9.gray(` \u8DEF\u5F84: ${specPath}`));
|
|
242
257
|
lines.push("");
|
|
243
258
|
lines.push(chalk9.cyan(" \u4EFB\u52A1\u6982\u89C8:"));
|
|
244
|
-
for (const item of activeSession.specItems.slice(0,
|
|
259
|
+
for (const item of activeSession.specItems.slice(0, 8)) {
|
|
245
260
|
const icon = item.priority === "high" ? "\u{1F534}" : item.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
246
261
|
lines.push(chalk9.gray(` ${icon} [${item.id}] ${item.title}`));
|
|
247
262
|
}
|
|
248
|
-
if (activeSession.specItems.length >
|
|
263
|
+
if (activeSession.specItems.length > 8) {
|
|
249
264
|
lines.push(chalk9.gray(` ... \u5171 ${activeSession.specItems.length} \u4E2A\u4EFB\u52A1`));
|
|
250
265
|
}
|
|
251
266
|
lines.push("");
|
|
@@ -392,13 +407,15 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
392
407
|
activeSession.bddScenarios = generateBDDScenarios(
|
|
393
408
|
activeSession.refinedRequirement,
|
|
394
409
|
activeSession.context,
|
|
395
|
-
activeSession.clarificationQuestions
|
|
410
|
+
activeSession.clarificationQuestions,
|
|
411
|
+
activeSession.referenceResources
|
|
396
412
|
);
|
|
397
413
|
activeSession.specItems = generateSpecItems(
|
|
398
414
|
activeSession.refinedRequirement,
|
|
399
415
|
activeSession.context,
|
|
400
416
|
activeSession.bddScenarios,
|
|
401
|
-
activeSession.clarificationQuestions
|
|
417
|
+
activeSession.clarificationQuestions,
|
|
418
|
+
activeSession.referenceResources
|
|
402
419
|
);
|
|
403
420
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
404
421
|
return {
|
|
@@ -1124,6 +1141,89 @@ function generateSpecItems(requirement, context, bddScenarios, questions, refere
|
|
|
1124
1141
|
});
|
|
1125
1142
|
return items;
|
|
1126
1143
|
}
|
|
1144
|
+
async function generateSpecItemsWithAI(requirement, context, bddScenarios, questions, references, ctx) {
|
|
1145
|
+
const prompt2 = `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u9879\u76EE\u7ECF\u7406\u548C\u6280\u672F\u67B6\u6784\u5E08\u3002\u8BF7\u5C06\u4EE5\u4E0B\u9700\u6C42\u62C6\u5206\u4E3A\u7CBE\u7EC6\u5316\u7684\u5F00\u53D1\u4EFB\u52A1\u3002
|
|
1146
|
+
|
|
1147
|
+
## \u9700\u6C42\u63CF\u8FF0
|
|
1148
|
+
${requirement}
|
|
1149
|
+
|
|
1150
|
+
## \u9879\u76EE\u4E0A\u4E0B\u6587
|
|
1151
|
+
- \u6280\u672F\u6808: ${context.techStack?.join(", ") || "TypeScript"}
|
|
1152
|
+
- \u6846\u67B6: ${context.framework || "\u672A\u6307\u5B9A"}
|
|
1153
|
+
${context.devStandards ? `
|
|
1154
|
+
## \u5F00\u53D1\u89C4\u8303\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
|
|
1155
|
+
${context.devStandards.slice(0, 2e3)}
|
|
1156
|
+
` : ""}
|
|
1157
|
+
|
|
1158
|
+
## BDD \u573A\u666F\u53C2\u8003
|
|
1159
|
+
${bddScenarios.map((s) => `- Feature: ${s.feature} (${s.scenarios.length} \u4E2A\u573A\u666F)`).join("\n")}
|
|
1160
|
+
|
|
1161
|
+
## \u6F84\u6E05\u4FE1\u606F
|
|
1162
|
+
${questions.filter((q) => q.answered).map((q) => `- ${q.question}: ${q.answer}`).join("\n") || "\u65E0"}
|
|
1163
|
+
|
|
1164
|
+
## \u62C6\u5206\u8981\u6C42
|
|
1165
|
+
|
|
1166
|
+
\u8BF7\u5C06\u9700\u6C42\u62C6\u5206\u4E3A **\u7EC6\u7C92\u5EA6\u7684\u5F00\u53D1\u4EFB\u52A1**\uFF0C\u6BCF\u4E2A\u4EFB\u52A1\u5E94\u8BE5\uFF1A
|
|
1167
|
+
1. **\u5355\u4E00\u804C\u8D23** - \u4E00\u4E2A\u4EFB\u52A1\u53EA\u505A\u4E00\u4EF6\u4E8B
|
|
1168
|
+
2. **\u53EF\u72EC\u7ACB\u6D4B\u8BD5** - \u6709\u660E\u786E\u7684\u9A8C\u6536\u6807\u51C6
|
|
1169
|
+
3. **2-4\u5C0F\u65F6\u53EF\u5B8C\u6210** - \u5982\u679C\u4EFB\u52A1\u592A\u5927\uFF0C\u7EE7\u7EED\u62C6\u5206
|
|
1170
|
+
4. **\u6709\u660E\u786E\u7684\u8F93\u5165\u8F93\u51FA** - \u6E05\u695A\u77E5\u9053\u9700\u8981\u4EC0\u4E48\u3001\u4EA7\u51FA\u4EC0\u4E48
|
|
1171
|
+
|
|
1172
|
+
## \u8F93\u51FA\u683C\u5F0F (JSON)
|
|
1173
|
+
\`\`\`json
|
|
1174
|
+
[
|
|
1175
|
+
{
|
|
1176
|
+
"id": "T001",
|
|
1177
|
+
"title": "\u4EFB\u52A1\u6807\u9898\uFF08\u7B80\u77ED\u660E\u786E\uFF09",
|
|
1178
|
+
"description": "\u8BE6\u7EC6\u63CF\u8FF0\uFF1A\u8981\u505A\u4EC0\u4E48\u3001\u5982\u4F55\u505A\u3001\u9A8C\u6536\u6807\u51C6",
|
|
1179
|
+
"priority": "high",
|
|
1180
|
+
"estimatedHours": 2,
|
|
1181
|
+
"dependencies": [],
|
|
1182
|
+
"acceptanceCriteria": ["\u9A8C\u6536\u6807\u51C61", "\u9A8C\u6536\u6807\u51C62"]
|
|
1183
|
+
}
|
|
1184
|
+
]
|
|
1185
|
+
\`\`\`
|
|
1186
|
+
|
|
1187
|
+
## \u62C6\u5206\u5EFA\u8BAE
|
|
1188
|
+
\u5BF9\u4E8E\u590D\u6742\u529F\u80FD\uFF08\u5982\u7B97\u6CD5\u7C7B\uFF09\uFF0C\u5E94\u8BE5\u62C6\u5206\u4E3A\uFF1A
|
|
1189
|
+
- \u6570\u636E\u7ED3\u6784/\u6A21\u578B\u5B9A\u4E49
|
|
1190
|
+
- \u6838\u5FC3\u7B97\u6CD5\u5206\u6B65\u5B9E\u73B0\uFF08\u6BCF\u4E2A\u8BA1\u7B97\u6B65\u9AA4\u4E00\u4E2A\u4EFB\u52A1\uFF09
|
|
1191
|
+
- \u8F93\u5165\u9A8C\u8BC1
|
|
1192
|
+
- \u7ED3\u679C\u683C\u5F0F\u5316
|
|
1193
|
+
- UI \u5C55\u793A\u7EC4\u4EF6
|
|
1194
|
+
- \u96C6\u6210\u6D4B\u8BD5
|
|
1195
|
+
|
|
1196
|
+
\u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\u3002`;
|
|
1197
|
+
const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
|
|
1198
|
+
loader.start();
|
|
1199
|
+
try {
|
|
1200
|
+
const response = await ctx.modelService.sendMessage([
|
|
1201
|
+
{ role: "user", content: prompt2 }
|
|
1202
|
+
], {
|
|
1203
|
+
temperature: 0.3,
|
|
1204
|
+
maxTokens: 4e3,
|
|
1205
|
+
timeout: 12e4
|
|
1206
|
+
});
|
|
1207
|
+
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
|
|
1208
|
+
if (jsonMatch) {
|
|
1209
|
+
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
1210
|
+
loader.stop(chalk9.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
|
|
1211
|
+
return parsed.map((item) => ({
|
|
1212
|
+
id: item.id || `T${String(parsed.indexOf(item) + 1).padStart(3, "0")}`,
|
|
1213
|
+
title: item.title,
|
|
1214
|
+
description: item.description,
|
|
1215
|
+
priority: item.priority || "medium",
|
|
1216
|
+
files: [],
|
|
1217
|
+
tests: item.acceptanceCriteria || []
|
|
1218
|
+
}));
|
|
1219
|
+
}
|
|
1220
|
+
loader.stop(chalk9.yellow(" \u26A0 \u89E3\u6790\u5931\u8D25\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
|
|
1221
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1222
|
+
} catch (error) {
|
|
1223
|
+
loader.stop(chalk9.yellow(" \u26A0 AI \u62C6\u5206\u5931\u8D25\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
|
|
1224
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1127
1227
|
async function saveSpecFile(workingDir, session) {
|
|
1128
1228
|
const specDir = path5.join(workingDir, "openspec", "changes");
|
|
1129
1229
|
await fs4.mkdir(specDir, { recursive: true });
|