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.
- package/dist/index.js +57 -32
- 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
|
-
|
|
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(
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
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.
|
|
1547
|
+
ws.terminate();
|
|
1533
1548
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
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(
|
|
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
|
|