ai-project-manage-cli 6.0.28 → 6.0.29

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 +57 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1266,18 +1266,6 @@ ${JSON.stringify(event, null, 2)}
1266
1266
  }
1267
1267
 
1268
1268
  // src/commands/connect/cursor-message-log.ts
1269
- function assistantStreamChunk(event) {
1270
- if (event.type !== "assistant") {
1271
- return "";
1272
- }
1273
- let text = "";
1274
- for (const block of event.message.content) {
1275
- if (block.type === "text" && block.text) {
1276
- text += block.text;
1277
- }
1278
- }
1279
- return text;
1280
- }
1281
1269
  var CURSOR_MESSAGE_LOG_SYNC_INTERVAL_MS = 2e3;
1282
1270
  function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1283
1271
  let lastRunAt = 0;
@@ -1358,7 +1346,11 @@ var logCtx = (ctx, agentId) => ({
1358
1346
  messageId: ctx.messageId,
1359
1347
  agentId
1360
1348
  });
1361
- async function runCursorAgent(cfg, ctx) {
1349
+ async function runCursorAgent(cfg, ctx, options) {
1350
+ const signal = options?.signal;
1351
+ if (signal?.aborted) {
1352
+ throw new Error("\u8FDE\u63A5\u5DF2\u5173\u95ED\uFF0C\u4EFB\u52A1\u4E2D\u65AD");
1353
+ }
1362
1354
  const apiKey = ctx.apiKey.trim();
1363
1355
  if (!apiKey) {
1364
1356
  throw new Error("\u7F3A\u5C11 apiKey\uFF0C\u65E0\u6CD5\u8C03\u7528 Cursor SDK");
@@ -1388,12 +1380,22 @@ async function runCursorAgent(cfg, ctx) {
1388
1380
  );
1389
1381
  }
1390
1382
  );
1383
+ let activeRun;
1384
+ const abortRun = () => {
1385
+ if (!activeRun?.supports("cancel")) return;
1386
+ void activeRun.cancel().catch(() => void 0);
1387
+ };
1388
+ signal?.addEventListener("abort", abortRun, { once: true });
1391
1389
  try {
1392
1390
  const run = await agent.send(prompt);
1391
+ activeRun = run;
1393
1392
  console.log(`[apm] Cursor run id=${run.id} agentId=${agent.agentId}`);
1394
1393
  for await (const event of run.stream()) {
1394
+ if (signal?.aborted) {
1395
+ abortRun();
1396
+ throw new Error("\u8FDE\u63A5\u5DF2\u5173\u95ED\uFF0C\u4EFB\u52A1\u4E2D\u65AD");
1397
+ }
1395
1398
  eventSession.addEvent(event);
1396
- const chunk = assistantStreamChunk(event);
1397
1399
  syncRemoteLog.schedule(eventSession);
1398
1400
  }
1399
1401
  await syncRemoteLog.flush(eventSession);
@@ -1413,6 +1415,7 @@ async function runCursorAgent(cfg, ctx) {
1413
1415
  }
1414
1416
  throw err;
1415
1417
  } finally {
1418
+ signal?.removeEventListener("abort", abortRun);
1416
1419
  await agent[Symbol.asyncDispose]();
1417
1420
  }
1418
1421
  }
@@ -1429,7 +1432,9 @@ async function appendMessageContent(cfg, messageId, content) {
1429
1432
  await api.cli.appendMessageContent({ id: messageId, content });
1430
1433
  console.log(`[apm] \u5DF2\u8FFD\u52A0\u6D88\u606F\u5185\u5BB9: ${messageId}`);
1431
1434
  }
