优化: token消息级持久化 + 技能注入修复 + TopBar减法/UI调

token持久化(方案A,治压缩/切会话后历史token不显):ChatMessage/AiMessageRecord 加 prompt_tokens/completion_tokens(serde + DB V38 迁移 + message_repo 映射);agentic push_assistant_message 设本轮 token + provider/title 构造默认 None;前端 AiMessage 加字段 + switchConversation reload 映射 tokenUsage(双轨:消息级新+会话级旧累计保留)

技能注入修复:read_skill_content_stripped 改 skills_cached 扫盘(防御 SKILLS None 致不注入)+ 细化诊断(缓存/path/fs 各步)

TopBar减法/UI:删铅笔新建(与侧栏+重复)/删垃圾桶clear-chat(危险,clear-context归档替代)/删系统就绪装饰占位;更多菜单popout CSS补全(修样式错乱);provider绿点有信息化(绿/红/灰基于AI请求成败)+垂直居中;goals面板补top:100%(修位置飘)+dot/check/remove CSS+goals/history item统一+history index边距;4面板互斥(点一个收其他)

MessageList token v-if 去 !streaming(修发新消息历史token消失)
This commit is contained in:
lxy
2026-08-02 18:17:30 +08:00
parent f736f435bc
commit 864c696b70
16 changed files with 244 additions and 113 deletions
+27 -1
View File
@@ -45,7 +45,7 @@ pub fn run(conn: &Connection) -> Result<()> {
// 什么数据库、Redis 在哪、有没有 MQ"的基础设施上下文。
// V33 = 审批重启恢复:ai_conversations 加 pending_approvals TEXT 列,持久化挂起审批快照,
// 重启后从 DB 恢复 pending_approvals 内存态,使待审批不丢。
let steps: [(i32, fn(&Connection) -> Result<()>); 37] = [
let steps: [(i32, fn(&Connection) -> Result<()>); 38] = [
(1, migrate_v1),
(2, migrate_v2),
(3, migrate_v3),
@@ -83,6 +83,7 @@ pub fn run(conn: &Connection) -> Result<()> {
(35, migrate_v35),
(36, migrate_v36),
(37, migrate_v37),
(38, migrate_v38),
];
for (version, migrate_fn) in steps {
@@ -1135,6 +1136,27 @@ fn migrate_v37(conn: &Connection) -> Result<()> {
Ok(())
}
/// V38: ai_messages 加 prompt_tokens / completion_tokens 列(消息级 token 持久化)
///
/// 解「压缩/切会话后历史 assistant 消息 token 不显」:原 token 仅前端内存态
/// (useAiEvents AiCompleted 设 tokenUsage),DB 仅会话级累计
/// (ai_conversations.prompt_tokens/completion_tokens)。本迁移加消息级两列,
/// 让 push_assistant_message 设的本轮 token 经 save_conversation → AiMessageRecord
/// 落库,前端 reload 时映射回 tokenUsage。NULL(老消息)→ 前端 tokenUsage=undefined(向前兼容)。
fn migrate_v38(conn: &Connection) -> Result<()> {
if !column_exists(conn, "ai_messages", "prompt_tokens") {
conn.execute("ALTER TABLE ai_messages ADD COLUMN prompt_tokens INTEGER", [])?;
tracing::info!("v38: ai_messages 加 prompt_tokens 列");
}
if !column_exists(conn, "ai_messages", "completion_tokens") {
conn.execute("ALTER TABLE ai_messages ADD COLUMN completion_tokens INTEGER", [])?;
tracing::info!("v38: ai_messages 加 completion_tokens 列");
}
conn.execute("INSERT INTO schema_version (version) VALUES (?)", [38])?;
tracing::info!("迁移 v38 完成: ai_messages 加消息级 token 列");
Ok(())
}
/// V21 建表 SQL — 消息拆分存储 ai_messages 表
///
/// 与 V9_SQL 中的 ai_messages 镜像(V9 给新库,此 const 给老库 V21 迁移用 IF NOT EXISTS)。
@@ -1154,6 +1176,8 @@ CREATE TABLE IF NOT EXISTS ai_messages (
reasoning_content TEXT,
timestamp INTEGER,
created_at TEXT NOT NULL,
prompt_tokens INTEGER,
completion_tokens INTEGER,
UNIQUE(conversation_id, seq)
);
@@ -1412,6 +1436,8 @@ CREATE TABLE IF NOT EXISTS ai_messages (
reasoning_content TEXT,
timestamp INTEGER,
created_at TEXT NOT NULL,
prompt_tokens INTEGER,
completion_tokens INTEGER,
UNIQUE(conversation_id, seq)
);