release: v8.0.4 — 会话 SQLite 存储 + 去加载动画 + 展示截断 + 工具调用解析加固

- 会话数据改用 SQLite(chat_history/conversations.db,WAL):sessions / snapshots 两表,
  首次启动自动迁移旧 JSON,/chat 与 /resume 改走 SQLite,memory 搜索兼容数据库
- 去掉流式显示(_typeprint 改整段打印)与常驻加载动画(移除 show_animation 线程及逐帧输出)
- 展示给用户的消息过长自动截断(仅展示层,底层 messages 完整保存)
- 工具调用解析加固:_loads_json 四级兜底修复;新增 _extract_last_action_json 成对错括号扫描;
  续轮也下发 Function Calling 工具,减少长文本格式错误浪费 token
- 版本号统一更新至 8.0.4(README/about.txt/constants/TUI banner/LSP·MCP clientInfo)
- 12 项 session 单测 + 8 项 JSON 提取边界用例全部通过

Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
This commit is contained in:
shuiyu67andWorkBuddy committed 2026-08-08 00:54:18 +08:00
1 parent 66de8eea13
commit 749fb3f91c
15 files changed
+510 -249

No files matched your search

+37 -1
View File
@@ -248,7 +248,7 @@ class MemoryManager:
md_file, keyword_lower, name, limit - len(results)
))
# 搜索聊天记录
# 搜索聊天记录(遗留 JSON 文件,兼容迁移前的历史)
for json_file in sorted(glob.glob(os.path.join(self.chat_dir, "*.json")), reverse=True):
if len(results) >= limit:
break
@@ -257,6 +257,42 @@ class MemoryManager:
json_file, keyword_lower, name, limit - len(results)
))
# 搜索聊天记录(SQLite conversations.db,迁移后的主存储)
db_path = os.path.join(self.chat_dir, "conversations.db")
if os.path.exists(db_path):
try:
import sqlite3 as _sqlite3
conn = _sqlite3.connect(db_path)
conn.row_factory = _sqlite3.Row
rows = conn.execute(
"SELECT id, messages FROM sessions "
"UNION ALL SELECT name AS id, messages FROM snapshots"
).fetchall()
conn.close()
for row in rows:
if len(results) >= limit:
break
try:
msgs = json.loads(row["messages"] or "[]")
except (json.JSONDecodeError, ValueError, TypeError):
msgs = []
text = "\n".join(
str(m.get("content", "")) for m in msgs
if isinstance(m, dict)
)
source = f"chat/{row['id']}"
for i, line in enumerate(text.split("\n"), 1):
if keyword_lower in line.lower():
results.append({
"source": source,
"line": i,
"snippet": line.strip()[:120],
})
if len(results) >= limit:
break
except Exception:
pass
return results[:limit]
def _search_file(self, path: str, keyword: str, source: str, limit: int) -> List[Dict]: