fix: 修复滚动限制 + 自动检测Shell类型

滚动修复:
- scroll() 使用实际渲染行数而非消息数计算 maxOffset
- 解决 /help 等多行输出无法滚动到顶部的问题

Shell 检测:
- Windows 自动检测 PowerShell 7+ > Windows PowerShell > cmd.exe
- 动态调整 BashTool 描述,告知AI使用正确的命令语法
- 系统提示词包含详细的 Shell 使用指南(PowerShell cmdlets)
- header 显示检测到的 Shell 类型
- Unix 优先 bash,回退 sh

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
abel533
2026-04-04 18:33:42 +08:00
co-authored by Copilot
parent e47a3445df
commit a30dfa9ad0
3 changed files with 156 additions and 17 deletions
@@ -6,6 +6,7 @@ import com.claudecode.console.BannerPrinter;
import com.claudecode.core.AgentLoop;
import com.claudecode.core.TokenTracker;
import com.claudecode.tool.ToolRegistry;
import com.claudecode.tool.impl.BashTool;
import com.claudecode.tui.UIMessage.*;
import io.mybatis.jink.component.*;
import io.mybatis.jink.input.Key;
@@ -92,6 +93,9 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
private volatile boolean askInputMode = false; // 是否在自由输入模式(选择"其他"后)
private volatile String askQuestion; // 当前问题文本
/** 最近一次渲染的总行数(用于滚动限制) */
private volatile int lastRenderedItemCount = 0;
/** 首次用户输入回调(用于 conversation summary */
private Consumer<String> onFirstUserInput;
@@ -226,8 +230,8 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
Text.of(
Text.of("Tools: ").dimmed(),
Text.of(String.valueOf(toolCount)).color(Color.BRIGHT_CYAN),
Text.of("Commands: ").dimmed(),
Text.of(String.valueOf(cmdCount)).color(Color.BRIGHT_CYAN)
Text.of("Shell: ").dimmed(),
Text.of(BashTool.getDetectedShellName()).color(Color.BRIGHT_CYAN)
)
};
@@ -283,6 +287,9 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
));
}
// 记录总行数(供 scroll() 使用)
lastRenderedItemCount = allItems.size();
// 虚拟滚动
List<Renderable> visibleItems;
if (maxLines > 0 && allItems.size() > maxLines) {
@@ -984,8 +991,8 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
// ==================== 滚动 ====================
private void scroll(TuiState s, int delta) {
int totalMessages = s.messages.size() + 1; // +1 for initial system msg
int maxOffset = Math.max(0, totalMessages - 1);
int totalItems = lastRenderedItemCount;
int maxOffset = Math.max(0, totalItems - 1);
int newOffset = Math.max(0, Math.min(s.scrollOffset + delta, maxOffset));
setState(new TuiState(s.inputText, s.messages, newOffset, s.thinking, s.thinkingText));
}