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.
- package/dist/index.js +235 -12
- 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
|
-
|
|
236
|
-
|
|
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
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
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
|
-
|
|
1050
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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}`);
|