ai-project-manage-cli 3.0.9 → 3.0.11
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 +158 -16
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -114,6 +114,10 @@ var requestConfig = {
|
|
|
114
114
|
updateDevStatus: defineEndpoint({
|
|
115
115
|
method: "POST",
|
|
116
116
|
path: "/cli/requirements/update-dev-status"
|
|
117
|
+
}),
|
|
118
|
+
updateTaskStatus: defineEndpoint({
|
|
119
|
+
method: "POST",
|
|
120
|
+
path: "/cli/requirements/update-task-status"
|
|
117
121
|
})
|
|
118
122
|
},
|
|
119
123
|
requirementArtifact: {
|
|
@@ -223,8 +227,12 @@ async function runComment(requirementId, file, model) {
|
|
|
223
227
|
}
|
|
224
228
|
|
|
225
229
|
// src/commands/connect.ts
|
|
230
|
+
import { execSync } from "child_process";
|
|
226
231
|
import { randomUUID } from "crypto";
|
|
227
232
|
import WebSocket from "ws";
|
|
233
|
+
import { Agent } from "@cursor/sdk";
|
|
234
|
+
import { appendFileSync } from "fs";
|
|
235
|
+
import { resolve as resolve2 } from "path";
|
|
228
236
|
function runConnect(opts) {
|
|
229
237
|
void (async () => {
|
|
230
238
|
const cfg = await ensureApmConfig();
|
|
@@ -240,6 +248,7 @@ function runConnect(opts) {
|
|
|
240
248
|
console.error(`[apm] \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${APM_CONFIG_PATH}`);
|
|
241
249
|
process.exit(1);
|
|
242
250
|
}
|
|
251
|
+
const api = createApmApiClient(cfg);
|
|
243
252
|
const url = buildAgentWsUrl(cfg.baseUrl, cfg.token);
|
|
244
253
|
console.error(`[apm] \u8FDE\u63A5 ${url.replace(cfg.token, "<token>")} \u2026`);
|
|
245
254
|
const ws = new WebSocket(url);
|
|
@@ -258,9 +267,142 @@ function runConnect(opts) {
|
|
|
258
267
|
const interval = setInterval(sendHeartbeat, 15e3);
|
|
259
268
|
ws.on("close", () => clearInterval(interval));
|
|
260
269
|
});
|
|
261
|
-
ws.on("message", (data) => {
|
|
270
|
+
ws.on("message", async (data) => {
|
|
262
271
|
const text = typeof data === "string" ? data : data.toString();
|
|
263
|
-
|
|
272
|
+
try {
|
|
273
|
+
const msg = JSON.parse(text);
|
|
274
|
+
if (msg.type !== "JOB") {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const payload = msg.payload;
|
|
278
|
+
try {
|
|
279
|
+
execSync(`apm pull ${payload.requirementId}`, {
|
|
280
|
+
cwd: payload.cwd,
|
|
281
|
+
encoding: "utf8"
|
|
282
|
+
});
|
|
283
|
+
} catch (pullErr) {
|
|
284
|
+
console.error("[apm] apm pull \u5931\u8D25:", pullErr);
|
|
285
|
+
throw pullErr;
|
|
286
|
+
}
|
|
287
|
+
const agent = await Agent.create({
|
|
288
|
+
apiKey: payload.apiKey,
|
|
289
|
+
model: { id: payload.model ?? "default" },
|
|
290
|
+
local: { cwd: payload.cwd }
|
|
291
|
+
});
|
|
292
|
+
await api.cliRequirements.updateDevStatus({
|
|
293
|
+
requirementId: payload.requirementId,
|
|
294
|
+
status: "WORKING"
|
|
295
|
+
});
|
|
296
|
+
let IN_PROGRESS = false;
|
|
297
|
+
const events = [];
|
|
298
|
+
let data2 = {};
|
|
299
|
+
const run = await agent.send(payload.prompt);
|
|
300
|
+
for await (const event of run.stream()) {
|
|
301
|
+
if (!IN_PROGRESS) {
|
|
302
|
+
await api.cliRequirements.updateTaskStatus({
|
|
303
|
+
taskId: payload.taskId,
|
|
304
|
+
requirementId: payload.requirementId,
|
|
305
|
+
status: "IN_PROGRESS"
|
|
306
|
+
});
|
|
307
|
+
IN_PROGRESS = true;
|
|
308
|
+
}
|
|
309
|
+
data2 = {};
|
|
310
|
+
if (event.type === "assistant") {
|
|
311
|
+
const output = event.message.content[0].text;
|
|
312
|
+
console.log(`[Output]`, output);
|
|
313
|
+
if (data2.type && data2.type !== "output") {
|
|
314
|
+
events.push(data2);
|
|
315
|
+
data2 = {};
|
|
316
|
+
} else {
|
|
317
|
+
data2.type = "output";
|
|
318
|
+
if (!data2.content) {
|
|
319
|
+
data2.content = "";
|
|
320
|
+
}
|
|
321
|
+
data2.content += output;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (event.type === "thinking") {
|
|
325
|
+
const thinking = event.text;
|
|
326
|
+
console.log(`[Thinking]`, thinking);
|
|
327
|
+
if (data2.type && data2.type !== "thinking") {
|
|
328
|
+
events.push(data2);
|
|
329
|
+
data2 = {};
|
|
330
|
+
} else {
|
|
331
|
+
data2.type = "thinking";
|
|
332
|
+
if (!data2.content) {
|
|
333
|
+
data2.content = "";
|
|
334
|
+
}
|
|
335
|
+
data2.content += thinking;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (event.type === "tool_call") {
|
|
339
|
+
if (event.status === "completed" || event.status === "error") {
|
|
340
|
+
console.log(`[ToolCall(${event.call_id}) Result]`);
|
|
341
|
+
console.log(JSON.stringify(event.args));
|
|
342
|
+
console.log(JSON.stringify(event.result, null, 2));
|
|
343
|
+
console.log("---------------\u8C03\u7528\u5B8C\u6210-----------------");
|
|
344
|
+
if (data2.type && data2.type !== "tool_call") {
|
|
345
|
+
events.push(data2);
|
|
346
|
+
data2 = {};
|
|
347
|
+
} else {
|
|
348
|
+
data2.type = "tool_call";
|
|
349
|
+
data2.call_id = event.call_id;
|
|
350
|
+
data2.args = event.args;
|
|
351
|
+
data2.result = event.result;
|
|
352
|
+
data2.status = event.status;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (event.type === "task") {
|
|
357
|
+
console.log(`[Task:${event.status}]`);
|
|
358
|
+
console.log("--------------------------------");
|
|
359
|
+
console.log(event.text || "\u65E0");
|
|
360
|
+
console.log("--------------------------------");
|
|
361
|
+
if (data2.type && data2.type !== "task") {
|
|
362
|
+
events.push(data2);
|
|
363
|
+
data2 = {};
|
|
364
|
+
} else {
|
|
365
|
+
data2.type = "task";
|
|
366
|
+
data2.status = event.status;
|
|
367
|
+
data2.text = event.text;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (event.type === "request") {
|
|
371
|
+
console.log(JSON.stringify(event, null, 2));
|
|
372
|
+
if (data2.type && data2.type !== "request") {
|
|
373
|
+
events.push(data2);
|
|
374
|
+
data2 = {};
|
|
375
|
+
} else {
|
|
376
|
+
data2 = event;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (data2.type) {
|
|
381
|
+
events.push(data2);
|
|
382
|
+
data2 = {};
|
|
383
|
+
}
|
|
384
|
+
await api.cliRequirements.updateTaskStatus({
|
|
385
|
+
taskId: payload.taskId,
|
|
386
|
+
requirementId: payload.requirementId,
|
|
387
|
+
status: "PENDING_ACCEPTANCE"
|
|
388
|
+
});
|
|
389
|
+
await api.cliRequirements.updateDevStatus({
|
|
390
|
+
requirementId: payload.requirementId,
|
|
391
|
+
status: "IDLE"
|
|
392
|
+
});
|
|
393
|
+
console.log("[Done]");
|
|
394
|
+
const sessionsDir = resolve2(
|
|
395
|
+
payload.cwd,
|
|
396
|
+
`.apm/workitems/${payload.requirementId}/sessions`
|
|
397
|
+
);
|
|
398
|
+
ensureDirExists(sessionsDir);
|
|
399
|
+
const sessionFile = resolve2(sessionsDir, `${run.agentId}.md`);
|
|
400
|
+
for (const event of events) {
|
|
401
|
+
appendFileSync(sessionFile, JSON.stringify(event, null, 2) + "\n=====================================================\n");
|
|
402
|
+
}
|
|
403
|
+
} catch {
|
|
404
|
+
console.error("[apm] \u65E0\u6CD5\u89E3\u6790 WebSocket \u6D88\u606F:", text);
|
|
405
|
+
}
|
|
264
406
|
});
|
|
265
407
|
ws.on("error", (err) => {
|
|
266
408
|
console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
|
|
@@ -334,13 +476,13 @@ async function runLogin(opts) {
|
|
|
334
476
|
|
|
335
477
|
// src/commands/branch.ts
|
|
336
478
|
import { execFile } from "child_process";
|
|
337
|
-
import { resolve as
|
|
479
|
+
import { resolve as resolve3 } from "path";
|
|
338
480
|
import { promisify } from "util";
|
|
339
481
|
var execFileAsync = promisify(execFile);
|
|
340
482
|
async function fetchBaselineBranchFromApi(requirementId, cwd) {
|
|
341
483
|
const cfg = await ensureLoggedConfig();
|
|
342
484
|
const api = createApmApiClient(cfg);
|
|
343
|
-
const workdirPath =
|
|
485
|
+
const workdirPath = resolve3(cwd);
|
|
344
486
|
const { baselineBranch } = await api.cliRequirements.branchBaseline({
|
|
345
487
|
requirementId,
|
|
346
488
|
workdirPath
|
|
@@ -725,11 +867,11 @@ import path5 from "node:path";
|
|
|
725
867
|
|
|
726
868
|
// src/commands/deploy/lib/apm-config.ts
|
|
727
869
|
import { existsSync as existsSync3, readFileSync as readFileSync6 } from "node:fs";
|
|
728
|
-
import { resolve as
|
|
870
|
+
import { resolve as resolve4 } from "node:path";
|
|
729
871
|
function loadApmConfig(options) {
|
|
730
|
-
const p =
|
|
872
|
+
const p = resolve4(
|
|
731
873
|
process.cwd(),
|
|
732
|
-
options?.configPath ??
|
|
874
|
+
options?.configPath ?? resolve4(WORKSPACE_APM_DIR, "apm.config.json")
|
|
733
875
|
);
|
|
734
876
|
if (!existsSync3(p)) {
|
|
735
877
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
@@ -973,17 +1115,17 @@ var DockerodeClient = class {
|
|
|
973
1115
|
await this.client.getImage(image).remove({ force: true });
|
|
974
1116
|
}
|
|
975
1117
|
async pullImage(image, auth) {
|
|
976
|
-
const stream = await new Promise((
|
|
1118
|
+
const stream = await new Promise((resolve5, reject) => {
|
|
977
1119
|
const pullOptions = auth ? { authconfig: auth } : void 0;
|
|
978
1120
|
this.client.pull(image, pullOptions, (err, output) => {
|
|
979
1121
|
if (err || !output) {
|
|
980
1122
|
reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
|
|
981
1123
|
return;
|
|
982
1124
|
}
|
|
983
|
-
|
|
1125
|
+
resolve5(output);
|
|
984
1126
|
});
|
|
985
1127
|
});
|
|
986
|
-
await new Promise((
|
|
1128
|
+
await new Promise((resolve5, reject) => {
|
|
987
1129
|
this.client.modem.followProgress(
|
|
988
1130
|
stream,
|
|
989
1131
|
(err) => {
|
|
@@ -991,7 +1133,7 @@ var DockerodeClient = class {
|
|
|
991
1133
|
reject(err);
|
|
992
1134
|
return;
|
|
993
1135
|
}
|
|
994
|
-
|
|
1136
|
+
resolve5();
|
|
995
1137
|
},
|
|
996
1138
|
() => void 0
|
|
997
1139
|
);
|
|
@@ -1136,7 +1278,7 @@ function assertDeployImageTag(tag) {
|
|
|
1136
1278
|
import { platform } from "node:os";
|
|
1137
1279
|
|
|
1138
1280
|
// src/commands/deploy/lib/backend-deploy/command-runner.ts
|
|
1139
|
-
import { execSync } from "child_process";
|
|
1281
|
+
import { execSync as execSync2 } from "child_process";
|
|
1140
1282
|
|
|
1141
1283
|
// src/commands/deploy/lib/backend-deploy/logger.ts
|
|
1142
1284
|
var Logger = class {
|
|
@@ -1162,7 +1304,7 @@ var CommandRunner = class {
|
|
|
1162
1304
|
static exec(command, cwd) {
|
|
1163
1305
|
try {
|
|
1164
1306
|
Logger.info(`\u6267\u884C\u547D\u4EE4: ${command}`);
|
|
1165
|
-
const result =
|
|
1307
|
+
const result = execSync2(command, {
|
|
1166
1308
|
cwd,
|
|
1167
1309
|
encoding: "utf8",
|
|
1168
1310
|
stdio: "pipe"
|
|
@@ -1180,7 +1322,7 @@ var CommandRunner = class {
|
|
|
1180
1322
|
static execWithOutput(command, cwd) {
|
|
1181
1323
|
try {
|
|
1182
1324
|
Logger.info(`\u6267\u884C\u547D\u4EE4: ${command}`);
|
|
1183
|
-
|
|
1325
|
+
execSync2(command, {
|
|
1184
1326
|
cwd,
|
|
1185
1327
|
stdio: "inherit"
|
|
1186
1328
|
});
|
|
@@ -1507,14 +1649,14 @@ var MinioClient = class {
|
|
|
1507
1649
|
async deleteObjectsByPrefix(bucket, prefix) {
|
|
1508
1650
|
const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
|
|
1509
1651
|
const keys = [];
|
|
1510
|
-
await new Promise((
|
|
1652
|
+
await new Promise((resolve5, reject) => {
|
|
1511
1653
|
objectsStream.on("data", (obj) => {
|
|
1512
1654
|
if (obj.name) {
|
|
1513
1655
|
keys.push(obj.name);
|
|
1514
1656
|
}
|
|
1515
1657
|
});
|
|
1516
1658
|
objectsStream.on("error", reject);
|
|
1517
|
-
objectsStream.on("end",
|
|
1659
|
+
objectsStream.on("end", resolve5);
|
|
1518
1660
|
});
|
|
1519
1661
|
const chunkSize = 500;
|
|
1520
1662
|
for (let i = 0; i < keys.length; i += chunkSize) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-project-manage-cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.11",
|
|
4
4
|
"description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
"test": "vitest run",
|
|
20
20
|
"test:watch": "vitest",
|
|
21
21
|
"test:init": "vitest run tests/cli-init.test.ts",
|
|
22
|
-
"test:pull": "vitest run tests/cli-pull.test.ts"
|
|
22
|
+
"test:pull": "vitest run tests/cli-pull.test.ts",
|
|
23
|
+
"test:cursor": "vitest run tests/cursor.test.ts"
|
|
24
|
+
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
25
27
|
"@types/node": "^22.0.0",
|
|
@@ -38,6 +40,7 @@
|
|
|
38
40
|
"commander": "~14.0.3",
|
|
39
41
|
"yaml": "~2.8.4",
|
|
40
42
|
"minio": "~8.0.7",
|
|
41
|
-
"dockerode": "~5.0.0"
|
|
43
|
+
"dockerode": "~5.0.0",
|
|
44
|
+
"@cursor/sdk": "~1.0.12"
|
|
42
45
|
}
|
|
43
46
|
}
|