@nick848/sf-cli 1.0.15 → 1.0.17
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/CHANGELOG.md +24 -0
- package/dist/cli/index.js +843 -656
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +250 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +250 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -408,7 +408,7 @@ interface CLIConfig {
|
|
|
408
408
|
theme: 'light' | 'dark' | 'auto';
|
|
409
409
|
}
|
|
410
410
|
type WorkflowStep = 'explore' | 'new' | 'continue' | 'apply' | 'archive' | 'propose';
|
|
411
|
-
type WorkflowPhase = 'context' | 'clarify' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
|
|
411
|
+
type WorkflowPhase = 'context' | 'clarify' | 'reference' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
|
|
412
412
|
type WorkflowType = 'complex' | 'simple';
|
|
413
413
|
type WorkflowStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
414
414
|
interface WorkflowState {
|
package/dist/index.d.ts
CHANGED
|
@@ -408,7 +408,7 @@ interface CLIConfig {
|
|
|
408
408
|
theme: 'light' | 'dark' | 'auto';
|
|
409
409
|
}
|
|
410
410
|
type WorkflowStep = 'explore' | 'new' | 'continue' | 'apply' | 'archive' | 'propose';
|
|
411
|
-
type WorkflowPhase = 'context' | 'clarify' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
|
|
411
|
+
type WorkflowPhase = 'context' | 'clarify' | 'reference' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
|
|
412
412
|
type WorkflowType = 'complex' | 'simple';
|
|
413
413
|
type WorkflowStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
414
414
|
interface WorkflowState {
|
package/dist/index.js
CHANGED
|
@@ -84,6 +84,7 @@ async function handleNew(args, ctx) {
|
|
|
84
84
|
context: null,
|
|
85
85
|
clarityScore: 0,
|
|
86
86
|
clarificationQuestions: [],
|
|
87
|
+
referenceResources: [],
|
|
87
88
|
complexity: 0,
|
|
88
89
|
bddScenarios: [],
|
|
89
90
|
specItems: [],
|
|
@@ -126,7 +127,7 @@ async function executeWorkflow(ctx) {
|
|
|
126
127
|
const lines = [];
|
|
127
128
|
try {
|
|
128
129
|
if (activeSession.phase === "context") {
|
|
129
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/
|
|
130
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/9: \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6 \u2501\u2501\u2501"));
|
|
130
131
|
lines.push("");
|
|
131
132
|
activeSession.context = await readProjectContext(ctx.options.workingDirectory);
|
|
132
133
|
lines.push(chalk9__default.default.gray(` \u9879\u76EE: ${activeSession.context.name}`));
|
|
@@ -140,7 +141,7 @@ async function executeWorkflow(ctx) {
|
|
|
140
141
|
}
|
|
141
142
|
if (activeSession.phase === "clarify") {
|
|
142
143
|
lines.push("");
|
|
143
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 2/
|
|
144
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 2/9: \u9700\u6C42\u6F84\u6E05 \u2501\u2501\u2501"));
|
|
144
145
|
lines.push("");
|
|
145
146
|
const clarityResult = analyzeRequirementClarity(
|
|
146
147
|
activeSession.requirement,
|
|
@@ -166,11 +167,40 @@ async function executeWorkflow(ctx) {
|
|
|
166
167
|
return { output: lines.join("\n") };
|
|
167
168
|
}
|
|
168
169
|
lines.push(chalk9__default.default.green(" \u2713 \u9700\u6C42\u6E05\u6670\uFF0C\u7EE7\u7EED\u4E0B\u4E00\u6B65"));
|
|
170
|
+
activeSession.phase = "reference";
|
|
171
|
+
}
|
|
172
|
+
if (activeSession.phase === "reference") {
|
|
173
|
+
lines.push("");
|
|
174
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 3/9: \u53C2\u8003\u8D44\u6E90\u5206\u6790 \u2501\u2501\u2501"));
|
|
175
|
+
lines.push("");
|
|
176
|
+
const urls = extractUrls(activeSession.refinedRequirement);
|
|
177
|
+
if (urls.length > 0) {
|
|
178
|
+
lines.push(chalk9__default.default.gray(` \u53D1\u73B0 ${urls.length} \u4E2A\u53C2\u8003\u94FE\u63A5`));
|
|
179
|
+
lines.push("");
|
|
180
|
+
for (const url of urls) {
|
|
181
|
+
lines.push(chalk9__default.default.gray(` \u{1F4CE} ${url}`));
|
|
182
|
+
try {
|
|
183
|
+
const resource = await fetchAndAnalyzeReference(url, ctx);
|
|
184
|
+
activeSession.referenceResources.push(resource);
|
|
185
|
+
lines.push(chalk9__default.default.green(` \u2713 \u5DF2\u5206\u6790`));
|
|
186
|
+
activeSession.refinedRequirement += `
|
|
187
|
+
|
|
188
|
+
\u3010\u53C2\u8003\u8D44\u6E90\u5206\u6790 - ${url}\u3011
|
|
189
|
+
${resource.analysis}`;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
lines.push(chalk9__default.default.yellow(` \u26A0 \u83B7\u53D6\u5931\u8D25: ${error.message}`));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
lines.push("");
|
|
195
|
+
lines.push(chalk9__default.default.green(" \u2713 \u53C2\u8003\u8D44\u6E90\u5206\u6790\u5B8C\u6210"));
|
|
196
|
+
} else {
|
|
197
|
+
lines.push(chalk9__default.default.gray(" \u65E0\u5916\u90E8\u53C2\u8003\u94FE\u63A5"));
|
|
198
|
+
}
|
|
169
199
|
activeSession.phase = "analysis";
|
|
170
200
|
}
|
|
171
201
|
if (activeSession.phase === "analysis") {
|
|
172
202
|
lines.push("");
|
|
173
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
203
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 4/9: \u590D\u6742\u5EA6\u8BC4\u4F30 \u2501\u2501\u2501"));
|
|
174
204
|
lines.push("");
|
|
175
205
|
activeSession.complexity = analyzeComplexity(
|
|
176
206
|
activeSession.refinedRequirement,
|
|
@@ -187,12 +217,13 @@ async function executeWorkflow(ctx) {
|
|
|
187
217
|
}
|
|
188
218
|
if (activeSession.phase === "bdd") {
|
|
189
219
|
lines.push("");
|
|
190
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
220
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 5/9: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
|
|
191
221
|
lines.push("");
|
|
192
222
|
activeSession.bddScenarios = generateBDDScenarios(
|
|
193
223
|
activeSession.refinedRequirement,
|
|
194
224
|
activeSession.context,
|
|
195
|
-
activeSession.clarificationQuestions
|
|
225
|
+
activeSession.clarificationQuestions,
|
|
226
|
+
activeSession.referenceResources
|
|
196
227
|
);
|
|
197
228
|
for (const scenario of activeSession.bddScenarios) {
|
|
198
229
|
lines.push(chalk9__default.default.white(` Feature: ${scenario.feature}`));
|
|
@@ -207,13 +238,14 @@ async function executeWorkflow(ctx) {
|
|
|
207
238
|
}
|
|
208
239
|
if (activeSession.phase === "spec") {
|
|
209
240
|
lines.push("");
|
|
210
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
241
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
211
242
|
lines.push("");
|
|
212
243
|
activeSession.specItems = generateSpecItems(
|
|
213
244
|
activeSession.refinedRequirement,
|
|
214
245
|
activeSession.context,
|
|
215
246
|
activeSession.bddScenarios,
|
|
216
|
-
activeSession.clarificationQuestions
|
|
247
|
+
activeSession.clarificationQuestions,
|
|
248
|
+
activeSession.referenceResources
|
|
217
249
|
);
|
|
218
250
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
219
251
|
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -237,7 +269,7 @@ async function executeWorkflow(ctx) {
|
|
|
237
269
|
}
|
|
238
270
|
if (activeSession.phase === "tdd") {
|
|
239
271
|
lines.push("");
|
|
240
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
272
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/9: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
|
|
241
273
|
lines.push("");
|
|
242
274
|
activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession);
|
|
243
275
|
lines.push(chalk9__default.default.green(" \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -248,7 +280,7 @@ async function executeWorkflow(ctx) {
|
|
|
248
280
|
}
|
|
249
281
|
if (activeSession.phase === "develop") {
|
|
250
282
|
lines.push("");
|
|
251
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
283
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/9: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
252
284
|
lines.push("");
|
|
253
285
|
lines.push(chalk9__default.default.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
254
286
|
try {
|
|
@@ -273,7 +305,7 @@ async function executeWorkflow(ctx) {
|
|
|
273
305
|
}
|
|
274
306
|
if (activeSession.phase === "review") {
|
|
275
307
|
lines.push("");
|
|
276
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
308
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 9/9: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
277
309
|
lines.push("");
|
|
278
310
|
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
279
311
|
try {
|
|
@@ -815,13 +847,41 @@ function analyzeComplexity(requirement, context) {
|
|
|
815
847
|
if (!context.framework) score += 0.5;
|
|
816
848
|
return Math.max(1, Math.min(10, Math.round(score)));
|
|
817
849
|
}
|
|
818
|
-
function generateBDDScenarios(requirement, context, questions) {
|
|
850
|
+
function generateBDDScenarios(requirement, context, questions, references = []) {
|
|
819
851
|
const scenarios = [];
|
|
820
852
|
questions.find((q) => q.category === "ui" && q.answered)?.answer;
|
|
821
853
|
const interactionAnswer = questions.find((q) => q.category === "interaction" && q.answered)?.answer;
|
|
822
854
|
const edgeAnswer = questions.find((q) => q.category === "edge" && q.answered)?.answer;
|
|
855
|
+
if (references.length > 0) {
|
|
856
|
+
for (const ref of references) {
|
|
857
|
+
const refFeatures = extractFeaturesFromReference(ref);
|
|
858
|
+
for (const feature of refFeatures) {
|
|
859
|
+
const scenario = {
|
|
860
|
+
feature: feature.title,
|
|
861
|
+
description: feature.description,
|
|
862
|
+
scenarios: []
|
|
863
|
+
};
|
|
864
|
+
scenario.scenarios.push({
|
|
865
|
+
name: `\u6B63\u5E38\u6D41\u7A0B: ${feature.title}`,
|
|
866
|
+
given: [`\u7528\u6237\u8FDB\u5165\u76F8\u5173\u9875\u9762`],
|
|
867
|
+
when: [`\u7528\u6237\u6267\u884C "${feature.title}" \u64CD\u4F5C`],
|
|
868
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5E76\u8FD4\u56DE\u9884\u671F\u7ED3\u679C`]
|
|
869
|
+
});
|
|
870
|
+
if (feature.hasInput) {
|
|
871
|
+
scenario.scenarios.push({
|
|
872
|
+
name: `\u8FB9\u754C\u60C5\u51B5: \u8F93\u5165\u9A8C\u8BC1`,
|
|
873
|
+
given: [`\u7528\u6237\u8FDB\u5165\u8F93\u5165\u754C\u9762`],
|
|
874
|
+
when: [`\u7528\u6237\u8F93\u5165\u8FB9\u754C\u503C\u6216\u7A7A\u503C`],
|
|
875
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u8FB9\u754C\u60C5\u51B5`]
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
scenarios.push(scenario);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
823
882
|
const features = extractFeatures(requirement);
|
|
824
883
|
for (const feature of features) {
|
|
884
|
+
if (scenarios.some((s) => s.feature === feature.title)) continue;
|
|
825
885
|
const scenario = {
|
|
826
886
|
feature: feature.title,
|
|
827
887
|
description: feature.description,
|
|
@@ -853,6 +913,46 @@ function generateBDDScenarios(requirement, context, questions) {
|
|
|
853
913
|
}
|
|
854
914
|
return scenarios;
|
|
855
915
|
}
|
|
916
|
+
function extractFeaturesFromReference(ref) {
|
|
917
|
+
const features = [];
|
|
918
|
+
const analysis = ref.analysis.toLowerCase();
|
|
919
|
+
if (analysis.includes("\u8F93\u5165") || analysis.includes("\u8868\u5355")) {
|
|
920
|
+
features.push({
|
|
921
|
+
title: "\u8F93\u5165\u8868\u5355",
|
|
922
|
+
description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u8F93\u5165\u8868\u5355\u529F\u80FD",
|
|
923
|
+
hasInput: true
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
if (analysis.includes("\u6309\u94AE") || analysis.includes("\u64CD\u4F5C")) {
|
|
927
|
+
features.push({
|
|
928
|
+
title: "\u4EA4\u4E92\u6309\u94AE",
|
|
929
|
+
description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u6309\u94AE\u4EA4\u4E92",
|
|
930
|
+
hasInput: false
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
if (analysis.includes("\u8868\u683C") || analysis.includes("\u5217\u8868")) {
|
|
934
|
+
features.push({
|
|
935
|
+
title: "\u6570\u636E\u5217\u8868",
|
|
936
|
+
description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u6570\u636E\u5C55\u793A",
|
|
937
|
+
hasInput: false
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
if (analysis.includes("\u56FE\u8868") || analysis.includes("\u53EF\u89C6\u5316")) {
|
|
941
|
+
features.push({
|
|
942
|
+
title: "\u56FE\u8868\u5C55\u793A",
|
|
943
|
+
description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u56FE\u8868\u53EF\u89C6\u5316",
|
|
944
|
+
hasInput: false
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
if (features.length === 0) {
|
|
948
|
+
features.push({
|
|
949
|
+
title: "\u53C2\u8003\u529F\u80FD\u5B9E\u73B0",
|
|
950
|
+
description: `\u57FA\u4E8E\u53C2\u8003\u8D44\u6E90 ${ref.url} \u5B9E\u73B0\u7684\u529F\u80FD`,
|
|
951
|
+
hasInput: true
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
return features;
|
|
955
|
+
}
|
|
856
956
|
function extractFeatures(requirement) {
|
|
857
957
|
const features = [];
|
|
858
958
|
const urlMatch = requirement.match(/https?:\/\/[^\s]+/);
|
|
@@ -893,15 +993,26 @@ function extractFeatures(requirement) {
|
|
|
893
993
|
}
|
|
894
994
|
return features;
|
|
895
995
|
}
|
|
896
|
-
function generateSpecItems(requirement, context, bddScenarios, questions) {
|
|
996
|
+
function generateSpecItems(requirement, context, bddScenarios, questions, references = []) {
|
|
897
997
|
const items = [];
|
|
898
998
|
let id = 1;
|
|
999
|
+
for (const ref of references) {
|
|
1000
|
+
items.push({
|
|
1001
|
+
id: `T${id.toString().padStart(3, "0")}`,
|
|
1002
|
+
title: `\u53C2\u8003\u5206\u6790: ${ref.type}`,
|
|
1003
|
+
description: `\u5206\u6790\u53C2\u8003\u8D44\u6E90 ${ref.url}`,
|
|
1004
|
+
priority: "high",
|
|
1005
|
+
files: [],
|
|
1006
|
+
tests: []
|
|
1007
|
+
});
|
|
1008
|
+
id++;
|
|
1009
|
+
}
|
|
899
1010
|
for (const scenario of bddScenarios) {
|
|
900
1011
|
items.push({
|
|
901
1012
|
id: `T${id.toString().padStart(3, "0")}`,
|
|
902
1013
|
title: scenario.feature,
|
|
903
1014
|
description: scenario.description,
|
|
904
|
-
priority: id <=
|
|
1015
|
+
priority: id <= 3 ? "high" : "medium",
|
|
905
1016
|
files: [],
|
|
906
1017
|
tests: []
|
|
907
1018
|
});
|
|
@@ -944,6 +1055,19 @@ function formatSpecFile(session) {
|
|
|
944
1055
|
lines.push("---");
|
|
945
1056
|
lines.push("");
|
|
946
1057
|
}
|
|
1058
|
+
if (session.referenceResources.length > 0) {
|
|
1059
|
+
lines.push("## \u53C2\u8003\u8D44\u6E90");
|
|
1060
|
+
lines.push("");
|
|
1061
|
+
for (const ref of session.referenceResources) {
|
|
1062
|
+
lines.push(`### ${ref.url}`);
|
|
1063
|
+
lines.push(`> \u7C7B\u578B: ${ref.type}`);
|
|
1064
|
+
lines.push("");
|
|
1065
|
+
lines.push(ref.analysis);
|
|
1066
|
+
lines.push("");
|
|
1067
|
+
}
|
|
1068
|
+
lines.push("---");
|
|
1069
|
+
lines.push("");
|
|
1070
|
+
}
|
|
947
1071
|
if (session.clarificationQuestions.some((q) => q.answered)) {
|
|
948
1072
|
lines.push("## \u9700\u6C42\u6F84\u6E05");
|
|
949
1073
|
lines.push("");
|
|
@@ -1049,6 +1173,96 @@ function generateSessionId() {
|
|
|
1049
1173
|
const random = Math.random().toString(36).slice(2, 6);
|
|
1050
1174
|
return `WF-${timestamp}-${random}`.toUpperCase();
|
|
1051
1175
|
}
|
|
1176
|
+
function extractUrls(text) {
|
|
1177
|
+
const urlRegex = /https?:\/\/[^\s<>"{}|\\^`\[\]]+/gi;
|
|
1178
|
+
const matches = text.match(urlRegex);
|
|
1179
|
+
return matches ? [...new Set(matches)] : [];
|
|
1180
|
+
}
|
|
1181
|
+
async function fetchAndAnalyzeReference(url, ctx) {
|
|
1182
|
+
const type = detectResourceType(url);
|
|
1183
|
+
let content = "";
|
|
1184
|
+
let analysis = "";
|
|
1185
|
+
try {
|
|
1186
|
+
const response = await fetch(url, {
|
|
1187
|
+
headers: {
|
|
1188
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
1189
|
+
}
|
|
1190
|
+
});
|
|
1191
|
+
if (!response.ok) {
|
|
1192
|
+
throw new Error(`HTTP ${response.status}`);
|
|
1193
|
+
}
|
|
1194
|
+
content = await response.text();
|
|
1195
|
+
if (ctx.modelService.getCurrentModel()) {
|
|
1196
|
+
analysis = await analyzeReferenceContent(url, content, type, ctx);
|
|
1197
|
+
} else {
|
|
1198
|
+
analysis = extractBasicInfo(content, type);
|
|
1199
|
+
}
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
throw new Error(`\u65E0\u6CD5\u83B7\u53D6\u53C2\u8003\u8D44\u6E90: ${error.message}`);
|
|
1202
|
+
}
|
|
1203
|
+
return { url, type, content: content.slice(0, 1e4), analysis };
|
|
1204
|
+
}
|
|
1205
|
+
function detectResourceType(url) {
|
|
1206
|
+
if (url.includes("figma.com") || url.includes("lanhuapp.com")) {
|
|
1207
|
+
return "design";
|
|
1208
|
+
}
|
|
1209
|
+
if (/\.(png|jpg|jpeg|gif|webp|svg)$/i.test(url)) {
|
|
1210
|
+
return "image";
|
|
1211
|
+
}
|
|
1212
|
+
if (/api\//i.test(url)) {
|
|
1213
|
+
return "api";
|
|
1214
|
+
}
|
|
1215
|
+
return "webpage";
|
|
1216
|
+
}
|
|
1217
|
+
async function analyzeReferenceContent(url, content, type, ctx) {
|
|
1218
|
+
const typePrompts = {
|
|
1219
|
+
webpage: "\u5206\u6790\u8FD9\u4E2A\u7F51\u9875\u7684\u529F\u80FD\u3001UI\u7EC4\u4EF6\u548C\u4EA4\u4E92\u65B9\u5F0F",
|
|
1220
|
+
design: "\u5206\u6790\u8FD9\u4E2A\u8BBE\u8BA1\u7A3F\u7684\u5E03\u5C40\u3001\u7EC4\u4EF6\u548C\u6837\u5F0F",
|
|
1221
|
+
image: "\u63CF\u8FF0\u8FD9\u4E2A\u56FE\u7247\u7684\u5185\u5BB9\u548C\u8BBE\u8BA1\u5143\u7D20",
|
|
1222
|
+
api: "\u5206\u6790\u8FD9\u4E2AAPI\u7684\u7ED3\u6784\u548C\u53C2\u6570"
|
|
1223
|
+
};
|
|
1224
|
+
const prompt2 = `
|
|
1225
|
+
\u8BF7\u5206\u6790\u4EE5\u4E0B\u53C2\u8003\u8D44\u6E90\u7684 URL\uFF0C\u63D0\u53D6\u5BF9\u5F00\u53D1\u6709\u7528\u7684\u4FE1\u606F\uFF1A
|
|
1226
|
+
|
|
1227
|
+
URL: ${url}
|
|
1228
|
+
\u7C7B\u578B: ${type}
|
|
1229
|
+
|
|
1230
|
+
\u5185\u5BB9\u6458\u8981:
|
|
1231
|
+
${content.slice(0, 5e3)}
|
|
1232
|
+
|
|
1233
|
+
${typePrompts[type]}
|
|
1234
|
+
|
|
1235
|
+
\u8BF7\u63D0\u53D6\uFF1A
|
|
1236
|
+
1. \u4E3B\u8981\u529F\u80FD\u70B9
|
|
1237
|
+
2. UI\u7EC4\u4EF6\u7ED3\u6784
|
|
1238
|
+
3. \u4EA4\u4E92\u65B9\u5F0F
|
|
1239
|
+
4. \u6570\u636E\u7ED3\u6784\uFF08\u5982\u679C\u6709\uFF09
|
|
1240
|
+
5. \u6280\u672F\u5B9E\u73B0\u5EFA\u8BAE
|
|
1241
|
+
|
|
1242
|
+
\u4EE5\u7B80\u6D01\u7684\u8981\u70B9\u5F62\u5F0F\u8F93\u51FA\u3002
|
|
1243
|
+
`;
|
|
1244
|
+
try {
|
|
1245
|
+
const response = await ctx.modelService.sendMessage([
|
|
1246
|
+
{ role: "user", content: prompt2 }
|
|
1247
|
+
], { temperature: 0.3, maxTokens: 2e3 });
|
|
1248
|
+
return response.content;
|
|
1249
|
+
} catch {
|
|
1250
|
+
return extractBasicInfo(content, type);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
function extractBasicInfo(content, type) {
|
|
1254
|
+
const titleMatch = content.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
1255
|
+
const descMatch = content.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']+)["']/i);
|
|
1256
|
+
const parts = [];
|
|
1257
|
+
if (titleMatch) {
|
|
1258
|
+
parts.push(`\u6807\u9898: ${titleMatch[1]}`);
|
|
1259
|
+
}
|
|
1260
|
+
if (descMatch) {
|
|
1261
|
+
parts.push(`\u63CF\u8FF0: ${descMatch[1]}`);
|
|
1262
|
+
}
|
|
1263
|
+
parts.push(`\u8D44\u6E90\u7C7B\u578B: ${type}`);
|
|
1264
|
+
return parts.join("\n");
|
|
1265
|
+
}
|
|
1052
1266
|
function generateComplexityBar(score) {
|
|
1053
1267
|
const filled = Math.round(score / 2);
|
|
1054
1268
|
const empty = 5 - filled;
|
|
@@ -1058,6 +1272,7 @@ function getPhaseLabel(phase) {
|
|
|
1058
1272
|
const labels = {
|
|
1059
1273
|
context: "\u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6",
|
|
1060
1274
|
clarify: "\u9700\u6C42\u6F84\u6E05",
|
|
1275
|
+
reference: "\u53C2\u8003\u8D44\u6E90\u5206\u6790",
|
|
1061
1276
|
analysis: "\u590D\u6742\u5EA6\u8BC4\u4F30",
|
|
1062
1277
|
bdd: "BDD \u573A\u666F\u62C6\u89E3",
|
|
1063
1278
|
spec: "OpenSpec \u89C4\u683C",
|
|
@@ -7601,25 +7816,21 @@ ${chalk9__default.default.yellow("\u793A\u4F8B:")}
|
|
|
7601
7816
|
|
|
7602
7817
|
// src/commands/model.ts
|
|
7603
7818
|
init_cjs_shims();
|
|
7604
|
-
|
|
7605
|
-
// src/services/index.ts
|
|
7606
|
-
init_cjs_shims();
|
|
7607
|
-
|
|
7608
|
-
// src/commands/model.ts
|
|
7609
7819
|
async function handleModel(args, ctx) {
|
|
7610
7820
|
const subCommand = args[0];
|
|
7611
7821
|
const configManager = ctx.configManager;
|
|
7822
|
+
const modelService = ctx.modelService;
|
|
7612
7823
|
switch (subCommand) {
|
|
7613
7824
|
case "list":
|
|
7614
7825
|
return listModels();
|
|
7615
7826
|
case "current":
|
|
7616
7827
|
return showCurrentModel(configManager);
|
|
7617
7828
|
case "set":
|
|
7618
|
-
return setModelDirectly(args[1], configManager);
|
|
7829
|
+
return setModelDirectly(args[1], configManager, modelService);
|
|
7619
7830
|
case "verify":
|
|
7620
7831
|
return verifyCurrentModel(configManager);
|
|
7621
7832
|
default:
|
|
7622
|
-
return selectModel(configManager);
|
|
7833
|
+
return selectModel(configManager, modelService);
|
|
7623
7834
|
}
|
|
7624
7835
|
}
|
|
7625
7836
|
async function listModels() {
|
|
@@ -7660,7 +7871,7 @@ async function showCurrentModel(configManager) {
|
|
|
7660
7871
|
];
|
|
7661
7872
|
return { output: lines.join("\n") };
|
|
7662
7873
|
}
|
|
7663
|
-
async function setModelDirectly(modelId, configManager) {
|
|
7874
|
+
async function setModelDirectly(modelId, configManager, modelService) {
|
|
7664
7875
|
if (!modelId) {
|
|
7665
7876
|
return {
|
|
7666
7877
|
output: chalk9__default.default.red("\u8BF7\u6307\u5B9A\u6A21\u578BID\uFF0C\u4F8B\u5982: /model set gpt-4o")
|
|
@@ -7675,11 +7886,22 @@ async function setModelDirectly(modelId, configManager) {
|
|
|
7675
7886
|
}
|
|
7676
7887
|
configManager.set("model", modelId);
|
|
7677
7888
|
await configManager.save();
|
|
7889
|
+
const apiKey = configManager.get("apiKey");
|
|
7890
|
+
if (apiKey) {
|
|
7891
|
+
try {
|
|
7892
|
+
await modelService.configureModel({
|
|
7893
|
+
provider: modelInfo.provider,
|
|
7894
|
+
model: modelId,
|
|
7895
|
+
apiKey
|
|
7896
|
+
});
|
|
7897
|
+
} catch {
|
|
7898
|
+
}
|
|
7899
|
+
}
|
|
7678
7900
|
return {
|
|
7679
7901
|
output: chalk9__default.default.green(`\u2713 \u5DF2\u5207\u6362\u5230\u6A21\u578B: ${modelInfo.name} (${modelInfo.provider})`)
|
|
7680
7902
|
};
|
|
7681
7903
|
}
|
|
7682
|
-
async function verifyCurrentModel(configManager) {
|
|
7904
|
+
async function verifyCurrentModel(configManager, modelService) {
|
|
7683
7905
|
const currentModel = configManager.get("model");
|
|
7684
7906
|
const apiKey = configManager.get("apiKey");
|
|
7685
7907
|
if (!apiKey) {
|
|
@@ -7712,7 +7934,7 @@ async function verifyCurrentModel(configManager) {
|
|
|
7712
7934
|
};
|
|
7713
7935
|
}
|
|
7714
7936
|
}
|
|
7715
|
-
async function selectModel(configManager) {
|
|
7937
|
+
async function selectModel(configManager, modelService) {
|
|
7716
7938
|
try {
|
|
7717
7939
|
const currentModel = configManager.get("model");
|
|
7718
7940
|
const currentApiKey = configManager.get("apiKey");
|
|
@@ -7776,6 +7998,11 @@ async function selectModel(configManager) {
|
|
|
7776
7998
|
configManager.set("model", modelResponse.model);
|
|
7777
7999
|
configManager.set("apiKey", apiKeyResponse.apiKey);
|
|
7778
8000
|
await configManager.save();
|
|
8001
|
+
await modelService.configureModel({
|
|
8002
|
+
provider: selectedModel.provider,
|
|
8003
|
+
model: modelResponse.model,
|
|
8004
|
+
apiKey: apiKeyResponse.apiKey
|
|
8005
|
+
});
|
|
7779
8006
|
return {
|
|
7780
8007
|
output: chalk9__default.default.green(`
|
|
7781
8008
|
\u2713 \u6A21\u578B\u914D\u7F6E\u5B8C\u6210
|