1432
- async function handleInboundMessage(cfg, raw) {
1435
+ var SHUTDOWN_DRAIN_MS = 3e3;
1436
+ async function handleInboundMessage(cfg, raw, signal) {
1437
+ if (signal.aborted) return;
1433
1438
  const parsed = parseAgentWsMessage(raw);
1434
1439
  if (parsed === null) {
1435
1440
  console.error("[apm] \u6536\u5230\u65E0\u6548 JSON");
@@ -1449,18 +1454,26 @@ async function handleInboundMessage(cfg, raw) {
1449
1454
  const msg = validated.data;
1450
1455
  const messageId = msg.messageId;
1451
1456
  try {
1457
+ if (signal.aborted) return;
1452
1458
  await runBranch(msg.sessionId, { cwd: msg.workdir });
1459
+ if (signal.aborted) return;
1453
1460
  await runPull(msg.sessionId, workspaceApmDir(msg.workdir));
1461
+ if (signal.aborted) return;
1454
1462
  await commitWorkingTreeIfDirty(msg.workdir, "fix: apm pull");
1463
+ if (signal.aborted) return;
1455
1464
  await updateMessageStatus(cfg, messageId, "TYPING");
1456
- await runCursorAgent(cfg, {
1457
- messageId: msg.messageId,
1458
- sessionId: msg.sessionId,
1459
- prompt: msg.content,
1460
- model: msg.model,
1461
- apiKey: msg.apiKey,
1462
- workdir: msg.workdir
1463
- });
1465
+ await runCursorAgent(
1466
+ cfg,
1467
+ {
1468
+ messageId: msg.messageId,
1469
+ sessionId: msg.sessionId,
1470
+ prompt: msg.content,
1471
+ model: msg.model,
1472
+ apiKey: msg.apiKey,
1473
+ workdir: msg.workdir
1474
+ },
1475
+ { signal }
1476
+ );
1464
1477
  await syncSessionDocuments(
1465
1478
  cfg,
1466
1479
  msg.sessionId,
@@ -1523,32 +1536,42 @@ async function runConnect(options) {
1523
1536
  const ws = new WebSocket(url);
1524
1537
  let stopHeartbeat;
1525
1538
  let shuttingDown = false;
1539
+ const shutdownAbort = new AbortController();
1526
1540
  let inboundQueue = Promise.resolve();
1527
- const shutdown = (code = 0) => {
1541
+ const shutdown = async (code = 0) => {
1528
1542
  if (shuttingDown) return;
1529
1543
  shuttingDown = true;
1544
+ shutdownAbort.abort();
1530
1545
  stopHeartbeat?.();
1531
1546
  if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
1532
- ws.close();
1547
+ ws.terminate();
1533
1548
  }
1534
- resolve5();
1535
- if (code !== 0) {
1536
- process.exit(code);
1549
+ try {
1550
+ await Promise.race([
1551
+ inboundQueue,
1552
+ new Promise((r) => setTimeout(r, SHUTDOWN_DRAIN_MS))
1553
+ ]);
1554
+ } catch {
1537
1555
  }
1556
+ resolve5();
1557
+ process.exit(code);
1538
1558
  };
1539
1559
  ws.on("open", () => {
1540
1560
  console.log("[apm] WebSocket \u5DF2\u8FDE\u63A5");
1541
1561
  stopHeartbeat = startHeartbeat(ws, clientMachineId);
1542
1562
  });
1543
1563
  ws.on("message", (data) => {
1564
+ if (shuttingDown) return;
1544
1565
  const text = Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
1545
- inboundQueue = inboundQueue.then(() => handleInboundMessage(cfg, text));
1566
+ inboundQueue = inboundQueue.then(
1567
+ () => handleInboundMessage(cfg, text, shutdownAbort.signal)
1568
+ );
1546
1569
  });
1547
1570
  ws.on("close", (code, reason) => {
1548
1571
  console.log(
1549
1572
  `[apm] \u8FDE\u63A5\u5DF2\u65AD\u5F00 code=${code}${reason ? ` reason=${reason.toString()}` : ""}`
1550
1573
  );
1551
- shutdown();
1574
+ void shutdown();
1552
1575
  });
1553
1576
  ws.on("error", (err) => {
1554
1577
  console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
@@ -1556,9 +1579,11 @@ async function runConnect(options) {
1556
1579
  });
1557
1580
  process.on("SIGINT", () => {
1558
1581
  console.log("[apm] \u6B63\u5728\u5173\u95ED\u2026");
1559
- shutdown();
1582
+ void shutdown();
1583
+ });
1584
+ process.on("SIGTERM", () => {
1585
+ void shutdown();
1560
1586
  });
1561
- process.on("SIGTERM", () => shutdown());
1562
1587
  });
1563
1588
  }
1564
1589
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.28",
3
+ "version": "6.0.29",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,