ai-project-manage-cli 4.0.4 → 4.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +94 -50
- package/package.json +1 -1
- package/template/workitems/README.md +2 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { readFileSync as readFileSync10 } from "fs";
|
|
5
|
-
import { dirname as dirname2, join as
|
|
5
|
+
import { dirname as dirname2, join as join10 } from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
|
|
@@ -116,6 +116,17 @@ var requestConfig = {
|
|
|
116
116
|
path: "/cli/requirements/update-dev-status"
|
|
117
117
|
})
|
|
118
118
|
},
|
|
119
|
+
requirementAttachment: {
|
|
120
|
+
list: defineEndpoint({
|
|
121
|
+
method: "GET",
|
|
122
|
+
path: "/requirement-attachments/list"
|
|
123
|
+
}),
|
|
124
|
+
download: defineEndpoint({
|
|
125
|
+
method: "GET",
|
|
126
|
+
path: "/requirement-attachments/download",
|
|
127
|
+
mode: "download"
|
|
128
|
+
})
|
|
129
|
+
},
|
|
119
130
|
requirementArtifact: {
|
|
120
131
|
list: defineEndpoint({
|
|
121
132
|
method: "GET",
|
|
@@ -246,7 +257,7 @@ async function runComment(requirementId, file, model) {
|
|
|
246
257
|
import { randomUUID } from "crypto";
|
|
247
258
|
import WebSocket from "ws";
|
|
248
259
|
import { Agent } from "@cursor/sdk";
|
|
249
|
-
import { join as
|
|
260
|
+
import { join as join6 } from "path";
|
|
250
261
|
|
|
251
262
|
// src/session-utils.ts
|
|
252
263
|
import { appendFileSync } from "fs";
|
|
@@ -381,8 +392,33 @@ ${JSON.stringify(event, null, 2)}
|
|
|
381
392
|
};
|
|
382
393
|
|
|
383
394
|
// src/commands/upload-artifact.ts
|
|
384
|
-
import { existsSync as
|
|
385
|
-
import { join as
|
|
395
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
396
|
+
import { join as join4, relative, sep } from "path";
|
|
397
|
+
|
|
398
|
+
// src/commands/sync-requirement-attachments.ts
|
|
399
|
+
import { existsSync as existsSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
400
|
+
import { join as join3 } from "path";
|
|
401
|
+
var REQUIREMENT_ATTACHMENTS_SUBDIR = "attachments";
|
|
402
|
+
async function syncRequirementAttachments(api, requirementId, workitemsDir) {
|
|
403
|
+
const dir = join3(workitemsDir, REQUIREMENT_ATTACHMENTS_SUBDIR);
|
|
404
|
+
await ensureDirExists(dir);
|
|
405
|
+
const { items } = await api.requirementAttachment.list({ requirementId });
|
|
406
|
+
if (items.length === 0) return;
|
|
407
|
+
for (const item of items) {
|
|
408
|
+
const dest = join3(dir, item.fileName);
|
|
409
|
+
if (existsSync2(dest)) continue;
|
|
410
|
+
const { blob } = await api.requirementAttachment.download({
|
|
411
|
+
attachmentId: item.id
|
|
412
|
+
});
|
|
413
|
+
const buffer = Buffer.from(await blob.arrayBuffer());
|
|
414
|
+
writeFileSync2(dest, buffer);
|
|
415
|
+
console.log(
|
|
416
|
+
`[apm] \u5DF2\u4E0B\u8F7D\u9644\u4EF6: ${REQUIREMENT_ATTACHMENTS_SUBDIR}/${item.fileName}`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// src/commands/upload-artifact.ts
|
|
386
422
|
var EXCLUDED_RELATIVE_PATHS = /* @__PURE__ */ new Set([
|
|
387
423
|
"defect.xml",
|
|
388
424
|
"prd.md",
|
|
@@ -406,7 +442,8 @@ function* walkMarkdownFiles(dir) {
|
|
|
406
442
|
const names = readdirSync2(dir);
|
|
407
443
|
for (const name of names) {
|
|
408
444
|
if (name.startsWith(".")) continue;
|
|
409
|
-
|
|
445
|
+
if (name === REQUIREMENT_ATTACHMENTS_SUBDIR) continue;
|
|
446
|
+
const full = join4(dir, name);
|
|
410
447
|
const st = statSync2(full);
|
|
411
448
|
if (st.isDirectory()) {
|
|
412
449
|
yield* walkMarkdownFiles(full);
|
|
@@ -421,7 +458,7 @@ async function runUploadArtifact(requirementId, workspaceDir) {
|
|
|
421
458
|
const cfg = await ensureLoggedConfig();
|
|
422
459
|
const api = createApmApiClient(cfg);
|
|
423
460
|
const root = requirementWorkitemsDir(requirementId, workspaceDir);
|
|
424
|
-
if (!
|
|
461
|
+
if (!existsSync3(root)) {
|
|
425
462
|
console.error(
|
|
426
463
|
`[apm] \u76EE\u5F55\u4E0D\u5B58\u5728: ${root}
|
|
427
464
|
\u8BF7\u5148\u6267\u884C: apm pull ${requirementId}`
|
|
@@ -444,8 +481,8 @@ async function runUploadArtifact(requirementId, workspaceDir) {
|
|
|
444
481
|
}
|
|
445
482
|
|
|
446
483
|
// src/commands/pull.ts
|
|
447
|
-
import { writeFileSync as
|
|
448
|
-
import { join as
|
|
484
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
485
|
+
import { join as join5 } from "path";
|
|
449
486
|
import { stringify as yamlStringify } from "yaml";
|
|
450
487
|
var PULL_ARTIFACT_FILE_NAMES = ["api.md", "backend.md"];
|
|
451
488
|
function normalizeArtifactPath(fileName) {
|
|
@@ -555,13 +592,13 @@ async function runPull(requirementId, workspaceDir) {
|
|
|
555
592
|
},
|
|
556
593
|
{ lineWidth: 0 }
|
|
557
594
|
);
|
|
558
|
-
|
|
559
|
-
|
|
595
|
+
writeFileSync3(
|
|
596
|
+
join5(WORKITEMS_DIR, "requirement-status.yaml"),
|
|
560
597
|
statusYaml.endsWith("\n") ? statusYaml : `${statusYaml}
|
|
561
598
|
`,
|
|
562
599
|
"utf8"
|
|
563
600
|
);
|
|
564
|
-
|
|
601
|
+
writeFileSync3(join5(WORKITEMS_DIR, "prd.md"), req2.content || "", "utf8");
|
|
565
602
|
const reviews = data.reviews ?? [];
|
|
566
603
|
const reviewsXml = [
|
|
567
604
|
"<reviews>",
|
|
@@ -581,15 +618,15 @@ async function runPull(requirementId, workspaceDir) {
|
|
|
581
618
|
"</reviews>",
|
|
582
619
|
""
|
|
583
620
|
].join("\n");
|
|
584
|
-
|
|
621
|
+
writeFileSync3(join5(WORKITEMS_DIR, "reviews.xml"), reviewsXml, "utf8");
|
|
585
622
|
const defectsXml = defectsToXml(data.defects ?? []);
|
|
586
|
-
|
|
623
|
+
writeFileSync3(join5(WORKITEMS_DIR, "defect.xml"), defectsXml, "utf8");
|
|
587
624
|
const testCasesXml = unknownArrayToXml(
|
|
588
625
|
"testcases",
|
|
589
626
|
"case",
|
|
590
627
|
data.testCases ?? []
|
|
591
628
|
);
|
|
592
|
-
|
|
629
|
+
writeFileSync3(join5(WORKITEMS_DIR, "testcase.xml"), testCasesXml, "utf8");
|
|
593
630
|
for (const fileName of PULL_ARTIFACT_FILE_NAMES) {
|
|
594
631
|
const content = await fetchArtifactContentByFileName(
|
|
595
632
|
api,
|
|
@@ -597,9 +634,10 @@ async function runPull(requirementId, workspaceDir) {
|
|
|
597
634
|
fileName
|
|
598
635
|
);
|
|
599
636
|
if (content !== null) {
|
|
600
|
-
|
|
637
|
+
writeFileSync3(join5(WORKITEMS_DIR, fileName), content, "utf8");
|
|
601
638
|
}
|
|
602
639
|
}
|
|
640
|
+
await syncRequirementAttachments(api, requirementId, WORKITEMS_DIR);
|
|
603
641
|
return WORKITEMS_DIR;
|
|
604
642
|
}
|
|
605
643
|
|
|
@@ -646,7 +684,7 @@ function runConnect(opts) {
|
|
|
646
684
|
return;
|
|
647
685
|
}
|
|
648
686
|
const payload = msg.payload;
|
|
649
|
-
const apmRoot =
|
|
687
|
+
const apmRoot = join6(payload.cwd, ".apm");
|
|
650
688
|
console.log("[apm] ROOT:", apmRoot);
|
|
651
689
|
console.log("[apm] workflow node:", payload.nodeId);
|
|
652
690
|
try {
|
|
@@ -749,17 +787,17 @@ function runConnect(opts) {
|
|
|
749
787
|
}
|
|
750
788
|
|
|
751
789
|
// src/commands/init.ts
|
|
752
|
-
import { join as
|
|
753
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
790
|
+
import { join as join7 } from "path";
|
|
791
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
754
792
|
async function runInit(name) {
|
|
755
793
|
await ensureWorkspaceApmDirForInit();
|
|
756
794
|
await copyTemplateFiles(WORKSPACE_APM_DIR);
|
|
757
795
|
if (name) {
|
|
758
|
-
const apmConfigPath =
|
|
796
|
+
const apmConfigPath = join7(WORKSPACE_APM_DIR, "apm.config.json");
|
|
759
797
|
const config = readFileSync4(apmConfigPath, "utf8");
|
|
760
798
|
const configJson = JSON.parse(config);
|
|
761
799
|
configJson.name = name;
|
|
762
|
-
|
|
800
|
+
writeFileSync4(apmConfigPath, JSON.stringify(configJson, null, 2), "utf8");
|
|
763
801
|
}
|
|
764
802
|
}
|
|
765
803
|
|
|
@@ -817,11 +855,17 @@ async function fetchBaselineBranchFromApi(requirementId, cwd) {
|
|
|
817
855
|
const cfg = await ensureLoggedConfig();
|
|
818
856
|
const api = createApmApiClient(cfg);
|
|
819
857
|
const workdirPath = resolve3(cwd);
|
|
820
|
-
const
|
|
858
|
+
const res = await api.cliRequirements.branchBaseline({
|
|
821
859
|
requirementId,
|
|
822
860
|
workdirPath
|
|
823
861
|
});
|
|
824
|
-
|
|
862
|
+
if (!res.repositoryId) {
|
|
863
|
+
throw new Error(
|
|
864
|
+
`[apm] \u672A\u5728\u5E73\u53F0\u627E\u5230\u4E0E\u5F53\u524D\u76EE\u5F55\u5339\u914D\u7684\u5DE5\u4F5C\u76EE\u5F55\u767B\u8BB0\uFF1A${workdirPath}
|
|
865
|
+
\u8BF7\u5148\u5728\u5E73\u53F0\u767B\u8BB0\u8BE5\u8DEF\u5F84\u5BF9\u5E94\u7684\u5DE5\u4F5C\u76EE\u5F55\u4E0E\u4ED3\u5E93\u3002`
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
const name = (res.defaultBranch ?? "").trim();
|
|
825
869
|
if (!name) {
|
|
826
870
|
throw new Error("[apm] \u5E73\u53F0\u8FD4\u56DE\u7684\u57FA\u7EBF\u5206\u652F\u540D\u4E3A\u7A7A");
|
|
827
871
|
}
|
|
@@ -948,10 +992,10 @@ async function runBranch(requirementId, options = {}) {
|
|
|
948
992
|
|
|
949
993
|
// src/commands/refine.ts
|
|
950
994
|
import { readFileSync as readFileSync5 } from "fs";
|
|
951
|
-
import { join as
|
|
995
|
+
import { join as join8 } from "path";
|
|
952
996
|
async function runRefine(requirementId) {
|
|
953
997
|
const cfg = await ensureLoggedConfig();
|
|
954
|
-
const filePath =
|
|
998
|
+
const filePath = join8(WORKSPACE_APM_DIR, "workitems", requirementId, "prd.md");
|
|
955
999
|
const content = readFileSync5(filePath, "utf8");
|
|
956
1000
|
const api = createApmApiClient(cfg);
|
|
957
1001
|
const data = await api.cliRequirements.refine({ requirementId, content });
|
|
@@ -984,14 +1028,14 @@ async function runUpdateStatus(requirementId, status) {
|
|
|
984
1028
|
import path5 from "node:path";
|
|
985
1029
|
|
|
986
1030
|
// src/commands/deploy/internal/apm-config.ts
|
|
987
|
-
import { existsSync as
|
|
1031
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "node:fs";
|
|
988
1032
|
import { resolve as resolve4 } from "node:path";
|
|
989
1033
|
function loadApmConfig(options) {
|
|
990
1034
|
const p = resolve4(
|
|
991
1035
|
process.cwd(),
|
|
992
1036
|
options?.configPath ?? resolve4(WORKSPACE_APM_DIR, "apm.config.json")
|
|
993
1037
|
);
|
|
994
|
-
if (!
|
|
1038
|
+
if (!existsSync4(p)) {
|
|
995
1039
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
996
1040
|
process.exit(1);
|
|
997
1041
|
}
|
|
@@ -1095,7 +1139,7 @@ import path4 from "node:path";
|
|
|
1095
1139
|
import Docker from "dockerode";
|
|
1096
1140
|
|
|
1097
1141
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
1098
|
-
import { existsSync as
|
|
1142
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "node:fs";
|
|
1099
1143
|
import path from "node:path";
|
|
1100
1144
|
function asOptionalTlsBuffer(value) {
|
|
1101
1145
|
if (typeof value !== "string") {
|
|
@@ -1107,7 +1151,7 @@ function asOptionalTlsBuffer(value) {
|
|
|
1107
1151
|
if (normalized === "") {
|
|
1108
1152
|
return void 0;
|
|
1109
1153
|
}
|
|
1110
|
-
if (
|
|
1154
|
+
if (existsSync5(normalized)) {
|
|
1111
1155
|
return readFileSync7(normalized);
|
|
1112
1156
|
}
|
|
1113
1157
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
@@ -1318,7 +1362,7 @@ var DockerodeClient = class {
|
|
|
1318
1362
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
1319
1363
|
|
|
1320
1364
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
1321
|
-
import { existsSync as
|
|
1365
|
+
import { existsSync as existsSync6, readFileSync as readFileSync8, statSync as statSync3 } from "node:fs";
|
|
1322
1366
|
import path2 from "node:path";
|
|
1323
1367
|
function stripSurroundingQuotes(value) {
|
|
1324
1368
|
const t = value.trim();
|
|
@@ -1335,7 +1379,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
1335
1379
|
return {};
|
|
1336
1380
|
}
|
|
1337
1381
|
const targetPath = path2.resolve(envFilePath);
|
|
1338
|
-
if (!
|
|
1382
|
+
if (!existsSync6(targetPath) || !statSync3(targetPath).isFile()) {
|
|
1339
1383
|
return {};
|
|
1340
1384
|
}
|
|
1341
1385
|
const raw = readFileSync8(targetPath, "utf-8");
|
|
@@ -1509,12 +1553,12 @@ function dockerPushImage(params, cwd) {
|
|
|
1509
1553
|
}
|
|
1510
1554
|
|
|
1511
1555
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
1512
|
-
import { existsSync as
|
|
1556
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
1513
1557
|
import path3 from "node:path";
|
|
1514
1558
|
function resolveDockerBuildPaths(cwd) {
|
|
1515
1559
|
const dockerfilePath = path3.join(cwd, "Dockerfile");
|
|
1516
1560
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
1517
|
-
if (!
|
|
1561
|
+
if (!existsSync7(dockerfilePath)) {
|
|
1518
1562
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
1519
1563
|
}
|
|
1520
1564
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -1643,11 +1687,11 @@ import { copyFile, readdir as readdir2, stat } from "node:fs/promises";
|
|
|
1643
1687
|
import path7 from "node:path";
|
|
1644
1688
|
|
|
1645
1689
|
// src/commands/deploy/internal/load-apm-dotenv.ts
|
|
1646
|
-
import { existsSync as
|
|
1647
|
-
import { join as
|
|
1690
|
+
import { existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
|
|
1691
|
+
import { join as join9 } from "node:path";
|
|
1648
1692
|
function loadApmDotEnvIfPresent() {
|
|
1649
|
-
const p =
|
|
1650
|
-
if (!
|
|
1693
|
+
const p = join9(WORKSPACE_APM_DIR, ".env");
|
|
1694
|
+
if (!existsSync8(p)) {
|
|
1651
1695
|
return;
|
|
1652
1696
|
}
|
|
1653
1697
|
let text;
|
|
@@ -2011,7 +2055,7 @@ function registerDeployCommands(program) {
|
|
|
2011
2055
|
function readCliVersion() {
|
|
2012
2056
|
try {
|
|
2013
2057
|
const dir = dirname2(fileURLToPath2(import.meta.url));
|
|
2014
|
-
const pkgPath =
|
|
2058
|
+
const pkgPath = join10(dir, "..", "package.json");
|
|
2015
2059
|
const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
|
|
2016
2060
|
return pkg.version ?? "0.0.0";
|
|
2017
2061
|
} catch {
|
|
@@ -2026,22 +2070,24 @@ function buildProgram() {
|
|
|
2026
2070
|
).version(readCliVersion(), "-V, --version", "\u663E\u793A\u7248\u672C\u53F7").helpOption("-h, --help", "\u663E\u793A\u5E2E\u52A9").showHelpAfterError(true);
|
|
2027
2071
|
program.command("login").description(
|
|
2028
2072
|
"\u8C03\u7528 POST /api/auth/login\uFF0C\u5C06 token \u5199\u5165 ~/.config/apm/config.json"
|
|
2029
|
-
).requiredOption("--email <\u90AE\u7BB1>", "\u767B\u5F55\u90AE\u7BB1").requiredOption("--password <\u5BC6\u7801>", "\u767B\u5F55\u5BC6\u7801").option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u4F8B\u5982 http://127.0.0.1:3000").action(
|
|
2030
|
-
|
|
2031
|
-
|
|
2073
|
+
).requiredOption("--email <\u90AE\u7BB1>", "\u767B\u5F55\u90AE\u7BB1").requiredOption("--password <\u5BC6\u7801>", "\u767B\u5F55\u5BC6\u7801").option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u4F8B\u5982 http://127.0.0.1:3000").action(
|
|
2074
|
+
async (opts) => {
|
|
2075
|
+
await runLogin(opts);
|
|
2076
|
+
}
|
|
2077
|
+
);
|
|
2032
2078
|
program.command("connect").description("\u8FDE\u63A5 WebSocket /ws/agent\uFF0C\u5E76\u6309\u56FA\u5B9A\u95F4\u9694\u53D1\u9001 HEARTBEAT").option("--server <url>", "API \u6839\u5730\u5740\uFF08\u5199\u5165\u672C\u5730\u914D\u7F6E\uFF09").action((opts) => {
|
|
2033
2079
|
runConnect(opts);
|
|
2034
2080
|
});
|
|
2035
|
-
program.command("init").description(
|
|
2036
|
-
"\u5728\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u521D\u59CB\u5316 .apm \u6A21\u677F\uFF08\u82E5 .apm \u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\u5219\u62A5\u9519\uFF09"
|
|
2037
|
-
).option("--name <name>", "\u5DE5\u4F5C\u76EE\u5F55\u540D\u79F0").action(async (opts) => {
|
|
2081
|
+
program.command("init").description("\u5728\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u521D\u59CB\u5316 .apm \u6A21\u677F\uFF08\u82E5 .apm \u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\u5219\u62A5\u9519\uFF09").option("--name <name>", "\u5DE5\u4F5C\u76EE\u5F55\u540D\u79F0").action(async (opts) => {
|
|
2038
2082
|
await runInit(opts.name);
|
|
2039
2083
|
});
|
|
2040
|
-
program.command("pull").description(
|
|
2084
|
+
program.command("pull").description(
|
|
2085
|
+
"GET /api/cli/requirements/pull\uFF0C\u540C\u6B65\u6570\u636E\u4E0E\u9644\u4EF6\u5230 .apm/workitems/<\u9700\u6C42ID>"
|
|
2086
|
+
).argument("<requirementId>", "\u9700\u6C42 ID").action(async (requirementId) => {
|
|
2041
2087
|
await runPull(requirementId);
|
|
2042
2088
|
});
|
|
2043
2089
|
program.command("upload-artifact").description(
|
|
2044
|
-
"\u5148\u6E05\u7A7A\u8BE5\u9700\u6C42\u5728\u5E73\u53F0\u4E0A\u7684\u4EA7\u7269\u6587\u6863\uFF0C\u518D\u5C06 .apm/workitems/<\u9700\u6C42ID> \u4E0B Markdown \u540C\u6B65\u4E0A\u53BB\uFF08\u6392\u9664 pull \u7CFB\u7EDF\u6587\u4EF6\uFF09"
|
|
2090
|
+
"\u5148\u6E05\u7A7A\u8BE5\u9700\u6C42\u5728\u5E73\u53F0\u4E0A\u7684\u4EA7\u7269\u6587\u6863\uFF0C\u518D\u5C06 .apm/workitems/<\u9700\u6C42ID> \u4E0B Markdown \u540C\u6B65\u4E0A\u53BB\uFF08\u6392\u9664 pull \u7CFB\u7EDF\u6587\u4EF6\u4E0E attachments \u76EE\u5F55\uFF09"
|
|
2045
2091
|
).argument("<requirementId>", "\u9700\u6C42 ID").action(async (requirementId) => {
|
|
2046
2092
|
await runUploadArtifact(requirementId);
|
|
2047
2093
|
});
|
|
@@ -2050,11 +2096,9 @@ function buildProgram() {
|
|
|
2050
2096
|
).argument("<requirementId>", "\u9700\u6C42 ID").option(
|
|
2051
2097
|
"-m, --message <text>",
|
|
2052
2098
|
"\u5DF2\u5728\u76EE\u6807\u5206\u652F\u4E14\u9700\u63D0\u4EA4\u672C\u5730\u6539\u52A8\u65F6\u4F7F\u7528\u7684\u63D0\u4EA4\u8BF4\u660E\uFF08\u9ED8\u8BA4\u81EA\u52A8\u751F\u6210\uFF09"
|
|
2053
|
-
).action(
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
}
|
|
2057
|
-
);
|
|
2099
|
+
).action(async (requirementId, opts) => {
|
|
2100
|
+
await runBranch(requirementId, { message: opts.message });
|
|
2101
|
+
});
|
|
2058
2102
|
program.command("comment").description("POST /api/cli/requirements/comment\uFF08\u6B63\u6587\u6765\u81EA\u6587\u4EF6\uFF09").argument("<requirementId>", "\u9700\u6C42 ID").requiredOption("--file <path>", "\u8BC4\u8BBA\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84").option("--model <model>", "\u8BC4\u8BBA\u6A21\u578B").action(
|
|
2059
2103
|
async (requirementId, options) => {
|
|
2060
2104
|
await runComment(requirementId, options.file, options.model);
|
package/package.json
CHANGED
|
@@ -10,10 +10,11 @@ workitems/<需求 ID>
|
|
|
10
10
|
|
|
11
11
|
- `status.yaml`: 需求的状态(包含当前的分支名称,需求状态,缺陷列表及状态)
|
|
12
12
|
- `prd.md`: pull 后写入的需求聚合正文
|
|
13
|
+
- `attachments/`: pull 后从平台同步的需求附件(本地已存在则跳过下载)
|
|
13
14
|
- `reviews.xml`: pull 后写入的评论与回复
|
|
14
15
|
- `defect.xml`: 缺陷信息
|
|
15
16
|
- `testcase.xml`: 测试用例占位数据
|
|
16
17
|
- `change.md`: 代码变更信息
|
|
17
18
|
- `specs/proposal.md`: 提议
|
|
18
19
|
- `specs/tasks.md`: 任务
|
|
19
|
-
- `specs/`
|
|
20
|
+
- `specs/`
|