ai-project-manage-cli 5.0.20 → 5.0.22

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 +62 -38
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1051,11 +1051,16 @@ import { resolve as resolve3 } from "path";
1051
1051
  // src/session-utils.ts
1052
1052
  var EventSession = class {
1053
1053
  events = [];
1054
+ dirtyIndices = /* @__PURE__ */ new Set();
1054
1055
  constructor(prompt) {
1055
1056
  this.events.push({
1056
1057
  type: "input",
1057
1058
  content: prompt
1058
1059
  });
1060
+ this.markDirty(0);
1061
+ }
1062
+ markDirty(index) {
1063
+ this.dirtyIndices.add(index);
1059
1064
  }
1060
1065
  addEvent(event) {
1061
1066
  const latestEvent = this.events[this.events.length - 1];
@@ -1064,16 +1069,19 @@ var EventSession = class {
1064
1069
  return;
1065
1070
  }
1066
1071
  if (formatedEvent.type === "tool_call") {
1067
- const existingToolCall = this.events.find(
1072
+ const existingIndex = this.events.findIndex(
1068
1073
  (e) => e.type === "tool_call" && e.call_id === formatedEvent.call_id
1069
1074
  );
1070
- if (existingToolCall) {
1075
+ if (existingIndex >= 0) {
1076
+ const existingToolCall = this.events[existingIndex];
1071
1077
  existingToolCall.args = formatedEvent.args;
1072
1078
  existingToolCall.result = formatedEvent.result;
1073
1079
  existingToolCall.status = formatedEvent.status;
1080
+ this.markDirty(existingIndex);
1074
1081
  return;
1075
1082
  }
1076
1083
  this.events.push(formatedEvent);
1084
+ this.markDirty(this.events.length - 1);
1077
1085
  return;
1078
1086
  }
1079
1087
  if (formatedEvent.type === "status") {
@@ -1081,6 +1089,7 @@ var EventSession = class {
1081
1089
  }
1082
1090
  if (formatedEvent.type === "request") {
1083
1091
  this.events.push(formatedEvent);
1092
+ this.markDirty(this.events.length - 1);
1084
1093
  return;
1085
1094
  }
1086
1095
  if (latestEvent?.type === formatedEvent.type) {
@@ -1096,9 +1105,11 @@ var EventSession = class {
1096
1105
  latestEvent.text = formatedEvent.text;
1097
1106
  break;
1098
1107
  }
1108
+ this.markDirty(this.events.length - 1);
1099
1109
  return;
1100
1110
  }
1101
1111
  this.events.push(formatedEvent);
1112
+ this.markDirty(this.events.length - 1);
1102
1113
  }
1103
1114
  formatEvent(event) {
1104
1115
  switch (event.type) {
@@ -1143,45 +1154,57 @@ var EventSession = class {
1143
1154
  return { type: "status", status: event.status, message: event.message };
1144
1155
  }
1145
1156
  }
1157
+ getDirtyEvents() {
1158
+ return [...this.dirtyIndices].sort((a, b) => a - b).map((index) => {
1159
+ const event = this.events[index];
1160
+ return {
1161
+ index,
1162
+ type: event.type,
1163
+ data: JSON.stringify(event)
1164
+ };
1165
+ });
1166
+ }
1167
+ clearDirty(indices) {
1168
+ for (const index of indices) {
1169
+ this.dirtyIndices.delete(index);
1170
+ }
1171
+ }
1146
1172
  /** 合并所有 assistant 片段,供剧场成员回传等场景使用 */
1147
1173
  getAssistantText() {
1148
1174
  return this.events.filter((e) => e.type === "assistant").map((e) => String(e.content ?? "")).join("\n").trim();
1149
1175
  }
1150
1176
  resolveLogContent() {
1151
- return this.events.map((event) => {
1152
- const type = event.type;
1153
- const content = (function(type2) {
1154
- if (type2 === "input") {
1155
- return `## \u7528\u6237\u8F93\u5165
1177
+ return this.events.map((event) => formatLogEvent(event.type, event)).join("\n");
1178
+ }
1179
+ };
1180
+ function formatLogEvent(type, event) {
1181
+ if (type === "input") {
1182
+ return `## \u7528\u6237\u8F93\u5165
1156
1183
 
1157
- ${event.content}
1184
+ ${String(event.content ?? "")}
1158
1185
  `;
1159
- }
1160
- if (type2 === "assistant") {
1161
- return `## \u6A21\u578B\u8F93\u51FA
1186
+ }
1187
+ if (type === "assistant") {
1188
+ return `## \u6A21\u578B\u8F93\u51FA
1162
1189
 
1163
- ${event.content}
1190
+ ${String(event.content ?? "")}
1164
1191
  `;
1165
- }
1166
- if (type2 === "thinking") {
1167
- return `## \u6A21\u578B\u601D\u8003
1192
+ }
1193
+ if (type === "thinking") {
1194
+ return `## \u6A21\u578B\u601D\u8003
1168
1195
 
1169
- ${event.content}
1196
+ ${String(event.content ?? "")}
1170
1197
  `;
1171
- }
1172
- if (type2 === "tool_call") {
1173
- return "````toolcall\n" + JSON.stringify(event, null, 2) + "\n````\n";
1174
- }
1175
- return `## \u672A\u77E5\u4E8B\u4EF6\uFF1A${type2}
1198
+ }
1199
+ if (type === "tool_call") {
1200
+ return "````toolcall\n" + JSON.stringify(event, null, 2) + "\n````\n";
1201
+ }
1202
+ return `## \u672A\u77E5\u4E8B\u4EF6\uFF1A${type}
1176
1203
 
1177
1204
  \`\`\`json
1178
1205
  ${JSON.stringify(event, null, 2)}
1179
1206
  \`\`\``;
1180
- })(type);
1181
- return content;
1182
- }).join("\n");
1183
- }
1184
- };
1207
+ }
1185
1208
 
1186
1209
  // src/commands/connect/cursor-message-log.ts
1187
1210
  function assistantStreamChunk(event) {
@@ -1201,14 +1224,15 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1201
1224
  let lastRunAt = 0;
1202
1225
  let timer;
1203
1226
  let latestSession;
1204
- const execute = async () => {
1205
- const session = latestSession;
1206
- if (!session) {
1227
+ const syncDirtyEvents = async (session) => {
1228
+ const events = session.getDirtyEvents();
1229
+ if (events.length === 0) {
1207
1230
  return;
1208
1231
  }
1209
1232
  lastRunAt = Date.now();
1210
1233
  try {
1211
- await syncCursorMessageLog(cfg, ctx, session);
1234
+ await syncCursorMessageLog(cfg, ctx, events);
1235
+ session.clearDirty(events.map((event) => event.index));
1212
1236
  } catch (err) {
1213
1237
  onError(err);
1214
1238
  }
@@ -1223,7 +1247,7 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1223
1247
  clearTimeout(timer);
1224
1248
  timer = void 0;
1225
1249
  }
1226
- void execute();
1250
+ void syncDirtyEvents(session);
1227
1251
  return;
1228
1252
  }
1229
1253
  if (timer) {
@@ -1231,7 +1255,7 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1231
1255
  }
1232
1256
  timer = setTimeout(() => {
1233
1257
  timer = void 0;
1234
- void execute();
1258
+ void syncDirtyEvents(latestSession);
1235
1259
  }, CURSOR_MESSAGE_LOG_SYNC_INTERVAL_MS - elapsed);
1236
1260
  },
1237
1261
  async flush(session) {
@@ -1240,14 +1264,13 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1240
1264
  clearTimeout(timer);
1241
1265
  timer = void 0;
1242
1266
  }
1243
- await execute();
1267
+ await syncDirtyEvents(session);
1244
1268
  }
1245
1269
  };
1246
1270
  }
1247
- async function syncCursorMessageLog(cfg, ctx, session) {
1271
+ async function syncCursorMessageLog(cfg, ctx, events) {
1248
1272
  const agentId = ctx.agentId.trim();
1249
- const data = session.resolveLogContent().trim();
1250
- if (!agentId || !data) {
1273
+ if (!agentId || events.length === 0) {
1251
1274
  return;
1252
1275
  }
1253
1276
  const api = createApmApiClient(cfg);
@@ -1255,7 +1278,7 @@ async function syncCursorMessageLog(cfg, ctx, session) {
1255
1278
  sessionId: ctx.sessionId,
1256
1279
  messageId: ctx.messageId,
1257
1280
  agentId,
1258
- data
1281
+ events
1259
1282
  });
1260
1283
  }
1261
1284
 
@@ -1421,6 +1444,7 @@ async function runConnect(options) {
1421
1444
  const ws = new WebSocket(url);
1422
1445
  let stopHeartbeat;
1423
1446
  let shuttingDown = false;
1447
+ let inboundQueue = Promise.resolve();
1424
1448
  const shutdown = (code = 0) => {
1425
1449
  if (shuttingDown) return;
1426
1450
  shuttingDown = true;
@@ -1439,7 +1463,7 @@ async function runConnect(options) {
1439
1463
  });
1440
1464
  ws.on("message", (data) => {
1441
1465
  const text = Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
1442
- void handleInboundMessage(cfg, text);
1466
+ inboundQueue = inboundQueue.then(() => handleInboundMessage(cfg, text));
1443
1467
  });
1444
1468
  ws.on("close", (code, reason) => {
1445
1469
  console.log(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "5.0.20",
3
+ "version": "5.0.22",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -29,7 +29,7 @@
29
29
  "node": ">=18"
30
30
  },
31
31
  "dependencies": {
32
- "@cursor/sdk": "~1.0.17",
32
+ "@cursor/sdk": "~1.0.18",
33
33
  "ws": "~8.18.0",
34
34
  "listpage-http": "~0.0.318",
35
35
  "commander": "~14.0.3",
@@ -37,4 +37,4 @@
37
37
  "minio": "~8.0.7",
38
38
  "dockerode": "~5.0.0"
39
39
  }
40
- }
40
+ }