ai-project-manage-cli 6.0.33 → 6.0.34

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 +93 -39
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1014,7 +1014,8 @@ var VALID_STATUSES = [
1014
1014
  "CREATED",
1015
1015
  "TYPING",
1016
1016
  "SUCCESS",
1017
- "FAILED"
1017
+ "FAILED",
1018
+ "CANCELLED"
1018
1019
  ];
1019
1020
  async function runUpdateMessageStatus(options) {
1020
1021
  const messageId = options.id?.trim();
@@ -1052,25 +1053,17 @@ function parseAgentWsMessage(raw) {
1052
1053
  function serializeAgentWsMessage(msg) {
1053
1054
  return JSON.stringify(msg);
1054
1055
  }
1055
- function validateAgentWsMessage(value, kind) {
1056
- if (typeof value !== "object" || value === null) {
1057
- return { ok: false, reason: "\u6D88\u606F\u4F53\u4E0D\u662F JSON \u5BF9\u8C61" };
1056
+ function validateHeartbeat(o) {
1057
+ if (o.type !== "heartbeat") {
1058
+ return { ok: false, reason: "\u671F\u671B heartbeat" };
1058
1059
  }
1059
- const o = value;
1060
- const type = o.type;
1061
- if (type !== "heartbeat" && type !== "message") {
1062
- return { ok: false, reason: `\u672A\u77E5 type: ${String(type)}` };
1060
+ if (!nonEmptyString(o.userId)) {
1061
+ return { ok: false, reason: "heartbeat \u7F3A\u5C11 userId" };
1063
1062
  }
1064
- if (kind === "heartbeat" || type === "heartbeat") {
1065
- if (type !== "heartbeat") {
1066
- return { ok: false, reason: "\u671F\u671B heartbeat" };
1067
- }
1068
- if (!nonEmptyString(o.userId)) {
1069
- return { ok: false, reason: "heartbeat \u7F3A\u5C11 userId" };
1070
- }
1071
- return { ok: true, data: { type: "heartbeat", userId: o.userId.trim() } };
1072
- }
1073
- if (type !== "message") {
1063
+ return { ok: true, data: { type: "heartbeat", userId: o.userId.trim() } };
1064
+ }
1065
+ function validateMessagePush(o) {
1066
+ if (o.type !== "message") {
1074
1067
  return { ok: false, reason: "\u671F\u671B message" };
1075
1068
  }
1076
1069
  if (!nonEmptyString(o.messageId)) {
@@ -1108,6 +1101,35 @@ function validateAgentWsMessage(value, kind) {
1108
1101
  }
1109
1102
  };
1110
1103
  }
1104
+ function validateCancel(o) {
1105
+ if (o.type !== "cancel") {
1106
+ return { ok: false, reason: "\u671F\u671B cancel" };
1107
+ }
1108
+ if (!nonEmptyString(o.messageId)) {
1109
+ return { ok: false, reason: "cancel \u7F3A\u5C11 messageId" };
1110
+ }
1111
+ return {
1112
+ ok: true,
1113
+ data: { type: "cancel", messageId: o.messageId.trim() }
1114
+ };
1115
+ }
1116
+ function validateAgentWsMessage(value, kind) {
1117
+ if (typeof value !== "object" || value === null) {
1118
+ return { ok: false, reason: "\u6D88\u606F\u4F53\u4E0D\u662F JSON \u5BF9\u8C61" };
1119
+ }
1120
+ const o = value;
1121
+ const type = o.type;
1122
+ if (type !== "heartbeat" && type !== "message" && type !== "cancel") {
1123
+ return { ok: false, reason: `\u672A\u77E5 type: ${String(type)}` };
1124
+ }
1125
+ if (kind === "heartbeat" || type === "heartbeat") {
1126
+ return validateHeartbeat(o);
1127
+ }
1128
+ if (type === "cancel") {
1129
+ return validateCancel(o);
1130
+ }
1131
+ return validateMessagePush(o);
1132
+ }
1111
1133
 
1112
1134
  // src/commands/connect/abort-signal-debug.ts
1113
1135
  import {
@@ -1509,25 +1531,12 @@ async function setMessageError(cfg, messageId, error) {
1509
1531
  console.log(`[apm] \u5DF2\u8BBE\u7F6E\u6D88\u606F\u9519\u8BEF: ${messageId}`);
1510
1532
  }
1511
1533
  var SHUTDOWN_DRAIN_MS = 3e3;
1512
- async function handleInboundMessage(cfg, raw, signal) {
1534
+ function isUserCancelled(ctx) {
1535
+ return ctx.perMessageSignal.aborted && !ctx.shutdownSignal.aborted;
1536
+ }
1537
+ async function handleInboundMessage(cfg, msg, signal, ctx) {
1538
+ if (isUserCancelled(ctx)) return;
1513
1539
  if (signal.aborted) return;
1514
- const parsed = parseAgentWsMessage(raw);
1515
- if (parsed === null) {
1516
- console.error("[apm] \u6536\u5230\u65E0\u6548 JSON");
1517
- return;
1518
- }
1519
- if (typeof parsed === "object" && parsed !== null && parsed.type === "heartbeat") {
1520
- return;
1521
- }
1522
- const validated = validateAgentWsMessage(parsed, "outbound");
1523
- if (!validated.ok) {
1524
- console.error(`[apm] \u6536\u5230\u65E0\u6548 message: ${validated.reason}`);
1525
- return;
1526
- }
1527
- if (validated.data.type !== "message") {
1528
- return;
1529
- }
1530
- const msg = validated.data;
1531
1540
  const messageId = msg.messageId;
1532
1541
  const runStep = async (step, fn) => {
1533
1542
  try {
@@ -1589,6 +1598,10 @@ async function handleInboundMessage(cfg, raw, signal) {
1589
1598
  () => updateMessageStatus(cfg, messageId, "SUCCESS")
1590
1599
  );
1591
1600
  } catch (err) {
1601
+ if (isUserCancelled(ctx)) {
1602
+ console.log(`[apm] \u6D88\u606F\u5DF2\u7EC8\u6B62 messageId=${messageId}`);
1603
+ return;
1604
+ }
1592
1605
  console.error(
1593
1606
  "[apm] \u5904\u7406\u6D88\u606F\u5931\u8D25:",
1594
1607
  err instanceof Error ? err.message : err
@@ -1644,6 +1657,8 @@ async function runConnect(options) {
1644
1657
  let shuttingDown = false;
1645
1658
  const shutdownAbort = new AbortController();
1646
1659
  let inboundQueue = Promise.resolve();
1660
+ const activeRuns = /* @__PURE__ */ new Map();
1661
+ const pendingCancels = /* @__PURE__ */ new Set();
1647
1662
  const shutdown = async (code = 0) => {
1648
1663
  if (shuttingDown) return;
1649
1664
  shuttingDown = true;
@@ -1674,9 +1689,48 @@ async function runConnect(options) {
1674
1689
  ws.on("message", (data) => {
1675
1690
  if (shuttingDown) return;
1676
1691
  const text = Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
1677
- inboundQueue = inboundQueue.then(
1678
- () => handleInboundMessage(cfg, text, shutdownAbort.signal)
1679
- );
1692
+ const parsed = parseAgentWsMessage(text);
1693
+ if (parsed === null) {
1694
+ console.error("[apm] \u6536\u5230\u65E0\u6548 JSON");
1695
+ return;
1696
+ }
1697
+ if (typeof parsed === "object" && parsed !== null && parsed.type === "heartbeat") {
1698
+ return;
1699
+ }
1700
+ const validated = validateAgentWsMessage(parsed, "outbound");
1701
+ if (!validated.ok) {
1702
+ console.error(`[apm] \u6536\u5230\u65E0\u6548 WS \u5305: ${validated.reason}`);
1703
+ return;
1704
+ }
1705
+ if (validated.data.type === "cancel") {
1706
+ const { messageId } = validated.data;
1707
+ pendingCancels.add(messageId);
1708
+ activeRuns.get(messageId)?.abort();
1709
+ return;
1710
+ }
1711
+ if (validated.data.type !== "message") {
1712
+ return;
1713
+ }
1714
+ const msg = validated.data;
1715
+ const perMessageController = new AbortController();
1716
+ activeRuns.set(msg.messageId, perMessageController);
1717
+ if (pendingCancels.has(msg.messageId)) {
1718
+ activeRuns.delete(msg.messageId);
1719
+ pendingCancels.delete(msg.messageId);
1720
+ return;
1721
+ }
1722
+ const signal = AbortSignal.any([
1723
+ shutdownAbort.signal,
1724
+ perMessageController.signal
1725
+ ]);
1726
+ const ctx = {
1727
+ shutdownSignal: shutdownAbort.signal,
1728
+ perMessageSignal: perMessageController.signal
1729
+ };
1730
+ inboundQueue = inboundQueue.then(() => handleInboundMessage(cfg, msg, signal, ctx)).finally(() => {
1731
+ activeRuns.delete(msg.messageId);
1732
+ pendingCancels.delete(msg.messageId);
1733
+ });
1680
1734
  });
1681
1735
  ws.on("close", (code, reason) => {
1682
1736
  console.log(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.33",
3
+ "version": "6.0.34",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,