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>
This commit is contained in:
@@ -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(),
|
||||||
|
|||||||
Reference in New Issue
Block a user