@zjex/git-workflow 0.2.16 → 0.2.18
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 +587 -158
- package/dist/index.js +168 -125
- package/package.json +1 -1
- package/scripts/publish.js +18 -5
- package/src/ai-service.ts +5 -44
- package/src/commands/commit.ts +26 -23
- package/src/commands/help.ts +4 -1
- package/src/commands/init.ts +99 -47
- package/src/config.ts +46 -11
- package/src/index.ts +11 -2
- package/src/update-notifier.ts +4 -19
package/dist/index.js
CHANGED
|
@@ -75,6 +75,7 @@ import ora from "ora";
|
|
|
75
75
|
// src/config.ts
|
|
76
76
|
import { existsSync, readFileSync } from "fs";
|
|
77
77
|
import { join } from "path";
|
|
78
|
+
import { homedir } from "os";
|
|
78
79
|
var defaultConfig = {
|
|
79
80
|
featurePrefix: "feature",
|
|
80
81
|
hotfixPrefix: "hotfix",
|
|
@@ -108,19 +109,47 @@ function findConfigFile() {
|
|
|
108
109
|
}
|
|
109
110
|
return null;
|
|
110
111
|
}
|
|
112
|
+
function findGlobalConfigFile() {
|
|
113
|
+
const globalConfigPath = join(homedir(), ".gwrc.json");
|
|
114
|
+
return existsSync(globalConfigPath) ? globalConfigPath : null;
|
|
115
|
+
}
|
|
111
116
|
function loadConfig() {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
117
|
+
let config2 = { ...defaultConfig };
|
|
118
|
+
const globalConfigPath = findGlobalConfigFile();
|
|
119
|
+
if (globalConfigPath) {
|
|
120
|
+
try {
|
|
121
|
+
const content = readFileSync(globalConfigPath, "utf-8");
|
|
122
|
+
const globalConfig = JSON.parse(content);
|
|
123
|
+
config2 = {
|
|
124
|
+
...config2,
|
|
125
|
+
...globalConfig,
|
|
126
|
+
aiCommit: {
|
|
127
|
+
...config2.aiCommit,
|
|
128
|
+
...globalConfig.aiCommit
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.warn(`\u5168\u5C40\u914D\u7F6E\u6587\u4EF6\u89E3\u6790\u5931\u8D25: ${globalConfigPath}`);
|
|
133
|
+
}
|
|
115
134
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
const projectConfigPath = findConfigFile();
|
|
136
|
+
if (projectConfigPath) {
|
|
137
|
+
try {
|
|
138
|
+
const content = readFileSync(projectConfigPath, "utf-8");
|
|
139
|
+
const projectConfig = JSON.parse(content);
|
|
140
|
+
config2 = {
|
|
141
|
+
...config2,
|
|
142
|
+
...projectConfig,
|
|
143
|
+
aiCommit: {
|
|
144
|
+
...config2.aiCommit,
|
|
145
|
+
...projectConfig.aiCommit
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.warn(`\u9879\u76EE\u914D\u7F6E\u6587\u4EF6\u89E3\u6790\u5931\u8D25: ${projectConfigPath}`);
|
|
150
|
+
}
|
|
123
151
|
}
|
|
152
|
+
return config2;
|
|
124
153
|
}
|
|
125
154
|
var config = null;
|
|
126
155
|
function getConfig() {
|
|
@@ -860,8 +889,9 @@ async function release() {
|
|
|
860
889
|
|
|
861
890
|
// src/commands/init.ts
|
|
862
891
|
import { existsSync as existsSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
892
|
+
import { join as join2 } from "path";
|
|
893
|
+
import { homedir as homedir2 } from "os";
|
|
863
894
|
import { select as select4, input as input3 } from "@inquirer/prompts";
|
|
864
|
-
var CONFIG_FILE = ".gwrc.json";
|
|
865
895
|
var DEFAULT_COMMIT_EMOJIS = {
|
|
866
896
|
feat: "\u2728",
|
|
867
897
|
fix: "\u{1F41B}",
|
|
@@ -876,9 +906,30 @@ var DEFAULT_COMMIT_EMOJIS = {
|
|
|
876
906
|
revert: "\u23EA"
|
|
877
907
|
};
|
|
878
908
|
async function init() {
|
|
879
|
-
|
|
909
|
+
console.log("");
|
|
910
|
+
console.log(colors.bold("\u2699\uFE0F \u521D\u59CB\u5316 git-workflow \u914D\u7F6E"));
|
|
911
|
+
console.log("");
|
|
912
|
+
const configScope = await select4({
|
|
913
|
+
message: "\u9009\u62E9\u914D\u7F6E\u8303\u56F4:",
|
|
914
|
+
choices: [
|
|
915
|
+
{
|
|
916
|
+
name: "\u5168\u5C40\u914D\u7F6E\uFF08\u6240\u6709\u9879\u76EE\u751F\u6548\uFF09",
|
|
917
|
+
value: "global",
|
|
918
|
+
description: "\u4FDD\u5B58\u5230 ~/.gwrc.json\uFF0C\u6240\u6709\u9879\u76EE\u90FD\u4F1A\u4F7F\u7528\u6B64\u914D\u7F6E"
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
name: "\u9879\u76EE\u914D\u7F6E\uFF08\u4EC5\u5F53\u524D\u9879\u76EE\uFF09",
|
|
922
|
+
value: "project",
|
|
923
|
+
description: "\u4FDD\u5B58\u5230\u5F53\u524D\u76EE\u5F55 .gwrc.json\uFF0C\u4EC5\u5F53\u524D\u9879\u76EE\u4F7F\u7528"
|
|
924
|
+
}
|
|
925
|
+
],
|
|
926
|
+
theme
|
|
927
|
+
});
|
|
928
|
+
const isGlobal = configScope === "global";
|
|
929
|
+
const configFile = isGlobal ? join2(homedir2(), ".gwrc.json") : ".gwrc.json";
|
|
930
|
+
if (existsSync2(configFile)) {
|
|
880
931
|
const overwrite = await select4({
|
|
881
|
-
message: `${
|
|
932
|
+
message: `${isGlobal ? "\u5168\u5C40" : "\u9879\u76EE"}\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u662F\u5426\u8986\u76D6?`,
|
|
882
933
|
choices: [
|
|
883
934
|
{ name: "\u5426\uFF0C\u53D6\u6D88", value: false },
|
|
884
935
|
{ name: "\u662F\uFF0C\u8986\u76D6", value: true }
|
|
@@ -903,13 +954,13 @@ async function init() {
|
|
|
903
954
|
default: "feature",
|
|
904
955
|
theme
|
|
905
956
|
});
|
|
906
|
-
|
|
957
|
+
config2.featurePrefix = featurePrefix;
|
|
907
958
|
const hotfixPrefix = await input3({
|
|
908
959
|
message: "Hotfix \u5206\u652F\u524D\u7F00:",
|
|
909
960
|
default: "hotfix",
|
|
910
961
|
theme
|
|
911
962
|
});
|
|
912
|
-
|
|
963
|
+
config2.hotfixPrefix = hotfixPrefix;
|
|
913
964
|
divider();
|
|
914
965
|
const requireId = await select4({
|
|
915
966
|
message: "\u662F\u5426\u8981\u6C42\u5FC5\u586B ID (Story ID / Issue ID)?",
|
|
@@ -919,19 +970,19 @@ async function init() {
|
|
|
919
970
|
],
|
|
920
971
|
theme
|
|
921
972
|
});
|
|
922
|
-
|
|
973
|
+
config2.requireId = requireId;
|
|
923
974
|
const featureIdLabel = await input3({
|
|
924
975
|
message: "Feature \u5206\u652F ID \u6807\u7B7E:",
|
|
925
976
|
default: "Story ID",
|
|
926
977
|
theme
|
|
927
978
|
});
|
|
928
|
-
|
|
979
|
+
config2.featureIdLabel = featureIdLabel;
|
|
929
980
|
const hotfixIdLabel = await input3({
|
|
930
981
|
message: "Hotfix \u5206\u652F ID \u6807\u7B7E:",
|
|
931
982
|
default: "Issue ID",
|
|
932
983
|
theme
|
|
933
984
|
});
|
|
934
|
-
|
|
985
|
+
config2.hotfixIdLabel = hotfixIdLabel;
|
|
935
986
|
divider();
|
|
936
987
|
const defaultTagPrefix = await input3({
|
|
937
988
|
message: "\u9ED8\u8BA4 Tag \u524D\u7F00 (\u7559\u7A7A\u5219\u6BCF\u6B21\u9009\u62E9):",
|
|
@@ -947,8 +998,11 @@ async function init() {
|
|
|
947
998
|
],
|
|
948
999
|
theme
|
|
949
1000
|
});
|
|
950
|
-
if (autoPushChoice === "yes")
|
|
951
|
-
|
|
1001
|
+
if (autoPushChoice === "yes") {
|
|
1002
|
+
config2.autoPush = true;
|
|
1003
|
+
} else if (autoPushChoice === "no") {
|
|
1004
|
+
config2.autoPush = false;
|
|
1005
|
+
}
|
|
952
1006
|
divider();
|
|
953
1007
|
const autoStage = await select4({
|
|
954
1008
|
message: "Commit \u65F6\u662F\u5426\u81EA\u52A8\u6682\u5B58\u6240\u6709\u66F4\u6539?",
|
|
@@ -958,7 +1012,7 @@ async function init() {
|
|
|
958
1012
|
],
|
|
959
1013
|
theme
|
|
960
1014
|
});
|
|
961
|
-
|
|
1015
|
+
config2.autoStage = autoStage;
|
|
962
1016
|
const useEmoji = await select4({
|
|
963
1017
|
message: "Commit \u65F6\u662F\u5426\u4F7F\u7528 emoji?",
|
|
964
1018
|
choices: [
|
|
@@ -967,7 +1021,7 @@ async function init() {
|
|
|
967
1021
|
],
|
|
968
1022
|
theme
|
|
969
1023
|
});
|
|
970
|
-
|
|
1024
|
+
config2.useEmoji = useEmoji;
|
|
971
1025
|
config2.commitEmojis = DEFAULT_COMMIT_EMOJIS;
|
|
972
1026
|
divider();
|
|
973
1027
|
console.log(
|
|
@@ -990,11 +1044,6 @@ async function init() {
|
|
|
990
1044
|
value: "github",
|
|
991
1045
|
description: "\u4F7F\u7528 GitHub \u8D26\u53F7\uFF0C\u6BCF\u5929 150 \u6B21\u514D\u8D39"
|
|
992
1046
|
},
|
|
993
|
-
{
|
|
994
|
-
name: "Groq\uFF08\u514D\u8D39\uFF09",
|
|
995
|
-
value: "groq",
|
|
996
|
-
description: "\u9700\u8981\u6CE8\u518C\uFF0C\u6BCF\u5929 14,400 \u6B21\u514D\u8D39"
|
|
997
|
-
},
|
|
998
1047
|
{
|
|
999
1048
|
name: "OpenAI\uFF08\u4ED8\u8D39\uFF09",
|
|
1000
1049
|
value: "openai",
|
|
@@ -1013,26 +1062,36 @@ async function init() {
|
|
|
1013
1062
|
],
|
|
1014
1063
|
theme
|
|
1015
1064
|
});
|
|
1016
|
-
const useBuiltinKey = await select4({
|
|
1017
|
-
message: "API Key \u914D\u7F6E:",
|
|
1018
|
-
choices: [
|
|
1019
|
-
{
|
|
1020
|
-
name: "\u4F7F\u7528\u5185\u7F6E Key\uFF08\u5F00\u7BB1\u5373\u7528\uFF09",
|
|
1021
|
-
value: true,
|
|
1022
|
-
description: "\u4F7F\u7528\u5DE5\u5177\u5185\u7F6E\u7684 API key\uFF0C\u5171\u4EAB\u9650\u989D"
|
|
1023
|
-
},
|
|
1024
|
-
{
|
|
1025
|
-
name: "\u4F7F\u7528\u81EA\u5DF1\u7684 Key\uFF08\u63A8\u8350\uFF09",
|
|
1026
|
-
value: false,
|
|
1027
|
-
description: "\u914D\u7F6E\u81EA\u5DF1\u7684 API key\uFF0C\u72EC\u4EAB\u9650\u989D"
|
|
1028
|
-
}
|
|
1029
|
-
],
|
|
1030
|
-
theme
|
|
1031
|
-
});
|
|
1032
1065
|
let apiKey = "";
|
|
1033
|
-
if (
|
|
1066
|
+
if (aiProvider === "github") {
|
|
1067
|
+
console.log("");
|
|
1068
|
+
console.log(colors.cyan("\u{1F4A1} \u5982\u4F55\u83B7\u53D6 GitHub Token:"));
|
|
1069
|
+
console.log(
|
|
1070
|
+
colors.dim(" 1. \u8BBF\u95EE: https://github.com/settings/tokens/new")
|
|
1071
|
+
);
|
|
1072
|
+
console.log(colors.dim(" 2. \u52FE\u9009 'repo' \u6743\u9650"));
|
|
1073
|
+
console.log(colors.dim(" 3. \u751F\u6210\u5E76\u590D\u5236 token"));
|
|
1074
|
+
console.log("");
|
|
1034
1075
|
apiKey = await input3({
|
|
1035
|
-
message:
|
|
1076
|
+
message: "\u8F93\u5165\u4F60\u7684 GitHub Token:",
|
|
1077
|
+
validate: (value) => {
|
|
1078
|
+
if (!value.trim()) return "GitHub Token \u4E0D\u80FD\u4E3A\u7A7A";
|
|
1079
|
+
return true;
|
|
1080
|
+
},
|
|
1081
|
+
theme
|
|
1082
|
+
});
|
|
1083
|
+
} else if (aiProvider !== "ollama") {
|
|
1084
|
+
console.log("");
|
|
1085
|
+
if (aiProvider === "openai") {
|
|
1086
|
+
console.log(colors.cyan("\u{1F4A1} \u5982\u4F55\u83B7\u53D6 OpenAI API Key:"));
|
|
1087
|
+
console.log(colors.dim(" \u8BBF\u95EE: https://platform.openai.com/api-keys"));
|
|
1088
|
+
} else {
|
|
1089
|
+
console.log(colors.cyan("\u{1F4A1} \u5982\u4F55\u83B7\u53D6 Claude API Key:"));
|
|
1090
|
+
console.log(colors.dim(" \u8BBF\u95EE: https://console.anthropic.com/"));
|
|
1091
|
+
}
|
|
1092
|
+
console.log("");
|
|
1093
|
+
apiKey = await input3({
|
|
1094
|
+
message: `\u8F93\u5165\u4F60\u7684 ${aiProvider === "openai" ? "OpenAI API Key" : "Claude API Key"}:`,
|
|
1036
1095
|
validate: (value) => {
|
|
1037
1096
|
if (!value.trim()) return "API Key \u4E0D\u80FD\u4E3A\u7A7A";
|
|
1038
1097
|
return true;
|
|
@@ -1056,7 +1115,6 @@ async function init() {
|
|
|
1056
1115
|
};
|
|
1057
1116
|
const defaultModels = {
|
|
1058
1117
|
github: "gpt-4o-mini",
|
|
1059
|
-
groq: "llama-3.1-8b-instant",
|
|
1060
1118
|
openai: "gpt-4o-mini",
|
|
1061
1119
|
claude: "claude-3-haiku-20240307",
|
|
1062
1120
|
ollama: "qwen2.5-coder:7b"
|
|
@@ -1069,13 +1127,30 @@ async function init() {
|
|
|
1069
1127
|
}
|
|
1070
1128
|
divider();
|
|
1071
1129
|
const content = JSON.stringify(config2, null, 2);
|
|
1072
|
-
writeFileSync2(
|
|
1073
|
-
console.log(colors.green(`\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${CONFIG_FILE}`));
|
|
1130
|
+
writeFileSync2(configFile, content + "\n");
|
|
1074
1131
|
console.log(
|
|
1075
|
-
colors.
|
|
1076
|
-
|
|
1132
|
+
colors.green(
|
|
1133
|
+
`\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${isGlobal ? "\u5168\u5C40\u914D\u7F6E\u6587\u4EF6" : "\u9879\u76EE\u914D\u7F6E\u6587\u4EF6"}: ${configFile}`
|
|
1077
1134
|
)
|
|
1078
1135
|
);
|
|
1136
|
+
if (isGlobal) {
|
|
1137
|
+
console.log("");
|
|
1138
|
+
console.log(colors.cyan("\u{1F4A1} \u63D0\u793A:"));
|
|
1139
|
+
console.log(
|
|
1140
|
+
colors.dim(" \u2022 \u5168\u5C40\u914D\u7F6E\u5BF9\u6240\u6709\u9879\u76EE\u751F\u6548\uFF0C\u65E0\u9700\u5728\u6BCF\u4E2A\u9879\u76EE\u4E2D\u91CD\u590D\u914D\u7F6E")
|
|
1141
|
+
);
|
|
1142
|
+
console.log(
|
|
1143
|
+
colors.dim(" \u2022 \u5982\u9700\u4E3A\u7279\u5B9A\u9879\u76EE\u81EA\u5B9A\u4E49\u914D\u7F6E\uFF0C\u53EF\u5728\u9879\u76EE\u4E2D\u8FD0\u884C gw init")
|
|
1144
|
+
);
|
|
1145
|
+
console.log(colors.dim(" \u2022 \u9879\u76EE\u914D\u7F6E\u4F1A\u8986\u76D6\u5168\u5C40\u914D\u7F6E"));
|
|
1146
|
+
} else {
|
|
1147
|
+
console.log("");
|
|
1148
|
+
console.log(
|
|
1149
|
+
colors.dim(
|
|
1150
|
+
"\u63D0\u793A: \u53EF\u4EE5\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u4FEE\u6539 commitEmojis \u6765\u81EA\u5B9A\u4E49\u5404\u7C7B\u578B\u7684 emoji"
|
|
1151
|
+
)
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1079
1154
|
if (config2.aiCommit?.enabled) {
|
|
1080
1155
|
console.log(
|
|
1081
1156
|
colors.dim(
|
|
@@ -1344,13 +1419,6 @@ var AI_PROVIDERS = {
|
|
|
1344
1419
|
free: true,
|
|
1345
1420
|
needsKey: true
|
|
1346
1421
|
},
|
|
1347
|
-
groq: {
|
|
1348
|
-
name: "Groq",
|
|
1349
|
-
endpoint: "https://api.groq.com/openai/v1/chat/completions",
|
|
1350
|
-
defaultModel: "llama-3.1-8b-instant",
|
|
1351
|
-
free: true,
|
|
1352
|
-
needsKey: true
|
|
1353
|
-
},
|
|
1354
1422
|
openai: {
|
|
1355
1423
|
name: "OpenAI",
|
|
1356
1424
|
endpoint: "https://api.openai.com/v1/chat/completions",
|
|
@@ -1393,7 +1461,8 @@ function buildPrompt(diff, language) {
|
|
|
1393
1461
|
2. type \u5FC5\u987B\u662F\u4EE5\u4E0B\u4E4B\u4E00\uFF1Afeat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
1394
1462
|
3. scope \u662F\u53EF\u9009\u7684\uFF0C\u8868\u793A\u5F71\u54CD\u8303\u56F4
|
|
1395
1463
|
4. subject \u7528\u4E2D\u6587\u63CF\u8FF0\uFF0C\u7B80\u6D01\u660E\u4E86\uFF0C\u4E0D\u8D85\u8FC7 50 \u5B57
|
|
1396
|
-
5. \u53EA\u8FD4\u56DE commit message\uFF0C\
|
|
1464
|
+
5. \u53EA\u8FD4\u56DE\u4E00\u6761 commit message\uFF0C\u5373\u4F7F\u6709\u591A\u4E2A\u6587\u4EF6\u6539\u52A8\u4E5F\u8981\u603B\u7ED3\u6210\u4E00\u6761
|
|
1465
|
+
6. \u4E0D\u8981\u6709\u5176\u4ED6\u89E3\u91CA\u6216\u591A\u4F59\u5185\u5BB9
|
|
1397
1466
|
|
|
1398
1467
|
\u793A\u4F8B\uFF1A
|
|
1399
1468
|
- feat(auth): \u6DFB\u52A0\u7528\u6237\u767B\u5F55\u529F\u80FD
|
|
@@ -1405,7 +1474,8 @@ Rules:
|
|
|
1405
1474
|
2. type must be one of: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
1406
1475
|
3. scope is optional, indicates the affected area
|
|
1407
1476
|
4. subject should be concise, no more than 50 characters
|
|
1408
|
-
5. Return only
|
|
1477
|
+
5. Return only ONE commit message, even if multiple files are changed, summarize into one message
|
|
1478
|
+
6. No explanations or extra content
|
|
1409
1479
|
|
|
1410
1480
|
Examples:
|
|
1411
1481
|
- feat(auth): add user login functionality
|
|
@@ -1441,27 +1511,6 @@ async function callGitHubAPI(prompt, apiKey, model, maxTokens) {
|
|
|
1441
1511
|
const data = await response.json();
|
|
1442
1512
|
return data.choices[0]?.message?.content?.trim() || "";
|
|
1443
1513
|
}
|
|
1444
|
-
async function callGroqAPI(prompt, apiKey, model, maxTokens) {
|
|
1445
|
-
const response = await fetch(AI_PROVIDERS.groq.endpoint, {
|
|
1446
|
-
method: "POST",
|
|
1447
|
-
headers: {
|
|
1448
|
-
Authorization: `Bearer ${apiKey}`,
|
|
1449
|
-
"Content-Type": "application/json"
|
|
1450
|
-
},
|
|
1451
|
-
body: JSON.stringify({
|
|
1452
|
-
model,
|
|
1453
|
-
messages: [{ role: "user", content: prompt }],
|
|
1454
|
-
max_tokens: maxTokens,
|
|
1455
|
-
temperature: 0.3
|
|
1456
|
-
})
|
|
1457
|
-
});
|
|
1458
|
-
if (!response.ok) {
|
|
1459
|
-
const error = await response.text();
|
|
1460
|
-
throw new Error(`Groq API \u9519\u8BEF: ${response.status} ${error}`);
|
|
1461
|
-
}
|
|
1462
|
-
const data = await response.json();
|
|
1463
|
-
return data.choices[0]?.message?.content?.trim() || "";
|
|
1464
|
-
}
|
|
1465
1514
|
async function callOpenAIAPI(prompt, apiKey, model, maxTokens) {
|
|
1466
1515
|
const response = await fetch(AI_PROVIDERS.openai.endpoint, {
|
|
1467
1516
|
method: "POST",
|
|
@@ -1536,7 +1585,7 @@ async function callOllamaAPI(prompt, model, maxTokens) {
|
|
|
1536
1585
|
}
|
|
1537
1586
|
async function generateAICommitMessage(config2) {
|
|
1538
1587
|
const aiConfig = config2.aiCommit || {};
|
|
1539
|
-
const provider = aiConfig.provider || "
|
|
1588
|
+
const provider = aiConfig.provider || "github";
|
|
1540
1589
|
const language = aiConfig.language || "zh-CN";
|
|
1541
1590
|
const maxTokens = aiConfig.maxTokens || 200;
|
|
1542
1591
|
const diff = getGitDiff();
|
|
@@ -1560,8 +1609,6 @@ async function generateAICommitMessage(config2) {
|
|
|
1560
1609
|
switch (provider) {
|
|
1561
1610
|
case "github":
|
|
1562
1611
|
return await callGitHubAPI(prompt, apiKey, model, maxTokens);
|
|
1563
|
-
case "groq":
|
|
1564
|
-
return await callGroqAPI(prompt, apiKey, model, maxTokens);
|
|
1565
1612
|
case "openai":
|
|
1566
1613
|
return await callOpenAIAPI(prompt, apiKey, model, maxTokens);
|
|
1567
1614
|
case "claude":
|
|
@@ -1634,18 +1681,7 @@ function formatFileStatus(status) {
|
|
|
1634
1681
|
async function commit() {
|
|
1635
1682
|
const config2 = getConfig();
|
|
1636
1683
|
let { staged, unstaged } = parseGitStatus();
|
|
1637
|
-
if (
|
|
1638
|
-
if (unstaged.length === 0) {
|
|
1639
|
-
console.log(colors.yellow("\u5DE5\u4F5C\u533A\u5E72\u51C0\uFF0C\u6CA1\u6709\u9700\u8981\u63D0\u4EA4\u7684\u66F4\u6539"));
|
|
1640
|
-
return;
|
|
1641
|
-
}
|
|
1642
|
-
console.log(colors.yellow("\u6CA1\u6709\u6682\u5B58\u7684\u66F4\u6539"));
|
|
1643
|
-
divider();
|
|
1644
|
-
console.log("\u672A\u6682\u5B58\u7684\u6587\u4EF6:");
|
|
1645
|
-
for (const { status, file } of unstaged) {
|
|
1646
|
-
console.log(` ${formatFileStatus(status)} ${file}`);
|
|
1647
|
-
}
|
|
1648
|
-
divider();
|
|
1684
|
+
if (unstaged.length > 0) {
|
|
1649
1685
|
const autoStage = config2.autoStage ?? true;
|
|
1650
1686
|
if (autoStage) {
|
|
1651
1687
|
execSync5("git add -A", { stdio: "pipe" });
|
|
@@ -1653,7 +1689,15 @@ async function commit() {
|
|
|
1653
1689
|
divider();
|
|
1654
1690
|
const newStatus = parseGitStatus();
|
|
1655
1691
|
staged = newStatus.staged;
|
|
1656
|
-
|
|
1692
|
+
unstaged = newStatus.unstaged;
|
|
1693
|
+
} else if (staged.length === 0) {
|
|
1694
|
+
console.log(colors.yellow("\u6CA1\u6709\u6682\u5B58\u7684\u66F4\u6539"));
|
|
1695
|
+
divider();
|
|
1696
|
+
console.log("\u672A\u6682\u5B58\u7684\u6587\u4EF6:");
|
|
1697
|
+
for (const { status, file } of unstaged) {
|
|
1698
|
+
console.log(` ${formatFileStatus(status)} ${file}`);
|
|
1699
|
+
}
|
|
1700
|
+
divider();
|
|
1657
1701
|
const filesToStage = await checkbox({
|
|
1658
1702
|
message: "\u9009\u62E9\u8981\u6682\u5B58\u7684\u6587\u4EF6:",
|
|
1659
1703
|
choices: unstaged.map(({ status, file }) => ({
|
|
@@ -1675,13 +1719,16 @@ async function commit() {
|
|
|
1675
1719
|
const newStatus = parseGitStatus();
|
|
1676
1720
|
staged = newStatus.staged;
|
|
1677
1721
|
}
|
|
1678
|
-
} else {
|
|
1679
|
-
console.log("\u5DF2\u6682\u5B58\u7684\u6587\u4EF6:");
|
|
1680
|
-
for (const { status, file } of staged) {
|
|
1681
|
-
console.log(` ${formatFileStatus(status)} ${file}`);
|
|
1682
|
-
}
|
|
1683
|
-
divider();
|
|
1684
1722
|
}
|
|
1723
|
+
if (staged.length === 0) {
|
|
1724
|
+
console.log(colors.yellow("\u5DE5\u4F5C\u533A\u5E72\u51C0\uFF0C\u6CA1\u6709\u9700\u8981\u63D0\u4EA4\u7684\u66F4\u6539"));
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
console.log("\u5DF2\u6682\u5B58\u7684\u6587\u4EF6:");
|
|
1728
|
+
for (const { status, file } of staged) {
|
|
1729
|
+
console.log(` ${formatFileStatus(status)} ${file}`);
|
|
1730
|
+
}
|
|
1731
|
+
divider();
|
|
1685
1732
|
const aiAvailable = isAICommitAvailable(config2);
|
|
1686
1733
|
let commitMode = "manual";
|
|
1687
1734
|
if (aiAvailable) {
|
|
@@ -1876,7 +1923,10 @@ Tag \u547D\u4EE4:
|
|
|
1876
1923
|
gw r \u540C\u4E0A (\u522B\u540D)
|
|
1877
1924
|
|
|
1878
1925
|
\u914D\u7F6E\u547D\u4EE4:
|
|
1879
|
-
gw init \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6
|
|
1926
|
+
gw init \u521D\u59CB\u5316\u914D\u7F6E\u6587\u4EF6
|
|
1927
|
+
\u2022 \u5168\u5C40\u914D\u7F6E: ~/.gwrc.json (\u6240\u6709\u9879\u76EE\u751F\u6548)
|
|
1928
|
+
\u2022 \u9879\u76EE\u914D\u7F6E: .gwrc.json (\u4EC5\u5F53\u524D\u9879\u76EE)
|
|
1929
|
+
\u8FD0\u884C\u65F6\u53EF\u9009\u62E9\u914D\u7F6E\u8303\u56F4
|
|
1880
1930
|
|
|
1881
1931
|
Stash \u547D\u4EE4:
|
|
1882
1932
|
gw stash \u4EA4\u4E92\u5F0F\u7BA1\u7406 stash
|
|
@@ -1911,8 +1961,8 @@ Commit \u547D\u4EE4:
|
|
|
1911
1961
|
// src/update-notifier.ts
|
|
1912
1962
|
import { execSync as execSync6 } from "child_process";
|
|
1913
1963
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
|
|
1914
|
-
import { homedir } from "os";
|
|
1915
|
-
import { join as
|
|
1964
|
+
import { homedir as homedir3 } from "os";
|
|
1965
|
+
import { join as join3 } from "path";
|
|
1916
1966
|
import boxen from "boxen";
|
|
1917
1967
|
import { select as select7 } from "@inquirer/prompts";
|
|
1918
1968
|
import ora5 from "ora";
|
|
@@ -2007,15 +2057,7 @@ async function performUpdate(packageName) {
|
|
|
2007
2057
|
spinner: "dots"
|
|
2008
2058
|
}).start();
|
|
2009
2059
|
try {
|
|
2010
|
-
|
|
2011
|
-
execSync6(`npm uninstall -g ${packageName}`, {
|
|
2012
|
-
encoding: "utf-8",
|
|
2013
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
2014
|
-
});
|
|
2015
|
-
spinner.text = "\u6B63\u5728\u5B89\u88C5\u65B0\u7248\u672C...";
|
|
2016
|
-
} catch {
|
|
2017
|
-
}
|
|
2018
|
-
execSync6(`npm install -g ${packageName}`, {
|
|
2060
|
+
execSync6(`npm install -g ${packageName}@latest`, {
|
|
2019
2061
|
encoding: "utf-8",
|
|
2020
2062
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2021
2063
|
});
|
|
@@ -2026,11 +2068,7 @@ async function performUpdate(packageName) {
|
|
|
2026
2068
|
[
|
|
2027
2069
|
colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01"),
|
|
2028
2070
|
"",
|
|
2029
|
-
colors.dim("\u8BF7\
|
|
2030
|
-
"",
|
|
2031
|
-
colors.yellow(" hash -r && gw --version"),
|
|
2032
|
-
"",
|
|
2033
|
-
colors.dim("\u6216\u8005\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF")
|
|
2071
|
+
colors.dim("\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF\u4F7F\u7528\u65B0\u7248\u672C")
|
|
2034
2072
|
].join("\n"),
|
|
2035
2073
|
{
|
|
2036
2074
|
padding: 1,
|
|
@@ -2046,13 +2084,13 @@ async function performUpdate(packageName) {
|
|
|
2046
2084
|
spinner.fail(colors.red("\u66F4\u65B0\u5931\u8D25"));
|
|
2047
2085
|
console.log("");
|
|
2048
2086
|
console.log(colors.dim(" \u4F60\u53EF\u4EE5\u624B\u52A8\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u66F4\u65B0:"));
|
|
2049
|
-
console.log(colors.cyan(` npm install -g ${packageName}`));
|
|
2087
|
+
console.log(colors.cyan(` npm install -g ${packageName}@latest`));
|
|
2050
2088
|
console.log("");
|
|
2051
2089
|
}
|
|
2052
2090
|
}
|
|
2053
2091
|
function readCache() {
|
|
2054
2092
|
try {
|
|
2055
|
-
const cacheFile =
|
|
2093
|
+
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
2056
2094
|
if (!existsSync3(cacheFile)) {
|
|
2057
2095
|
return null;
|
|
2058
2096
|
}
|
|
@@ -2064,7 +2102,7 @@ function readCache() {
|
|
|
2064
2102
|
}
|
|
2065
2103
|
function writeCache(cache) {
|
|
2066
2104
|
try {
|
|
2067
|
-
const cacheFile =
|
|
2105
|
+
const cacheFile = join3(homedir3(), CACHE_FILE);
|
|
2068
2106
|
writeFileSync3(cacheFile, JSON.stringify(cache), "utf-8");
|
|
2069
2107
|
} catch {
|
|
2070
2108
|
}
|
|
@@ -2095,7 +2133,7 @@ process.on("SIGTERM", () => {
|
|
|
2095
2133
|
console.log("");
|
|
2096
2134
|
process.exit(0);
|
|
2097
2135
|
});
|
|
2098
|
-
var version = true ? "0.2.
|
|
2136
|
+
var version = true ? "0.2.18" : "0.0.0-dev";
|
|
2099
2137
|
async function mainMenu() {
|
|
2100
2138
|
console.log(
|
|
2101
2139
|
colors.green(`
|
|
@@ -2107,7 +2145,7 @@ async function mainMenu() {
|
|
|
2107
2145
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
|
|
2108
2146
|
`)
|
|
2109
2147
|
);
|
|
2110
|
-
console.log(colors.dim(` git-workflow v${version}
|
|
2148
|
+
console.log(colors.dim(` git-workflow v${colors.yellow(version)}
|
|
2111
2149
|
`));
|
|
2112
2150
|
const action = await select8({
|
|
2113
2151
|
message: "\u9009\u62E9\u64CD\u4F5C:",
|
|
@@ -2275,5 +2313,10 @@ cli.help((sections) => {
|
|
|
2275
2313
|
body: showHelp()
|
|
2276
2314
|
});
|
|
2277
2315
|
});
|
|
2278
|
-
cli.
|
|
2316
|
+
cli.option("-v, --version", "\u663E\u793A\u7248\u672C\u53F7");
|
|
2317
|
+
var args = process.argv.slice(2);
|
|
2318
|
+
if (args.includes("-v") || args.includes("--version")) {
|
|
2319
|
+
console.log(colors.yellow(`v${version}`));
|
|
2320
|
+
process.exit(0);
|
|
2321
|
+
}
|
|
2279
2322
|
cli.parse();
|
package/package.json
CHANGED
package/scripts/publish.js
CHANGED
|
@@ -29,12 +29,15 @@ function exec(command, silent = false) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function runStep(stepNum, stepName, command) {
|
|
32
|
+
async function runStep(stepNum, stepName, command) {
|
|
33
33
|
const spinner = ora({
|
|
34
34
|
text: `${colors.blue(`[${stepNum}/${TOTAL_STEPS}]`)} ${stepName}...`,
|
|
35
35
|
spinner: "dots",
|
|
36
36
|
}).start();
|
|
37
37
|
|
|
38
|
+
// 给 spinner 一点时间渲染
|
|
39
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
40
|
+
|
|
38
41
|
try {
|
|
39
42
|
execSync(command, { encoding: "utf-8", stdio: "pipe" });
|
|
40
43
|
spinner.succeed(
|
|
@@ -56,7 +59,7 @@ async function main() {
|
|
|
56
59
|
console.log("");
|
|
57
60
|
|
|
58
61
|
// [1] 检查 Git 仓库
|
|
59
|
-
if (!runStep(1, "检查 Git 仓库", "git rev-parse --git-dir")) {
|
|
62
|
+
if (!(await runStep(1, "检查 Git 仓库", "git rev-parse --git-dir"))) {
|
|
60
63
|
console.log(colors.red("✖ 当前目录不是 git 仓库"));
|
|
61
64
|
process.exit(1);
|
|
62
65
|
}
|
|
@@ -67,6 +70,8 @@ async function main() {
|
|
|
67
70
|
spinner: "dots",
|
|
68
71
|
}).start();
|
|
69
72
|
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
74
|
+
|
|
70
75
|
const status = exec("git status --porcelain", true);
|
|
71
76
|
if (status && status.trim()) {
|
|
72
77
|
spinner2.fail(`${colors.blue("[2/11]")} 检查工作区状态`);
|
|
@@ -86,6 +91,8 @@ async function main() {
|
|
|
86
91
|
spinner: "dots",
|
|
87
92
|
}).start();
|
|
88
93
|
|
|
94
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
95
|
+
|
|
89
96
|
const npmUser = exec("npm whoami", true);
|
|
90
97
|
if (!npmUser) {
|
|
91
98
|
spinner3.fail(`${colors.blue("[3/11]")} 检查 npm 登录状态`);
|
|
@@ -102,7 +109,7 @@ async function main() {
|
|
|
102
109
|
const currentBranch = exec("git branch --show-current", true).trim();
|
|
103
110
|
|
|
104
111
|
// [4] 拉取最新代码
|
|
105
|
-
if (!runStep(4, "拉取最新代码", `git pull origin ${currentBranch}`)) {
|
|
112
|
+
if (!(await runStep(4, "拉取最新代码", `git pull origin ${currentBranch}`))) {
|
|
106
113
|
process.exit(1);
|
|
107
114
|
}
|
|
108
115
|
|
|
@@ -167,12 +174,12 @@ async function main() {
|
|
|
167
174
|
);
|
|
168
175
|
|
|
169
176
|
// [6] 构建项目
|
|
170
|
-
if (!runStep(6, "构建项目", "npm run build")) {
|
|
177
|
+
if (!(await runStep(6, "构建项目", "npm run build"))) {
|
|
171
178
|
process.exit(1);
|
|
172
179
|
}
|
|
173
180
|
|
|
174
181
|
// [7] 生成 CHANGELOG
|
|
175
|
-
if (!runStep(7, "生成 CHANGELOG", "npm run changelog")) {
|
|
182
|
+
if (!(await runStep(7, "生成 CHANGELOG", "npm run changelog"))) {
|
|
176
183
|
process.exit(1);
|
|
177
184
|
}
|
|
178
185
|
|
|
@@ -182,6 +189,8 @@ async function main() {
|
|
|
182
189
|
spinner: "dots",
|
|
183
190
|
}).start();
|
|
184
191
|
|
|
192
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
193
|
+
|
|
185
194
|
try {
|
|
186
195
|
execSync("git add package.json CHANGELOG.md", { stdio: "pipe" });
|
|
187
196
|
execSync(`git commit -m "🔖 chore(release): 发布 v${newVersion}"`, {
|
|
@@ -206,6 +215,8 @@ async function main() {
|
|
|
206
215
|
spinner: "dots",
|
|
207
216
|
}).start();
|
|
208
217
|
|
|
218
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
219
|
+
|
|
209
220
|
try {
|
|
210
221
|
execSync(`git tag -a "v${newVersion}" -m "Release v${newVersion}"`, {
|
|
211
222
|
stdio: "pipe",
|
|
@@ -227,6 +238,8 @@ async function main() {
|
|
|
227
238
|
spinner: "dots",
|
|
228
239
|
}).start();
|
|
229
240
|
|
|
241
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
242
|
+
|
|
230
243
|
try {
|
|
231
244
|
execSync(`git push origin ${currentBranch}`, { stdio: "pipe" });
|
|
232
245
|
execSync(`git push origin v${newVersion}`, { stdio: "pipe" });
|