ai-project-manage-cli 5.0.18 → 5.0.19

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 +235 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -231,10 +231,12 @@ var requestConfig = {
231
231
  method: "GET",
232
232
  path: "/cli/documents"
233
233
  }),
234
- listAttachments: defineEndpoint({
235
- method: "GET",
236
- path: "/cli/attachments"
237
- }),
234
+ listAttachments: defineEndpoint(
235
+ {
236
+ method: "GET",
237
+ path: "/cli/attachments"
238
+ }
239
+ ),
238
240
  upsertDocument: defineEndpoint({
239
241
  method: "PUT",
240
242
  path: "/cli/documents/upsert"
@@ -243,6 +245,10 @@ var requestConfig = {
243
245
  method: "PUT",
244
246
  path: "/cli/messages/content"
245
247
  }),
248
+ upsertCursorMessageLog: defineEndpoint({
249
+ method: "PUT",
250
+ path: "/cli/cursor-message-logs"
251
+ }),
246
252
  updateMessageStatus: defineEndpoint({
247
253
  method: "PUT",
248
254
  path: "/cli/messages/status"
@@ -1042,23 +1048,225 @@ function validateAgentWsMessage(value, kind) {
1042
1048
  // src/commands/connect/cursor-agent.ts
1043
1049
  import { Agent, CursorAgentError } from "@cursor/sdk";
1044
1050
  import { resolve as resolve3 } from "path";
1045
- function extractAssistantTextFromStream(event) {
1046
- if (event.type !== "assistant") {
1047
- return "";
1051
+
1052
+ // src/session-utils.ts
1053
+ var EventSession = class {
1054
+ events = [];
1055
+ constructor(prompt) {
1056
+ this.events.push({
1057
+ type: "input",
1058
+ content: prompt
1059
+ });
1048
1060
  }
1049
- const msg = event.message;
1050
- if (!msg?.content) {
1061
+ addEvent(event) {
1062
+ const latestEvent = this.events[this.events.length - 1];
1063
+ const formatedEvent = this.formatEvent(event);
1064
+ if (!formatedEvent) {
1065
+ return;
1066
+ }
1067
+ if (formatedEvent.type === "tool_call") {
1068
+ const existingToolCall = this.events.find(
1069
+ (e) => e.type === "tool_call" && e.call_id === formatedEvent.call_id
1070
+ );
1071
+ if (existingToolCall) {
1072
+ existingToolCall.args = formatedEvent.args;
1073
+ existingToolCall.result = formatedEvent.result;
1074
+ existingToolCall.status = formatedEvent.status;
1075
+ return;
1076
+ }
1077
+ this.events.push(formatedEvent);
1078
+ return;
1079
+ }
1080
+ if (formatedEvent.type === "status") {
1081
+ return;
1082
+ }
1083
+ if (formatedEvent.type === "request") {
1084
+ this.events.push(formatedEvent);
1085
+ return;
1086
+ }
1087
+ if (latestEvent?.type === formatedEvent.type) {
1088
+ switch (formatedEvent.type) {
1089
+ case "assistant":
1090
+ latestEvent.content += formatedEvent.content;
1091
+ break;
1092
+ case "thinking":
1093
+ latestEvent.content += formatedEvent.content;
1094
+ break;
1095
+ case "task":
1096
+ latestEvent.status = formatedEvent.status;
1097
+ latestEvent.text = formatedEvent.text;
1098
+ break;
1099
+ }
1100
+ return;
1101
+ }
1102
+ this.events.push(formatedEvent);
1103
+ }
1104
+ formatEvent(event) {
1105
+ switch (event.type) {
1106
+ case "assistant": {
1107
+ let content = "";
1108
+ for (const block of event.message.content) {
1109
+ if (block.type === "text" && block.text) {
1110
+ content += block.text;
1111
+ }
1112
+ }
1113
+ return {
1114
+ type: "assistant",
1115
+ content: content || event.content || ""
1116
+ };
1117
+ }
1118
+ case "thinking":
1119
+ return {
1120
+ type: "thinking",
1121
+ content: event.text || event.content || ""
1122
+ };
1123
+ case "tool_call":
1124
+ return {
1125
+ type: "tool_call",
1126
+ args: event.args,
1127
+ result: event.result,
1128
+ status: event.status,
1129
+ call_id: event.call_id,
1130
+ name: event.name
1131
+ };
1132
+ case "task":
1133
+ return {
1134
+ type: "task",
1135
+ status: event.status,
1136
+ text: event.text
1137
+ };
1138
+ case "request":
1139
+ return {
1140
+ ...event,
1141
+ type: "request"
1142
+ };
1143
+ case "status":
1144
+ return { type: "status", status: event.status, message: event.message };
1145
+ }
1146
+ }
1147
+ /** 合并所有 assistant 片段,供剧场成员回传等场景使用 */
1148
+ getAssistantText() {
1149
+ return this.events.filter((e) => e.type === "assistant").map((e) => String(e.content ?? "")).join("\n").trim();
1150
+ }
1151
+ resolveLogContent() {
1152
+ return this.events.map((event) => {
1153
+ const type = event.type;
1154
+ const content = (function(type2) {
1155
+ if (type2 === "input") {
1156
+ return `## \u7528\u6237\u8F93\u5165
1157
+
1158
+ ${event.content}
1159
+ `;
1160
+ }
1161
+ if (type2 === "assistant") {
1162
+ return `## \u6A21\u578B\u8F93\u51FA
1163
+
1164
+ ${event.content}
1165
+ `;
1166
+ }
1167
+ if (type2 === "thinking") {
1168
+ return `## \u6A21\u578B\u601D\u8003
1169
+
1170
+ ${event.content}
1171
+ `;
1172
+ }
1173
+ if (type2 === "tool_call") {
1174
+ return "````toolcall\n" + JSON.stringify(event, null, 2) + "\n````\n";
1175
+ }
1176
+ return `## \u672A\u77E5\u4E8B\u4EF6\uFF1A${type2}
1177
+
1178
+ \`\`\`json
1179
+ ${JSON.stringify(event, null, 2)}
1180
+ \`\`\``;
1181
+ })(type);
1182
+ return content;
1183
+ }).join("\n");
1184
+ }
1185
+ };
1186
+
1187
+ // src/commands/connect/cursor-message-log.ts
1188
+ function assistantStreamChunk(event) {
1189
+ if (event.type !== "assistant") {
1051
1190
  return "";
1052
1191
  }
1053
1192
  let text = "";
1054
- for (const block of msg.content) {
1193
+ for (const block of event.message.content) {
1055
1194
  if (block.type === "text" && block.text) {
1056
1195
  text += block.text;
1057
1196
  }
1058
1197
  }
1059
1198
  return text;
1060
1199
  }
1061
- async function runCursorAgent(_cfg, ctx) {
1200
+ var CURSOR_MESSAGE_LOG_SYNC_INTERVAL_MS = 2e3;
1201
+ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1202
+ let lastRunAt = 0;
1203
+ let timer;
1204
+ let latestSession;
1205
+ const execute = async () => {
1206
+ const session = latestSession;
1207
+ if (!session) {
1208
+ return;
1209
+ }
1210
+ lastRunAt = Date.now();
1211
+ try {
1212
+ await syncCursorMessageLog(cfg, ctx, session);
1213
+ } catch (err) {
1214
+ onError(err);
1215
+ }
1216
+ };
1217
+ return {
1218
+ schedule(session) {
1219
+ latestSession = session;
1220
+ const now = Date.now();
1221
+ const elapsed = now - lastRunAt;
1222
+ if (elapsed >= CURSOR_MESSAGE_LOG_SYNC_INTERVAL_MS) {
1223
+ if (timer) {
1224
+ clearTimeout(timer);
1225
+ timer = void 0;
1226
+ }
1227
+ void execute();
1228
+ return;
1229
+ }
1230
+ if (timer) {
1231
+ return;
1232
+ }
1233
+ timer = setTimeout(() => {
1234
+ timer = void 0;
1235
+ void execute();
1236
+ }, CURSOR_MESSAGE_LOG_SYNC_INTERVAL_MS - elapsed);
1237
+ },
1238
+ async flush(session) {
1239
+ latestSession = session;
1240
+ if (timer) {
1241
+ clearTimeout(timer);
1242
+ timer = void 0;
1243
+ }
1244
+ await execute();
1245
+ }
1246
+ };
1247
+ }
1248
+ async function syncCursorMessageLog(cfg, ctx, session) {
1249
+ const agentId = ctx.agentId.trim();
1250
+ const data = session.resolveLogContent().trim();
1251
+ if (!agentId || !data) {
1252
+ return;
1253
+ }
1254
+ const api = createApmApiClient(cfg);
1255
+ await api.cli.upsertCursorMessageLog({
1256
+ sessionId: ctx.sessionId,
1257
+ messageId: ctx.messageId,
1258
+ agentId,
1259
+ data
1260
+ });
1261
+ }
1262
+
1263
+ // src/commands/connect/cursor-agent.ts
1264
+ var logCtx = (ctx, agentId) => ({
1265
+ sessionId: ctx.sessionId,
1266
+ messageId: ctx.messageId,
1267
+ agentId
1268
+ });
1269
+ async function runCursorAgent(cfg, ctx) {
1062
1270
  const apiKey = ctx.apiKey.trim();
1063
1271
  if (!apiKey) {
1064
1272
  throw new Error("\u7F3A\u5C11 apiKey\uFF0C\u65E0\u6CD5\u8C03\u7528 Cursor SDK");
@@ -1076,15 +1284,30 @@ async function runCursorAgent(_cfg, ctx) {
1076
1284
  settingSources: []
1077
1285
  }
1078
1286
  });
1287
+ const eventSession = new EventSession(prompt);
1288
+ const remoteLogCtx = logCtx(ctx, agent.agentId);
1289
+ const syncRemoteLog = createThrottledCursorMessageLogSync(
1290
+ cfg,
1291
+ remoteLogCtx,
1292
+ (err) => {
1293
+ console.warn(
1294
+ "[apm] \u540C\u6B65 Cursor \u6D88\u606F\u65E5\u5FD7\u5931\u8D25:",
1295
+ err instanceof Error ? err.message : err
1296
+ );
1297
+ }
1298
+ );
1079
1299
  try {
1080
1300
  const run = await agent.send(prompt);
1081
1301
  console.log(`[apm] Cursor run id=${run.id} agentId=${agent.agentId}`);
1082
1302
  for await (const event of run.stream()) {
1083
- const chunk = extractAssistantTextFromStream(event);
1303
+ eventSession.addEvent(event);
1304
+ const chunk = assistantStreamChunk(event);
1084
1305
  if (chunk) {
1085
1306
  process.stdout.write(chunk);
1086
1307
  }
1308
+ syncRemoteLog.schedule(eventSession);
1087
1309
  }
1310
+ await syncRemoteLog.flush(eventSession);
1088
1311
  const result = await run.wait();
1089
1312
  if (result.status === "error") {
1090
1313
  throw new Error(`Cursor run \u5931\u8D25: ${result.id}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "5.0.18",
3
+ "version": "5.0.19",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,