package com.claudecode.command.impl;
import com.claudecode.command.CommandContext;
import com.claudecode.command.SlashCommand;
import com.claudecode.console.AnsiStyle;
import java.util.List;
import java.util.Map;
/**
* /model 命令 —— 显示或切换当前 AI 模型。
*
* 支持查看当前模型信息和切换到其他模型。
*/
public class ModelCommand implements SlashCommand {
private static final Map AVAILABLE_MODELS = Map.of(
"sonnet", "claude-sonnet-4-20250514",
"opus", "claude-opus-4-20250514",
"haiku", "claude-haiku-4-20250514",
"sonnet-3.5", "claude-3-5-sonnet-20241022"
);
@Override
public String name() {
return "model";
}
@Override
public String description() {
return "Show or switch AI model";
}
@Override
public List aliases() {
return List.of("m");
}
@Override
public String execute(String args, CommandContext context) {
if (args == null || args.isBlank()) {
return showCurrentModel(context);
}
return switchModel(args.strip(), context);
}
private String showCurrentModel(CommandContext context) {
String currentModel = context.agentLoop().getTokenTracker().getModelName();
StringBuilder sb = new StringBuilder();
sb.append("\n");
sb.append(AnsiStyle.bold(" 🤖 Model Configuration\n"));
sb.append(" ").append("─".repeat(40)).append("\n\n");
sb.append(" Current: ").append(AnsiStyle.cyan(currentModel)).append("\n\n");
sb.append(AnsiStyle.dim(" Available shortcuts:\n"));
for (var entry : AVAILABLE_MODELS.entrySet()) {
String marker = entry.getValue().equals(currentModel) ? " ◀" : "";
sb.append(AnsiStyle.dim(" " + entry.getKey() + " → " + entry.getValue() + marker)).append("\n");
}
sb.append("\n");
sb.append(AnsiStyle.dim(" Usage: /model (e.g., /model opus, /model claude-3-5-sonnet-20241022)"));
return sb.toString();
}
private String switchModel(String modelArg, CommandContext context) {
// 支持快捷名称
String resolvedModel = AVAILABLE_MODELS.getOrDefault(modelArg.toLowerCase(), modelArg);
String oldModel = context.agentLoop().getTokenTracker().getModelName();
context.agentLoop().getTokenTracker().setModel(resolvedModel);
StringBuilder sb = new StringBuilder();
sb.append(AnsiStyle.green(" ✅ Model switched")).append("\n");
sb.append(" From: ").append(AnsiStyle.dim(oldModel)).append("\n");
sb.append(" To: ").append(AnsiStyle.cyan(resolvedModel)).append("\n");
sb.append(AnsiStyle.dim(" Note: Changes take effect on next API call."));
sb.append("\n").append(AnsiStyle.dim(" Note: Runtime model switch only updates pricing. Actual API model is set in application.yml."));
return sb.toString();
}
}