ai-project-manage-cli 3.0.8 → 3.0.10

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 +112 -6
  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,10 @@ 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";
228
234
  function runConnect(opts) {
229
235
  void (async () => {
230
236
  const cfg = await ensureApmConfig();
@@ -240,6 +246,7 @@ function runConnect(opts) {
240
246
  console.error(`[apm] \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${APM_CONFIG_PATH}`);
241
247
  process.exit(1);
242
248
  }
249
+ const api = createApmApiClient(cfg);
243
250
  const url = buildAgentWsUrl(cfg.baseUrl, cfg.token);
244
251
  console.error(`[apm] \u8FDE\u63A5 ${url.replace(cfg.token, "<token>")} \u2026`);
245
252
  const ws = new WebSocket(url);
@@ -258,9 +265,88 @@ function runConnect(opts) {
258
265
  const interval = setInterval(sendHeartbeat, 15e3);
259
266
  ws.on("close", () => clearInterval(interval));
260
267
  });
261
- ws.on("message", (data) => {
268
+ ws.on("message", async (data) => {
262
269
  const text = typeof data === "string" ? data : data.toString();
263
- console.log(text);
270
+ try {
271
+ const msg = JSON.parse(text);
272
+ if (msg.type !== "JOB") {
273
+ return;
274
+ }
275
+ const payload = msg.payload;
276
+ try {
277
+ execSync(`apm pull ${payload.requirementId}`, {
278
+ cwd: payload.cwd,
279
+ encoding: "utf8"
280
+ });
281
+ } catch (pullErr) {
282
+ console.error("[apm] apm pull \u5931\u8D25:", pullErr);
283
+ throw pullErr;
284
+ }
285
+ const agent = await Agent.create({
286
+ apiKey: payload.apiKey,
287
+ model: { id: payload.model ?? "default" },
288
+ local: { cwd: payload.cwd }
289
+ });
290
+ await api.cliRequirements.updateDevStatus({
291
+ requirementId: payload.requirementId,
292
+ status: "WORKING"
293
+ });
294
+ const run = await agent.send(payload.prompt);
295
+ for await (const event of run.stream()) {
296
+ if (event.type === "system") {
297
+ console.log("[Ready]", JSON.stringify(event));
298
+ await api.cliRequirements.updateTaskStatus({
299
+ taskId: payload.taskId,
300
+ requirementId: payload.requirementId,
301
+ status: "IN_PROGRESS"
302
+ });
303
+ }
304
+ if (event.type === "user") {
305
+ console.log(
306
+ `[Input]`,
307
+ JSON.stringify(event.message.content[0].text)
308
+ );
309
+ }
310
+ if (event.type === "assistant") {
311
+ console.log(`[Output]`, JSON.stringify(event.message.content));
312
+ }
313
+ if (event.type === "thinking") {
314
+ console.log(`[Thinking]`, JSON.stringify(event.text));
315
+ }
316
+ if (event.type === "tool_call") {
317
+ if (event.result) {
318
+ console.log(
319
+ `[ToolCall(${event.call_id}) Result]`,
320
+ JSON.stringify(event.result)
321
+ );
322
+ }
323
+ console.log(
324
+ `[ToolCall(${event.call_id}) Args]`,
325
+ JSON.stringify(event.args)
326
+ );
327
+ }
328
+ if (event.type === "task") {
329
+ console.log(`[Task:${event.status}]`);
330
+ console.log("--------------------------------");
331
+ console.log(event.text || "\u65E0");
332
+ console.log("--------------------------------");
333
+ }
334
+ if (event.type === "request") {
335
+ console.log(JSON.stringify(event, null, 2));
336
+ }
337
+ }
338
+ await api.cliRequirements.updateTaskStatus({
339
+ taskId: payload.taskId,
340
+ requirementId: payload.requirementId,
341
+ status: "PENDING_ACCEPTANCE"
342
+ });
343
+ await api.cliRequirements.updateDevStatus({
344
+ requirementId: payload.requirementId,
345
+ status: "IDLE"
346
+ });
347
+ } catch {
348
+ console.error("[apm] \u65E0\u6CD5\u89E3\u6790 WebSocket \u6D88\u606F:", text);
349
+ }
264
350
  });
265
351
  ws.on("error", (err) => {
266
352
  console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
@@ -516,6 +602,26 @@ function tasksForStatusYaml(tasks) {
516
602
  executor: t.executorType
517
603
  }));
518
604
  }
605
+ function escapeForCdata(text) {
606
+ return text.replace(/\]\]>/g, "]]]]><![CDATA[>");
607
+ }
608
+ function defectsToXml(defects) {
609
+ const sorted = [...defects].sort(
610
+ (a, b) => new Date(a.createdAt ?? 0).getTime() - new Date(b.createdAt ?? 0).getTime()
611
+ );
612
+ const lines = ["<defects>"];
613
+ for (const d of sorted) {
614
+ lines.push(` <defect id="${xmlEscape(d.id)}">`);
615
+ lines.push(` <status>${xmlEscape(d.status)}</status>`);
616
+ lines.push(` <current><![CDATA[${escapeForCdata(d.currentState ?? "")}]]></current>`);
617
+ lines.push(
618
+ ` <expected><![CDATA[${escapeForCdata(d.expectedEffect ?? "")}]]></expected>`
619
+ );
620
+ lines.push(` </defect>`);
621
+ }
622
+ lines.push("</defects>", "");
623
+ return lines.join("\n");
624
+ }
519
625
  async function runPull(requirementId) {
520
626
  const cfg = await ensureLoggedConfig();
521
627
  const api = createApmApiClient(cfg);
@@ -560,7 +666,7 @@ async function runPull(requirementId) {
560
666
  ""
561
667
  ].join("\n");
562
668
  writeFileSync3(join4(WORKITEMS_DIR, "reviews.xml"), reviewsXml, "utf8");
563
- const defectsXml = unknownArrayToXml("defects", "defect", data.defects ?? []);
669
+ const defectsXml = defectsToXml(data.defects ?? []);
564
670
  writeFileSync3(join4(WORKITEMS_DIR, "defect.xml"), defectsXml, "utf8");
565
671
  const testCasesXml = unknownArrayToXml(
566
672
  "testcases",
@@ -1116,7 +1222,7 @@ function assertDeployImageTag(tag) {
1116
1222
  import { platform } from "node:os";
1117
1223
 
1118
1224
  // src/commands/deploy/lib/backend-deploy/command-runner.ts
1119
- import { execSync } from "child_process";
1225
+ import { execSync as execSync2 } from "child_process";
1120
1226
 
1121
1227
  // src/commands/deploy/lib/backend-deploy/logger.ts
1122
1228
  var Logger = class {
@@ -1142,7 +1248,7 @@ var CommandRunner = class {
1142
1248
  static exec(command, cwd) {
1143
1249
  try {
1144
1250
  Logger.info(`\u6267\u884C\u547D\u4EE4: ${command}`);
1145
- const result = execSync(command, {
1251
+ const result = execSync2(command, {
1146
1252
  cwd,
1147
1253
  encoding: "utf8",
1148
1254
  stdio: "pipe"
@@ -1160,7 +1266,7 @@ var CommandRunner = class {
1160
1266
  static execWithOutput(command, cwd) {
1161
1267
  try {
1162
1268
  Logger.info(`\u6267\u884C\u547D\u4EE4: ${command}`);
1163
- execSync(command, {
1269
+ execSync2(command, {
1164
1270
  cwd,
1165
1271
  stdio: "inherit"
1166
1272
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "3.0.8",
3
+ "version": "3.0.10",
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
  }