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.
Files changed (2) hide show
  1. package/dist/index.js +158 -16
  2. 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
- console.log(text);
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 resolve2 } from "path";
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 = resolve2(cwd);
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 resolve3 } from "node:path";
870
+ import { resolve as resolve4 } from "node:path";
729
871
  function loadApmConfig(options) {
730
- const p = resolve3(
872
+ const p = resolve4(
731
873
  process.cwd(),
732
- options?.configPath ?? resolve3(WORKSPACE_APM_DIR, "apm.config.json")
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((resolve4, reject) => {
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
- resolve4(output);
1125
+ resolve5(output);
984
1126
  });
985
1127
  });
986
- await new Promise((resolve4, reject) => {
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
- resolve4();
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 = execSync(command, {
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
- execSync(command, {
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((resolve4, reject) => {
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", resolve4);
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.9",
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
  }