@nick848/sf-cli 1.0.2 → 1.0.3
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 +44 -0
- package/README.md +4 -23
- package/dist/cli/index.js +272 -30
- 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 +251 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +250 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import * as path5 from 'path';
|
|
|
2
2
|
import path5__default from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import * as fs4 from 'fs/promises';
|
|
5
|
-
import * as
|
|
5
|
+
import * as fs10 from 'fs';
|
|
6
6
|
import * as crypto from 'crypto';
|
|
7
7
|
import * as os from 'os';
|
|
8
8
|
import { encoding_for_model } from 'tiktoken';
|
|
@@ -31,8 +31,8 @@ var KEY_FILE = ".key";
|
|
|
31
31
|
function getOrCreateEncryptionKey() {
|
|
32
32
|
const keyPath = path5.join(os.homedir(), KEY_DIR, KEY_FILE);
|
|
33
33
|
try {
|
|
34
|
-
if (
|
|
35
|
-
const keyBase64 =
|
|
34
|
+
if (fs10.existsSync(keyPath)) {
|
|
35
|
+
const keyBase64 = fs10.readFileSync(keyPath, "utf-8").trim();
|
|
36
36
|
return Buffer.from(keyBase64, "base64");
|
|
37
37
|
}
|
|
38
38
|
} catch {
|
|
@@ -40,10 +40,10 @@ function getOrCreateEncryptionKey() {
|
|
|
40
40
|
const key = crypto.randomBytes(32);
|
|
41
41
|
try {
|
|
42
42
|
const keyDir = path5.dirname(keyPath);
|
|
43
|
-
if (!
|
|
44
|
-
|
|
43
|
+
if (!fs10.existsSync(keyDir)) {
|
|
44
|
+
fs10.mkdirSync(keyDir, { recursive: true, mode: 448 });
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
fs10.writeFileSync(keyPath, key.toString("base64"), {
|
|
47
47
|
mode: 384,
|
|
48
48
|
// 仅所有者可读写
|
|
49
49
|
encoding: "utf-8"
|
|
@@ -2520,10 +2520,10 @@ var FRONTEND_DEV_AGENT = {
|
|
|
2520
2520
|
var CODE_REVIEWER_AGENT = {
|
|
2521
2521
|
id: "code-reviewer",
|
|
2522
2522
|
name: "\u4EE3\u7801\u5BA1\u6838",
|
|
2523
|
-
description: "\u5BA1\u6838\u4EE3\u7801\u8D28\u91CF\u3001\u5B89\u5168\u6027\u548C\u89C4\u8303\u6027\uFF0C\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE",
|
|
2523
|
+
description: "\u5BA1\u6838\u4EE3\u7801\u8D28\u91CF\u3001\u5B89\u5168\u6027\u548C\u89C4\u8303\u6027\uFF0C\u6267\u884C\u56DE\u5F52\u6D4B\u8BD5\uFF0C\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE",
|
|
2524
2524
|
icon: "\u{1F50D}",
|
|
2525
|
-
version: "1.
|
|
2526
|
-
role: "\u4F60\u662F\u4E00\u540D\u8D44\u6DF1\u4EE3\u7801\u5BA1\u6838\u4E13\u5BB6\uFF0C\u4E13\u6CE8\u4E8E\u4EE3\u7801\u8D28\u91CF\u3001\u5B89\u5168\u6027\u548C\u6700\u4F73\u5B9E\u8DF5\u3002\u4F60\u8D1F\u8D23\u5BA1\u67E5\u4EE3\u7801\u5E76\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE\u3002",
|
|
2525
|
+
version: "1.1.0",
|
|
2526
|
+
role: "\u4F60\u662F\u4E00\u540D\u8D44\u6DF1\u4EE3\u7801\u5BA1\u6838\u4E13\u5BB6\uFF0C\u4E13\u6CE8\u4E8E\u4EE3\u7801\u8D28\u91CF\u3001\u5B89\u5168\u6027\u548C\u6700\u4F73\u5B9E\u8DF5\u3002\u4F60\u8D1F\u8D23\u5BA1\u67E5\u4EE3\u7801\u3001\u6267\u884C\u56DE\u5F52\u6D4B\u8BD5\u5E76\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE\u3002",
|
|
2527
2527
|
capabilities: [
|
|
2528
2528
|
{
|
|
2529
2529
|
id: "quality-review",
|
|
@@ -2544,13 +2544,24 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2544
2544
|
id: "performance-review",
|
|
2545
2545
|
name: "\u6027\u80FD\u5BA1\u67E5",
|
|
2546
2546
|
description: "\u68C0\u67E5\u6027\u80FD\u95EE\u9898\u548C\u4F18\u5316\u5EFA\u8BAE"
|
|
2547
|
+
},
|
|
2548
|
+
{
|
|
2549
|
+
id: "regression-test",
|
|
2550
|
+
name: "\u56DE\u5F52\u6D4B\u8BD5",
|
|
2551
|
+
description: "\u6267\u884C\u6D4B\u8BD5\u5957\u4EF6\uFF0C\u786E\u4FDD\u4FEE\u6539\u4E0D\u7834\u574F\u5DF2\u6709\u529F\u80FD"
|
|
2552
|
+
},
|
|
2553
|
+
{
|
|
2554
|
+
id: "coverage-analysis",
|
|
2555
|
+
name: "\u8986\u76D6\u7387\u5206\u6790",
|
|
2556
|
+
description: "\u5206\u6790\u6D4B\u8BD5\u8986\u76D6\u7387\u5E76\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE"
|
|
2547
2557
|
}
|
|
2548
2558
|
],
|
|
2549
2559
|
tools: [
|
|
2550
2560
|
{ name: "read_file", description: "\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9", permission: "full" },
|
|
2551
2561
|
{ name: "glob", description: "\u641C\u7D22\u6587\u4EF6", permission: "full" },
|
|
2552
2562
|
{ name: "search_file_content", description: "\u641C\u7D22\u6587\u4EF6\u5185\u5BB9", permission: "full" },
|
|
2553
|
-
{ name: "list_directory", description: "\u5217\u51FA\u76EE\u5F55\u5185\u5BB9", permission: "full" }
|
|
2563
|
+
{ name: "list_directory", description: "\u5217\u51FA\u76EE\u5F55\u5185\u5BB9", permission: "full" },
|
|
2564
|
+
{ name: "run_shell_command", description: "\u6267\u884C\u6D4B\u8BD5\u547D\u4EE4", permission: "confirm" }
|
|
2554
2565
|
],
|
|
2555
2566
|
triggers: [
|
|
2556
2567
|
{ type: "workflow", condition: { workflowStep: "apply" }, priority: 10 },
|
|
@@ -2561,6 +2572,7 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2561
2572
|
protectedPaths: ["node_modules", ".git"]
|
|
2562
2573
|
},
|
|
2563
2574
|
behavior: {
|
|
2575
|
+
requireConfirmation: ["run_shell_command"],
|
|
2564
2576
|
autoCommit: false
|
|
2565
2577
|
}
|
|
2566
2578
|
},
|
|
@@ -2569,6 +2581,7 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2569
2581
|
## \u4F60\u7684\u804C\u8D23
|
|
2570
2582
|
- \u5BA1\u67E5\u4EE3\u7801\u8D28\u91CF\u548C\u53EF\u7EF4\u62A4\u6027
|
|
2571
2583
|
- \u68C0\u67E5\u5B89\u5168\u6F0F\u6D1E\u548C\u98CE\u9669
|
|
2584
|
+
- \u6267\u884C\u56DE\u5F52\u6D4B\u8BD5\uFF0C\u786E\u4FDD\u4FEE\u6539\u4E0D\u7834\u574F\u5DF2\u6709\u529F\u80FD
|
|
2572
2585
|
- \u63D0\u4F9B\u5177\u4F53\u7684\u6539\u8FDB\u5EFA\u8BAE
|
|
2573
2586
|
- \u786E\u4FDD\u9075\u5FAA\u6700\u4F73\u5B9E\u8DF5
|
|
2574
2587
|
|
|
@@ -2577,8 +2590,20 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2577
2590
|
2. **\u5B89\u5168\u6027**: XSS\u3001\u6CE8\u5165\u3001\u654F\u611F\u6570\u636E\u5904\u7406
|
|
2578
2591
|
3. **\u6027\u80FD**: \u7B97\u6CD5\u6548\u7387\u3001\u5185\u5B58\u4F7F\u7528\u3001\u6E32\u67D3\u4F18\u5316
|
|
2579
2592
|
4. **\u89C4\u8303\u6027**: \u547D\u540D\u3001\u683C\u5F0F\u3001\u6CE8\u91CA
|
|
2593
|
+
5. **\u6D4B\u8BD5\u8986\u76D6**: \u56DE\u5F52\u6D4B\u8BD5\u7ED3\u679C\u3001\u8986\u76D6\u7387\u5206\u6790
|
|
2594
|
+
|
|
2595
|
+
## \u56DE\u5F52\u6D4B\u8BD5\u6D41\u7A0B
|
|
2596
|
+
1. \u6267\u884C \`npm test -- --run\` \u8FD0\u884C\u6D4B\u8BD5\u5957\u4EF6
|
|
2597
|
+
2. \u5206\u6790\u6D4B\u8BD5\u7ED3\u679C\uFF0C\u8BC6\u522B\u5931\u8D25\u7684\u6D4B\u8BD5\u7528\u4F8B
|
|
2598
|
+
3. \u5982\u679C\u6D4B\u8BD5\u5931\u8D25\uFF0C\u963B\u6B62\u5F52\u6863\u5E76\u63D0\u793A\u4FEE\u590D
|
|
2599
|
+
4. \u63D0\u4F9B\u8986\u76D6\u7387\u62A5\u544A\u548C\u6539\u8FDB\u5EFA\u8BAE
|
|
2580
2600
|
|
|
2581
2601
|
## \u8F93\u51FA\u683C\u5F0F
|
|
2602
|
+
### \u56DE\u5F52\u6D4B\u8BD5\u7ED3\u679C
|
|
2603
|
+
- \u6D4B\u8BD5\u901A\u8FC7/\u5931\u8D25\u72B6\u6001
|
|
2604
|
+
- \u901A\u8FC7/\u5931\u8D25\u6570\u91CF
|
|
2605
|
+
- \u8986\u76D6\u7387\u767E\u5206\u6BD4
|
|
2606
|
+
|
|
2582
2607
|
### \u5BA1\u67E5\u7ED3\u679C
|
|
2583
2608
|
- \u901A\u8FC7/\u9700\u4FEE\u6539/\u4E0D\u901A\u8FC7
|
|
2584
2609
|
|
|
@@ -2604,7 +2629,7 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2604
2629
|
## \u4E0A\u4E0B\u6587
|
|
2605
2630
|
{{context}}
|
|
2606
2631
|
|
|
2607
|
-
\u8BF7\u5BF9\u4EE5\u4E0A\u6587\u4EF6\u8FDB\u884C\u5168\u9762\u5BA1\u67E5\uFF0C\u63D0\u4F9B\u8BE6\u7EC6\u7684\u5BA1\u67E5\u62A5\u544A\u548C\u6539\u8FDB\u5EFA\u8BAE\u3002`,
|
|
2632
|
+
\u8BF7\u5BF9\u4EE5\u4E0A\u6587\u4EF6\u8FDB\u884C\u5168\u9762\u5BA1\u67E5\uFF0C\u6267\u884C\u56DE\u5F52\u6D4B\u8BD5\uFF0C\u5E76\u63D0\u4F9B\u8BE6\u7EC6\u7684\u5BA1\u67E5\u62A5\u544A\u548C\u6539\u8FDB\u5EFA\u8BAE\u3002`,
|
|
2608
2633
|
outputFormat: {
|
|
2609
2634
|
type: "markdown"
|
|
2610
2635
|
}
|
|
@@ -5594,8 +5619,8 @@ var CommandParser = class {
|
|
|
5594
5619
|
};
|
|
5595
5620
|
}
|
|
5596
5621
|
parseAtPath(input) {
|
|
5597
|
-
const
|
|
5598
|
-
if (!
|
|
5622
|
+
const path15 = input.slice(1).trim();
|
|
5623
|
+
if (!path15) {
|
|
5599
5624
|
return { success: false, error: "\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84" };
|
|
5600
5625
|
}
|
|
5601
5626
|
return {
|
|
@@ -5603,7 +5628,7 @@ var CommandParser = class {
|
|
|
5603
5628
|
command: {
|
|
5604
5629
|
type: "at" /* AT */,
|
|
5605
5630
|
raw: input,
|
|
5606
|
-
path:
|
|
5631
|
+
path: path15
|
|
5607
5632
|
}
|
|
5608
5633
|
};
|
|
5609
5634
|
}
|
|
@@ -6447,10 +6472,26 @@ function createSpinner(message) {
|
|
|
6447
6472
|
stop: () => process.stdout.write(" ".repeat(message.length + 10) + "\r")
|
|
6448
6473
|
};
|
|
6449
6474
|
}
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6475
|
+
function getPackageInfo() {
|
|
6476
|
+
const possiblePaths = [
|
|
6477
|
+
path5.resolve(__dirname$1, "..", "..", "package.json"),
|
|
6478
|
+
path5.resolve(__dirname$1, "..", "..", "..", "package.json")
|
|
6479
|
+
];
|
|
6480
|
+
for (const pkgPath of possiblePaths) {
|
|
6481
|
+
try {
|
|
6482
|
+
if (fs10.existsSync(pkgPath)) {
|
|
6483
|
+
const content = fs10.readFileSync(pkgPath, "utf-8");
|
|
6484
|
+
return JSON.parse(content);
|
|
6485
|
+
}
|
|
6486
|
+
} catch {
|
|
6487
|
+
continue;
|
|
6488
|
+
}
|
|
6489
|
+
}
|
|
6490
|
+
return { version: "1.0.0", name: "@nick848/sf-cli" };
|
|
6491
|
+
}
|
|
6492
|
+
var packageInfo = getPackageInfo();
|
|
6493
|
+
var CURRENT_VERSION = packageInfo.version;
|
|
6494
|
+
var PACKAGE_NAME = packageInfo.name;
|
|
6454
6495
|
async function handleUpdate(args, ctx) {
|
|
6455
6496
|
const options = {
|
|
6456
6497
|
check: args.includes("--check") || args.includes("-c"),
|
|
@@ -6904,6 +6945,78 @@ function extractTitle(requirement) {
|
|
|
6904
6945
|
return requirement.slice(0, 47) + "...";
|
|
6905
6946
|
}
|
|
6906
6947
|
var autoScheduleEnabled = true;
|
|
6948
|
+
var DEFAULT_REGRESSION_CONFIG = {
|
|
6949
|
+
enabled: true,
|
|
6950
|
+
command: "npm test -- --run",
|
|
6951
|
+
timeout: 12e4,
|
|
6952
|
+
// 2分钟
|
|
6953
|
+
coverageThreshold: 80
|
|
6954
|
+
};
|
|
6955
|
+
async function runRegressionTest(workingDirectory, config = DEFAULT_REGRESSION_CONFIG) {
|
|
6956
|
+
const startTime = Date.now();
|
|
6957
|
+
const result = {
|
|
6958
|
+
success: false,
|
|
6959
|
+
passed: 0,
|
|
6960
|
+
failed: 0,
|
|
6961
|
+
total: 0,
|
|
6962
|
+
duration: 0,
|
|
6963
|
+
output: "",
|
|
6964
|
+
errors: []
|
|
6965
|
+
};
|
|
6966
|
+
return new Promise((resolve4) => {
|
|
6967
|
+
const proc = spawn(config.command, [], {
|
|
6968
|
+
cwd: workingDirectory,
|
|
6969
|
+
shell: true,
|
|
6970
|
+
stdio: "pipe"
|
|
6971
|
+
});
|
|
6972
|
+
let stdout = "";
|
|
6973
|
+
let stderr = "";
|
|
6974
|
+
proc.stdout?.on("data", (data) => {
|
|
6975
|
+
stdout += data.toString();
|
|
6976
|
+
});
|
|
6977
|
+
proc.stderr?.on("data", (data) => {
|
|
6978
|
+
stderr += data.toString();
|
|
6979
|
+
});
|
|
6980
|
+
const timeout = setTimeout(() => {
|
|
6981
|
+
proc.kill();
|
|
6982
|
+
result.errors.push("\u6D4B\u8BD5\u8D85\u65F6");
|
|
6983
|
+
result.output = stdout + stderr;
|
|
6984
|
+
result.duration = Date.now() - startTime;
|
|
6985
|
+
resolve4(result);
|
|
6986
|
+
}, config.timeout);
|
|
6987
|
+
proc.on("close", (code) => {
|
|
6988
|
+
clearTimeout(timeout);
|
|
6989
|
+
result.output = stdout + stderr;
|
|
6990
|
+
result.duration = Date.now() - startTime;
|
|
6991
|
+
const passMatch = stdout.match(/(\d+)\s+(?:passed|tests?\s+passed)/i);
|
|
6992
|
+
const failMatch = stdout.match(/(\d+)\s+(?:failed|tests?\s+failed)/i);
|
|
6993
|
+
const totalMatch = stdout.match(/Tests?:\s*(\d+)/i);
|
|
6994
|
+
if (passMatch) {
|
|
6995
|
+
result.passed = parseInt(passMatch[1], 10);
|
|
6996
|
+
}
|
|
6997
|
+
if (failMatch) {
|
|
6998
|
+
result.failed = parseInt(failMatch[1], 10);
|
|
6999
|
+
}
|
|
7000
|
+
if (totalMatch) {
|
|
7001
|
+
result.total = parseInt(totalMatch[1], 10);
|
|
7002
|
+
} else {
|
|
7003
|
+
result.total = result.passed + result.failed;
|
|
7004
|
+
}
|
|
7005
|
+
const coverageMatch = stdout.match(/All files[^\d]*(\d+(?:\.\d+)?)/);
|
|
7006
|
+
if (coverageMatch) {
|
|
7007
|
+
result.coverage = parseFloat(coverageMatch[1]);
|
|
7008
|
+
}
|
|
7009
|
+
result.success = code === 0 && result.failed === 0;
|
|
7010
|
+
resolve4(result);
|
|
7011
|
+
});
|
|
7012
|
+
proc.on("error", (err) => {
|
|
7013
|
+
clearTimeout(timeout);
|
|
7014
|
+
result.errors.push(err.message);
|
|
7015
|
+
result.duration = Date.now() - startTime;
|
|
7016
|
+
resolve4(result);
|
|
7017
|
+
});
|
|
7018
|
+
});
|
|
7019
|
+
}
|
|
6907
7020
|
async function handleOpsx(command, args, ctx) {
|
|
6908
7021
|
const step = command.replace("opsx:", "");
|
|
6909
7022
|
const workflow = new WorkflowEngine();
|
|
@@ -6918,7 +7031,7 @@ async function handleOpsx(command, args, ctx) {
|
|
|
6918
7031
|
case "apply":
|
|
6919
7032
|
return handleApply(workflow);
|
|
6920
7033
|
case "archive":
|
|
6921
|
-
return handleArchive(workflow, args);
|
|
7034
|
+
return handleArchive(workflow, args, ctx);
|
|
6922
7035
|
case "propose":
|
|
6923
7036
|
return handlePropose(workflow, args);
|
|
6924
7037
|
case "status":
|
|
@@ -6933,12 +7046,50 @@ async function handleOpsx(command, args, ctx) {
|
|
|
6933
7046
|
return handleNext(workflow);
|
|
6934
7047
|
case "auto":
|
|
6935
7048
|
return handleAutoSchedule(args);
|
|
7049
|
+
case "test":
|
|
7050
|
+
return handleRegressionTest(ctx);
|
|
6936
7051
|
default:
|
|
6937
7052
|
return {
|
|
6938
7053
|
output: chalk9.red(`\u672A\u77E5\u7684OpenSpec\u547D\u4EE4: /${command}`)
|
|
6939
7054
|
};
|
|
6940
7055
|
}
|
|
6941
7056
|
}
|
|
7057
|
+
async function handleRegressionTest(ctx) {
|
|
7058
|
+
const lines = [];
|
|
7059
|
+
lines.push(chalk9.cyan("\u{1F50D} \u6267\u884C\u56DE\u5F52\u6D4B\u8BD5..."));
|
|
7060
|
+
lines.push(chalk9.gray(` \u5DE5\u4F5C\u76EE\u5F55: ${ctx.options.workingDirectory}`));
|
|
7061
|
+
lines.push("");
|
|
7062
|
+
const result = await runRegressionTest(ctx.options.workingDirectory);
|
|
7063
|
+
lines.push(chalk9.gray("\u2500".repeat(50)));
|
|
7064
|
+
if (result.success) {
|
|
7065
|
+
lines.push(chalk9.green("\u2713 \u56DE\u5F52\u6D4B\u8BD5\u901A\u8FC7"));
|
|
7066
|
+
} else {
|
|
7067
|
+
lines.push(chalk9.red("\u2717 \u56DE\u5F52\u6D4B\u8BD5\u5931\u8D25"));
|
|
7068
|
+
}
|
|
7069
|
+
lines.push("");
|
|
7070
|
+
lines.push(chalk9.cyan("\u6D4B\u8BD5\u7ED3\u679C:"));
|
|
7071
|
+
lines.push(chalk9.gray(` \u901A\u8FC7: ${result.passed}`));
|
|
7072
|
+
lines.push(chalk9.gray(` \u5931\u8D25: ${result.failed}`));
|
|
7073
|
+
lines.push(chalk9.gray(` \u603B\u8BA1: ${result.total}`));
|
|
7074
|
+
lines.push(chalk9.gray(` \u8017\u65F6: ${(result.duration / 1e3).toFixed(2)}s`));
|
|
7075
|
+
if (result.coverage !== void 0) {
|
|
7076
|
+
const coverageColor = result.coverage >= 80 ? chalk9.green : result.coverage >= 60 ? chalk9.yellow : chalk9.red;
|
|
7077
|
+
lines.push(coverageColor(` \u8986\u76D6\u7387: ${result.coverage}%`));
|
|
7078
|
+
}
|
|
7079
|
+
if (result.errors.length > 0) {
|
|
7080
|
+
lines.push("");
|
|
7081
|
+
lines.push(chalk9.red("\u9519\u8BEF\u4FE1\u606F:"));
|
|
7082
|
+
for (const error of result.errors) {
|
|
7083
|
+
lines.push(chalk9.gray(` - ${error}`));
|
|
7084
|
+
}
|
|
7085
|
+
}
|
|
7086
|
+
if (result.failed > 0) {
|
|
7087
|
+
lines.push("");
|
|
7088
|
+
lines.push(chalk9.yellow("\u26A0 \u5B58\u5728\u5931\u8D25\u7684\u6D4B\u8BD5\u7528\u4F8B\uFF0C\u8BF7\u68C0\u67E5\u5E76\u4FEE\u590D"));
|
|
7089
|
+
lines.push(chalk9.gray("\u4F7F\u7528 /opsx:rollback \u53EF\u56DE\u6EDA\u5230\u4E4B\u524D\u7684\u9636\u6BB5"));
|
|
7090
|
+
}
|
|
7091
|
+
return { output: lines.join("\n") };
|
|
7092
|
+
}
|
|
6942
7093
|
function handleAutoSchedule(args) {
|
|
6943
7094
|
const action = args[0]?.toLowerCase();
|
|
6944
7095
|
if (!action) {
|
|
@@ -7068,13 +7219,70 @@ async function handleArchive(workflow, args, ctx) {
|
|
|
7068
7219
|
${generateConfirmationPrompt(confirmation.point)}`) + chalk9.cyan("\n\n\u4F7F\u7528 /opsx:confirm code-review \u786E\u8BA4\u540E\u5F52\u6863")
|
|
7069
7220
|
};
|
|
7070
7221
|
}
|
|
7222
|
+
const lines = [];
|
|
7223
|
+
lines.push(chalk9.cyan("\u{1F50D} \u6267\u884C\u5F52\u6863\u524D\u56DE\u5F52\u6D4B\u8BD5..."));
|
|
7224
|
+
lines.push("");
|
|
7225
|
+
const testResult = await runRegressionTest(ctx.options.workingDirectory);
|
|
7226
|
+
if (!testResult.success) {
|
|
7227
|
+
lines.push(chalk9.red("\u2717 \u56DE\u5F52\u6D4B\u8BD5\u5931\u8D25"));
|
|
7228
|
+
lines.push(chalk9.gray(` \u901A\u8FC7: ${testResult.passed} | \u5931\u8D25: ${testResult.failed} | \u603B\u8BA1: ${testResult.total}`));
|
|
7229
|
+
lines.push("");
|
|
7230
|
+
lines.push(chalk9.yellow("\u26A0 \u5F52\u6863\u88AB\u963B\u6B62"));
|
|
7231
|
+
lines.push(chalk9.gray("\n\u8BF7\u4FEE\u590D\u5931\u8D25\u7684\u6D4B\u8BD5\u7528\u4F8B\u540E\u91CD\u8BD5"));
|
|
7232
|
+
lines.push(chalk9.gray("\u4F7F\u7528 /opsx:rollback \u53EF\u56DE\u6EDA\u5230\u4E4B\u524D\u7684\u9636\u6BB5"));
|
|
7233
|
+
lines.push(chalk9.gray("\u4F7F\u7528 /opsx:test \u53EF\u5355\u72EC\u8FD0\u884C\u56DE\u5F52\u6D4B\u8BD5"));
|
|
7234
|
+
return { output: lines.join("\n") };
|
|
7235
|
+
}
|
|
7236
|
+
lines.push(chalk9.green("\u2713 \u56DE\u5F52\u6D4B\u8BD5\u901A\u8FC7"));
|
|
7237
|
+
lines.push(chalk9.gray(` \u901A\u8FC7: ${testResult.passed} | \u8017\u65F6: ${(testResult.duration / 1e3).toFixed(2)}s`));
|
|
7238
|
+
lines.push("");
|
|
7071
7239
|
const changeId = state.id;
|
|
7072
7240
|
const summary = args.join(" ") || "\u5B8C\u6210\u53D8\u66F4";
|
|
7073
7241
|
await workflow.archive(summary);
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
\u53D8\u66F4ID: ${changeId}`) + chalk9.cyan("\n\n\u5F52\u6863\u6587\u6863\u5DF2\u751F\u6210\u5230 openspec/spec/ \u76EE\u5F55")
|
|
7077
|
-
};
|
|
7242
|
+
await updateChangelog(ctx.options.workingDirectory, summary, changeId);
|
|
7243
|
+
lines.push(chalk9.green("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u5F52\u6863") + chalk9.gray(`
|
|
7244
|
+
\u53D8\u66F4ID: ${changeId}`) + chalk9.cyan("\n\n\u5F52\u6863\u6587\u6863\u5DF2\u751F\u6210\u5230 openspec/spec/ \u76EE\u5F55") + chalk9.gray("\nCHANGELOG.md \u5DF2\u66F4\u65B0"));
|
|
7245
|
+
return { output: lines.join("\n") };
|
|
7246
|
+
}
|
|
7247
|
+
async function updateChangelog(workingDirectory, summary, changeId) {
|
|
7248
|
+
try {
|
|
7249
|
+
const changelogPath = path5.join(workingDirectory, "CHANGELOG.md");
|
|
7250
|
+
const pkgPath = path5.join(workingDirectory, "package.json");
|
|
7251
|
+
let version = "1.0.0";
|
|
7252
|
+
try {
|
|
7253
|
+
const pkgContent = fs10.readFileSync(pkgPath, "utf-8");
|
|
7254
|
+
const pkg = JSON.parse(pkgContent);
|
|
7255
|
+
version = pkg.version || "1.0.0";
|
|
7256
|
+
} catch {
|
|
7257
|
+
}
|
|
7258
|
+
const today = /* @__PURE__ */ new Date();
|
|
7259
|
+
const dateStr = today.toISOString().split("T")[0];
|
|
7260
|
+
const entry = `
|
|
7261
|
+
## v${version} (${dateStr})
|
|
7262
|
+
|
|
7263
|
+
**\u53D8\u66F4\u5185\u5BB9**
|
|
7264
|
+
|
|
7265
|
+
- ${summary} (${changeId})
|
|
7266
|
+
`;
|
|
7267
|
+
if (fs10.existsSync(changelogPath)) {
|
|
7268
|
+
const content = fs10.readFileSync(changelogPath, "utf-8");
|
|
7269
|
+
const versionPattern = /^## v\d+\.\d+\.\d+/m;
|
|
7270
|
+
const match = content.match(versionPattern);
|
|
7271
|
+
if (match && match.index !== void 0) {
|
|
7272
|
+
const newContent = content.slice(0, match.index) + entry + content.slice(match.index);
|
|
7273
|
+
fs10.writeFileSync(changelogPath, newContent, "utf-8");
|
|
7274
|
+
} else {
|
|
7275
|
+
fs10.appendFileSync(changelogPath, entry, "utf-8");
|
|
7276
|
+
}
|
|
7277
|
+
} else {
|
|
7278
|
+
const header = `# Changelog
|
|
7279
|
+
|
|
7280
|
+
All notable changes to this project will be documented in this file.
|
|
7281
|
+
`;
|
|
7282
|
+
fs10.writeFileSync(changelogPath, header + entry, "utf-8");
|
|
7283
|
+
}
|
|
7284
|
+
} catch (error) {
|
|
7285
|
+
}
|
|
7078
7286
|
}
|
|
7079
7287
|
async function handlePropose(workflow, args, ctx) {
|
|
7080
7288
|
const state = workflow.getState();
|
|
@@ -7265,9 +7473,25 @@ ${generateConfirmationPrompt(e.point)}`) + chalk9.cyan(`
|
|
|
7265
7473
|
}
|
|
7266
7474
|
|
|
7267
7475
|
// src/commands/runner.ts
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7476
|
+
function getVersion() {
|
|
7477
|
+
const possiblePaths = [
|
|
7478
|
+
path5.resolve(__dirname$1, "..", "..", "package.json"),
|
|
7479
|
+
path5.resolve(__dirname$1, "..", "..", "..", "package.json")
|
|
7480
|
+
];
|
|
7481
|
+
for (const pkgPath of possiblePaths) {
|
|
7482
|
+
try {
|
|
7483
|
+
if (fs10.existsSync(pkgPath)) {
|
|
7484
|
+
const content = fs10.readFileSync(pkgPath, "utf-8");
|
|
7485
|
+
const pkg = JSON.parse(content);
|
|
7486
|
+
return pkg.version;
|
|
7487
|
+
}
|
|
7488
|
+
} catch {
|
|
7489
|
+
continue;
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
return "1.0.0";
|
|
7493
|
+
}
|
|
7494
|
+
var VERSION2 = getVersion();
|
|
7271
7495
|
async function runSlashCommand(command, args, ctx) {
|
|
7272
7496
|
const normalizedCommand = normalizeCommand(command);
|
|
7273
7497
|
switch (normalizedCommand) {
|