ai-project-manage-cli 2.0.3 → 2.0.5

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/api/cli.d.ts CHANGED
@@ -27,4 +27,43 @@ export type ResCliLoginByEmployee = {
27
27
  token: string;
28
28
  id: number;
29
29
  };
30
+ /** 对应 lpm-server `POST /cli/resource/requirement` */
31
+ export type ReqCliResourceRequirementGet = {
32
+ id: number;
33
+ };
34
+ export type ResCliResourceRequirementGet = {
35
+ content: string;
36
+ comments: {
37
+ reviewer: number;
38
+ content: string;
39
+ reply: string;
40
+ employeeId: number;
41
+ }[];
42
+ };
43
+ /** 对应 lpm-server `POST /cli/resource/requirement/comment`(更新 RequirementDeveloper) */
44
+ export type ReqCliResourceRequirementCommentSet = {
45
+ id: number;
46
+ content: string;
47
+ };
48
+ export type ResCliResourceRequirementCommentSet = {
49
+ id: number;
50
+ workitemId: string;
51
+ title: string;
52
+ workdirId: number;
53
+ model: string;
54
+ status: string;
55
+ reviewResult: string | null;
56
+ reviewReply: string | null;
57
+ branchName: string | null;
58
+ };
59
+ /** 对应 lpm-server `POST /cli/resource/requirement/content`(同步需求正文) */
60
+ export type ReqCliResourceRequirementContentSet = {
61
+ id: number;
62
+ content: string;
63
+ };
64
+ export type ResCliResourceRequirementContentSet = {
65
+ id: number;
66
+ workitemId: string;
67
+ clearedRequirementDevelopers: number;
68
+ };
30
69
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/api/cli.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEtC,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAEF,gEAAgE;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/api/cli.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEtC,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAEF,gEAAgE;AAChE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,qDAAqD;AACrD,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CAAC;CACL,CAAC;AAEF,sFAAsF;AACtF,MAAM,MAAM,mCAAmC,GAAG;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,qEAAqE;AACrE,MAAM,MAAM,mCAAmC,GAAG;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B,EAAE,MAAM,CAAC;CACtC,CAAC"}
@@ -11,6 +11,9 @@ export declare function createApmClient(options: CreateApmClientOptions): ApmCli
11
11
  declare const api: ApiClient<{
12
12
  readonly cli: {
13
13
  readonly variablesGet: import("listpage-http").EndpointConfig<void, import("./cli").ResCliVariables>;
14
+ readonly resourceRequirementGet: import("listpage-http").EndpointConfig<import("./cli").ReqCliResourceRequirementGet, import("./cli").ResCliResourceRequirementGet>;
15
+ readonly resourceRequirementCommentSet: import("listpage-http").EndpointConfig<import("./cli").ReqCliResourceRequirementCommentSet, import("./cli").ResCliResourceRequirementCommentSet>;
16
+ readonly resourceRequirementContentSet: import("listpage-http").EndpointConfig<import("./cli").ReqCliResourceRequirementContentSet, import("./cli").ResCliResourceRequirementContentSet>;
14
17
  };
15
18
  readonly employee: {
16
19
  readonly auth: import("listpage-http").EndpointConfig<import("./cli").ReqCliLoginByEmployee, import("./cli").ResCliLoginByEmployee>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,MAAM,MAAM,sBAAsB,GAAG;IACnC,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAMF,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,aAAa,CAAC,CAAC;AAExD,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,SAAS,CAkB1E;AAID,QAAA,MAAM,GAAG;;;;;;;EAGP,CAAC;AAEH,eAAe,GAAG,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,MAAM,MAAM,sBAAsB,GAAG;IACnC,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAMF,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,aAAa,CAAC,CAAC;AAExD,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,SAAS,CAkB1E;AAID,QAAA,MAAM,GAAG;;;;;;;;;;EAGP,CAAC;AAEH,eAAe,GAAG,CAAC"}
@@ -2,5 +2,5 @@ export type { ApiClient } from "listpage-http";
2
2
  export { ApiError, ERROR_CODE_NETWORK, RequestTimeoutException, defineEndpoint, } from "listpage-http";
3
3
  export { createApmClient, type ApmClient, type CreateApmClientOptions, } from "./client";
4
4
  export { requestConfig, type RequestConfig } from "./request-config";
5
- export type { ReqCliLoginByEmployee, ReqCliVariablesGet, ResCliLoginByEmployee, ResCliVariables, } from "./cli";
5
+ export type { ReqCliLoginByEmployee, ReqCliResourceRequirementCommentSet, ReqCliResourceRequirementGet, ReqCliVariablesGet, ResCliLoginByEmployee, ResCliResourceRequirementCommentSet, ResCliResourceRequirementGet, ResCliVariables, } from "./cli";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,KAAK,SAAS,EACd,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,GAChB,MAAM,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,KAAK,SAAS,EACd,KAAK,sBAAsB,GAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EACV,qBAAqB,EACrB,mCAAmC,EACnC,4BAA4B,EAC5B,kBAAkB,EAClB,qBAAqB,EACrB,mCAAmC,EACnC,4BAA4B,EAC5B,eAAe,GAChB,MAAM,OAAO,CAAC"}
@@ -1,7 +1,10 @@
1
- import type { ReqCliLoginByEmployee, ResCliLoginByEmployee, ResCliVariables } from "./cli";
1
+ import type { ReqCliLoginByEmployee, ReqCliResourceRequirementCommentSet, ReqCliResourceRequirementContentSet, ReqCliResourceRequirementGet, ResCliLoginByEmployee, ResCliResourceRequirementCommentSet, ResCliResourceRequirementContentSet, ResCliResourceRequirementGet, ResCliVariables } from "./cli";
2
2
  export declare const requestConfig: {
3
3
  readonly cli: {
4
4
  readonly variablesGet: import("listpage-http").EndpointConfig<void, ResCliVariables>;
5
+ readonly resourceRequirementGet: import("listpage-http").EndpointConfig<ReqCliResourceRequirementGet, ResCliResourceRequirementGet>;
6
+ readonly resourceRequirementCommentSet: import("listpage-http").EndpointConfig<ReqCliResourceRequirementCommentSet, ResCliResourceRequirementCommentSet>;
7
+ readonly resourceRequirementContentSet: import("listpage-http").EndpointConfig<ReqCliResourceRequirementContentSet, ResCliResourceRequirementContentSet>;
5
8
  };
6
9
  readonly employee: {
7
10
  /** 登录等鉴权(路径落在 `/cli/employee/auth`,便于与业务接口区分) */
@@ -1 +1 @@
1
- {"version":3,"file":"request-config.d.ts","sourceRoot":"","sources":["../../src/api/request-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,qBAAqB,EAErB,qBAAqB,EACrB,eAAe,EAChB,MAAM,OAAO,CAAC;AAEf,eAAO,MAAM,aAAa;;;;;QAQtB,iDAAiD;;;CAO3C,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC"}
1
+ {"version":3,"file":"request-config.d.ts","sourceRoot":"","sources":["../../src/api/request-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,qBAAqB,EACrB,mCAAmC,EACnC,mCAAmC,EACnC,4BAA4B,EAE5B,qBAAqB,EACrB,mCAAmC,EACnC,mCAAmC,EACnC,4BAA4B,EAC5B,eAAe,EAChB,MAAM,OAAO,CAAC;AAEf,eAAO,MAAM,aAAa;;;;;;;;QA6BtB,iDAAiD;;;CAO3C,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC"}
@@ -8,6 +8,18 @@ exports.requestConfig = {
8
8
  method: "POST",
9
9
  path: "/cli/variables/get",
10
10
  }),
11
+ resourceRequirementGet: (0, listpage_http_1.defineEndpoint)({
12
+ method: "POST",
13
+ path: "/cli/resource/requirement",
14
+ }),
15
+ resourceRequirementCommentSet: (0, listpage_http_1.defineEndpoint)({
16
+ method: "POST",
17
+ path: "/cli/resource/requirement/comment",
18
+ }),
19
+ resourceRequirementContentSet: (0, listpage_http_1.defineEndpoint)({
20
+ method: "POST",
21
+ path: "/cli/resource/requirement/content",
22
+ }),
11
23
  },
12
24
  employee: {
13
25
  /** 登录等鉴权(路径落在 `/cli/employee/auth`,便于与业务接口区分) */
@@ -1 +1 @@
1
- {"version":3,"file":"request-config.js","sourceRoot":"","sources":["../../src/api/request-config.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AASlC,QAAA,aAAa,GAAG;IAC3B,GAAG,EAAE;QACH,YAAY,EAAE,IAAA,8BAAc,EAAsC;YAChE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,oBAAoB;SAC3B,CAAC;KACH;IACD,QAAQ,EAAE;QACR,iDAAiD;QACjD,IAAI,EAAE,IAAA,8BAAc,EAA+C;YACjE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,oBAAoB;YAC1B,YAAY,EAAE,KAAK;SACpB,CAAC;KACH;CACO,CAAC"}
1
+ {"version":3,"file":"request-config.js","sourceRoot":"","sources":["../../src/api/request-config.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AAelC,QAAA,aAAa,GAAG;IAC3B,GAAG,EAAE;QACH,YAAY,EAAE,IAAA,8BAAc,EAAsC;YAChE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,oBAAoB;SAC3B,CAAC;QACF,sBAAsB,EAAE,IAAA,8BAAc,EAGpC;YACA,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,2BAA2B;SAClC,CAAC;QACF,6BAA6B,EAAE,IAAA,8BAAc,EAG3C;YACA,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,mCAAmC;SAC1C,CAAC;QACF,6BAA6B,EAAE,IAAA,8BAAc,EAG3C;YACA,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,mCAAmC;SAC1C,CAAC;KACH;IACD,QAAQ,EAAE;QACR,iDAAiD;QACjD,IAAI,EAAE,IAAA,8BAAc,EAA+C;YACjE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,oBAAoB;YAC1B,YAAY,EAAE,KAAK;SACpB,CAAC;KACH;CACO,CAAC"}
@@ -11,11 +11,11 @@ function registerConfigCommands(program) {
11
11
  .option("--url <url>", "服务根地址")
12
12
  .action(async (id, opts) => {
13
13
  if ((0, apm_config_1.isApmConfigExists)()) {
14
- await (0, apm_config_1.syncApmConfig)();
14
+ await (0, apm_config_1.syncApmConfig)({ id: Number(id), url: opts.url });
15
15
  console.log("APM 配置已存在,已为您更新");
16
16
  }
17
17
  else {
18
- await (0, apm_config_1.createApmConfig)({ id: Number(id), url: opts.url });
18
+ (0, apm_config_1.createApmConfig)({ id: Number(id), url: opts.url });
19
19
  console.log("已为您创建 APM 配置");
20
20
  }
21
21
  });
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":";;AAOA,wDAiBC;AAvBD,sDAI+B;AAE/B,SAAgB,sBAAsB,CAAC,OAAgB;IACrD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAEnE,SAAS;SACN,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2BAA2B,CAAC;SACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;SACxB,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC;SAC9B,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAsB,EAAE,EAAE;QACnD,IAAI,IAAA,8BAAiB,GAAE,EAAE,CAAC;YACxB,MAAM,IAAA,0BAAa,GAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,IAAA,4BAAe,EAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":";;AAOA,wDAiBC;AAvBD,sDAI+B;AAE/B,SAAgB,sBAAsB,CAAC,OAAgB;IACrD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAEnE,SAAS;SACN,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2BAA2B,CAAC;SACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;SACxB,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC;SAC9B,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAsB,EAAE,EAAE;QACnD,IAAI,IAAA,8BAAiB,GAAE,EAAE,CAAC;YACxB,MAAM,IAAA,0BAAa,EAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAA,4BAAe,EAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerGetCommands(program: Command): void;
3
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/get.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmD1D"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerGetCommands = registerGetCommands;
7
+ const node_fs_1 = require("node:fs");
8
+ const client_1 = __importDefault(require("../../api/client"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const apm_config_1 = require("../../core/apm-config");
11
+ function parseRequirementId(value) {
12
+ const n = Number.parseInt(value, 10);
13
+ if (!Number.isFinite(n) || n < 1) {
14
+ throw new Error(`无效的需求 ID: ${value}`);
15
+ }
16
+ return n;
17
+ }
18
+ function registerGetCommands(program) {
19
+ const getCmd = program.command("get").description("从服务端拉取资源");
20
+ getCmd
21
+ .command("requirement")
22
+ .description("按需求 ID 获取需求文档正文")
23
+ .argument("<id>", "需求 ID", parseRequirementId)
24
+ .option("--all", "包含该需求下的所有评论")
25
+ .action(async (id, opts) => {
26
+ const res = await client_1.default.cli.resourceRequirementGet({ id });
27
+ if (!res.content) {
28
+ throw new Error("需求文档内容为空");
29
+ }
30
+ const prdPath = path_1.default.join(".apm/workitems", String(id), "prd.md");
31
+ (0, node_fs_1.mkdirSync)(path_1.default.dirname(prdPath), { recursive: true });
32
+ (0, node_fs_1.writeFileSync)(prdPath, res.content);
33
+ const config = (0, apm_config_1.loadApmConfig)();
34
+ const currentComment = res.comments.find((c) => c.employeeId === config.auth.id);
35
+ if (currentComment) {
36
+ (0, node_fs_1.writeFileSync)(path_1.default.join(".apm/workitems", String(id), "comment.md"), `======当前评论内容======
37
+ ${currentComment.content}
38
+ =========当前评论回复==========
39
+ ${currentComment.reply || ""}
40
+ `);
41
+ }
42
+ if (opts.all) {
43
+ const text = `======需求内容======
44
+ ${res.content}
45
+ =========评论内容==========
46
+ ${res.comments
47
+ .map((c) => `### ${c.reviewer}\n#### 内容\n${c.content}\n#### 回复\n${c.reply}`)
48
+ .join("\n\n")}
49
+ `;
50
+ (0, node_fs_1.writeFileSync)(path_1.default.join(".apm/workitems", String(id), "comment.md"), text);
51
+ return;
52
+ }
53
+ console.log(`需求内容如下(已保存到 ${prdPath}):`);
54
+ console.log("--------------------------------");
55
+ console.log(res.content);
56
+ console.log("--------------------------------");
57
+ });
58
+ }
59
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../src/cli/commands/get.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerSetCommands(program: Command): void;
3
+ //# sourceMappingURL=set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/set.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwD1D"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerSetCommands = registerSetCommands;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const client_1 = __importDefault(require("../../api/client"));
10
+ function parseRequirementId(value) {
11
+ const n = Number.parseInt(value, 10);
12
+ if (!Number.isFinite(n) || n < 1) {
13
+ throw new Error(`无效的需求 ID: ${value}`);
14
+ }
15
+ return n;
16
+ }
17
+ function registerSetCommands(program) {
18
+ const setCmd = program.command("set").description("向服务端提交本地资源");
19
+ setCmd
20
+ .command("requirement")
21
+ .description("读取本地需求正文文件并同步到服务端(默认:.apm/workitems/<需求ID>/prd.md)")
22
+ .argument("<id>", "需求 ID", parseRequirementId)
23
+ .action(async (id) => {
24
+ const filePath = node_path_1.default.join(process.cwd(), ".apm/workitems", String(id), "prd.md");
25
+ if (!(0, node_fs_1.existsSync)(filePath)) {
26
+ console.error(`未找到文件: ${filePath}`);
27
+ process.exit(1);
28
+ }
29
+ const content = (0, node_fs_1.readFileSync)(filePath, "utf8");
30
+ if (!content.trim()) {
31
+ console.error("需求正文为空");
32
+ process.exit(1);
33
+ }
34
+ const res = await client_1.default.cli.resourceRequirementContentSet({ id, content });
35
+ console.log(`需求正文已同步(id=${res.id}`);
36
+ });
37
+ setCmd
38
+ .command("comment")
39
+ .description("读取 .apm/workitems/<需求ID>/comment.md 并提交评审记录(写入服务端需求字段)")
40
+ .argument("<id>", "需求 ID", parseRequirementId)
41
+ .action(async (id) => {
42
+ const commentPath = node_path_1.default.join(process.cwd(), ".apm/workitems", String(id), "comment.md");
43
+ if (!(0, node_fs_1.existsSync)(commentPath)) {
44
+ console.error(`未找到文件: ${commentPath}`);
45
+ process.exit(1);
46
+ }
47
+ const content = (0, node_fs_1.readFileSync)(commentPath, "utf8");
48
+ if (!content.trim()) {
49
+ console.error("comment.md 内容为空");
50
+ process.exit(1);
51
+ }
52
+ await client_1.default.cli.resourceRequirementCommentSet({ id, content });
53
+ console.log("评审记录已提交");
54
+ });
55
+ }
56
+ //# sourceMappingURL=set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.js","sourceRoot":"","sources":["../../../src/cli/commands/set.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ws.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoBzD"}
1
+ {"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ws.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkBzD"}
@@ -4,8 +4,8 @@ exports.registerWsCommands = registerWsCommands;
4
4
  const ws_client_1 = require("../../core/ws-client");
5
5
  function registerWsCommands(program) {
6
6
  program
7
- .command("ws")
8
- .description("启动员工 WebSocket 客户端,连接后等待服务端推送(Ctrl+C 退出)。可通过 --token 直接传入")
7
+ .command("connect")
8
+ .description("启动员工 WebSocket 客户端(Ctrl+C 退出)")
9
9
  .action(() => {
10
10
  const ws = new ws_client_1.EmployeeWebSocketClient();
11
11
  const shutdown = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"ws.js","sourceRoot":"","sources":["../../../src/cli/commands/ws.ts"],"names":[],"mappings":";;AAGA,gDAoBC;AAtBD,oDAA+D;AAE/D,SAAgB,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,IAAI,CAAC;SACb,WAAW,CACV,2DAA2D,CAC5D;SACA,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,GAAG,IAAI,mCAAuB,EAAE,CAAC;QAEzC,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,IAAI,CAAC;gBACH,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"ws.js","sourceRoot":"","sources":["../../../src/cli/commands/ws.ts"],"names":[],"mappings":";;AAGA,gDAkBC;AApBD,oDAA+D;AAE/D,SAAgB,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,+BAA+B,CAAC;SAC5C,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,GAAG,IAAI,mCAAuB,EAAE,CAAC;QAEzC,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,IAAI,CAAC;gBACH,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/cli.js CHANGED
@@ -4,8 +4,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
5
  const auth_1 = require("./cli/commands/auth");
6
6
  const config_1 = require("./cli/commands/config");
7
+ const get_1 = require("./cli/commands/get");
7
8
  const init_1 = require("./cli/commands/init");
8
9
  const publish_1 = require("./cli/commands/publish");
10
+ const set_1 = require("./cli/commands/set");
9
11
  const update_1 = require("./cli/commands/update");
10
12
  const ws_1 = require("./cli/commands/ws");
11
13
  const constants_1 = require("./core/constants");
@@ -15,6 +17,8 @@ const program = new commander_1.Command()
15
17
  .version(constants_1.PACKAGE_VERSION);
16
18
  (0, config_1.registerConfigCommands)(program);
17
19
  (0, auth_1.registerAuthCommands)(program);
20
+ (0, get_1.registerGetCommands)(program);
21
+ (0, set_1.registerSetCommands)(program);
18
22
  (0, ws_1.registerWsCommands)(program);
19
23
  (0, update_1.registerUpdateCommands)(program);
20
24
  (0, init_1.registerInitCommands)(program);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,8CAA2D;AAC3D,kDAA+D;AAC/D,8CAA2D;AAC3D,oDAAiE;AACjE,kDAA+D;AAC/D,0CAAuD;AACvD,gDAAwE;AAExE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE;KAC1B,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,+BAAmB,CAAC;KAChC,OAAO,CAAC,2BAAe,CAAC,CAAC;AAE5B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,uBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,iCAAuB,EAAC,OAAO,CAAC,CAAC;AAEjC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,8CAA2D;AAC3D,kDAA+D;AAC/D,4CAAyD;AACzD,8CAA2D;AAC3D,oDAAiE;AACjE,4CAAyD;AACzD,kDAA+D;AAC/D,0CAAuD;AACvD,gDAAwE;AAExE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE;KAC1B,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,+BAAmB,CAAC;KAChC,OAAO,CAAC,2BAAe,CAAC,CAAC;AAE5B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,uBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,iCAAuB,EAAC,OAAO,CAAC,CAAC;AAEjC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -17,7 +17,10 @@ export type ApmConfig = {
17
17
  };
18
18
  };
19
19
  export declare function loadApmConfig(): ApmConfig;
20
- export declare function syncApmConfig(): Promise<void>;
20
+ export declare function syncApmConfig(options: {
21
+ id: number;
22
+ url?: string;
23
+ }): Promise<void>;
21
24
  export declare function isApmConfigExists(): boolean;
22
25
  export declare function saveApmToken(token: string): void;
23
26
  export declare function createApmConfig(options: {
@@ -1 +1 @@
1
- {"version":3,"file":"apm-config.d.ts","sourceRoot":"","sources":["../../src/core/apm-config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE;QAEJ,EAAE,EAAE,MAAM,CAAC;QAEX,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,EAAE;QAEN,GAAG,EAAE,MAAM,CAAC;QAEZ,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,wBAAgB,aAAa,IAAI,SAAS,CAczC;AAGD,wBAAsB,aAAa,kBAMlC;AAMD,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,QAKzC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,QA2BpE"}
1
+ {"version":3,"file":"apm-config.d.ts","sourceRoot":"","sources":["../../src/core/apm-config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE;QAEJ,EAAE,EAAE,MAAM,CAAC;QAEX,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,EAAE;QAEN,GAAG,EAAE,MAAM,CAAC;QAEZ,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,wBAAgB,aAAa,IAAI,SAAS,CAYzC;AAGD,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBAYxE;AAMD,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,QAKzC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,QA2BpE"}
@@ -17,8 +17,6 @@ function loadApmConfig() {
17
17
  const p = getApmConfigPath();
18
18
  if (!(0, node_fs_1.existsSync)(p)) {
19
19
  createApmConfig({ id: 0 });
20
- console.error("配置文件不存在,请确保当前目录下存在 apm.config.json");
21
- process.exit(1);
22
20
  }
23
21
  const j = JSON.parse((0, node_fs_1.readFileSync)(p, "utf8"));
24
22
  return j;
@@ -29,9 +27,15 @@ function loadApmConfig() {
29
27
  }
30
28
  }
31
29
  // 同步远程的配置项到本地
32
- async function syncApmConfig() {
30
+ async function syncApmConfig(options) {
33
31
  const p = getApmConfigPath();
34
32
  const cfg = loadApmConfig();
33
+ if (options.id) {
34
+ cfg.auth.id = options.id;
35
+ }
36
+ if (options.url) {
37
+ cfg.server.url = options.url;
38
+ }
35
39
  const res = await client_1.default.cli.variablesGet();
36
40
  const j = JSON.stringify({ ...cfg, ...res }, null, 2);
37
41
  (0, node_fs_1.writeFileSync)(p, j);
@@ -1 +1 @@
1
- {"version":3,"file":"apm-config.js","sourceRoot":"","sources":["../../src/core/apm-config.ts"],"names":[],"mappings":";;;;;AA4BA,sCAcC;AAGD,sCAMC;AAMD,8CAOC;AAED,oCAKC;AAED,0CA2BC;AApGD,0DAA6B;AAC7B,qCAA4E;AAC5E,+CAAmC;AACnC,2DAAgC;AAyBhC,SAAgB,aAAa;IAC3B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,gBAAgB,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAA,oBAAU,EAAC,CAAC,CAAC,EAAE,CAAC;YACnB,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,CAAC,EAAE,MAAM,CAAC,CAAc,CAAC;QAC3D,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,cAAc;AACP,KAAK,UAAU,aAAa;IACjC,MAAM,CAAC,GAAG,gBAAgB,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,gBAAG,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACtD,IAAA,uBAAa,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,mBAAI,CAAC,IAAI,CAAC,IAAA,kBAAG,GAAE,EAAE,sBAAsB,CAAC,CAAC;AAClD,CAAC;AAED,SAAgB,iBAAiB;IAC/B,MAAM,CAAC,GAAG,gBAAgB,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,OAAO,IAAA,kBAAQ,EAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAgB,YAAY,CAAC,KAAa;IACxC,MAAM,CAAC,GAAG,gBAAgB,EAAE,CAAC;IAC7B,MAAM,aAAa,GAAG,aAAa,EAAE,CAAC;IACtC,aAAa,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACjC,IAAA,uBAAa,EAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAgB,eAAe,CAAC,OAAqC;IACnE,MAAM,CAAC,GAAG,gBAAgB,EAAE,CAAC;IAC7B,IAAA,uBAAa,EACX,CAAC,EACD,IAAI,CAAC,SAAS,CACZ;QACE,IAAI,EAAE;YACJ,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,KAAK,EAAE,EAAE;SACV;QACD,MAAM,EAAE;YACN,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,uBAAuB;YAC3C,MAAM,EAAE,IAAI;SACb;QACD,MAAM,EAAE;YACN,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,EAAE;YACV,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,EAAE;SACd;KACF,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"apm-config.js","sourceRoot":"","sources":["../../src/core/apm-config.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "private": false,
5
5
  "description": "AI 项目管理 CLI 工具,结合飞书项目实现AI项目开发工作流",
6
6
  "main": "./dist/index.js",
@@ -1,33 +1,19 @@
1
1
  ---
2
- name: requirement-doc-refine
3
- description: 依据用户提供的补充信息(如对评审的回复、澄清与拍板口径)完善需求文档,合并定稿后经 CLI(apm comment process)存档。须同时提供需求原文、评审内容作对照与 requirementId、versionSeq;以补充信息为准,未回应的评审点不自动当成待办。仅在用户明确声明使用本技能时应用(例如 @ 本 SKILL 或写明 requirement-doc-refine);不因泛泛表述自动启用。
2
+ name: requirement-prd-sync
3
+ description: 根据评论与用户回复合并修订需求 PRD,覆盖本地 prd.md 并同步服务端;仅当用户主动提及该技能时使用,依赖需求 ID。
4
4
  ---
5
5
 
6
- # 需求文档完善(基于补充信息)
6
+ # 需求 PRD 修订与同步
7
7
 
8
- 本技能用于在**需求原文**之上,结合用户给出的**补充信息**,把零散说明整理成**结构清晰、可执行**的一版需求正文,并通过 CLI 提交以写入需求内容版本。补充信息**常见**为针对评审的逐条回应,亦可包含用户明确提供的其他修订说明;**仅**将用户明确要写入的口径并入正文,不替用户发挥。
8
+ 本技能用于在**需求原文**之上,结合用户给出的**补充信息**,把零散说明整理成**结构清晰、可执行**的一版需求正文:先将定稿**覆盖**本地 `prd.md`,再通过 **`apm set requirement`** 将正文同步到服务端。补充信息**常见**为针对评审的逐条回应,亦可包含用户明确提供的其他修订说明;**仅**将用户明确要写入的口径并入正文,不替用户发挥。
9
9
 
10
10
  ## 触发条件
11
11
 
12
- - **必须**:用户**明确声明**使用本技能(例如在对话中 @ 本 `SKILL.md`、或写明使用 `requirement-doc-refine` /「用需求文档完善技能」等可核验的指代)。
13
- - 未作上述声明时,**不**因「帮我完善需求」「合并补充信息进 PRD」「根据评审改需求」「更新需求文档」等表述自动套用本技能的工作方式与模板。
12
+ 用户**明确声明**使用本技能(例如在对话中 @ 本 SKILL
14
13
 
15
- 满足触发后,再按下节收集材料并执行;若缺「需求原文」「补充信息(用户回应)」「评审内容」或存档所需的 **`requirementId`**、**`versionSeq`**(修订所基于的版本序号),先索要再执行。
14
+ ## 输入
16
15
 
17
- ## 输入(按需收集)
18
-
19
- 声明使用本技能后,还须具备:
20
-
21
- - **必需**:**需求原文**、**评审内容**、**补充信息(用户回应)**(含对哪些点做了补充;可不要求逐条对齐评审编号)、**`requirementId`**(需求 id,整数)、**`versionSeq`**(该需求下作为修订基准的版本序号,与界面 `v1`、`v2` 一致,非数据库 id),与定稿正文一起在首轮给出,供第 5 步 `apm comment process` 使用。
22
- - **评审内容**:完整评审 Markdown(或与本次修订对应的摘录),用于把补充信息与评审条目对上号;**不得**据此单方面改需求。
23
-
24
- | 输入 | 说明 |
25
- |------|------|
26
- | **需求原文** | 待完善的 PRD/需求全文或关键段落 |
27
- | **评审内容** | 与本次修订对应的评审正文(或摘录);用于对照,**不得**单独驱动改写 |
28
- | **补充信息(用户回应)** | 用户明确要写入需求或明确补充/修正的口径;**未提及的评审点一律不主动处理** |
29
- | **`requirementId`** | 需求 id,对应 CLI `--requirement-id` |
30
- | **`versionSeq`** | 修订所基于的版本序号(与界面 `v1`、`v2` 一致),对应 CLI `--version-seq` |
16
+ - **`requirementId`(必须)**:需求 ID。
31
17
 
32
18
  可选:**修订范围**(全文重写 / 只改某几节)、**术语表**、**必须保留的编号**。
33
19
 
@@ -43,51 +29,34 @@ description: 依据用户提供的补充信息(如对评审的回复、澄清
43
29
 
44
30
  ## 输出
45
31
 
46
- - **默认**:输出 **Markdown** 形式的**更新后需求**(或用户指定章节),结构参考 [updated-requirement-template.md](updated-requirement-template.md);**定稿全文**作为第 5 步传给 `apm comment process` 的正文(`--content` 或 `--content-file`)。
32
+ - **默认**:输出 **Markdown** 形式的**更新后需求**(或用户指定章节),结构参考 [updated-requirement-template.md](updated-requirement-template.md)
47
33
  - **用户只要补丁**:仍须合并为**完整一版**正文再存档(对话中可附「变更摘要」便于阅读)。
48
34
  - **语言**:与需求原文一致(中文为主时全文中文)。
49
35
 
50
36
  ## 执行步骤
51
37
 
52
- 1. 以**原文**为底稿,对照**评审内容**,逐条落实**补充信息**中明确要求写进需求的修改。
53
- 2. 仅当某条补充信息明显对应某条评审时,再辅助定位修改位置;**跳过**用户完全未提的评审条目(仍须已提供评审全文/摘录以便对照,但不据此发挥)。
54
- 3. **「待确认」**:仅当**用户自己在补充信息里**留下未决口径、或明确说「待定」「再议」时写入;**不因**评审提了而用户未提供对应补充就填「待确认」。
55
- 4. 通读检查:无内部矛盾;正文无不来自补充信息的「新需求」。
56
- 5. **存档需求版本(使用 CLI)**:将第 4 步定稿的**完整修订稿**通过 CLI 命令提交,由服务端处理该版本下「待处理」评论并创建新版本(同步需求正文)。
57
-
58
- - **命令**:`apm comment process`
59
- - **必填参数**:
60
- - `--requirement-id <id>`:需求 id(即本技能输入的 `requirementId`)
61
- - `--version-seq <n>`:该需求下的版本序号(与界面 `1`、`2` 一致,非数据库 id)
62
- - `--content <text>` 或 `--content-file <path>`:修订后的需求正文全文(二选一)
38
+ 1. **拉取需求与评论(使用 CLI)**:执行 `apm get requirement <requirementId> --all`,获取需求文档及**全部评论**;该命令会将需求信息(含正文、版本与评论等)打印到终端,作为后续修订的**原文与评审依据**。
39
+ 2. 以**原文**为底稿,对照**评审内容**,逐条落实**补充信息**中明确要求写进需求的修改。
40
+ 3. 仅当某条补充信息明显对应某条评审时,再辅助定位修改位置;**跳过**用户完全未提的评审条目(仍须已提供评审全文/摘录以便对照,但不据此发挥)。
41
+ 4. **「待确认」**:仅当**用户自己在补充信息里**留下未决口径、或明确说「待定」「再议」时写入;**不因**评审提了而用户未提供对应补充就填「待确认」。
42
+ 5. 通读检查:无内部矛盾;正文无不来自补充信息的「新需求」。
43
+ 6. **存档并同步到服务端(两步)**:
63
44
 
64
- **示例(推荐文件方式,避免多行转义)**:
45
+ **6.1 覆盖本地需求文档**:将第 5 步定稿的**完整修订稿**写入 **`.apm/workitems/<requirementId>/prd.md`**(**覆盖**原文件,与 `apm get requirement` 拉取下来的路径一致)。
65
46
 
66
- ```bash
67
- apm comment process \
68
- --requirement-id 1 \
69
- --version-seq 2 \
70
- --content-file ./updated-requirement.md
71
- ```
72
-
73
- **示例(直接传文本)**:
47
+ **6.2 同步到服务器**:在仓库根目录执行 **`apm set requirement <requirementId>`**
74
48
 
75
49
  ```bash
76
- apm comment process \
77
- --requirement-id 1 \
78
- --version-seq 2 \
79
- --content "这是要存档的一版需求正文内容……"
50
+ apm set requirement 1
80
51
  ```
81
52
 
82
- 实际调用时把 `requirementId`、`versionSeq` 换成首轮给出的值,把 `content`(或 `content-file` 指向的文件内容)换成第 4 步成文结果。命令失败时说明错误信息;成功时可简要确认已创建新版本并返回处理结果。若用户**另行**要求写入仓库内某路径,再按需保存文件。
83
-
84
53
  ## 自检清单
85
54
 
86
55
  - [ ] 修订稿中的新增/变更均可追溯到补充信息(或用户要求保留的原文),无「替用户采纳评审」的发挥
87
56
  - [ ] 未把未回应的评审当成待解决问题写进文档
88
57
  - [ ] 未把评审人猜测当事实写进需求
89
58
  - [ ] 修订稿单读可理解,不依赖聊天记录才能懂
90
- - [ ] `apm comment process` 传入的正文与定稿修订稿一致,`--requirement-id`、`--version-seq` 与用户给定一致
59
+ - [ ] `.apm/workitems/<requirementId>/prd.md`与定稿修订稿一致,且已成功执行 `apm set requirement`
91
60
 
92
61
  ## 附加资源
93
62
 
@@ -1,32 +1,26 @@
1
1
  ---
2
2
  name: requirement-review
3
- description: 结合本仓库上下文对需求做结构化评审,按 output-template.md 形成完整 Markdown 评审正文;**始终**将正文落盘到 `.apm/workitems/<name>/comment-<commentId>.md` 并通过 CLI `--content-file` 写入评论(**不删除**该文件)。输入为需求正文、`commentId`、workitem 目录名 `<name>`(首轮一并给出或可从 `.apm/workitems/` 唯一定位)。仅在用户明确声明使用本技能时应用。
3
+ description: 结合本仓库上下文对需求做结构化评审,只有当用户主动提及该技能时才可被使用,该技能调用依赖需求ID。
4
4
  ---
5
5
 
6
- # 需求评审(仓库内)
6
+ # 需求评审
7
7
 
8
8
  ## 触发条件
9
9
 
10
- - **必须**:用户**明确声明**使用本技能(例如在对话中 @ 本 SKILL)
11
- - 未作上述声明时,**不**因「帮我看看需求」「评审一下」等表述自动套用本技能的工作方式与输出模板
12
-
13
- 满足触发后,用户须在**首轮对话**中一并给出:**需求正文**、`commentId`(评论 id)、**workitem 目录名 `<name>`**(与 `.apm/workitems/<name>/prd.md` 等同级产物所在目录一致,通常为 kebab-case)。若未给出 `<name>` 但仓库内**仅有一个**合理关联的 workitem 目录,可据 `.apm/workitems/` 推断;否则须先索要。不要求其他附件。
10
+ 用户**明确声明**使用本技能(例如在对话中 @ 本 SKILL)
14
11
 
15
12
  ## 输入
16
13
 
17
- - **需求正文**:用户粘贴的待评审内容
18
- - **`commentId`**:评论记录 id(整数,与正文一起在对话中给出)
19
- - **`<name>`**:`.apm/workitems/<name>/` 下的目录名,用于落盘评论存档(见下文);与首轮一并给出或由仓库唯一定位
20
-
21
- 若首轮未给出 `commentId` 或无法确定 `<name>`,须先向用户索要(或澄清)后再执行第 6 步。
14
+ - **`requirementId`(必须)**:需求 ID。
22
15
 
23
16
  ## 输出
24
17
 
25
- - **评审正文**:须先按模板在**逻辑上**成文(完整 Markdown 字符串),不得仅给零散要点。可在回复中展示。**落盘(强制)**:将第 4 步全文以 UTF-8 写入 **`.apm/workitems/<name>/comment-<commentId>.md`**(文件名中的 id 与输入 `commentId` 一致,例如 `comment-42.md`);**始终保留该文件**,不因 CLI 成功而删除,也不使用临时目录替代。第 6 步**统一**用该路径作为 `--content-file` 更新评论(避免 shell 参数长度与转义问题)。
18
+ - **评审正文(须写入 comment)**:须先按模板在**逻辑上**成文(完整 Markdown 字符串),不得仅给零散要点。**对话中不要粘贴完整评审正文**;全文仅写入 **`.apm/workitems/<requirementId>/comment.md`** 并通过 **`apm set comment`** 提交,供用户在需求侧或系统中查看。
26
19
  - 将需求拆成若干条「需求点」(若本就一条则一条),对每条按 [output-template.md](output-template.md) 的**字段规则与并存关系**输出结论。
27
- - 语言面向产品/研发可读:少堆砌实现细节,**不**用具体文件路径、函数名当「证据」;仓库仅用于理解**能力边界、术语与业务上下文**。
20
+ - **项目隐性知识沉淀建议(必选,唯一在对话中展示的长文)**:在完成评审正文并**提交 comment 之后**,在对话里**只**输出这一段(可用 Markdown 小标题);**不要**在对话中重复贴评审模板全文。目的**不是**把需求写得更细,而是让**仓库侧**的文档、约定、可复用模式更清晰(必要时含代码组织/命名层面的改进方向),使日后**简短需求**也能被 AI 定位「改哪里、怎么改」,减少与「通用/行业默认」不一致时的重复追问(例如本项目的交互惯例、删除是否确认、与已有类似流程应对齐的隐性规则等)。须紧扣**本次需求内容**与**本次评审中暴露的、源于项目与常识差异的盲区**,给出可执行的沉淀项;**禁止**泛泛而谈。**不得**写入 **`.apm/workitems/<requirementId>/comment.md`**,**不得**作为 `apm set comment` 的正文内容。
21
+ - 语言面向产品可读:少堆砌实现细节,**不**用具体文件路径、函数名当「证据」;仓库仅用于理解**能力边界、术语与业务上下文**。
28
22
 
29
- 结构要点(细节以 `output-template.md` 为准):`### 需求点 n`、`- **需求描述:**:` 及可选的 `业务合理性` / `问题` / `可行性` / `风险点`;**严禁** H1/H2 与表格。
23
+ 结构要点(写入 comment 的部分以 `output-template.md` 为准):`### 评审人`、`### 需求点 n`、`- **需求描述:**:` 及可选的 `业务合理性` / `问题` / `可行性` / `风险点`。**不包含**「隐性知识沉淀」类段落。
30
24
 
31
25
  ## 评审原则
32
26
 
@@ -37,24 +31,17 @@ description: 结合本仓库上下文对需求做结构化评审,按 output-te
37
31
  - 仅当 PRD/需求信息**不足以**形成开发可执行描述(关键落点、口径、范围、汇总规则等无法确定)时,写 `- **问题:**`,此时**不写**可行性与风险点。
38
32
  - 若已足以判断「可以实现」(非关键细节不阻塞落地),写 `- **可行性:**`(成本低/中/高 + 精简说明);影响面大时再追加 `- **风险点:**`。
39
33
  5. **澄清优先但不泛问**:不阻塞落地则不提问;不问可推断的琐碎问题。
34
+ 6. **隐性知识沉淀可执行**:对用户单独输出的每条沉淀建议应能回答「在仓库里补什么、能消除哪类隐性歧义」;若本次未发现值得沉淀的差异点,仍须给出一句结论(例如「未发现与通用假设显著偏离、需单独成文的隐性规则」)。
40
35
 
41
36
  ## 执行步骤
42
37
 
43
- 1. **锁定正文**:以用户提供的全部需求正文为准;若明显缺段或指代不清,在「问题」中列出待澄清点。
44
- 2. **按需读仓库**:快速扫 `AGENTS.md`、`apps/fe/AGENTS.md`、`servers/be/AGENTS.md` 及 `.apm/product-capability-inventory` 中与需求相关的条目;不展开无关模块代码。
38
+ 1. **获取需求正文**:`apm get requirement <requirementId>`,如果报错则停止后面的步骤
39
+ 2. **读代码**:阅读仓库源码以及 `.apm/product-capability-inventory` 中与需求相关的条目;不展开无关模块代码。
45
40
  3. **拆条**:多条诉求时拆成 `### 需求点 1..N`,每条独立走完「业务合理性(可选)→ 问题 或 可行性(+风险)」逻辑。
46
- 4. **成文**:按 `output-template.md` 拼出完整 Markdown 字符串(顶格可加 `### 评审人` + 当前模型名);**随即**将全文写入 **`.apm/workitems/<name>/comment-<commentId>.md`**(目录不存在则创建;同一 id 重跑则**覆盖**该文件,仍不删除)。
47
- 5. **自检**:每条是否都有「需求描述」;「问题」与「可行性/风险」是否互斥符合 `output-template.md`;是否误引代码路径作论据。
48
- 6. **提交评审记录**:调用 **CLI 命令**,读取第 4 步已落盘的 **`.apm/workitems/<name>/comment-<commentId>.md`**,将内容与评论正文同步。
49
-
50
- - **CLI 命令**:`apm comment update --id <commentId> --content-file .apm/workitems/<name>/comment-<commentId>.md`
51
- - **禁止**:成功后 `rm` 该文件或使用仅存在于系统临时目录、意图事后删除的副本;评论存档以 workitem 目录下该文件为准。
52
-
53
- ```bash
54
- apm comment update --id 42 --content-file .apm/workitems/my-feature/comment-42.md
55
- ```
56
-
57
- 实际调用时替换为你的 `<commentId>`、`<name>`。失败时把命令报错贴出;成功时可简要确认评论已更新且 **`comment-<commentId>.md` 仍保留在仓库中**。
41
+ 4. **成文(仅评审模板)**:按 `output-template.md` 拼出写入 comment 的 Markdown(顶格可加 `### 评审人` + 当前模型名);**不含**「隐性知识沉淀」段落;**随即**将**该字符串**写入 **`.apm/workitems/<requirementId>/comment.md`**(如果存在则直接覆盖更新)。
42
+ 5. **自检**:每条是否都有「需求描述」;「问题」与「可行性/风险」是否互斥符合 `output-template.md`;是否误引代码路径作论据;comment 全文是否**未混入**隐性知识段落。
43
+ 6. **提交评审记录**:`apm set comment <requirementId>`(正文与 comment.md 一致,仅为评审模板内容)。
44
+ 7. **对用户的单独陈述**:在对话中**仅**输出「项目隐性知识沉淀建议」(见上文「输出」);开头可用一句告知「完整评审已写入 comment / 已提交,以下仅为隐性知识沉淀」;**不要**在对话中粘贴评审正文,也**不要**把隐性知识段写入 comment 或重复提交。
58
45
 
59
46
  ## 附加资源
60
47
 
@@ -1,5 +1,3 @@
1
- > 本文件定义 `requirement-review` 技能的**评审输出** Markdown 结构与字段规则;迭代本技能时优先改此文件。
2
-
3
1
  ### 评审人
4
2
 
5
3
  模型名称