@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.d.mts
CHANGED
|
@@ -1772,7 +1772,7 @@ declare function createAgentExecutor(modelService: ModelService, normsManager: N
|
|
|
1772
1772
|
declare const FRONTEND_DEV_AGENT: AgentDefinition;
|
|
1773
1773
|
/**
|
|
1774
1774
|
* 代码审核 Agent
|
|
1775
|
-
*
|
|
1775
|
+
* 负责代码质量检查、安全审查、最佳实践建议、回归测试
|
|
1776
1776
|
*/
|
|
1777
1777
|
declare const CODE_REVIEWER_AGENT: AgentDefinition;
|
|
1778
1778
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1772,7 +1772,7 @@ declare function createAgentExecutor(modelService: ModelService, normsManager: N
|
|
|
1772
1772
|
declare const FRONTEND_DEV_AGENT: AgentDefinition;
|
|
1773
1773
|
/**
|
|
1774
1774
|
* 代码审核 Agent
|
|
1775
|
-
*
|
|
1775
|
+
* 负责代码质量检查、安全审查、最佳实践建议、回归测试
|
|
1776
1776
|
*/
|
|
1777
1777
|
declare const CODE_REVIEWER_AGENT: AgentDefinition;
|
|
1778
1778
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fs4 = require('fs/promises');
|
|
4
|
-
var
|
|
4
|
+
var fs10 = require('fs');
|
|
5
5
|
var path4 = require('path');
|
|
6
6
|
var crypto = require('crypto');
|
|
7
7
|
var os = require('os');
|
|
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
var fs4__namespace = /*#__PURE__*/_interopNamespace(fs4);
|
|
37
|
-
var
|
|
37
|
+
var fs10__namespace = /*#__PURE__*/_interopNamespace(fs10);
|
|
38
38
|
var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
|
|
39
39
|
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
40
40
|
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
@@ -55,8 +55,8 @@ var KEY_FILE = ".key";
|
|
|
55
55
|
function getOrCreateEncryptionKey() {
|
|
56
56
|
const keyPath = path4__namespace.join(os__namespace.homedir(), KEY_DIR, KEY_FILE);
|
|
57
57
|
try {
|
|
58
|
-
if (
|
|
59
|
-
const keyBase64 =
|
|
58
|
+
if (fs10__namespace.existsSync(keyPath)) {
|
|
59
|
+
const keyBase64 = fs10__namespace.readFileSync(keyPath, "utf-8").trim();
|
|
60
60
|
return Buffer.from(keyBase64, "base64");
|
|
61
61
|
}
|
|
62
62
|
} catch {
|
|
@@ -64,10 +64,10 @@ function getOrCreateEncryptionKey() {
|
|
|
64
64
|
const key = crypto__namespace.randomBytes(32);
|
|
65
65
|
try {
|
|
66
66
|
const keyDir = path4__namespace.dirname(keyPath);
|
|
67
|
-
if (!
|
|
68
|
-
|
|
67
|
+
if (!fs10__namespace.existsSync(keyDir)) {
|
|
68
|
+
fs10__namespace.mkdirSync(keyDir, { recursive: true, mode: 448 });
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
fs10__namespace.writeFileSync(keyPath, key.toString("base64"), {
|
|
71
71
|
mode: 384,
|
|
72
72
|
// 仅所有者可读写
|
|
73
73
|
encoding: "utf-8"
|
|
@@ -2544,10 +2544,10 @@ var FRONTEND_DEV_AGENT = {
|
|
|
2544
2544
|
var CODE_REVIEWER_AGENT = {
|
|
2545
2545
|
id: "code-reviewer",
|
|
2546
2546
|
name: "\u4EE3\u7801\u5BA1\u6838",
|
|
2547
|
-
description: "\u5BA1\u6838\u4EE3\u7801\u8D28\u91CF\u3001\u5B89\u5168\u6027\u548C\u89C4\u8303\u6027\uFF0C\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE",
|
|
2547
|
+
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",
|
|
2548
2548
|
icon: "\u{1F50D}",
|
|
2549
|
-
version: "1.
|
|
2550
|
-
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",
|
|
2549
|
+
version: "1.1.0",
|
|
2550
|
+
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",
|
|
2551
2551
|
capabilities: [
|
|
2552
2552
|
{
|
|
2553
2553
|
id: "quality-review",
|
|
@@ -2568,13 +2568,24 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2568
2568
|
id: "performance-review",
|
|
2569
2569
|
name: "\u6027\u80FD\u5BA1\u67E5",
|
|
2570
2570
|
description: "\u68C0\u67E5\u6027\u80FD\u95EE\u9898\u548C\u4F18\u5316\u5EFA\u8BAE"
|
|
2571
|
+
},
|
|
2572
|
+
{
|
|
2573
|
+
id: "regression-test",
|
|
2574
|
+
name: "\u56DE\u5F52\u6D4B\u8BD5",
|
|
2575
|
+
description: "\u6267\u884C\u6D4B\u8BD5\u5957\u4EF6\uFF0C\u786E\u4FDD\u4FEE\u6539\u4E0D\u7834\u574F\u5DF2\u6709\u529F\u80FD"
|
|
2576
|
+
},
|
|
2577
|
+
{
|
|
2578
|
+
id: "coverage-analysis",
|
|
2579
|
+
name: "\u8986\u76D6\u7387\u5206\u6790",
|
|
2580
|
+
description: "\u5206\u6790\u6D4B\u8BD5\u8986\u76D6\u7387\u5E76\u63D0\u4F9B\u6539\u8FDB\u5EFA\u8BAE"
|
|
2571
2581
|
}
|
|
2572
2582
|
],
|
|
2573
2583
|
tools: [
|
|
2574
2584
|
{ name: "read_file", description: "\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9", permission: "full" },
|
|
2575
2585
|
{ name: "glob", description: "\u641C\u7D22\u6587\u4EF6", permission: "full" },
|
|
2576
2586
|
{ name: "search_file_content", description: "\u641C\u7D22\u6587\u4EF6\u5185\u5BB9", permission: "full" },
|
|
2577
|
-
{ name: "list_directory", description: "\u5217\u51FA\u76EE\u5F55\u5185\u5BB9", permission: "full" }
|
|
2587
|
+
{ name: "list_directory", description: "\u5217\u51FA\u76EE\u5F55\u5185\u5BB9", permission: "full" },
|
|
2588
|
+
{ name: "run_shell_command", description: "\u6267\u884C\u6D4B\u8BD5\u547D\u4EE4", permission: "confirm" }
|
|
2578
2589
|
],
|
|
2579
2590
|
triggers: [
|
|
2580
2591
|
{ type: "workflow", condition: { workflowStep: "apply" }, priority: 10 },
|
|
@@ -2585,6 +2596,7 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2585
2596
|
protectedPaths: ["node_modules", ".git"]
|
|
2586
2597
|
},
|
|
2587
2598
|
behavior: {
|
|
2599
|
+
requireConfirmation: ["run_shell_command"],
|
|
2588
2600
|
autoCommit: false
|
|
2589
2601
|
}
|
|
2590
2602
|
},
|
|
@@ -2593,6 +2605,7 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2593
2605
|
## \u4F60\u7684\u804C\u8D23
|
|
2594
2606
|
- \u5BA1\u67E5\u4EE3\u7801\u8D28\u91CF\u548C\u53EF\u7EF4\u62A4\u6027
|
|
2595
2607
|
- \u68C0\u67E5\u5B89\u5168\u6F0F\u6D1E\u548C\u98CE\u9669
|
|
2608
|
+
- \u6267\u884C\u56DE\u5F52\u6D4B\u8BD5\uFF0C\u786E\u4FDD\u4FEE\u6539\u4E0D\u7834\u574F\u5DF2\u6709\u529F\u80FD
|
|
2596
2609
|
- \u63D0\u4F9B\u5177\u4F53\u7684\u6539\u8FDB\u5EFA\u8BAE
|
|
2597
2610
|
- \u786E\u4FDD\u9075\u5FAA\u6700\u4F73\u5B9E\u8DF5
|
|
2598
2611
|
|
|
@@ -2601,8 +2614,20 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2601
2614
|
2. **\u5B89\u5168\u6027**: XSS\u3001\u6CE8\u5165\u3001\u654F\u611F\u6570\u636E\u5904\u7406
|
|
2602
2615
|
3. **\u6027\u80FD**: \u7B97\u6CD5\u6548\u7387\u3001\u5185\u5B58\u4F7F\u7528\u3001\u6E32\u67D3\u4F18\u5316
|
|
2603
2616
|
4. **\u89C4\u8303\u6027**: \u547D\u540D\u3001\u683C\u5F0F\u3001\u6CE8\u91CA
|
|
2617
|
+
5. **\u6D4B\u8BD5\u8986\u76D6**: \u56DE\u5F52\u6D4B\u8BD5\u7ED3\u679C\u3001\u8986\u76D6\u7387\u5206\u6790
|
|
2618
|
+
|
|
2619
|
+
## \u56DE\u5F52\u6D4B\u8BD5\u6D41\u7A0B
|
|
2620
|
+
1. \u6267\u884C \`npm test -- --run\` \u8FD0\u884C\u6D4B\u8BD5\u5957\u4EF6
|
|
2621
|
+
2. \u5206\u6790\u6D4B\u8BD5\u7ED3\u679C\uFF0C\u8BC6\u522B\u5931\u8D25\u7684\u6D4B\u8BD5\u7528\u4F8B
|
|
2622
|
+
3. \u5982\u679C\u6D4B\u8BD5\u5931\u8D25\uFF0C\u963B\u6B62\u5F52\u6863\u5E76\u63D0\u793A\u4FEE\u590D
|
|
2623
|
+
4. \u63D0\u4F9B\u8986\u76D6\u7387\u62A5\u544A\u548C\u6539\u8FDB\u5EFA\u8BAE
|
|
2604
2624
|
|
|
2605
2625
|
## \u8F93\u51FA\u683C\u5F0F
|
|
2626
|
+
### \u56DE\u5F52\u6D4B\u8BD5\u7ED3\u679C
|
|
2627
|
+
- \u6D4B\u8BD5\u901A\u8FC7/\u5931\u8D25\u72B6\u6001
|
|
2628
|
+
- \u901A\u8FC7/\u5931\u8D25\u6570\u91CF
|
|
2629
|
+
- \u8986\u76D6\u7387\u767E\u5206\u6BD4
|
|
2630
|
+
|
|
2606
2631
|
### \u5BA1\u67E5\u7ED3\u679C
|
|
2607
2632
|
- \u901A\u8FC7/\u9700\u4FEE\u6539/\u4E0D\u901A\u8FC7
|
|
2608
2633
|
|
|
@@ -2628,7 +2653,7 @@ var CODE_REVIEWER_AGENT = {
|
|
|
2628
2653
|
## \u4E0A\u4E0B\u6587
|
|
2629
2654
|
{{context}}
|
|
2630
2655
|
|
|
2631
|
-
\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`,
|
|
2656
|
+
\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`,
|
|
2632
2657
|
outputFormat: {
|
|
2633
2658
|
type: "markdown"
|
|
2634
2659
|
}
|
|
@@ -5618,8 +5643,8 @@ var CommandParser = class {
|
|
|
5618
5643
|
};
|
|
5619
5644
|
}
|
|
5620
5645
|
parseAtPath(input) {
|
|
5621
|
-
const
|
|
5622
|
-
if (!
|
|
5646
|
+
const path14 = input.slice(1).trim();
|
|
5647
|
+
if (!path14) {
|
|
5623
5648
|
return { success: false, error: "\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84" };
|
|
5624
5649
|
}
|
|
5625
5650
|
return {
|
|
@@ -5627,7 +5652,7 @@ var CommandParser = class {
|
|
|
5627
5652
|
command: {
|
|
5628
5653
|
type: "at" /* AT */,
|
|
5629
5654
|
raw: input,
|
|
5630
|
-
path:
|
|
5655
|
+
path: path14
|
|
5631
5656
|
}
|
|
5632
5657
|
};
|
|
5633
5658
|
}
|
|
@@ -6471,10 +6496,26 @@ function createSpinner(message) {
|
|
|
6471
6496
|
stop: () => process.stdout.write(" ".repeat(message.length + 10) + "\r")
|
|
6472
6497
|
};
|
|
6473
6498
|
}
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6499
|
+
function getPackageInfo() {
|
|
6500
|
+
const possiblePaths = [
|
|
6501
|
+
path4__namespace.resolve(__dirname, "..", "..", "package.json"),
|
|
6502
|
+
path4__namespace.resolve(__dirname, "..", "..", "..", "package.json")
|
|
6503
|
+
];
|
|
6504
|
+
for (const pkgPath of possiblePaths) {
|
|
6505
|
+
try {
|
|
6506
|
+
if (fs10__namespace.existsSync(pkgPath)) {
|
|
6507
|
+
const content = fs10__namespace.readFileSync(pkgPath, "utf-8");
|
|
6508
|
+
return JSON.parse(content);
|
|
6509
|
+
}
|
|
6510
|
+
} catch {
|
|
6511
|
+
continue;
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
return { version: "1.0.0", name: "@nick848/sf-cli" };
|
|
6515
|
+
}
|
|
6516
|
+
var packageInfo = getPackageInfo();
|
|
6517
|
+
var CURRENT_VERSION = packageInfo.version;
|
|
6518
|
+
var PACKAGE_NAME = packageInfo.name;
|
|
6478
6519
|
async function handleUpdate(args, ctx) {
|
|
6479
6520
|
const options = {
|
|
6480
6521
|
check: args.includes("--check") || args.includes("-c"),
|
|
@@ -6928,6 +6969,78 @@ function extractTitle(requirement) {
|
|
|
6928
6969
|
return requirement.slice(0, 47) + "...";
|
|
6929
6970
|
}
|
|
6930
6971
|
var autoScheduleEnabled = true;
|
|
6972
|
+
var DEFAULT_REGRESSION_CONFIG = {
|
|
6973
|
+
enabled: true,
|
|
6974
|
+
command: "npm test -- --run",
|
|
6975
|
+
timeout: 12e4,
|
|
6976
|
+
// 2分钟
|
|
6977
|
+
coverageThreshold: 80
|
|
6978
|
+
};
|
|
6979
|
+
async function runRegressionTest(workingDirectory, config = DEFAULT_REGRESSION_CONFIG) {
|
|
6980
|
+
const startTime = Date.now();
|
|
6981
|
+
const result = {
|
|
6982
|
+
success: false,
|
|
6983
|
+
passed: 0,
|
|
6984
|
+
failed: 0,
|
|
6985
|
+
total: 0,
|
|
6986
|
+
duration: 0,
|
|
6987
|
+
output: "",
|
|
6988
|
+
errors: []
|
|
6989
|
+
};
|
|
6990
|
+
return new Promise((resolve4) => {
|
|
6991
|
+
const proc = child_process.spawn(config.command, [], {
|
|
6992
|
+
cwd: workingDirectory,
|
|
6993
|
+
shell: true,
|
|
6994
|
+
stdio: "pipe"
|
|
6995
|
+
});
|
|
6996
|
+
let stdout = "";
|
|
6997
|
+
let stderr = "";
|
|
6998
|
+
proc.stdout?.on("data", (data) => {
|
|
6999
|
+
stdout += data.toString();
|
|
7000
|
+
});
|
|
7001
|
+
proc.stderr?.on("data", (data) => {
|
|
7002
|
+
stderr += data.toString();
|
|
7003
|
+
});
|
|
7004
|
+
const timeout = setTimeout(() => {
|
|
7005
|
+
proc.kill();
|
|
7006
|
+
result.errors.push("\u6D4B\u8BD5\u8D85\u65F6");
|
|
7007
|
+
result.output = stdout + stderr;
|
|
7008
|
+
result.duration = Date.now() - startTime;
|
|
7009
|
+
resolve4(result);
|
|
7010
|
+
}, config.timeout);
|
|
7011
|
+
proc.on("close", (code) => {
|
|
7012
|
+
clearTimeout(timeout);
|
|
7013
|
+
result.output = stdout + stderr;
|
|
7014
|
+
result.duration = Date.now() - startTime;
|
|
7015
|
+
const passMatch = stdout.match(/(\d+)\s+(?:passed|tests?\s+passed)/i);
|
|
7016
|
+
const failMatch = stdout.match(/(\d+)\s+(?:failed|tests?\s+failed)/i);
|
|
7017
|
+
const totalMatch = stdout.match(/Tests?:\s*(\d+)/i);
|
|
7018
|
+
if (passMatch) {
|
|
7019
|
+
result.passed = parseInt(passMatch[1], 10);
|
|
7020
|
+
}
|
|
7021
|
+
if (failMatch) {
|
|
7022
|
+
result.failed = parseInt(failMatch[1], 10);
|
|
7023
|
+
}
|
|
7024
|
+
if (totalMatch) {
|
|
7025
|
+
result.total = parseInt(totalMatch[1], 10);
|
|
7026
|
+
} else {
|
|
7027
|
+
result.total = result.passed + result.failed;
|
|
7028
|
+
}
|
|
7029
|
+
const coverageMatch = stdout.match(/All files[^\d]*(\d+(?:\.\d+)?)/);
|
|
7030
|
+
if (coverageMatch) {
|
|
7031
|
+
result.coverage = parseFloat(coverageMatch[1]);
|
|
7032
|
+
}
|
|
7033
|
+
result.success = code === 0 && result.failed === 0;
|
|
7034
|
+
resolve4(result);
|
|
7035
|
+
});
|
|
7036
|
+
proc.on("error", (err) => {
|
|
7037
|
+
clearTimeout(timeout);
|
|
7038
|
+
result.errors.push(err.message);
|
|
7039
|
+
result.duration = Date.now() - startTime;
|
|
7040
|
+
resolve4(result);
|
|
7041
|
+
});
|
|
7042
|
+
});
|
|
7043
|
+
}
|
|
6931
7044
|
async function handleOpsx(command, args, ctx) {
|
|
6932
7045
|
const step = command.replace("opsx:", "");
|
|
6933
7046
|
const workflow = new WorkflowEngine();
|
|
@@ -6942,7 +7055,7 @@ async function handleOpsx(command, args, ctx) {
|
|
|
6942
7055
|
case "apply":
|
|
6943
7056
|
return handleApply(workflow);
|
|
6944
7057
|
case "archive":
|
|
6945
|
-
return handleArchive(workflow, args);
|
|
7058
|
+
return handleArchive(workflow, args, ctx);
|
|
6946
7059
|
case "propose":
|
|
6947
7060
|
return handlePropose(workflow, args);
|
|
6948
7061
|
case "status":
|
|
@@ -6957,12 +7070,50 @@ async function handleOpsx(command, args, ctx) {
|
|
|
6957
7070
|
return handleNext(workflow);
|
|
6958
7071
|
case "auto":
|
|
6959
7072
|
return handleAutoSchedule(args);
|
|
7073
|
+
case "test":
|
|
7074
|
+
return handleRegressionTest(ctx);
|
|
6960
7075
|
default:
|
|
6961
7076
|
return {
|
|
6962
7077
|
output: chalk9__default.default.red(`\u672A\u77E5\u7684OpenSpec\u547D\u4EE4: /${command}`)
|
|
6963
7078
|
};
|
|
6964
7079
|
}
|
|
6965
7080
|
}
|
|
7081
|
+
async function handleRegressionTest(ctx) {
|
|
7082
|
+
const lines = [];
|
|
7083
|
+
lines.push(chalk9__default.default.cyan("\u{1F50D} \u6267\u884C\u56DE\u5F52\u6D4B\u8BD5..."));
|
|
7084
|
+
lines.push(chalk9__default.default.gray(` \u5DE5\u4F5C\u76EE\u5F55: ${ctx.options.workingDirectory}`));
|
|
7085
|
+
lines.push("");
|
|
7086
|
+
const result = await runRegressionTest(ctx.options.workingDirectory);
|
|
7087
|
+
lines.push(chalk9__default.default.gray("\u2500".repeat(50)));
|
|
7088
|
+
if (result.success) {
|
|
7089
|
+
lines.push(chalk9__default.default.green("\u2713 \u56DE\u5F52\u6D4B\u8BD5\u901A\u8FC7"));
|
|
7090
|
+
} else {
|
|
7091
|
+
lines.push(chalk9__default.default.red("\u2717 \u56DE\u5F52\u6D4B\u8BD5\u5931\u8D25"));
|
|
7092
|
+
}
|
|
7093
|
+
lines.push("");
|
|
7094
|
+
lines.push(chalk9__default.default.cyan("\u6D4B\u8BD5\u7ED3\u679C:"));
|
|
7095
|
+
lines.push(chalk9__default.default.gray(` \u901A\u8FC7: ${result.passed}`));
|
|
7096
|
+
lines.push(chalk9__default.default.gray(` \u5931\u8D25: ${result.failed}`));
|
|
7097
|
+
lines.push(chalk9__default.default.gray(` \u603B\u8BA1: ${result.total}`));
|
|
7098
|
+
lines.push(chalk9__default.default.gray(` \u8017\u65F6: ${(result.duration / 1e3).toFixed(2)}s`));
|
|
7099
|
+
if (result.coverage !== void 0) {
|
|
7100
|
+
const coverageColor = result.coverage >= 80 ? chalk9__default.default.green : result.coverage >= 60 ? chalk9__default.default.yellow : chalk9__default.default.red;
|
|
7101
|
+
lines.push(coverageColor(` \u8986\u76D6\u7387: ${result.coverage}%`));
|
|
7102
|
+
}
|
|
7103
|
+
if (result.errors.length > 0) {
|
|
7104
|
+
lines.push("");
|
|
7105
|
+
lines.push(chalk9__default.default.red("\u9519\u8BEF\u4FE1\u606F:"));
|
|
7106
|
+
for (const error of result.errors) {
|
|
7107
|
+
lines.push(chalk9__default.default.gray(` - ${error}`));
|
|
7108
|
+
}
|
|
7109
|
+
}
|
|
7110
|
+
if (result.failed > 0) {
|
|
7111
|
+
lines.push("");
|
|
7112
|
+
lines.push(chalk9__default.default.yellow("\u26A0 \u5B58\u5728\u5931\u8D25\u7684\u6D4B\u8BD5\u7528\u4F8B\uFF0C\u8BF7\u68C0\u67E5\u5E76\u4FEE\u590D"));
|
|
7113
|
+
lines.push(chalk9__default.default.gray("\u4F7F\u7528 /opsx:rollback \u53EF\u56DE\u6EDA\u5230\u4E4B\u524D\u7684\u9636\u6BB5"));
|
|
7114
|
+
}
|
|
7115
|
+
return { output: lines.join("\n") };
|
|
7116
|
+
}
|
|
6966
7117
|
function handleAutoSchedule(args) {
|
|
6967
7118
|
const action = args[0]?.toLowerCase();
|
|
6968
7119
|
if (!action) {
|
|
@@ -7092,13 +7243,70 @@ async function handleArchive(workflow, args, ctx) {
|
|
|
7092
7243
|
${generateConfirmationPrompt(confirmation.point)}`) + chalk9__default.default.cyan("\n\n\u4F7F\u7528 /opsx:confirm code-review \u786E\u8BA4\u540E\u5F52\u6863")
|
|
7093
7244
|
};
|
|
7094
7245
|
}
|
|
7246
|
+
const lines = [];
|
|
7247
|
+
lines.push(chalk9__default.default.cyan("\u{1F50D} \u6267\u884C\u5F52\u6863\u524D\u56DE\u5F52\u6D4B\u8BD5..."));
|
|
7248
|
+
lines.push("");
|
|
7249
|
+
const testResult = await runRegressionTest(ctx.options.workingDirectory);
|
|
7250
|
+
if (!testResult.success) {
|
|
7251
|
+
lines.push(chalk9__default.default.red("\u2717 \u56DE\u5F52\u6D4B\u8BD5\u5931\u8D25"));
|
|
7252
|
+
lines.push(chalk9__default.default.gray(` \u901A\u8FC7: ${testResult.passed} | \u5931\u8D25: ${testResult.failed} | \u603B\u8BA1: ${testResult.total}`));
|
|
7253
|
+
lines.push("");
|
|
7254
|
+
lines.push(chalk9__default.default.yellow("\u26A0 \u5F52\u6863\u88AB\u963B\u6B62"));
|
|
7255
|
+
lines.push(chalk9__default.default.gray("\n\u8BF7\u4FEE\u590D\u5931\u8D25\u7684\u6D4B\u8BD5\u7528\u4F8B\u540E\u91CD\u8BD5"));
|
|
7256
|
+
lines.push(chalk9__default.default.gray("\u4F7F\u7528 /opsx:rollback \u53EF\u56DE\u6EDA\u5230\u4E4B\u524D\u7684\u9636\u6BB5"));
|
|
7257
|
+
lines.push(chalk9__default.default.gray("\u4F7F\u7528 /opsx:test \u53EF\u5355\u72EC\u8FD0\u884C\u56DE\u5F52\u6D4B\u8BD5"));
|
|
7258
|
+
return { output: lines.join("\n") };
|
|
7259
|
+
}
|
|
7260
|
+
lines.push(chalk9__default.default.green("\u2713 \u56DE\u5F52\u6D4B\u8BD5\u901A\u8FC7"));
|
|
7261
|
+
lines.push(chalk9__default.default.gray(` \u901A\u8FC7: ${testResult.passed} | \u8017\u65F6: ${(testResult.duration / 1e3).toFixed(2)}s`));
|
|
7262
|
+
lines.push("");
|
|
7095
7263
|
const changeId = state.id;
|
|
7096
7264
|
const summary = args.join(" ") || "\u5B8C\u6210\u53D8\u66F4";
|
|
7097
7265
|
await workflow.archive(summary);
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
\u53D8\u66F4ID: ${changeId}`) + chalk9__default.default.cyan("\n\n\u5F52\u6863\u6587\u6863\u5DF2\u751F\u6210\u5230 openspec/spec/ \u76EE\u5F55")
|
|
7101
|
-
};
|
|
7266
|
+
await updateChangelog(ctx.options.workingDirectory, summary, changeId);
|
|
7267
|
+
lines.push(chalk9__default.default.green("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u5F52\u6863") + chalk9__default.default.gray(`
|
|
7268
|
+
\u53D8\u66F4ID: ${changeId}`) + chalk9__default.default.cyan("\n\n\u5F52\u6863\u6587\u6863\u5DF2\u751F\u6210\u5230 openspec/spec/ \u76EE\u5F55") + chalk9__default.default.gray("\nCHANGELOG.md \u5DF2\u66F4\u65B0"));
|
|
7269
|
+
return { output: lines.join("\n") };
|
|
7270
|
+
}
|
|
7271
|
+
async function updateChangelog(workingDirectory, summary, changeId) {
|
|
7272
|
+
try {
|
|
7273
|
+
const changelogPath = path4__namespace.join(workingDirectory, "CHANGELOG.md");
|
|
7274
|
+
const pkgPath = path4__namespace.join(workingDirectory, "package.json");
|
|
7275
|
+
let version = "1.0.0";
|
|
7276
|
+
try {
|
|
7277
|
+
const pkgContent = fs10__namespace.readFileSync(pkgPath, "utf-8");
|
|
7278
|
+
const pkg = JSON.parse(pkgContent);
|
|
7279
|
+
version = pkg.version || "1.0.0";
|
|
7280
|
+
} catch {
|
|
7281
|
+
}
|
|
7282
|
+
const today = /* @__PURE__ */ new Date();
|
|
7283
|
+
const dateStr = today.toISOString().split("T")[0];
|
|
7284
|
+
const entry = `
|
|
7285
|
+
## v${version} (${dateStr})
|
|
7286
|
+
|
|
7287
|
+
**\u53D8\u66F4\u5185\u5BB9**
|
|
7288
|
+
|
|
7289
|
+
- ${summary} (${changeId})
|
|
7290
|
+
`;
|
|
7291
|
+
if (fs10__namespace.existsSync(changelogPath)) {
|
|
7292
|
+
const content = fs10__namespace.readFileSync(changelogPath, "utf-8");
|
|
7293
|
+
const versionPattern = /^## v\d+\.\d+\.\d+/m;
|
|
7294
|
+
const match = content.match(versionPattern);
|
|
7295
|
+
if (match && match.index !== void 0) {
|
|
7296
|
+
const newContent = content.slice(0, match.index) + entry + content.slice(match.index);
|
|
7297
|
+
fs10__namespace.writeFileSync(changelogPath, newContent, "utf-8");
|
|
7298
|
+
} else {
|
|
7299
|
+
fs10__namespace.appendFileSync(changelogPath, entry, "utf-8");
|
|
7300
|
+
}
|
|
7301
|
+
} else {
|
|
7302
|
+
const header = `# Changelog
|
|
7303
|
+
|
|
7304
|
+
All notable changes to this project will be documented in this file.
|
|
7305
|
+
`;
|
|
7306
|
+
fs10__namespace.writeFileSync(changelogPath, header + entry, "utf-8");
|
|
7307
|
+
}
|
|
7308
|
+
} catch (error) {
|
|
7309
|
+
}
|
|
7102
7310
|
}
|
|
7103
7311
|
async function handlePropose(workflow, args, ctx) {
|
|
7104
7312
|
const state = workflow.getState();
|
|
@@ -7289,9 +7497,25 @@ ${generateConfirmationPrompt(e.point)}`) + chalk9__default.default.cyan(`
|
|
|
7289
7497
|
}
|
|
7290
7498
|
|
|
7291
7499
|
// src/commands/runner.ts
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7500
|
+
function getVersion() {
|
|
7501
|
+
const possiblePaths = [
|
|
7502
|
+
path4__namespace.resolve(__dirname, "..", "..", "package.json"),
|
|
7503
|
+
path4__namespace.resolve(__dirname, "..", "..", "..", "package.json")
|
|
7504
|
+
];
|
|
7505
|
+
for (const pkgPath of possiblePaths) {
|
|
7506
|
+
try {
|
|
7507
|
+
if (fs10__namespace.existsSync(pkgPath)) {
|
|
7508
|
+
const content = fs10__namespace.readFileSync(pkgPath, "utf-8");
|
|
7509
|
+
const pkg = JSON.parse(content);
|
|
7510
|
+
return pkg.version;
|
|
7511
|
+
}
|
|
7512
|
+
} catch {
|
|
7513
|
+
continue;
|
|
7514
|
+
}
|
|
7515
|
+
}
|
|
7516
|
+
return "1.0.0";
|
|
7517
|
+
}
|
|
7518
|
+
var VERSION2 = getVersion();
|
|
7295
7519
|
async function runSlashCommand(command, args, ctx) {
|
|
7296
7520
|
const normalizedCommand = normalizeCommand(command);
|
|
7297
7521
|
switch (normalizedCommand) {
|