chatccc 0.2.79 → 0.2.81
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/package.json +1 -1
- package/src/session-chat-binding.ts +2 -0
- package/src/session.ts +58 -18
package/package.json
CHANGED
|
@@ -137,6 +137,8 @@ export interface DisplayCardState {
|
|
|
137
137
|
lastSentAccLen?: number;
|
|
138
138
|
/** WeChat delta: 上次发送时的 finalReply */
|
|
139
139
|
lastSentFinalReply?: string;
|
|
140
|
+
/** 上次 loop 读取到的 turnCount,用于检测轮次切换 */
|
|
141
|
+
lastTurnCount?: number;
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
export const displayCards = new Map<string, DisplayCardState>();
|
package/src/session.ts
CHANGED
|
@@ -861,6 +861,25 @@ export async function runAgentSession(
|
|
|
861
861
|
const wasStopped = prompt?.stopped ?? false;
|
|
862
862
|
activePrompts.delete(sessionId);
|
|
863
863
|
|
|
864
|
+
// 先写最终状态(done/stopped),确保 display loop 在下一轮消费前
|
|
865
|
+
// 读到新状态并终结旧卡片。否则 setImmediate 在 CHECK 阶段先于
|
|
866
|
+
// writeFile I/O(POLL 阶段)执行,display loop 会误以为旧轮仍在
|
|
867
|
+
// 运行中并更新旧卡片,而不是新建卡片。
|
|
868
|
+
const finalStatus = wasStopped ? "stopped" : "done";
|
|
869
|
+
const finalReply = pickFinalReply(state).trim();
|
|
870
|
+
await writeStreamState({
|
|
871
|
+
sessionId,
|
|
872
|
+
status: finalStatus,
|
|
873
|
+
accumulatedContent: state.accumulatedContent,
|
|
874
|
+
finalReply,
|
|
875
|
+
chunkCount: state.chunkCount,
|
|
876
|
+
turnCount: nextTurnCount,
|
|
877
|
+
contextTokens: existingInfo?.lastContextTokens ?? 0,
|
|
878
|
+
updatedAt: Date.now(),
|
|
879
|
+
cwd,
|
|
880
|
+
tool,
|
|
881
|
+
});
|
|
882
|
+
|
|
864
883
|
// 消费队列中的缓存消息(异步,不阻塞后续清理)
|
|
865
884
|
// 用户 /stop 后应丢弃队列消息,避免用户停止后又自动开始新轮
|
|
866
885
|
if (wasStopped) {
|
|
@@ -879,28 +898,16 @@ export async function runAgentSession(
|
|
|
879
898
|
setQueuePreservedChat(sessionId, preservedChat);
|
|
880
899
|
}
|
|
881
900
|
console.log(`[${ts()}] [QUEUE] Consuming queued message for session ${sessionId}: "${queued.text.slice(0, 50)}"`);
|
|
882
|
-
setImmediate
|
|
901
|
+
// setTimeout 而非 setImmediate:给 display loop 的 setInterval
|
|
902
|
+
// 足够时间读到 "done" 状态并终结旧卡片,避免新轮更新旧卡片的 bug。
|
|
903
|
+
// setImmediate 在 check 阶段触发早于下一个 timers 阶段,
|
|
904
|
+
// display loop (setInterval) 还没机会读到 "done" 就被新 "running" 覆盖。
|
|
905
|
+
setTimeout(() => {
|
|
883
906
|
consumeQueuedMessage(platform, queued);
|
|
884
|
-
});
|
|
907
|
+
}, 200);
|
|
885
908
|
}
|
|
886
909
|
}
|
|
887
910
|
|
|
888
|
-
// 写最终状态
|
|
889
|
-
const finalStatus = wasStopped ? "stopped" : "done";
|
|
890
|
-
const finalReply = pickFinalReply(state).trim();
|
|
891
|
-
await writeStreamState({
|
|
892
|
-
sessionId,
|
|
893
|
-
status: finalStatus,
|
|
894
|
-
accumulatedContent: state.accumulatedContent,
|
|
895
|
-
finalReply,
|
|
896
|
-
chunkCount: state.chunkCount,
|
|
897
|
-
turnCount: nextTurnCount,
|
|
898
|
-
contextTokens: existingInfo?.lastContextTokens ?? 0,
|
|
899
|
-
updatedAt: Date.now(),
|
|
900
|
-
cwd,
|
|
901
|
-
tool,
|
|
902
|
-
});
|
|
903
|
-
|
|
904
911
|
// display loop 下一轮会读到最终状态并发送消息
|
|
905
912
|
|
|
906
913
|
if (wasStopped) {
|
|
@@ -1100,11 +1107,44 @@ export function ensureDisplayLoop(sessionId: string): void {
|
|
|
1100
1107
|
cardCreatedAt: Date.now(),
|
|
1101
1108
|
lastSentContent: "",
|
|
1102
1109
|
streamErrorNotified: false,
|
|
1110
|
+
lastTurnCount: state.turnCount,
|
|
1103
1111
|
});
|
|
1104
1112
|
}
|
|
1105
1113
|
} else {
|
|
1106
1114
|
if (display.cardBusy) return;
|
|
1107
1115
|
|
|
1116
|
+
// 检测轮次切换:turnCount 变化说明上一轮已完成、本 tick 是新轮,
|
|
1117
|
+
// 但上一轮的 display 卡片因 setImmediate/setTimeout 时序问题
|
|
1118
|
+
// 还没被终结分支清除。此处主动终结旧卡、创建新卡。
|
|
1119
|
+
if (display.lastTurnCount !== undefined && display.lastTurnCount !== state.turnCount) {
|
|
1120
|
+
display.cardBusy = true;
|
|
1121
|
+
try {
|
|
1122
|
+
const doneSeq = display.sequence + 1;
|
|
1123
|
+
const doneCard = buildProgressCard("", { showStop: false, headerTitle: "完成" });
|
|
1124
|
+
await p.cardUpdate(display.cardId, doneCard, doneSeq).catch(() => {});
|
|
1125
|
+
displayCards.delete(chatId);
|
|
1126
|
+
} catch (_) { /* ignore */ }
|
|
1127
|
+
display.cardBusy = false;
|
|
1128
|
+
// 新建卡片
|
|
1129
|
+
const cardId = await p.cardCreate(buildProgressCard("", { showStop: true, headerTitle: "生成中..." })).catch(() => null);
|
|
1130
|
+
if (cardId) {
|
|
1131
|
+
await p.cardSend(chatId, cardId).catch(() => null);
|
|
1132
|
+
displayCards.set(chatId, {
|
|
1133
|
+
cardId,
|
|
1134
|
+
sequence: 1,
|
|
1135
|
+
cardBusy: false,
|
|
1136
|
+
cardCreatedAt: Date.now(),
|
|
1137
|
+
lastSentContent: "",
|
|
1138
|
+
streamErrorNotified: false,
|
|
1139
|
+
lastTurnCount: state.turnCount,
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// 更新当前 turn 的 lastTurnCount
|
|
1146
|
+
display.lastTurnCount = state.turnCount;
|
|
1147
|
+
|
|
1108
1148
|
// 卡片轮转
|
|
1109
1149
|
if (Date.now() - display.cardCreatedAt > CARD_ROTATE_MS) {
|
|
1110
1150
|
display.cardBusy = true;
|