@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/index.js CHANGED
@@ -254,23 +254,38 @@ ${resource.analysis}`;
254
254
  lines.push("");
255
255
  lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
256
256
  lines.push("");
257
- activeSession.specItems = generateSpecItems(
258
- activeSession.refinedRequirement,
259
- activeSession.context,
260
- activeSession.bddScenarios,
261
- activeSession.clarificationQuestions,
262
- activeSession.referenceResources
263
- );
257
+ const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
258
+ loader.start();
259
+ try {
260
+ activeSession.specItems = await generateSpecItemsWithAI(
261
+ activeSession.refinedRequirement,
262
+ activeSession.context,
263
+ activeSession.bddScenarios,
264
+ activeSession.clarificationQuestions,
265
+ activeSession.referenceResources,
266
+ ctx
267
+ );
268
+ loader.stop();
269
+ } catch {
270
+ loader.stop(chalk9__default.default.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840\u89C4\u683C\u62C6\u5206"));
271
+ activeSession.specItems = generateSpecItems(
272
+ activeSession.refinedRequirement,
273
+ activeSession.context,
274
+ activeSession.bddScenarios,
275
+ activeSession.clarificationQuestions,
276
+ activeSession.referenceResources
277
+ );
278
+ }
264
279
  const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
265
280
  lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
266
281
  lines.push(chalk9__default.default.gray(` \u8DEF\u5F84: ${specPath}`));
267
282
  lines.push("");
268
283
  lines.push(chalk9__default.default.cyan(" \u4EFB\u52A1\u6982\u89C8:"));
269
- for (const item of activeSession.specItems.slice(0, 5)) {
284
+ for (const item of activeSession.specItems.slice(0, 8)) {
270
285
  const icon = item.priority === "high" ? "\u{1F534}" : item.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
271
286
  lines.push(chalk9__default.default.gray(` ${icon} [${item.id}] ${item.title}`));
272
287
  }
273
- if (activeSession.specItems.length > 5) {
288
+ if (activeSession.specItems.length > 8) {
274
289
  lines.push(chalk9__default.default.gray(` ... \u5171 ${activeSession.specItems.length} \u4E2A\u4EFB\u52A1`));
275
290
  }
276
291
  lines.push("");
@@ -417,13 +432,15 @@ async function handleWorkflowInput(input, ctx) {
417
432
  activeSession.bddScenarios = generateBDDScenarios(
418
433
  activeSession.refinedRequirement,
419
434
  activeSession.context,
420
- activeSession.clarificationQuestions
435
+ activeSession.clarificationQuestions,
436
+ activeSession.referenceResources
421
437
  );
422
438
  activeSession.specItems = generateSpecItems(
423
439
  activeSession.refinedRequirement,
424
440
  activeSession.context,
425
441
  activeSession.bddScenarios,
426
- activeSession.clarificationQuestions
442
+ activeSession.clarificationQuestions,
443
+ activeSession.referenceResources
427
444
  );
428
445
  const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
429
446
  return {
@@ -1149,6 +1166,89 @@ function generateSpecItems(requirement, context, bddScenarios, questions, refere
1149
1166
  });
1150
1167
  return items;
1151
1168
  }
1169
+ async function generateSpecItemsWithAI(requirement, context, bddScenarios, questions, references, ctx) {
1170
+ 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
1171
+
1172
+ ## \u9700\u6C42\u63CF\u8FF0
1173
+ ${requirement}
1174
+
1175
+ ## \u9879\u76EE\u4E0A\u4E0B\u6587
1176
+ - \u6280\u672F\u6808: ${context.techStack?.join(", ") || "TypeScript"}
1177
+ - \u6846\u67B6: ${context.framework || "\u672A\u6307\u5B9A"}
1178
+ ${context.devStandards ? `
1179
+ ## \u5F00\u53D1\u89C4\u8303\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
1180
+ ${context.devStandards.slice(0, 2e3)}
1181
+ ` : ""}
1182
+
1183
+ ## BDD \u573A\u666F\u53C2\u8003
1184
+ ${bddScenarios.map((s) => `- Feature: ${s.feature} (${s.scenarios.length} \u4E2A\u573A\u666F)`).join("\n")}
1185
+
1186
+ ## \u6F84\u6E05\u4FE1\u606F
1187
+ ${questions.filter((q) => q.answered).map((q) => `- ${q.question}: ${q.answer}`).join("\n") || "\u65E0"}
1188
+
1189
+ ## \u62C6\u5206\u8981\u6C42
1190
+
1191
+ \u8BF7\u5C06\u9700\u6C42\u62C6\u5206\u4E3A **\u7EC6\u7C92\u5EA6\u7684\u5F00\u53D1\u4EFB\u52A1**\uFF0C\u6BCF\u4E2A\u4EFB\u52A1\u5E94\u8BE5\uFF1A
1192
+ 1. **\u5355\u4E00\u804C\u8D23** - \u4E00\u4E2A\u4EFB\u52A1\u53EA\u505A\u4E00\u4EF6\u4E8B
1193
+ 2. **\u53EF\u72EC\u7ACB\u6D4B\u8BD5** - \u6709\u660E\u786E\u7684\u9A8C\u6536\u6807\u51C6
1194
+ 3. **2-4\u5C0F\u65F6\u53EF\u5B8C\u6210** - \u5982\u679C\u4EFB\u52A1\u592A\u5927\uFF0C\u7EE7\u7EED\u62C6\u5206
1195
+ 4. **\u6709\u660E\u786E\u7684\u8F93\u5165\u8F93\u51FA** - \u6E05\u695A\u77E5\u9053\u9700\u8981\u4EC0\u4E48\u3001\u4EA7\u51FA\u4EC0\u4E48
1196
+
1197
+ ## \u8F93\u51FA\u683C\u5F0F (JSON)
1198
+ \`\`\`json
1199
+ [
1200
+ {
1201
+ "id": "T001",
1202
+ "title": "\u4EFB\u52A1\u6807\u9898\uFF08\u7B80\u77ED\u660E\u786E\uFF09",
1203
+ "description": "\u8BE6\u7EC6\u63CF\u8FF0\uFF1A\u8981\u505A\u4EC0\u4E48\u3001\u5982\u4F55\u505A\u3001\u9A8C\u6536\u6807\u51C6",
1204
+ "priority": "high",
1205
+ "estimatedHours": 2,
1206
+ "dependencies": [],
1207
+ "acceptanceCriteria": ["\u9A8C\u6536\u6807\u51C61", "\u9A8C\u6536\u6807\u51C62"]
1208
+ }
1209
+ ]
1210
+ \`\`\`
1211
+
1212
+ ## \u62C6\u5206\u5EFA\u8BAE
1213
+ \u5BF9\u4E8E\u590D\u6742\u529F\u80FD\uFF08\u5982\u7B97\u6CD5\u7C7B\uFF09\uFF0C\u5E94\u8BE5\u62C6\u5206\u4E3A\uFF1A
1214
+ - \u6570\u636E\u7ED3\u6784/\u6A21\u578B\u5B9A\u4E49
1215
+ - \u6838\u5FC3\u7B97\u6CD5\u5206\u6B65\u5B9E\u73B0\uFF08\u6BCF\u4E2A\u8BA1\u7B97\u6B65\u9AA4\u4E00\u4E2A\u4EFB\u52A1\uFF09
1216
+ - \u8F93\u5165\u9A8C\u8BC1
1217
+ - \u7ED3\u679C\u683C\u5F0F\u5316
1218
+ - UI \u5C55\u793A\u7EC4\u4EF6
1219
+ - \u96C6\u6210\u6D4B\u8BD5
1220
+
1221
+ \u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\u3002`;
1222
+ const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
1223
+ loader.start();
1224
+ try {
1225
+ const response = await ctx.modelService.sendMessage([
1226
+ { role: "user", content: prompt2 }
1227
+ ], {
1228
+ temperature: 0.3,
1229
+ maxTokens: 4e3,
1230
+ timeout: 12e4
1231
+ });
1232
+ const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
1233
+ if (jsonMatch) {
1234
+ const parsed = JSON.parse(jsonMatch[1].trim());
1235
+ loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
1236
+ return parsed.map((item) => ({
1237
+ id: item.id || `T${String(parsed.indexOf(item) + 1).padStart(3, "0")}`,
1238
+ title: item.title,
1239
+ description: item.description,
1240
+ priority: item.priority || "medium",
1241
+ files: [],
1242
+ tests: item.acceptanceCriteria || []
1243
+ }));
1244
+ }
1245
+ loader.stop(chalk9__default.default.yellow(" \u26A0 \u89E3\u6790\u5931\u8D25\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
1246
+ return generateSpecItems(requirement, context, bddScenarios, questions, references);
1247
+ } catch (error) {
1248
+ loader.stop(chalk9__default.default.yellow(" \u26A0 AI \u62C6\u5206\u5931\u8D25\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
1249
+ return generateSpecItems(requirement, context, bddScenarios, questions, references);
1250
+ }
1251
+ }
1152
1252
  async function saveSpecFile(workingDir, session) {
1153
1253
  const specDir = path4__namespace.join(workingDir, "openspec", "changes");
1154
1254
  await fs4__namespace.mkdir(specDir, { recursive: true });