优化: AI Chat 体验全面升级(图标/审批/目标提取/窗口管理)

- AI 入口图标:灯泡→星花 sparkles+发光,与灵感入口区分
- 目标提取根本性改造:用户消息规则→工具调用推理(infer_goal_from_tool_calls)
  - Vec<String>→Vec<GoalEntry>(text+status),active→completed 状态流转
  - 多条/轮提取,system_prompt 仅注入 active 目标
  - 代码拆分到 helpers.rs(解决 brace 嵌套致 pub(crate) 不可见)
- 审批修复:patch_file 全档位自动放行,批量审批防抖,乐观更新竞态保护
- 审批通知浮层:全局右上角 ApprovalOverlay,窗口遮挡时可见
- 设置导入导出移除:价值低占用空间,跨设备同步建议复制 SQLite
- 分离窗口默认置顶+置顶状态持久化(刷新后保持)
- header 菜单聚合:清空/压缩上下文收入 ... popout
- LLM 文字重叠防御:delta 重复检测+丢弃
- 置顶图标:星→大头针 pushpin
- 文档/注释更新:过期 Vec<String>/chat.rs 提取描述修正
This commit is contained in:
lxy
2026-07-03 13:07:03 +08:00
parent aa0701a2ea
commit 0dfaeb0f5b
26 changed files with 929 additions and 753 deletions
+34 -8
View File
@@ -140,7 +140,7 @@ pub enum AiChatEvent {
incomplete: Option<bool>,
conversation_id: Option<String>,
/// 当前会话 pinned_goals(G1 目标钉扎持久化,前端直接读取刷新)
pinned_goals: Vec<String>,
pinned_goals: Vec<GoalEntry>,
},
/// 错误
///
@@ -820,17 +820,15 @@ pub struct PerConvState {
/// 写收敛:经 GeneratingGuard/入口 transition_to 守卫迁移,非直接赋值。
/// 批3 双轨收口:generating bool 已退役,此 enum 成为生成态唯一真相源。
pub conv_state: ConvState,
/// G1 目标钉扎真相源:用户消息中提取的目标列表(内容态字段,与生命周期态正交)。
/// G1 目标钉扎真相源:从 LLM 工具调用推理的目标列表(内容态字段,与生命周期态正交)。
///
/// 治 R1(目标消息被压缩/compressed 物理出局,sanitize step0 过滤 is_active 致目标丢失):
/// 目标存本字段绕过消息 active 状态过滤,即使原始 user 消息出局,goal 仍在。
/// run_agentic_loop 入口拼进 system_prompt 尾部(system_prompt 是 loop 不变量,天然
/// 免疫压缩/裁剪/sanitize,见 agentic/mod.rs:683)。
/// run_agentic_loop 入口拼 active 目标进 system_prompt 尾部(system_prompt 是 loop 不变量)。
///
/// 写:chat.rs send/force_send/edit push 后提取目标追加到列表(去重,支持累积多目标);
/// 读:loop 入口拼接全部目标。GOAL_PIN_ENABLED=false 时不提取不注入,本字段永远空 Vec
/// 随会话销毁不落库(对齐 knowledge_extracted 语义,PerConvState 无 serde derive)。
pub pinned_goals: Vec<String>,
/// 2026-07-03 改:提取从「用户消息规则」→「工具调用推理」(infer_goal_from_tool_calls),
/// 每轮 LLM 回复后从工具名+路径推理目标追加(去重),支持多条/轮 + active→completed 状态流转
pub pinned_goals: Vec<GoalEntry>,
/// 停止信号(会话级):ai_chat_stop 置位,agentic loop / stream_llm 检测后尽快退出
pub stop_flag: Arc<AtomicBool>,
/// 即时停止唤醒(会话级):阻塞在 stream.next() 时 notify_one() 立即唤醒跳出 select!
@@ -863,6 +861,34 @@ pub struct PerConvState {
pub knowledge_extracted: bool,
}
/// 单个目标记录(含状态追踪)。
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoalEntry {
pub text: String,
#[serde(default = "default_goal_status")]
pub status: GoalStatus,
}
/// 目标状态。
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GoalStatus {
/// 正在进行中(当前 LLM 正在处理)
Active,
/// 已完成(LLM 已进入下一任务)
Completed,
}
fn default_goal_status() -> GoalStatus {
GoalStatus::Active
}
impl GoalEntry {
pub fn new(text: String) -> Self {
GoalEntry { text, status: GoalStatus::Active }
}
}
impl PerConvState {
/// 新建默认会话级状态。
///