mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
Fix/bypass root confirm (#1275)
* fix(ink): 主屏幕模式周期性终端重绘, 防止长时间运行 TUI 显示腐蚀 - 添加 lastMainScreenHealTime 字段, 每 5 秒触发一次全量终端重绘 - 使用 wall-clock 时间替代帧计数, 避免 drain frames (250fps) 加速周期 - 添加 isTTY 守卫, 防止非 TTY 环境泄漏 ANSI 转义序列 - 扩展 needsEraseBeforePaint 到主屏幕模式, BSU/ESU 确保原子性无闪烁 - 修复 log-update cursor 漂移和 blit ghosting 导致的文字重叠/残留 Co-Authored-By: deepseek-v4-pro <deepseek-ai@claude-code-best.win> * fix(messages): lookups 缓存感知 progress tick 替换, 修复 Bash 进度时间卡死 REPL.tsx 用原地替换处理 ephemeral progress (Bash/PowerShell/MCP) 以 限制 messages 数组增长, 但 computeMessageStructureKey 只把 parentToolUseID 计入 key, 替换前后 key 完全相同, Messages.tsx 的 lookups 缓存命中, updateMessageLookupsIncremental 长度相同时又直接返回 existing, 导致 progressMessagesByToolUseID 永远停在首条 tick, ShellProgressMessage 的 elapsed time 卡在首次显示值不动. - computeMessageStructureKey: 加入 progress.uuid, tick 替换后 key 必变 - updateMessageLookupsIncremental: 长度相同 + 末尾为 progress 时返回 null 触发 full rebuild, 让新 tick 进入 progressMessagesByToolUseID 补充 4 个测试覆盖 bug 行为与 fast path 保护. Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win> * fix: bypass 模式在 root/sudo 下改为警告 + y 确认而非直接退出 交互式 TTY 下打印风险警告并等待用户输入 y 才进入 bypass 模式; 非 TTY (pipe/ACP/CI) 维持原 exit(1) 行为,因为无法交互确认。 Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win> --------- Co-authored-by: deepseek-v4-pro <deepseek-ai@claude-code-best.win> Co-authored-by: glm-5.2 <zai-org@claude-code-best.win>
This commit is contained in:
@@ -165,6 +165,12 @@ export default class Ink {
|
||||
private frontFrame: Frame;
|
||||
private backFrame: Frame;
|
||||
private lastPoolResetTime = performance.now();
|
||||
/** Timestamp of last periodic full-redraw in main screen mode. Used to
|
||||
* recover from accumulated cursor drift / blit ghosting. Wall-clock
|
||||
* based (not frame-count) so drain scroll frames (250fps) don't
|
||||
* accelerate the cycle. Alt-screen doesn't need this — CSI H resets
|
||||
* cursor every frame. */
|
||||
private lastMainScreenHealTime = performance.now();
|
||||
private drainTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
private lastYogaCounters: {
|
||||
ms: number;
|
||||
@@ -521,7 +527,25 @@ export default class Ink {
|
||||
// an extra React re-render cycle.
|
||||
this.options.onBeforeRender?.();
|
||||
|
||||
// Periodic self-healing: every ~5s in main screen mode, force a full
|
||||
// terminal redraw to recover from accumulated cursor drift / blit
|
||||
// ghosting. Alt-screen doesn't need this — CSI H resets cursor to
|
||||
// (0,0) every frame. Wall-clock based so drain scroll frames (250fps)
|
||||
// don't accelerate the cycle. Guarded by isTTY so ANSI escape
|
||||
// sequences are not leaked into pipes / redirected output.
|
||||
const renderStart = performance.now();
|
||||
if (
|
||||
!this.altScreenActive &&
|
||||
!this.isPaused &&
|
||||
this.options.stdout.isTTY &&
|
||||
renderStart - this.lastMainScreenHealTime > 5000
|
||||
) {
|
||||
this.lastMainScreenHealTime = renderStart;
|
||||
this.repaint();
|
||||
this.prevFrameContaminated = true;
|
||||
this.needsEraseBeforePaint = true;
|
||||
}
|
||||
|
||||
const terminalWidth = this.options.stdout.columns || 80;
|
||||
const terminalRows = this.options.stdout.rows || 24;
|
||||
|
||||
@@ -725,6 +749,10 @@ export default class Ink {
|
||||
const optimized = optimize(diff);
|
||||
const optimizeMs = performance.now() - tOptimize;
|
||||
const hasDiff = optimized.length > 0;
|
||||
// Periodic self-healing: for main-screen mode, emit ERASE_SCREEN + HOME
|
||||
// to clear the terminal before the diff. Alt-screen has its own CSI H
|
||||
// anchor + cursor park below. BSU/ESU wraps erase+paint atomically on
|
||||
// supported terminals (main-screen always uses sync markers).
|
||||
if (this.altScreenActive && hasDiff) {
|
||||
// Prepend CSI H to anchor the physical cursor to (0,0) so
|
||||
// log-update's relative moves compute from a known spot (self-healing
|
||||
@@ -752,6 +780,13 @@ export default class Ink {
|
||||
optimized.unshift(CURSOR_HOME_PATCH);
|
||||
}
|
||||
optimized.push(this.altScreenParkPatch);
|
||||
} else if (this.needsEraseBeforePaint && hasDiff) {
|
||||
// Main-screen periodic self-healing: clear visible terminal before
|
||||
// painting the diff. Without this, rows past the new frame's height
|
||||
// would retain stale content from the previous frame. BSU/ESU keeps
|
||||
// old content visible until the full erase+paint is flushed atomically.
|
||||
this.needsEraseBeforePaint = false;
|
||||
optimized.unshift(ERASE_THEN_HOME_PATCH);
|
||||
}
|
||||
|
||||
// Native cursor positioning: park the terminal cursor at the declared
|
||||
|
||||
Reference in New Issue
Block a user