fix: CLI交互优化 - 流式缩进+输入框横线+日志降噪

- 流式输出: ● 标识与文本同行,续行4空格缩进对齐
- 输入框: 上下横线(─)分隔输入区域,宽度自适应终端
- 日志: 工具异常日志降为debug级别,避免终端输出stack trace

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pull/1/head
liuzh 1 month ago
parent 1e35cbe222
commit e3f60a5933
  1. 32
      src/main/java/com/claudecode/repl/ReplSession.java
  2. 2
      src/main/java/com/claudecode/tool/impl/AgentTool.java
  3. 2
      src/main/java/com/claudecode/tool/impl/AskUserQuestionTool.java
  4. 2
      src/main/java/com/claudecode/tool/impl/WebSearchTool.java

@ -192,9 +192,17 @@ public class ReplSession {
statusLine.enable(providerInfo.model(), agentLoop.getTokenTracker()); statusLine.enable(providerInfo.model(), agentLoop.getTokenTracker());
} }
// 输入框横线宽度
int termWidth = terminal.getWidth();
int lineWidth = termWidth > 10 ? termWidth - 2 : 78;
String inputLine = AnsiStyle.DIM + "─".repeat(lineWidth) + AnsiStyle.RESET;
CommandContext cmdContext = new CommandContext(agentLoop, toolRegistry, commandRegistry, out, () -> running = false); CommandContext cmdContext = new CommandContext(agentLoop, toolRegistry, commandRegistry, out, () -> running = false);
while (running) { while (running) {
// 输入框上横线
out.println(inputLine);
String input; String input;
try { try {
input = reader.readLine(prompt).strip(); input = reader.readLine(prompt).strip();
@ -206,6 +214,9 @@ public class ReplSession {
break; break;
} }
// 输入框下横线
out.println(inputLine);
if (input.isEmpty()) { if (input.isEmpty()) {
continue; continue;
} }
@ -317,12 +328,25 @@ public class ReplSession {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// AI 回复前的 ● 标识 // AI 回复前的 ● 标识(不换行,后续流式文本紧跟其后)
out.println(AnsiStyle.BRIGHT_CYAN + " ● " + AnsiStyle.RESET); out.print(AnsiStyle.BRIGHT_CYAN + " ● " + AnsiStyle.RESET);
// 流式回调:逐 token 输出到终端 // 流式回调:逐 token 输出到终端,自动在每行开头加缩进
final boolean[] isNewLine = {false}; // 跟踪是否刚输出换行符
String response = agentLoop.runStreaming(input, token -> { String response = agentLoop.runStreaming(input, token -> {
out.print(token); for (int i = 0; i < token.length(); i++) {
char c = token.charAt(i);
if (c == '\n') {
out.println();
isNewLine[0] = true;
} else {
if (isNewLine[0]) {
out.print(" "); // 续行缩进(与 ● 后文本对齐)
isNewLine[0] = false;
}
out.print(c);
}
}
out.flush(); out.flush();
}); });

@ -92,7 +92,7 @@ public class AgentTool implements Tool {
log.info("Sub-agent completed, result length: {} chars", result.length()); log.info("Sub-agent completed, result length: {} chars", result.length());
return result; return result;
} catch (Exception e) { } catch (Exception e) {
log.error("Sub-agent execution failed", e); log.debug("Sub-agent execution failed", e);
return "Error: Sub-agent failed: " + e.getMessage(); return "Error: Sub-agent failed: " + e.getMessage();
} }
} }

@ -119,7 +119,7 @@ public class AskUserQuestionTool implements Tool {
return "User response: " + userResponse; return "User response: " + userResponse;
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to get user input", e); log.debug("Failed to get user input", e);
return "Error: Failed to get user input - " + e.getMessage(); return "Error: Failed to get user input - " + e.getMessage();
} }
} }

@ -92,7 +92,7 @@ public class WebSearchTool implements Tool {
String html = fetchSearchPage(query); String html = fetchSearchPage(query);
return parseResults(html, maxResults); return parseResults(html, maxResults);
} catch (Exception e) { } catch (Exception e) {
log.error("Search failed: query={}", query, e); log.debug("Search failed: query={}", query, e);
return "Error: Search failed - " + e.getMessage(); return "Error: Search failed - " + e.getMessage();
} }
} }

Loading…
Cancel
Save