feat(v8.0): 基于 v5.4.1 重构立项 v8.0.0

- 版本立项: constants.VERSION=8.0.0,about.txt/README 同步。
- Rich 面板式 TUI (xcli_core/rich_tui.py): 默认 TUI 渲染器,rich 驱动;
  核心创新=快照出口(Console(record=True) -> text/svg/html),AI 开发界面
  时可把渲染读回自验,补上'看不见渲染'闭环。tools/tui_snapshot.py 无头生成
  演示快照。run_tui 优先 RichTUI,textual 作为回退。
- Token 感知压缩: openai_engine 捕获 usage.prompt_tokens -> last_prompt_tokens,
  新增 context_window()(模型名查表 MODEL_CONTEXT_WINDOWS + config 覆盖);
  memory.should_compress 升级为 token 感知(used/context_window >= ratio 触发,
  默认 0.7),消息数阈值兜底;cli_core.process_conversation 自动压缩并提示。
- 记忆模式增强: 保留 v5.4.1 的 MEMORY.md/日记/自动保存/AI 摘要压缩,新增
  /compress 手动压缩 与 /memory mode <companion|work> 切换。
- requirements 加 rich;.gitignore 忽略 .tui_snapshots/。
This commit is contained in:
shuiyu67 committed 2026-08-01 09:28:39 +08:00
1 parent b8faaae0c6
commit 79957eba0f
10 files changed
+359 -25

No files matched your search

+24 -3
View File
@@ -22,7 +22,8 @@ class MemoryManager:
self.memory_dir = os.path.join(project_dir, "memory")
self.memory_file = os.path.join(project_dir, "MEMORY.md")
self.chat_dir = os.path.join(project_dir, "chat_history")
self.compress_threshold = 50 # 超过 50 条消息触发压缩
self.compress_threshold = 50 # 超过 50 条消息触发压缩(兜底)
self.compress_ratio = 0.7 # token 感知压缩阈值:used/context_window >= 0.7 触发
self._ensure_dirs()
def _ensure_dirs(self):
@@ -299,8 +300,28 @@ class MemoryManager:
# 上下文压缩
# ══════════════════════════════════════════════
def should_compress(self, conversation: list) -> bool:
"""判断是否需要压缩上下文"""
def set_compress_ratio(self, ratio: float):
"""设置 token 感知压缩阈值(0~1)"""
try:
self.compress_ratio = float(ratio)
except (TypeError, ValueError):
pass
def should_compress(self, conversation: list, prompt_tokens=None, context_window=None, ratio=None) -> bool:
"""
判断是否需要压缩上下文。
优先级:
1. token 感知: prompt_tokens/context_window >= ratio 触发(OpenAI 格式可拿到真实 token 数)
2. 兜底: 消息数超过 compress_threshold
"""
if ratio is None:
ratio = self.compress_ratio
if prompt_tokens and context_window:
try:
if int(context_window) > 0 and (int(prompt_tokens) / int(context_window)) >= ratio:
return True
except (TypeError, ValueError):
pass
return len(conversation) > self.compress_threshold
def compress_context(self, conversation: list, engine=None) -> list: