ai-project-manage-cli 1.0.29 → 2.0.2
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 +30 -0
- package/dist/api/cli.d.ts.map +1 -0
- package/dist/api/cli.js +3 -0
- package/dist/api/cli.js.map +1 -0
- package/dist/api/client.d.ts +10 -4
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +7 -4
- package/dist/api/client.js.map +1 -1
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -4
- package/dist/api/index.js.map +1 -1
- package/dist/api/request-config.d.ts +6 -15
- package/dist/api/request-config.d.ts.map +1 -1
- package/dist/api/request-config.js +8 -41
- package/dist/api/request-config.js.map +1 -1
- package/dist/api/requirement.d.ts +0 -133
- package/dist/api/requirement.d.ts.map +1 -1
- package/dist/api/requirement.js +0 -4
- package/dist/api/requirement.js.map +1 -1
- package/dist/cli/commands/auth.d.ts.map +1 -1
- package/dist/cli/commands/auth.js +32 -51
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/config.js +12 -48
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/publish.d.ts.map +1 -1
- package/dist/cli/commands/publish.js +3 -16
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +2 -2
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/ws.d.ts.map +1 -1
- package/dist/cli/commands/ws.js +4 -73
- package/dist/cli/commands/ws.js.map +1 -1
- package/dist/cli/exit-api-error.d.ts.map +1 -1
- package/dist/cli/exit-api-error.js +6 -0
- package/dist/cli/exit-api-error.js.map +1 -1
- package/dist/cli.js +6 -38
- package/dist/cli.js.map +1 -1
- package/dist/core/apm-config.d.ts +27 -0
- package/dist/core/apm-config.d.ts.map +1 -0
- package/dist/core/apm-config.js +77 -0
- package/dist/core/apm-config.js.map +1 -0
- package/dist/core/constants.d.ts +3 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +9 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/cursor-cmd.d.ts +23 -0
- package/dist/core/cursor-cmd.d.ts.map +1 -0
- package/dist/core/cursor-cmd.js +137 -0
- package/dist/core/cursor-cmd.js.map +1 -0
- package/dist/core/std-event-handler.d.ts +25 -0
- package/dist/core/std-event-handler.d.ts.map +1 -0
- package/dist/core/std-event-handler.js +90 -0
- package/dist/core/std-event-handler.js.map +1 -0
- package/dist/core/utils.d.ts +19 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +71 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/core/ws-client.d.ts +24 -0
- package/dist/core/ws-client.d.ts.map +1 -0
- package/dist/core/ws-client.js +79 -0
- package/dist/core/ws-client.js.map +1 -0
- package/package.json +3 -3
- package/templates/skills/apm-auto-dev/SKILL.md +73 -16
- package/templates/skills/requirement-review/SKILL.md +12 -21
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CursorCmd = void 0;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const std_event_handler_1 = require("./std-event-handler");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
class CursorCmd {
|
|
8
|
+
workdir;
|
|
9
|
+
prompt;
|
|
10
|
+
model;
|
|
11
|
+
chatId;
|
|
12
|
+
name;
|
|
13
|
+
requirementId;
|
|
14
|
+
constructor(payload) {
|
|
15
|
+
this.workdir = payload.workdir;
|
|
16
|
+
const cleaned = (0, utils_1.cleanPrompt)(payload.prompt);
|
|
17
|
+
this.name = cleaned.headToken;
|
|
18
|
+
this.prompt = cleaned.bodyWithoutHead;
|
|
19
|
+
this.model = payload.model;
|
|
20
|
+
this.requirementId = payload.requirementId;
|
|
21
|
+
this.chatId = payload.chatId;
|
|
22
|
+
}
|
|
23
|
+
execute() {
|
|
24
|
+
if (!this.chatId) {
|
|
25
|
+
this.chatId = this.createChat();
|
|
26
|
+
}
|
|
27
|
+
if (!this.chatId) {
|
|
28
|
+
console.error("命令执行失败");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const argv = this.buildArgs();
|
|
32
|
+
return this.runPrompt(argv);
|
|
33
|
+
}
|
|
34
|
+
// 处理参数
|
|
35
|
+
buildArgs() {
|
|
36
|
+
const args = [];
|
|
37
|
+
if (this.model) {
|
|
38
|
+
args.push("--model", this.model);
|
|
39
|
+
}
|
|
40
|
+
if (this.workdir) {
|
|
41
|
+
args.push("--workspace", this.workdir);
|
|
42
|
+
}
|
|
43
|
+
if (this.chatId) {
|
|
44
|
+
args.push("--resume", this.chatId);
|
|
45
|
+
}
|
|
46
|
+
return [
|
|
47
|
+
"-f",
|
|
48
|
+
"-p",
|
|
49
|
+
...args,
|
|
50
|
+
"--trust",
|
|
51
|
+
"--output-format",
|
|
52
|
+
"stream-json",
|
|
53
|
+
"--stream-partial-output",
|
|
54
|
+
(0, utils_1.escapePromptForCliArg)(this.prompt),
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
// 执行提示词
|
|
58
|
+
runPrompt(args) {
|
|
59
|
+
const child = this.execCommand("agent", args);
|
|
60
|
+
const stdoutEventHandler = new std_event_handler_1.StdoutEventHandler((ev) => {
|
|
61
|
+
console.log(ev);
|
|
62
|
+
});
|
|
63
|
+
const stderrEventHandler = new std_event_handler_1.StderrEventHandler((ev) => {
|
|
64
|
+
console.log(ev);
|
|
65
|
+
});
|
|
66
|
+
const childProcessEventHandler = new std_event_handler_1.ChildProcessEventHandler(this.name, (ev) => {
|
|
67
|
+
console.log(ev);
|
|
68
|
+
});
|
|
69
|
+
child.stdout?.on("data", stdoutEventHandler.onData);
|
|
70
|
+
child.stdout?.on("end", stdoutEventHandler.onEnd);
|
|
71
|
+
child.stderr?.on("data", stderrEventHandler.onData);
|
|
72
|
+
child.stderr?.on("end", stderrEventHandler.onEnd);
|
|
73
|
+
child.on("close", childProcessEventHandler.onClose);
|
|
74
|
+
child.on("error", childProcessEventHandler.onError);
|
|
75
|
+
}
|
|
76
|
+
// 创建会话
|
|
77
|
+
createChat() {
|
|
78
|
+
const result = this.execCommandSync("agent", ["create-chat"]);
|
|
79
|
+
if (result.error) {
|
|
80
|
+
console.error(`创建会话失败: ${result.error.message}`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (typeof result.status === "number" && result.status !== 0) {
|
|
84
|
+
const stderr = String(result.stderr ?? "").trim();
|
|
85
|
+
console.error(`创建会话失败: ${stderr || `exit code ${result.status}`}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const output = String(result.stdout ?? "").trim();
|
|
89
|
+
if (!output) {
|
|
90
|
+
console.error("创建会话失败: 未获取到 chatId");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// 兼容命令输出中包含其他日志,取最后一个非空行作为 chatId。
|
|
94
|
+
const lines = output
|
|
95
|
+
.split(/\r?\n/)
|
|
96
|
+
.map((s) => s.trim())
|
|
97
|
+
.filter(Boolean);
|
|
98
|
+
const chatId = lines.at(-1) ?? "";
|
|
99
|
+
if (!chatId) {
|
|
100
|
+
console.error("创建会话失败: chatId 为空");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
return chatId;
|
|
104
|
+
}
|
|
105
|
+
execCommand(command, args) {
|
|
106
|
+
const isWin = process.platform === "win32";
|
|
107
|
+
if (isWin) {
|
|
108
|
+
return (0, node_child_process_1.spawn)("cmd.exe", ["/d", "/s", "/c", command, ...args], {
|
|
109
|
+
cwd: this.workdir,
|
|
110
|
+
windowsVerbatimArguments: false,
|
|
111
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return (0, node_child_process_1.spawn)(command, args, {
|
|
115
|
+
cwd: this.workdir,
|
|
116
|
+
shell: false,
|
|
117
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
execCommandSync(command, args) {
|
|
121
|
+
const isWin = process.platform === "win32";
|
|
122
|
+
if (isWin) {
|
|
123
|
+
return (0, node_child_process_1.spawnSync)("cmd.exe", ["/d", "/s", "/c", command, ...args], {
|
|
124
|
+
cwd: this.workdir,
|
|
125
|
+
windowsVerbatimArguments: false,
|
|
126
|
+
encoding: "utf8",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return (0, node_child_process_1.spawnSync)(command, args, {
|
|
130
|
+
cwd: this.workdir,
|
|
131
|
+
shell: false,
|
|
132
|
+
encoding: "utf8",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.CursorCmd = CursorCmd;
|
|
137
|
+
//# sourceMappingURL=cursor-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-cmd.js","sourceRoot":"","sources":["../../src/core/cursor-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare class StdoutEventHandler {
|
|
2
|
+
private onChunk;
|
|
3
|
+
cacheText: string;
|
|
4
|
+
constructor(onChunk: (chunk: any) => void);
|
|
5
|
+
onData: (chunk: Buffer) => void;
|
|
6
|
+
onEnd: () => void;
|
|
7
|
+
private log;
|
|
8
|
+
}
|
|
9
|
+
export declare class StderrEventHandler {
|
|
10
|
+
private onChunk;
|
|
11
|
+
private stderrDecoder;
|
|
12
|
+
constructor(onChunk: (chunk: any) => void);
|
|
13
|
+
onData: (chunk: Buffer) => void;
|
|
14
|
+
onEnd: () => void;
|
|
15
|
+
private log;
|
|
16
|
+
}
|
|
17
|
+
export declare class ChildProcessEventHandler {
|
|
18
|
+
private command;
|
|
19
|
+
private onChunk;
|
|
20
|
+
private errorMessage;
|
|
21
|
+
constructor(command: string, onChunk: (chunk: any) => void);
|
|
22
|
+
onClose: (code: number, signal: string) => void;
|
|
23
|
+
onError: (err: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=std-event-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"std-event-handler.d.ts","sourceRoot":"","sources":["../../src/core/std-event-handler.ts"],"names":[],"mappings":"AAGA,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,OAAO;IAF3B,SAAS,EAAE,MAAM,CAAM;gBAEH,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI;IAEjD,MAAM,UAAW,MAAM,UAerB;IAEF,KAAK,aAOH;IAEF,OAAO,CAAC,GAAG;CAGZ;AAED,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,OAAO;IAF3B,OAAO,CAAC,aAAa,CAAgB;gBAEjB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI;IAKjD,MAAM,UAAW,MAAM,UAMrB;IAEF,KAAK,aAKH;IAEF,OAAO,CAAC,GAAG;CAGZ;AAED,qBAAa,wBAAwB;IAEvB,OAAO,CAAC,OAAO;IAAU,OAAO,CAAC,OAAO;IADpD,OAAO,CAAC,YAAY,CAAc;gBACd,OAAO,EAAE,MAAM,EAAU,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI;IAE1E,OAAO,SAAU,MAAM,UAAU,MAAM,UAMrC;IAEF,OAAO,QAAS,KAAK,UAOnB;CACH"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChildProcessEventHandler = exports.StderrEventHandler = exports.StdoutEventHandler = void 0;
|
|
4
|
+
const node_string_decoder_1 = require("node:string_decoder");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
class StdoutEventHandler {
|
|
7
|
+
onChunk;
|
|
8
|
+
cacheText = "";
|
|
9
|
+
constructor(onChunk) {
|
|
10
|
+
this.onChunk = onChunk;
|
|
11
|
+
}
|
|
12
|
+
onData = (chunk) => {
|
|
13
|
+
const text = String(chunk);
|
|
14
|
+
// 输出到控制台
|
|
15
|
+
this.log(text);
|
|
16
|
+
this.cacheText += text;
|
|
17
|
+
let idx;
|
|
18
|
+
while ((idx = this.cacheText.indexOf("\n")) !== -1) {
|
|
19
|
+
const line = this.cacheText.slice(0, idx);
|
|
20
|
+
this.cacheText = this.cacheText.slice(idx + 1);
|
|
21
|
+
const ev = (0, utils_1.parseNdjsonLine)(line);
|
|
22
|
+
if (ev !== null) {
|
|
23
|
+
this.onChunk(ev);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
onEnd = () => {
|
|
28
|
+
const rest = this.cacheText;
|
|
29
|
+
this.cacheText = "";
|
|
30
|
+
const ev = (0, utils_1.parseNdjsonLine)(rest);
|
|
31
|
+
if (ev !== null) {
|
|
32
|
+
this.onChunk(ev);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
log(text) {
|
|
36
|
+
process.stdout.write(text);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.StdoutEventHandler = StdoutEventHandler;
|
|
40
|
+
class StderrEventHandler {
|
|
41
|
+
onChunk;
|
|
42
|
+
stderrDecoder;
|
|
43
|
+
constructor(onChunk) {
|
|
44
|
+
this.onChunk = onChunk;
|
|
45
|
+
const stderrDecoder = new node_string_decoder_1.StringDecoder("utf8");
|
|
46
|
+
this.stderrDecoder = stderrDecoder;
|
|
47
|
+
}
|
|
48
|
+
onData = (chunk) => {
|
|
49
|
+
const text = this.stderrDecoder.write(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
50
|
+
this.log(text);
|
|
51
|
+
this.onChunk(text);
|
|
52
|
+
};
|
|
53
|
+
onEnd = () => {
|
|
54
|
+
const tail = this.stderrDecoder.end();
|
|
55
|
+
if (!tail)
|
|
56
|
+
return;
|
|
57
|
+
this.log(tail);
|
|
58
|
+
this.onChunk(tail);
|
|
59
|
+
};
|
|
60
|
+
log(text) {
|
|
61
|
+
process.stderr.write(text);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.StderrEventHandler = StderrEventHandler;
|
|
65
|
+
class ChildProcessEventHandler {
|
|
66
|
+
command;
|
|
67
|
+
onChunk;
|
|
68
|
+
errorMessage = "";
|
|
69
|
+
constructor(command, onChunk) {
|
|
70
|
+
this.command = command;
|
|
71
|
+
this.onChunk = onChunk;
|
|
72
|
+
}
|
|
73
|
+
onClose = (code, signal) => {
|
|
74
|
+
if (this.errorMessage) {
|
|
75
|
+
console.error(`[${this.command}]执行出错: ${this.errorMessage}`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log(`[${this.command}]执行结束, ${code} ${signal}`);
|
|
79
|
+
};
|
|
80
|
+
onError = (err) => {
|
|
81
|
+
this.errorMessage = err.message;
|
|
82
|
+
this.onChunk({
|
|
83
|
+
type: "error",
|
|
84
|
+
message: err.message,
|
|
85
|
+
at: new Date().toISOString(),
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
exports.ChildProcessEventHandler = ChildProcessEventHandler;
|
|
90
|
+
//# sourceMappingURL=std-event-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"std-event-handler.js","sourceRoot":"","sources":["../../src/core/std-event-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function parseNdjsonLine(line: string): unknown | null;
|
|
2
|
+
/**
|
|
3
|
+
* 统一处理来自服务端或本地的 prompt:安全字符、空白与首词拆分。
|
|
4
|
+
* 典型用法:先 `cleanPrompt`,再对 `fullText` 或 `bodyWithoutHead` 调用 `escapePromptForCliArg` 作为 agent argv。
|
|
5
|
+
*/
|
|
6
|
+
export declare function cleanPrompt(raw: string): {
|
|
7
|
+
fullText: string;
|
|
8
|
+
headToken: string;
|
|
9
|
+
bodyWithoutHead: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 将用户 prompt 转为适合作为 CLI 单个 argv 的字符串。
|
|
13
|
+
* Windows 下经 cmd.exe 拼接时,换行、未配对引号等易破坏解析;使用 C 风格转义
|
|
14
|
+
*(\\、\\n、\\t、\\")压成单行。Unix 下 spawn argv 虽通常可原样传递,
|
|
15
|
+
* 为与 agent 行为一致仍做相同归一化。
|
|
16
|
+
*/
|
|
17
|
+
export declare function escapePromptForCliArg(raw: string): string;
|
|
18
|
+
export declare function readPackageJson(): any;
|
|
19
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/core/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAiB5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM;;;;EAatC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASzD;AAED,wBAAgB,eAAe,QAM9B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
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.parseNdjsonLine = parseNdjsonLine;
|
|
7
|
+
exports.cleanPrompt = cleanPrompt;
|
|
8
|
+
exports.escapePromptForCliArg = escapePromptForCliArg;
|
|
9
|
+
exports.readPackageJson = readPackageJson;
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
function parseNdjsonLine(line) {
|
|
13
|
+
const trimmed = line.replace(/\r$/, "").trim();
|
|
14
|
+
if (!trimmed)
|
|
15
|
+
return null;
|
|
16
|
+
let v;
|
|
17
|
+
try {
|
|
18
|
+
v = JSON.parse(trimmed);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return { type: "stdout", parseError: true, raw: trimmed };
|
|
22
|
+
}
|
|
23
|
+
if (typeof v === "string") {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(v);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return v;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return v;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 统一处理来自服务端或本地的 prompt:安全字符、空白与首词拆分。
|
|
35
|
+
* 典型用法:先 `cleanPrompt`,再对 `fullText` 或 `bodyWithoutHead` 调用 `escapePromptForCliArg` 作为 agent argv。
|
|
36
|
+
*/
|
|
37
|
+
function cleanPrompt(raw) {
|
|
38
|
+
let s = raw.replace(/\0/g, "");
|
|
39
|
+
s = s.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
40
|
+
s = s.replace(/\u2028/g, "\n").replace(/\u2029/g, "\n");
|
|
41
|
+
s = s.trim();
|
|
42
|
+
const parts = s.split(/\s+/).filter(Boolean);
|
|
43
|
+
const head = parts[0] ?? "";
|
|
44
|
+
const bodyWithoutHead = parts.slice(1).join(" ").trim();
|
|
45
|
+
return {
|
|
46
|
+
fullText: s,
|
|
47
|
+
headToken: head || "unknown",
|
|
48
|
+
bodyWithoutHead,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 将用户 prompt 转为适合作为 CLI 单个 argv 的字符串。
|
|
53
|
+
* Windows 下经 cmd.exe 拼接时,换行、未配对引号等易破坏解析;使用 C 风格转义
|
|
54
|
+
*(\\、\\n、\\t、\\")压成单行。Unix 下 spawn argv 虽通常可原样传递,
|
|
55
|
+
* 为与 agent 行为一致仍做相同归一化。
|
|
56
|
+
*/
|
|
57
|
+
function escapePromptForCliArg(raw) {
|
|
58
|
+
let s = raw.replace(/\0/g, "");
|
|
59
|
+
s = s.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
60
|
+
s = s.replace(/\u2028/g, "\n").replace(/\u2029/g, "\n");
|
|
61
|
+
s = s.replace(/\\/g, "\\\\");
|
|
62
|
+
s = s.replace(/\n/g, "\\n");
|
|
63
|
+
s = s.replace(/\t/g, "\\t");
|
|
64
|
+
s = s.replace(/"/g, '\\"');
|
|
65
|
+
return s;
|
|
66
|
+
}
|
|
67
|
+
function readPackageJson() {
|
|
68
|
+
const packageJson = (0, node_fs_1.readFileSync)(node_path_1.default.resolve(__dirname, "../../package.json"), "utf-8");
|
|
69
|
+
return JSON.parse(packageJson);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/core/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 员工 CLI WebSocket:与后端 `AppWebSocketGateway` 一致,
|
|
3
|
+
* 使用 URL 查询参数 `token`(`Employee.cliToken`),路径 `/ws`;
|
|
4
|
+
* 端口优先 `apm config set ws-port`,否则回退 {@link FALLBACK_EMPLOYEE_WS_PORT}。
|
|
5
|
+
*/
|
|
6
|
+
import WebSocket from "ws";
|
|
7
|
+
import { CursorCmdPayload } from "./cursor-cmd";
|
|
8
|
+
/** 与 `EmployeeWebsocketPushService.pushToEmployee` 发送格式一致 */
|
|
9
|
+
export type EmployeeWsServerMessage = {
|
|
10
|
+
event: string;
|
|
11
|
+
data: CursorCmdPayload;
|
|
12
|
+
};
|
|
13
|
+
export declare class EmployeeWebSocketClient {
|
|
14
|
+
client: WebSocket;
|
|
15
|
+
constructor();
|
|
16
|
+
buildEmployeeWebSocketUrl(): string;
|
|
17
|
+
parseMessageData(data: Buffer): EmployeeWsServerMessage | null;
|
|
18
|
+
close: () => void;
|
|
19
|
+
onOpen: () => void;
|
|
20
|
+
onClose: (code: number, reason: Buffer) => void;
|
|
21
|
+
onError: (err: Error) => void;
|
|
22
|
+
onMessage: (data: Buffer) => void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=ws-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-client.d.ts","sourceRoot":"","sources":["../../src/core/ws-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,SAAS,MAAM,IAAI,CAAC;AAE3B,OAAO,EAAa,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE3D,6DAA6D;AAC7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,gBAAgB,CAAC;CACxB,CAAC;AAEF,qBAAa,uBAAuB;IAClC,MAAM,EAAE,SAAS,CAAC;;IAYlB,yBAAyB,IAAI,MAAM;IAcnC,gBAAgB,CAAC,IAAI,EAAE,MAAM;IAmB7B,KAAK,aAEH;IAEF,MAAM,aAEJ;IAEF,OAAO,SAAU,MAAM,UAAU,MAAM,UAErC;IAEF,OAAO,QAAS,KAAK,UAEnB;IAEF,SAAS,SAAU,MAAM,UAQvB;CACH"}
|
|
@@ -0,0 +1,79 @@
|
|
|
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.EmployeeWebSocketClient = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* 员工 CLI WebSocket:与后端 `AppWebSocketGateway` 一致,
|
|
9
|
+
* 使用 URL 查询参数 `token`(`Employee.cliToken`),路径 `/ws`;
|
|
10
|
+
* 端口优先 `apm config set ws-port`,否则回退 {@link FALLBACK_EMPLOYEE_WS_PORT}。
|
|
11
|
+
*/
|
|
12
|
+
const ws_1 = __importDefault(require("ws"));
|
|
13
|
+
const apm_config_1 = require("./apm-config");
|
|
14
|
+
const cursor_cmd_1 = require("./cursor-cmd");
|
|
15
|
+
class EmployeeWebSocketClient {
|
|
16
|
+
client;
|
|
17
|
+
constructor() {
|
|
18
|
+
const url = this.buildEmployeeWebSocketUrl();
|
|
19
|
+
const client = new ws_1.default(url);
|
|
20
|
+
this.client = client;
|
|
21
|
+
client.on("open", this.onOpen);
|
|
22
|
+
client.on("close", this.onClose);
|
|
23
|
+
client.on("error", this.onError);
|
|
24
|
+
client.on("message", this.onMessage);
|
|
25
|
+
}
|
|
26
|
+
buildEmployeeWebSocketUrl() {
|
|
27
|
+
const config = (0, apm_config_1.loadApmConfig)();
|
|
28
|
+
const url = new URL(config.server.url);
|
|
29
|
+
const token = config.auth.token;
|
|
30
|
+
const port = config.server.wsPort || 4000;
|
|
31
|
+
if (!token) {
|
|
32
|
+
console.error("token 不存在,请先执行 apm login");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const wsProto = url.protocol === "https:" ? "wss:" : "ws:";
|
|
36
|
+
const params = new URLSearchParams({ token: token.trim() });
|
|
37
|
+
return `${wsProto}//${url.hostname}:${port}/ws?${params.toString()}`;
|
|
38
|
+
}
|
|
39
|
+
parseMessageData(data) {
|
|
40
|
+
const raw = Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
|
|
41
|
+
let parsed = null;
|
|
42
|
+
try {
|
|
43
|
+
const j = JSON.parse(raw);
|
|
44
|
+
if (j &&
|
|
45
|
+
typeof j === "object" &&
|
|
46
|
+
"event" in j &&
|
|
47
|
+
typeof j.event === "string") {
|
|
48
|
+
parsed = j;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* 非 JSON 时 parsed 保持 null */
|
|
53
|
+
}
|
|
54
|
+
return parsed;
|
|
55
|
+
}
|
|
56
|
+
close = () => {
|
|
57
|
+
this.client.close();
|
|
58
|
+
};
|
|
59
|
+
onOpen = () => {
|
|
60
|
+
console.log("已连接AI项目管理平台,等待服务指令...");
|
|
61
|
+
};
|
|
62
|
+
onClose = (code, reason) => {
|
|
63
|
+
console.log(`连接关闭 code=${code} ${reason.toString()}`);
|
|
64
|
+
};
|
|
65
|
+
onError = (err) => {
|
|
66
|
+
console.error(err.message);
|
|
67
|
+
};
|
|
68
|
+
onMessage = (data) => {
|
|
69
|
+
// 仅处理Cursor事件
|
|
70
|
+
const parsed = this.parseMessageData(data);
|
|
71
|
+
if (parsed?.event !== "cursor") {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const cmd = new cursor_cmd_1.CursorCmd(parsed.data);
|
|
75
|
+
cmd.execute();
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
exports.EmployeeWebSocketClient = EmployeeWebSocketClient;
|
|
79
|
+
//# sourceMappingURL=ws-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-client.js","sourceRoot":"","sources":["../../src/core/ws-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-project-manage-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "AI 项目管理 CLI 工具,结合飞书项目实现AI项目开发工作流",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
@@ -48,4 +48,4 @@
|
|
|
48
48
|
"typescript": "~5.7.3",
|
|
49
49
|
"@types/ws": "~8.18.1"
|
|
50
50
|
}
|
|
51
|
-
}
|
|
51
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apm-auto-dev
|
|
3
|
-
description: 按分支 ID、分支名、基准分支、需求 ID、版本序号全自动拉分支、更新分支状态、落盘 PRD
|
|
3
|
+
description: 按分支 ID、分支名、基准分支、需求 ID、版本序号全自动拉分支、更新分支状态、落盘 PRD;步骤 3 后主 Agent 据 PRD 二选一 Quick(直接实现)或 Spec(openspec-propose + openspec-apply-change);再生成 MR 评审说明、推送、部署与分支状态更新。在用户要求全自动开发、APM 自动交付、或给出上述参数时使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# APM 全自动开发(编排技能)
|
|
7
7
|
|
|
8
|
-
**角色**:主 Agent 只做参数传递、**串行**启动子 Agent、校验上一步产物、失败则停止并汇总(**例外见步骤 8/9**);**禁止**在同一对话里自己执行完整 propose+apply 长流程而不用子 Agent
|
|
8
|
+
**角色**:主 Agent 只做参数传递、**串行**启动子 Agent、校验上一步产物、失败则停止并汇总(**例外见步骤 8/9**);**禁止**在同一对话里自己执行完整 propose+apply 长流程而不用子 Agent。流程结束须输出**步骤结果汇总表**(见文末「主 Agent 汇总输出」)。
|
|
9
9
|
|
|
10
10
|
**输入(必填)**
|
|
11
11
|
|
|
@@ -21,8 +21,11 @@ description: 按分支 ID、分支名、基准分支、需求 ID、版本序号
|
|
|
21
21
|
|
|
22
22
|
## 子 Agent 强制隔离
|
|
23
23
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
24
|
+
- 步骤 **1~3** 各对应一次 **Task 子 Agent**;**步骤 3 之后**主 Agent 判定 **Quick / Spec**(二选一,见下节),再启动 **仅一条**开发路径:
|
|
25
|
+
- **Quick**:一步子 Agent 完成「步骤 4(Quick)」后,直接进入步骤 6。
|
|
26
|
+
- **Spec**:步骤 **4(Spec)— openspec-propose** 与 **步骤 5(Spec)— openspec-apply-change** 各一次子 Agent,再进入步骤 6。
|
|
27
|
+
- 步骤 **6~9** 各对应一次子 Agent,**严格串行**:仅当上一步子 Agent **明确结束**且主 Agent **已校验产物**后,再启动下一步(**步骤 8 发布失败时仍须启动步骤 9**,见步骤 8 说明)。
|
|
28
|
+
- **禁止**并行启动多个子 Agent 执行本流程中的步骤;**禁止**同一次流程中既走 Quick 又走 Spec。
|
|
26
29
|
- 子 Agent 需执行完毕:读 SKILL、跑命令、写文件、回报结构化结果(路径、变更名、成功/失败)。
|
|
27
30
|
|
|
28
31
|
---
|
|
@@ -78,7 +81,38 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status IN_DEVELOPMEN
|
|
|
78
81
|
|
|
79
82
|
---
|
|
80
83
|
|
|
81
|
-
##
|
|
84
|
+
## 开发模式判定(主 Agent,紧接步骤 3 之后)
|
|
85
|
+
|
|
86
|
+
在启动任何「步骤 4」子 Agent 之前,主 Agent 根据 **`.apm/workitems/<name>/prd.md`**(或步骤 2 回报摘要)判断本次采用 **Quick** 还是 **Spec**,**二者必选其一、互斥**:
|
|
87
|
+
|
|
88
|
+
| 倾向 Quick | 倾向 Spec |
|
|
89
|
+
|------------|-----------|
|
|
90
|
+
| 逻辑面少、改动范围小、对现有行为影响面低 | 涉及多模块、协议/数据模型/权限等契约变化 |
|
|
91
|
+
| 多为文案、样式、单点配置、小函数修补 | 需要可追溯规格与任务拆解、跨文件协调 |
|
|
92
|
+
| 回归路径清晰、不易引入隐蔽 BUG | 歧义多或易出边界 BUG,需 propose/tasks 约束 |
|
|
93
|
+
|
|
94
|
+
**规则**:若同时满足表中「倾向 Quick」的典型特征且不满足必须走 Spec 的红线,选 **Quick**;否则选 **Spec**。判定结果须写入最终汇总表(含一句简要理由)。
|
|
95
|
+
|
|
96
|
+
- 选 **Quick** → 只执行 **步骤 4(Quick)**,**跳过** openspec-propose 与 openspec-apply-change(原步骤 4/5 Spec)。
|
|
97
|
+
- 选 **Spec** → **跳过**步骤 4(Quick),依次执行 **步骤 4(Spec)**、**步骤 5(Spec)**。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 步骤 4(Quick)— 子 Agent:直接实现(与 Spec 二选一)
|
|
102
|
+
|
|
103
|
+
**前置**:开发模式判定为 **Quick**;本步与「步骤 4(Spec)+ 步骤 5(Spec)」**不得**同跑。
|
|
104
|
+
|
|
105
|
+
1. 读取 **`.apm/workitems/<name>/prd.md` 全文**,按 PRD 在仓库内**直接完成实现**(改代码、配置、测试等以项目惯例为准),**不**创建 `openspec/changes/` 下的变更目录,**不**调用 openspec-propose / openspec-apply-change。
|
|
106
|
+
2. 改动应可审阅:子 Agent 回报主要修改文件路径列表、自测结论(若有);**不要**向用户追问需求细节,歧义按合理假设处理。
|
|
107
|
+
3. 主 Agent 校验:工作区存在与 PRD 对应的实质变更(或子 Agent 明确说明无需改文件的合法情况)。
|
|
108
|
+
|
|
109
|
+
**完成判定**:PRD 要点已在代码库中落实;无未完成的中途阻塞。
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 步骤 4(Spec)— 子 Agent:openspec-propose(与 Quick 二选一)
|
|
114
|
+
|
|
115
|
+
**前置**:开发模式判定为 **Spec**;若已走 Quick,**不得**执行本节。
|
|
82
116
|
|
|
83
117
|
1. 读取并遵循项目内技能:`.cursor/skills/openspec-propose/SKILL.md`。
|
|
84
118
|
2. **输入**:仓库内文件路径 **`.apm/workitems/<name>/prd.md`**(子 Agent 应用 Read 读全文);变更名可据 PRD 归纳 kebab-case;**不要**向用户追问。
|
|
@@ -88,10 +122,12 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status IN_DEVELOPMEN
|
|
|
88
122
|
|
|
89
123
|
---
|
|
90
124
|
|
|
91
|
-
## 步骤 5
|
|
125
|
+
## 步骤 5(Spec)— 子 Agent:openspec-apply-change
|
|
126
|
+
|
|
127
|
+
**前置**:仅 **Spec** 模式;步骤 4(Spec)已成功。
|
|
92
128
|
|
|
93
129
|
1. 读取并遵循:`.cursor/skills/openspec-apply-change/SKILL.md`。
|
|
94
|
-
2. **输入(必须)**:上一步回报的变更目录路径或 **`<change-name>`**(与 openspec-propose 产出一致);主 Agent 必须将步骤 4
|
|
130
|
+
2. **输入(必须)**:上一步回报的变更目录路径或 **`<change-name>`**(与 openspec-propose 产出一致);主 Agent 必须将步骤 4(Spec)的结构化结果传入本子 Agent。
|
|
95
131
|
3. 按该 SKILL 执行任务直至完成或**硬阻塞**(硬阻塞时停止全流程,汇总原因)。
|
|
96
132
|
|
|
97
133
|
**完成判定**:该 SKILL 定义的完成/暂停语义达成;代码与任务勾选与仓库状态一致。
|
|
@@ -113,7 +149,7 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status IN_DEVELOPMEN
|
|
|
113
149
|
## 步骤 7 — 子 Agent:全量提交并推送
|
|
114
150
|
|
|
115
151
|
1. `git status`:若有未跟踪或已修改文件,则 `git add -A`。
|
|
116
|
-
2.
|
|
152
|
+
2. 若有暂存变更:生成提交说明——**Spec** 模式可写「全自动交付 + PRD/MR 文档 + OpenSpec 实现」;**Quick** 模式写「全自动交付 + PRD/MR 文档 + 直接实现」(可附 `change-name`、requirement id、version-seq,Quick 无 openspec 时可省略 change-name),执行 `git commit`。
|
|
117
153
|
3. **必须** `git push -u origin "<TARGET>"`(或当前分支已设 upstream 则 `git push`);推送失败则回报 stderr,全流程标记失败。
|
|
118
154
|
|
|
119
155
|
**完成判定**:推送成功;工作区干净或仅剩用户需自理的 stash 提示。
|
|
@@ -148,19 +184,40 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status PENDING_TEST
|
|
|
148
184
|
|
|
149
185
|
## 主 Agent 汇总输出
|
|
150
186
|
|
|
151
|
-
|
|
187
|
+
主 Agent 在流程末尾**必须**给出两部分:**(1)步骤结果汇总表**、**(2)补充说明**。
|
|
188
|
+
|
|
189
|
+
### (1)步骤结果汇总表(必填)
|
|
190
|
+
|
|
191
|
+
用 Markdown 表格列出**本流程实际执行的每一步**及结果(未执行的步骤标为「跳过」并简述原因)。列建议:`步骤` | `说明` | `结果` | `备注`。
|
|
192
|
+
|
|
193
|
+
示例结构(主 Agent 按实况填行,不得留空表):
|
|
194
|
+
|
|
195
|
+
| 步骤 | 说明 | 结果 | 备注 |
|
|
196
|
+
|------|------|------|------|
|
|
197
|
+
| 1 | Git 分支与未提交处理 | 成功/失败 | … |
|
|
198
|
+
| 2 | PRD 落盘 | … | `<name>` |
|
|
199
|
+
| 3 | 分支状态 → 开发中 | … | |
|
|
200
|
+
| 开发模式 | Quick 或 Spec | … | 一句判定理由 |
|
|
201
|
+
| 4 | Quick 直接实现 **或** Spec propose **或** 跳过 | … | 与模式一致 |
|
|
202
|
+
| 5 | Spec apply **或** 跳过 | … | Quick 时跳过 |
|
|
203
|
+
| 6 | change.md | … | |
|
|
204
|
+
| 7 | 提交与推送 | … | |
|
|
205
|
+
| 8 | test-env-release | … | 失败仍继续步骤 9 |
|
|
206
|
+
| 9 | 分支状态 → 待测试 | … | |
|
|
207
|
+
|
|
208
|
+
### (2)补充说明
|
|
209
|
+
|
|
210
|
+
在表后以精简列表补充:
|
|
152
211
|
|
|
153
|
-
- 分支名、`.apm/workitems/<name>/`
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
- 最终 commit SHA(若有)、远程推送结果
|
|
158
|
-
- 若有 stash:提醒用户在其他分支上 `git stash pop` 时注意冲突
|
|
212
|
+
- 分支名、`.apm/workitems/<name>/` 路径;**Spec** 时补充 `openspec/changes/<change-name>/`,**Quick** 时写明「未使用 OpenSpec 变更目录」。
|
|
213
|
+
- 步骤 8 测试环境部署结果(成功或失败原因;失败不阻断步骤 9)。
|
|
214
|
+
- 最终 commit SHA(若有)、远程推送结果。
|
|
215
|
+
- 若有 stash:提醒用户在其他分支上 `git stash pop` 时注意冲突。
|
|
159
216
|
|
|
160
217
|
---
|
|
161
218
|
|
|
162
219
|
## 护栏
|
|
163
220
|
|
|
164
221
|
- 任一步子 Agent 失败:**不要**静默跳过;停止后续步骤,输出失败步骤与可复现命令(**例外**:步骤 8 发布失败**不**停止步骤 9)。
|
|
165
|
-
- 全程**不向用户追问**澄清需求;歧义按 openspec / apply
|
|
222
|
+
- 全程**不向用户追问**澄清需求;歧义按 openspec / apply 技能中的「合理假设、不反问」处理;**Quick** 路径下同样适用合理假设、不反问。
|
|
166
223
|
- **全流程交付完成**以步骤 9(分支已置为待测试)成功为准;步骤 8 发布失败仅作为告警项写入汇总,**不**单独阻断「交付完成」判定(但若步骤 9 失败,仍不得宣称全流程完成)。
|