fix: improve command handling and add paste support

- Add ToolRegistry to ClaudeCodeComponent for proper command context
- Use ByteArrayOutputStream to capture command output in TUI mode
- Add onPaste() override for efficient multi-line paste handling
- Fix constructor to accept toolRegistry parameter

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pull/1/head
abel533 1 month ago
parent 199ad6259b
commit 45283c87e4
  1. 34
      src/main/java/com/claudecode/tui/ClaudeCodeComponent.java
  2. 1
      src/main/java/com/claudecode/tui/JinkReplSession.java

@ -5,12 +5,16 @@ import com.claudecode.command.CommandRegistry;
import com.claudecode.console.BannerPrinter; import com.claudecode.console.BannerPrinter;
import com.claudecode.core.AgentLoop; import com.claudecode.core.AgentLoop;
import com.claudecode.core.TokenTracker; import com.claudecode.core.TokenTracker;
import com.claudecode.tool.ToolRegistry;
import com.claudecode.tui.UIMessage.*; import com.claudecode.tui.UIMessage.*;
import io.mybatis.jink.component.*; import io.mybatis.jink.component.*;
import io.mybatis.jink.input.Key; import io.mybatis.jink.input.Key;
import io.mybatis.jink.style.*; import io.mybatis.jink.style.*;
import io.mybatis.jink.util.StringWidth; import io.mybatis.jink.util.StringWidth;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -57,6 +61,7 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
// --- 外部依赖(通过构造器注入) --- // --- 外部依赖(通过构造器注入) ---
private final AgentLoop agentLoop; private final AgentLoop agentLoop;
private final CommandRegistry commandRegistry; private final CommandRegistry commandRegistry;
private final ToolRegistry toolRegistry;
private final String provider; private final String provider;
private final String model; private final String model;
private final String baseUrl; private final String baseUrl;
@ -79,6 +84,7 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
public ClaudeCodeComponent(AgentLoop agentLoop, public ClaudeCodeComponent(AgentLoop agentLoop,
CommandRegistry commandRegistry, CommandRegistry commandRegistry,
ToolRegistry toolRegistry,
String provider, String model, String baseUrl, String provider, String model, String baseUrl,
int toolCount, int cmdCount, int toolCount, int cmdCount,
TokenTracker tokenTracker, TokenTracker tokenTracker,
@ -86,6 +92,7 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
super(TuiState.empty()); super(TuiState.empty());
this.agentLoop = agentLoop; this.agentLoop = agentLoop;
this.commandRegistry = commandRegistry; this.commandRegistry = commandRegistry;
this.toolRegistry = toolRegistry;
this.provider = provider; this.provider = provider;
this.model = model; this.model = model;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
@ -468,6 +475,14 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
} }
} }
@Override
public void onPaste(String text) {
if (agentRunning.get() || text == null || text.isEmpty()) return;
TuiState s = getState();
abandonHistoryPreview();
setState(new TuiState(s.inputText + text, s.messages, s.scrollOffset, false, ""));
}
/** 处理权限确认输入 */ /** 处理权限确认输入 */
private void handlePermissionInput(String input, Key key, TuiState s) { private void handlePermissionInput(String input, Key key, TuiState s) {
if (key.return_()) { if (key.return_()) {
@ -501,12 +516,25 @@ public class ClaudeCodeComponent extends Component<ClaudeCodeComponent.TuiState>
// 斜杠命令 // 斜杠命令
if (commandRegistry != null && commandRegistry.isCommand(text)) { if (commandRegistry != null && commandRegistry.isCommand(text)) {
addMessage(new UserMsg(text)); addMessage(new UserMsg(text));
CommandContext cmdCtx = new CommandContext(agentLoop, null, commandRegistry, // 捕获命令输出到 ByteArrayOutputStream
new java.io.PrintStream(java.io.OutputStream.nullOutputStream()), () -> { var baos = new ByteArrayOutputStream();
var capturedOut = new PrintStream(baos, true, StandardCharsets.UTF_8);
CommandContext cmdCtx = new CommandContext(agentLoop, toolRegistry, commandRegistry,
capturedOut, () -> {
if (onExit != null) onExit.run(); if (onExit != null) onExit.run();
}); });
Optional<String> result = commandRegistry.dispatch(text, cmdCtx); Optional<String> result = commandRegistry.dispatch(text, cmdCtx);
result.ifPresent(r -> addMessage(new CommandOutputMsg(r))); // 合并 dispatch 返回值和 capturedOut 的内容
StringBuilder output = new StringBuilder();
result.ifPresent(output::append);
String captured = baos.toString(StandardCharsets.UTF_8);
if (!captured.isBlank()) {
if (!output.isEmpty()) output.append("\n");
output.append(captured);
}
if (!output.isEmpty()) {
addMessage(new CommandOutputMsg(output.toString()));
}
setState(new TuiState("", getState().messages, 0, false, "")); setState(new TuiState("", getState().messages, 0, false, ""));
return; return;
} }

@ -74,6 +74,7 @@ public class JinkReplSession {
component = new ClaudeCodeComponent( component = new ClaudeCodeComponent(
agentLoop, agentLoop,
commandRegistry, commandRegistry,
toolRegistry,
providerInfo.provider(), providerInfo.provider(),
providerInfo.model(), providerInfo.model(),
providerInfo.baseUrl(), providerInfo.baseUrl(),

Loading…
Cancel
Save