feat: 多层上下文压缩 + 多级权限管理系统
权限管理: - PermissionTypes: 权限行为/模式/规则/决策/选择类型系统 - PermissionSettings: 用户级/项目级/会话级权限持久化(settings.json) - PermissionRuleEngine: 多层规则引擎(deny→allow→readOnly→mode→dangerous→ASK) - DangerousPatterns: 危险shell命令检测(rm -rf, eval, exec等) - ReplSession: Y/A/N/D四选项权限确认UI - ConfigCommand: permission-mode/list/reset子命令 - AgentLoop: 集成规则引擎,PermissionChoice回调 上下文压缩: - TokenTracker: 上下文窗口监控(93%自动压缩/82%警告/98%阻塞) - MicroCompact: 微压缩,裁剪旧tool_result(无API调用) - SessionMemoryCompact: Session Memory压缩,AI摘要旧消息保留近期段 - FullCompact: 全量压缩+PTL重试(按API Round逐步丢弃) - AutoCompactManager: 压缩编排器(micro→session→full),含熔断机制 - CompactCommand: 改造为委托FullCompact - StatusLine: token使用百分比+颜色告警(绿→黄→红→闪烁) - AppConfig: 注册PermissionSettings/RuleEngine/AutoCompactManager Bean Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,9 @@ package com.claudecode.command.impl;
|
||||
import com.claudecode.command.CommandContext;
|
||||
import com.claudecode.command.SlashCommand;
|
||||
import com.claudecode.console.AnsiStyle;
|
||||
import com.claudecode.permission.PermissionRuleEngine;
|
||||
import com.claudecode.permission.PermissionSettings;
|
||||
import com.claudecode.permission.PermissionTypes.PermissionMode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -10,8 +13,7 @@ import java.util.Map;
|
||||
/**
|
||||
* /config 命令 —— 查看和设置应用配置。
|
||||
* <p>
|
||||
* 支持查看当前配置、设置单个配置项。
|
||||
* 配置变更仅在当前会话内生效。
|
||||
* 支持查看当前配置、设置单个配置项,以及权限管理子命令。
|
||||
*/
|
||||
public class ConfigCommand implements SlashCommand {
|
||||
|
||||
@@ -21,9 +23,24 @@ public class ConfigCommand implements SlashCommand {
|
||||
"max-tokens", "Maximum output tokens per response",
|
||||
"temperature", "Response randomness (0.0-1.0)",
|
||||
"verbose", "Enable verbose logging (true/false)",
|
||||
"auto-compact", "Auto compact when context is large (true/false)"
|
||||
"auto-compact", "Auto compact when context is large (true/false)",
|
||||
"permission-mode", "Permission mode: default/accept-edits/bypass/dont-ask",
|
||||
"permission-list", "List all saved permission rules",
|
||||
"permission-reset", "Clear all permission rules"
|
||||
);
|
||||
|
||||
private PermissionSettings permissionSettings;
|
||||
|
||||
public ConfigCommand() {}
|
||||
|
||||
public ConfigCommand(PermissionSettings permissionSettings) {
|
||||
this.permissionSettings = permissionSettings;
|
||||
}
|
||||
|
||||
public void setPermissionSettings(PermissionSettings settings) {
|
||||
this.permissionSettings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "config";
|
||||
@@ -90,17 +107,6 @@ public class ConfigCommand implements SlashCommand {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String showConfig(String key, CommandContext context) {
|
||||
if (!CONFIG_KEYS.containsKey(key)) {
|
||||
return AnsiStyle.yellow(" ⚠ Unknown config key: " + key) + "\n"
|
||||
+ AnsiStyle.dim(" Available: " + String.join(", ", CONFIG_KEYS.keySet()));
|
||||
}
|
||||
|
||||
String desc = CONFIG_KEYS.get(key);
|
||||
return " " + AnsiStyle.bold(key) + ": " + AnsiStyle.dim(desc) + "\n"
|
||||
+ AnsiStyle.dim(" Set with: /config " + key + " <value>");
|
||||
}
|
||||
|
||||
private String setConfig(String key, String value, CommandContext context) {
|
||||
return switch (key) {
|
||||
case "model" -> {
|
||||
@@ -112,6 +118,9 @@ public class ConfigCommand implements SlashCommand {
|
||||
boolean verbose = Boolean.parseBoolean(value);
|
||||
yield AnsiStyle.green(" ✅ Verbose mode: " + (verbose ? "ON" : "OFF"));
|
||||
}
|
||||
case "permission-mode" -> setPermissionMode(value);
|
||||
case "permission-list" -> listPermissionRules();
|
||||
case "permission-reset" -> resetPermissionRules();
|
||||
default -> {
|
||||
if (!CONFIG_KEYS.containsKey(key)) {
|
||||
yield AnsiStyle.yellow(" ⚠ Unknown config key: " + key);
|
||||
@@ -121,4 +130,69 @@ public class ConfigCommand implements SlashCommand {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private String showConfig(String key, CommandContext context) {
|
||||
// 无参数的权限子命令
|
||||
if (key.equals("permission-list")) return listPermissionRules();
|
||||
if (key.equals("permission-reset")) return resetPermissionRules();
|
||||
|
||||
if (!CONFIG_KEYS.containsKey(key)) {
|
||||
return AnsiStyle.yellow(" ⚠ Unknown config key: " + key) + "\n"
|
||||
+ AnsiStyle.dim(" Available: " + String.join(", ", CONFIG_KEYS.keySet()));
|
||||
}
|
||||
|
||||
String desc = CONFIG_KEYS.get(key);
|
||||
return " " + AnsiStyle.bold(key) + ": " + AnsiStyle.dim(desc) + "\n"
|
||||
+ AnsiStyle.dim(" Set with: /config " + key + " <value>");
|
||||
}
|
||||
|
||||
// ── 权限管理子命令 ──
|
||||
|
||||
private String setPermissionMode(String value) {
|
||||
if (permissionSettings == null) {
|
||||
return AnsiStyle.yellow(" ⚠ Permission settings not initialized");
|
||||
}
|
||||
try {
|
||||
PermissionMode mode = switch (value.toLowerCase()) {
|
||||
case "default" -> PermissionMode.DEFAULT;
|
||||
case "accept-edits", "acceptedits" -> PermissionMode.ACCEPT_EDITS;
|
||||
case "bypass" -> PermissionMode.BYPASS;
|
||||
case "dont-ask", "dontask" -> PermissionMode.DONT_ASK;
|
||||
default -> throw new IllegalArgumentException(value);
|
||||
};
|
||||
permissionSettings.setCurrentMode(mode);
|
||||
return AnsiStyle.green(" ✅ Permission mode set to: " + mode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return AnsiStyle.yellow(" ⚠ Unknown mode: " + value) + "\n"
|
||||
+ AnsiStyle.dim(" Available: default, accept-edits, bypass, dont-ask");
|
||||
}
|
||||
}
|
||||
|
||||
private String listPermissionRules() {
|
||||
if (permissionSettings == null) {
|
||||
return AnsiStyle.yellow(" ⚠ Permission settings not initialized");
|
||||
}
|
||||
var rules = permissionSettings.listRules();
|
||||
if (rules.isEmpty()) {
|
||||
return AnsiStyle.dim(" No saved permission rules") + "\n"
|
||||
+ AnsiStyle.dim(" Mode: " + permissionSettings.getCurrentMode());
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\n");
|
||||
sb.append(AnsiStyle.bold(" 🔒 Permission Rules")).append("\n");
|
||||
sb.append(" ").append("─".repeat(40)).append("\n");
|
||||
sb.append(" ").append(AnsiStyle.bold("Mode: ")).append(permissionSettings.getCurrentMode()).append("\n\n");
|
||||
for (String rule : rules) {
|
||||
sb.append(" ").append(rule).append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String resetPermissionRules() {
|
||||
if (permissionSettings == null) {
|
||||
return AnsiStyle.yellow(" ⚠ Permission settings not initialized");
|
||||
}
|
||||
permissionSettings.clearAll();
|
||||
return AnsiStyle.green(" ✅ All permission rules cleared");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user