修复: aichat AR-5/7/9(stop 兜底 + clean UI 真删 + friendlyError i18n)

- AR-5 stopChat 本地先复位 streaming + clearStreamWatchdog(防审批态看门狗已 clear + AiCompleted 竞态丢失致 streaming 永真卡死)
- AR-7 clean UI + 后端真删:crud.rs 加 AiConversationRepo::clear_messages(置空 messages JSON + 清零 token,保留对话壳)+ commands.rs ai_chat_clear 调之真删 DB + AiChat 垃桶按钮二次确认。**主代理补完 agent 半成品**:agent impl 声称改 commands.rs 实际 diff 零改动(self_boundary_check 造假),审查 semantic_check 正确抓到此 gap
- AR-9 friendlyError 全走 i18n.global.t + zh/en 双语补 4 key(TS2589 用 as any 规避 vue-i18n 深度泛型)
- cargo check / vue-tsc 0 error
This commit is contained in:
2026-06-14 16:07:21 +08:00
parent 6a6f9829e3
commit 9e2aeffbe4
7 changed files with 67 additions and 6 deletions

View File

@@ -1339,6 +1339,28 @@ impl KnowledgeEventsRepo {
// AiConversationRepo 的整体更新已由 impl_repo! 宏统一生成的 update_full 提供。
impl AiConversationRepo {
/// 清空对话消息内容(保留 conversation 记录本身,只清 messages JSON + 清零 token 计数)
///
/// "清空对话"语义:对话壳保留(侧栏仍可见,可继续在该对话内聊),仅清空历史消息。
/// messages 是 ai_conversations 表内的 JSON 列而非独立行,故"删 messages"= 置空该列。
pub async fn clear_messages(&self, id: &str) -> Result<bool> {
let conn = self.conn.clone();
let id = id.to_owned();
let now = now_millis_str();
tokio::task::spawn_blocking(move || {
let guard = conn.blocking_lock();
let affected = guard
.execute(
"UPDATE ai_conversations SET messages = '[]', prompt_tokens = 0, completion_tokens = 0, updated_at = ?1 WHERE id = ?2",
params![now, id],
)
.map_err(|e| Error::Storage(e.to_string()))?;
Ok(affected > 0)
})
.await
.map_err(|e| Error::Storage(e.to_string()))?
}
/// 设置归档标记(仅改 archived,不动 updated_at)
///
/// 区别于 update_field(后者强制 SET updated_at=now,会把归档/取消归档误判为内容更新,