refactor: extract utility classes and split AppConfig

- CommandUtils: shared formatting (header, separator, formatBytes, formatDuration, progressBar, truncate)
- ToolValidator: input validation (requireString, getString, getInt, getBoolean, validatePathInWorkDir)
- ProcessExecutor: consolidated ProcessBuilder with timeout, cleanup, shell execution
- AbstractReadOnlyTool: base class for read-only tools
- Split AppConfig -> ToolConfiguration + CommandConfiguration + AppConfig (core)
- Applied CommandUtils to 16 command files, removed duplicated private methods
- Applied ToolValidator + ProcessExecutor to NotificationTool

Net: -403 lines removed, 87 tests still passing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
abel533
2026-04-05 12:32:49 +08:00
co-authored by Copilot
parent 5929f50b3a
commit 80f43480c1
24 changed files with 719 additions and 403 deletions
@@ -1,6 +1,7 @@
package com.claudecode.command.impl;
import com.claudecode.command.CommandContext;
import com.claudecode.command.CommandUtils;
import com.claudecode.command.SlashCommand;
import com.claudecode.console.AnsiStyle;
import com.claudecode.core.TokenTracker;
@@ -29,9 +30,7 @@ public class CostCommand implements SlashCommand {
int msgCount = context.agentLoop().getMessageHistory().size();
StringBuilder sb = new StringBuilder();
sb.append("\n");
sb.append(AnsiStyle.bold(" 💰 Token Usage & Cost\n"));
sb.append(" ").append("".repeat(40)).append("\n\n");
sb.append(CommandUtils.header("💰", "Token Usage & Cost"));
sb.append(" ").append(AnsiStyle.bold("Model: ")).append(AnsiStyle.cyan(tracker.getModelName())).append("\n");
sb.append(" ").append(AnsiStyle.bold("API Calls: ")).append(tracker.getApiCallCount()).append("\n");
@@ -47,7 +46,7 @@ public class CostCommand implements SlashCommand {
sb.append(" ").append(AnsiStyle.bold("Cache create: ")).append(formatTokenLine(tracker.getCacheCreationTokens())).append("\n");
}
sb.append(" ").append("".repeat(30)).append("\n");
sb.append(CommandUtils.separator(30)).append("\n");
sb.append(" ").append(AnsiStyle.bold("Total: ")).append(TokenTracker.formatTokens(tracker.getTotalTokens())).append(" tokens\n");
sb.append(" ").append(AnsiStyle.bold("Est. Cost: ")).append(AnsiStyle.green("$" + String.format("%.4f", tracker.estimateCost()))).append("\n");