新增: 压缩失败降级前端透出与vite看门修复
- E2:LLM压缩失败走关键词摘要兜底时新发AiContextDegraded事件, 前端toast「上下文已降级」不再静默失忆(实证76730ce8 seq166 用户被迫原句重发);不发AiError防误判生成结束 - keyword_fallback_commit返回inserted供emit判定,双调用点 (LLM失败/provider重建失败)透出 - vite watch忽略target/:cargo编译写.o触发EBUSY杀掉dev进程 验收:cargo check 0 error;keyword_fallback 3 passed;vue-tsc EXIT 0
This commit is contained in:
@@ -270,7 +270,7 @@ pub(super) async fn maybe_auto_compress(
|
||||
);
|
||||
// 复位 is_compressing 收口进 keyword_fallback_commit 单锁(909①-补:
|
||||
// 原先此处单独取锁复位,与提交之间留并发二次压缩窗口)。
|
||||
keyword_fallback_commit(
|
||||
let degraded = keyword_fallback_commit(
|
||||
&session_arc,
|
||||
&conv_id,
|
||||
protect_start,
|
||||
@@ -281,6 +281,16 @@ pub(super) async fn maybe_auto_compress(
|
||||
recall_on.then_some(data_dir.as_path()),
|
||||
)
|
||||
.await;
|
||||
// E2:降级不再静默(实证 76730ce8 seq166 用户被迫原句重发)
|
||||
if degraded {
|
||||
emit_ai_chat_event(
|
||||
&app_handle,
|
||||
AiChatEvent::AiContextDegraded {
|
||||
conversation_id: Some(conv_id.to_string()),
|
||||
reason: "压缩 provider 重建失败,已降级为关键词摘要".into(),
|
||||
},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -384,7 +394,7 @@ pub(super) async fn maybe_auto_compress(
|
||||
"[ai] 自动压缩失败(后台),降级走关键词摘要兜底(KEYWORD_FALLBACK_ENABLED={})",
|
||||
KEYWORD_FALLBACK_ENABLED,
|
||||
);
|
||||
keyword_fallback_commit(
|
||||
let degraded = keyword_fallback_commit(
|
||||
&session_arc,
|
||||
&conv_id,
|
||||
protect_start,
|
||||
@@ -395,6 +405,17 @@ pub(super) async fn maybe_auto_compress(
|
||||
recall_on.then_some(data_dir.as_path()),
|
||||
)
|
||||
.await;
|
||||
// E2:降级不再静默——AiError 语义是生成结束,此处 loop 仍在跑,
|
||||
// 用专用事件让前端透出降级状态条/提示(不打断流)
|
||||
if degraded {
|
||||
emit_ai_chat_event(
|
||||
&app_handle,
|
||||
AiChatEvent::AiContextDegraded {
|
||||
conversation_id: Some(conv_id.to_string()),
|
||||
reason: "LLM 压缩失败,已降级为关键词摘要".into(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}) // 闭 catch_unwind 内 async move
|
||||
@@ -444,11 +465,11 @@ async fn keyword_fallback_commit(
|
||||
log_head: &str,
|
||||
head_id: &Option<String>,
|
||||
recall: Option<&Path>,
|
||||
) {
|
||||
) -> bool {
|
||||
let inserted = {
|
||||
let mut session = session_arc.lock().await;
|
||||
if !session.per_conv.contains_key(conv_id) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let conv = session.conv(conv_id);
|
||||
// 939⑪ 内容版本守卫:上下文已被整体替换 → 丢弃兜底提交(标志亦不复位)。
|
||||
@@ -458,7 +479,7 @@ async fn keyword_fallback_commit(
|
||||
"[ai] {}兜底提交前上下文版本已变(疑似 clear 重建),丢弃",
|
||||
log_head
|
||||
);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// 复位与提交同锁原子(909①-补):消「锁外复位→再取锁提交」之间的并发二次压缩窗口。
|
||||
conv.messages.set_compressing(false);
|
||||
@@ -495,6 +516,7 @@ async fn keyword_fallback_commit(
|
||||
log_head
|
||||
);
|
||||
}
|
||||
inserted
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -317,6 +317,11 @@ pub enum AiChatEvent {
|
||||
/// 摘要 system 消息已由后端 insert_at,后续 stream 自然带出,无需整会话刷新。
|
||||
/// miniapp 仍插摘要气泡(对端发生压缩告知用户)。
|
||||
AiAutoCompressed { conversation_id: Option<String>, summary: String },
|
||||
/// E2 压缩失败降级透出(2026-10-18):LLM 压缩失败走关键词摘要兜底时,loop 仍在继续
|
||||
/// (不发 AiError——其 case 无条件 setStreaming(false) 会误判生成结束),但用户须知晓
|
||||
/// 上下文已降级(实证 76730ce8 seq166:静默降级→AI 失忆→用户被迫原句重发)。
|
||||
/// 前端弹一次性状态提示,不中断流。
|
||||
AiContextDegraded { conversation_id: Option<String>, reason: String },
|
||||
/// L1 求助协议(aichat 体验与 agent 能力系统化重构 §2.3,2026-06-21):
|
||||
///
|
||||
/// agent 断路器(§2.2)熔断 / 自省(识别"我反复失败")时发,区别于 prompt 教 AI
|
||||
|
||||
Reference in New Issue
Block a user