@vibe-lark/larkpal 0.1.21 → 0.1.23
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/main.mjs +64 -3
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -859,8 +859,18 @@ const log$25 = larkLogger("cc-runtime/process-manager");
|
|
|
859
859
|
* 此值不可更改,否则所有用户的历史会话将无法恢复。
|
|
860
860
|
*/
|
|
861
861
|
const LARKPAL_SESSION_NAMESPACE = "7c9e6679-7425-40de-944b-e07fc1f90ae7";
|
|
862
|
-
/**
|
|
863
|
-
|
|
862
|
+
/**
|
|
863
|
+
* CC 进程空闲超时时间(毫秒)。
|
|
864
|
+
* 通过 LARKPAL_CC_IDLE_TIMEOUT 环境变量配置(单位:秒),默认 0 表示永不超时。
|
|
865
|
+
* 多用户场景建议设为 0(进程常驻),避免 --resume 冷启动延迟。
|
|
866
|
+
*/
|
|
867
|
+
const IDLE_TIMEOUT_MS = (() => {
|
|
868
|
+
const envVal = process.env.LARKPAL_CC_IDLE_TIMEOUT;
|
|
869
|
+
if (envVal === void 0 || envVal === "") return 0;
|
|
870
|
+
const seconds = parseInt(envVal, 10);
|
|
871
|
+
if (isNaN(seconds) || seconds < 0) return 0;
|
|
872
|
+
return seconds * 1e3;
|
|
873
|
+
})();
|
|
864
874
|
/** 优雅关闭等待时间(5 秒) */
|
|
865
875
|
const GRACEFUL_SHUTDOWN_MS = 5e3;
|
|
866
876
|
var SessionProcessManager = class {
|
|
@@ -947,10 +957,15 @@ var SessionProcessManager = class {
|
|
|
947
957
|
*/
|
|
948
958
|
async executePrompt(config, callbacks) {
|
|
949
959
|
const { sessionId } = config;
|
|
960
|
+
const t0 = Date.now();
|
|
950
961
|
const prevLock = this.sessionLocks.get(sessionId);
|
|
951
962
|
if (prevLock) {
|
|
952
963
|
log$25.info("等待上一条消息处理完成", { sessionId });
|
|
953
964
|
await prevLock;
|
|
965
|
+
log$25.info("[perf] 串行锁等待完成", {
|
|
966
|
+
sessionId,
|
|
967
|
+
waitMs: Date.now() - t0
|
|
968
|
+
});
|
|
954
969
|
}
|
|
955
970
|
const completionPromise = this.createMessageCompletionPromise(sessionId);
|
|
956
971
|
this.sessionLocks.set(sessionId, completionPromise);
|
|
@@ -960,11 +975,16 @@ var SessionProcessManager = class {
|
|
|
960
975
|
log$25.info("向常驻进程发送消息", {
|
|
961
976
|
sessionId,
|
|
962
977
|
promptLength: config.prompt.length,
|
|
963
|
-
pid: existing.childProcess.pid
|
|
978
|
+
pid: existing.childProcess.pid,
|
|
979
|
+
prepareMs: Date.now() - t0
|
|
964
980
|
});
|
|
965
981
|
this.sendMessage(sessionId, config.prompt);
|
|
966
982
|
this.resetIdleTimer(sessionId);
|
|
967
983
|
await completionPromise;
|
|
984
|
+
log$25.info("[perf] executePrompt 完成(热进程)", {
|
|
985
|
+
sessionId,
|
|
986
|
+
totalMs: Date.now() - t0
|
|
987
|
+
});
|
|
968
988
|
return;
|
|
969
989
|
}
|
|
970
990
|
if (existing && (existing.status === "stopped" || existing.status === "crashed")) {
|
|
@@ -980,8 +1000,17 @@ var SessionProcessManager = class {
|
|
|
980
1000
|
await this.stopProcess(sessionId);
|
|
981
1001
|
this.sessionLocks.set(sessionId, completionPromise);
|
|
982
1002
|
}
|
|
1003
|
+
const tStart = Date.now();
|
|
983
1004
|
await this.startPersistentProcess(config);
|
|
1005
|
+
log$25.info("[perf] 冷启动进程完成", {
|
|
1006
|
+
sessionId,
|
|
1007
|
+
coldStartMs: Date.now() - tStart
|
|
1008
|
+
});
|
|
984
1009
|
await completionPromise;
|
|
1010
|
+
log$25.info("[perf] executePrompt 完成(冷启动)", {
|
|
1011
|
+
sessionId,
|
|
1012
|
+
totalMs: Date.now() - t0
|
|
1013
|
+
});
|
|
985
1014
|
}
|
|
986
1015
|
/**
|
|
987
1016
|
* 启动常驻 CC 进程
|
|
@@ -1197,10 +1226,31 @@ var SessionProcessManager = class {
|
|
|
1197
1226
|
*/
|
|
1198
1227
|
bindParserToCallbackProxy(parser, sessionId) {
|
|
1199
1228
|
const getCallbacks = () => this.activeCallbacks.get(sessionId);
|
|
1229
|
+
let firstTokenLogged = false;
|
|
1230
|
+
let messageSentAt = Date.now();
|
|
1231
|
+
const proc = this.processes.get(sessionId);
|
|
1232
|
+
if (proc) proc._resetPerfTimer = () => {
|
|
1233
|
+
firstTokenLogged = false;
|
|
1234
|
+
messageSentAt = Date.now();
|
|
1235
|
+
};
|
|
1200
1236
|
parser.on("textDelta", (text) => {
|
|
1237
|
+
if (!firstTokenLogged) {
|
|
1238
|
+
firstTokenLogged = true;
|
|
1239
|
+
log$25.info("[perf] 首 token (text)", {
|
|
1240
|
+
sessionId,
|
|
1241
|
+
ttftMs: Date.now() - messageSentAt
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1201
1244
|
getCallbacks()?.onTextDelta?.(text);
|
|
1202
1245
|
});
|
|
1203
1246
|
parser.on("thinkingDelta", (text) => {
|
|
1247
|
+
if (!firstTokenLogged) {
|
|
1248
|
+
firstTokenLogged = true;
|
|
1249
|
+
log$25.info("[perf] 首 token (thinking)", {
|
|
1250
|
+
sessionId,
|
|
1251
|
+
ttftMs: Date.now() - messageSentAt
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1204
1254
|
getCallbacks()?.onThinkingDelta?.(text);
|
|
1205
1255
|
});
|
|
1206
1256
|
parser.on("toolUseStart", (toolName, toolInput) => {
|
|
@@ -1213,9 +1263,18 @@ var SessionProcessManager = class {
|
|
|
1213
1263
|
getCallbacks()?.onToolProgress?.(toolName, elapsedSeconds);
|
|
1214
1264
|
});
|
|
1215
1265
|
parser.on("turnEnd", (stopReason) => {
|
|
1266
|
+
log$25.info("[perf] turnEnd", {
|
|
1267
|
+
sessionId,
|
|
1268
|
+
stopReason,
|
|
1269
|
+
sinceMessageMs: Date.now() - messageSentAt
|
|
1270
|
+
});
|
|
1216
1271
|
getCallbacks()?.onTurnEnd?.(stopReason);
|
|
1217
1272
|
});
|
|
1218
1273
|
parser.on("result", (result) => {
|
|
1274
|
+
log$25.info("[perf] result 事件", {
|
|
1275
|
+
sessionId,
|
|
1276
|
+
sinceMessageMs: Date.now() - messageSentAt
|
|
1277
|
+
});
|
|
1219
1278
|
getCallbacks()?.onResult?.(result);
|
|
1220
1279
|
this.resolveMessageCompletion(sessionId);
|
|
1221
1280
|
});
|
|
@@ -1239,6 +1298,7 @@ var SessionProcessManager = class {
|
|
|
1239
1298
|
log$25.error("无法发送消息:进程不存在或 stdin 不可用", { sessionId });
|
|
1240
1299
|
return;
|
|
1241
1300
|
}
|
|
1301
|
+
proc._resetPerfTimer?.();
|
|
1242
1302
|
const userMessageId = v4();
|
|
1243
1303
|
this.lastUserMessageIds.set(sessionId, userMessageId);
|
|
1244
1304
|
const payload = JSON.stringify({
|
|
@@ -1442,6 +1502,7 @@ var SessionProcessManager = class {
|
|
|
1442
1502
|
resetIdleTimer(sessionId) {
|
|
1443
1503
|
const existing = this.idleTimers.get(sessionId);
|
|
1444
1504
|
if (existing) clearTimeout(existing);
|
|
1505
|
+
if (IDLE_TIMEOUT_MS <= 0) return;
|
|
1445
1506
|
const timer = setTimeout(() => {
|
|
1446
1507
|
log$25.info("CC 常驻进程空闲超时,自动停止", {
|
|
1447
1508
|
sessionId,
|