fix: 定时器15秒间隔 + 滚动rAF + 闲置追踪

- 流式进度定时器改为15秒间隔
- lastContentTime 追踪真正的无新内容时长
- appendToolCardDOM/renderToolCalls 用 rAF 确保布局后滚动
This commit is contained in:
thzxx
2026-06-13 07:42:40 +08:00
parent 45777a5945
commit 87d3364886
2 changed files with 21 additions and 16 deletions
+6 -2
View File
@@ -831,8 +831,10 @@ function appendToolCardDOM(tc: ToolCallRecord): void {
if (card) {
card.dataset.toolName = tc.name;
container.appendChild(card);
// 新卡片出现时始终滚到底部(用户需要看到最新的工具状态)
// 等浏览器完成布局后再滚到底部
requestAnimationFrame(() => {
container.scrollTop = container.scrollHeight;
});
}
}
@@ -936,8 +938,10 @@ function renderToolCalls(): void {
html += renderToolCard(tc);
}
container.innerHTML = html;
// 全量渲染后滚到底部
// 等浏览器完成布局后再滚到底部
requestAnimationFrame(() => {
container.scrollTop = container.scrollHeight;
});
}
function getToolDisplayName(name: string): string {
+9 -8
View File
@@ -717,23 +717,24 @@ Shell: ${osInfo.shell}
// 流式调用
const streamStartTime = Date.now();
let lastLoggedLen = 0;
let lastProgressAt = 0;
const PROGRESS_INTERVAL = 5000; // 每5秒输出一次流式进度
let lastContentTime = streamStartTime; // 追踪最后一次收到新内容的时间
const PROGRESS_INTERVAL = 15000; // 每15秒输出一次流式进度
// ── 独立定时器:即使没有新 chunk 也会持续输出进度 ──
progressTimer = setInterval(() => {
const elapsed = Date.now() - streamStartTime;
const grew = content.length - lastLoggedLen;
const sinceLast = elapsed - lastProgressAt;
if (sinceLast >= PROGRESS_INTERVAL) {
lastProgressAt = elapsed;
const sec = Math.round(elapsed / 1000);
if (grew > 0) {
// 有新增内容 → 正常进度
lastLoggedLen = content.length;
lastContentTime = Date.now();
logStream(`流式输出中… ${content.length} 字 / ${sec}s${toolCalls.length > 0 ? ` [${toolCalls.length} 个工具调用]` : ''}`);
} else if (elapsed > 15000 && content.length > 0) {
// 超过 15 秒无新内容 → 可能模型卡住了
logStream(`⚠️ 无新内容 ${Math.round(sinceLast / 1000)}s,当前 ${content.length}`);
} else if (content.length > 0) {
// 内容不变 → 计算真正的无新内容时长
const idleSec = Math.round((Date.now() - lastContentTime) / 1000);
if (idleSec >= 10) {
logStream(`⚠️ ${idleSec}s 无新内容,当前 ${content.length}`);
}
}
}, PROGRESS_INTERVAL);