新增: Phase2 阶段收尾(Sprint 1-20)
重构:删 5 零引用 crate(df-evolve/plugin/stages/task/traceability)+ 清死模块、ai.rs 拆 11 子 module、ai.ts 拆 6 composable、i18n 拆目录 功能:知识库全栈(df-project/scan + CRUD + 时间线 + 前端)、Settings 拆分、appSettings KV 迁移、模型池、LLM 并发 Semaphore 修复:审批持久化根治、ConditionEngine 默认拒绝、NodeRegistry unimplemented 清除、promote 补偿删除、工具结果截断 50KB、路径校验防 symlink 逃逸 文档:B-03 人工审批设计、决策记录三分档、规格契约自检、经验记录、todo 看板、PROGRESS 更新 详见 PROGRESS.md。src-tauri/儿童每日打卡应用/ 与本项目无关,已排除。
This commit is contained in:
146
src-tauri/src/commands/ai/mod.rs
Normal file
146
src-tauri/src/commands/ai/mod.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
//! AI 聊天命令模块 — 流式对话、工具调用、审批门控、提供商管理
|
||||
//!
|
||||
//! 由原单文件 ai.rs(2663 行)按职责拆分为 11 个子模块。
|
||||
//!
|
||||
//! 模块布局:
|
||||
//! - [`commands`] — 所有 `#[tauri::command]` IPC 函数
|
||||
//! - [`agentic`] — run_agentic_loop / try_continue_agent_loop / MAX_AGENT_ITERATIONS
|
||||
//! - [`stream_recv`] — stream_llm 流式接收
|
||||
//! - [`conversation`] — save_conversation / TokenAccumulator / accumulate_tokens
|
||||
//! - [`title`] — 对话标题生成
|
||||
//! - [`audit`] — 工具调用审计 + pending 审批恢复 + 工具调用处理
|
||||
//! - [`skills`] — 本机 Claude 技能扫描
|
||||
//! - [`prompt`] — 系统提示词构建
|
||||
//! - [`tool_registry`] — AI 工具注册表构建 + 文件路径校验
|
||||
//! - [`knowledge_inject`] — 知识库注入 + 提炼
|
||||
//!
|
||||
//! 事件协议:通过 app.emit("ai-chat-event", payload) 流式推送到前端
|
||||
//! - AiTextDelta: 流式文本片段
|
||||
//! - AiToolCallStarted/Completed: 工具调用生命周期
|
||||
//! - AiApprovalRequired: 需要人工审批
|
||||
//! - AiCompleted/AiError: 完成/错误
|
||||
|
||||
pub mod agentic;
|
||||
pub mod audit;
|
||||
pub mod commands;
|
||||
pub mod conversation;
|
||||
pub mod knowledge_inject;
|
||||
pub mod prompt;
|
||||
pub mod skills;
|
||||
pub mod stream_recv;
|
||||
pub mod title;
|
||||
pub mod tool_registry;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use df_ai::ai_tools::RiskLevel;
|
||||
use df_ai::context::ContextManager;
|
||||
use df_ai::context::ContextConfig;
|
||||
|
||||
// ============================================================
|
||||
// 重导出 — 保路径不变(state.rs / lib.rs / knowledge.rs 在用)
|
||||
// ============================================================
|
||||
|
||||
// commands 子模块(glob 重导出) — `#[tauri::command]` 宏生成的命令函数 +
|
||||
// 内部符号(__cmd__xxx / __tauri_command_name_xxx)同源同模块定义,
|
||||
// glob 把它们全部拉到 commands::ai 路径,使 generate_handler! 能解析到。
|
||||
// 静默 unused_imports:glob 重导出用于跨模块路径解析,本文件不引用这些符号。
|
||||
#[allow(unused_imports)]
|
||||
pub use self::commands::*;
|
||||
|
||||
// 子模块的非命令 pub 项,逐个保路径
|
||||
#[allow(unused_imports)]
|
||||
pub use self::audit::restore_pending_approvals;
|
||||
#[allow(unused_imports)]
|
||||
pub use self::knowledge_inject::{spawn_embedding_for_knowledge, trigger_extraction_now};
|
||||
#[allow(unused_imports)]
|
||||
pub use self::tool_registry::build_ai_tool_registry;
|
||||
|
||||
// ============================================================
|
||||
// 事件载荷类型(放 mod.rs,各子文件经 use super::* 拿到)
|
||||
// ============================================================
|
||||
|
||||
/// AI 聊天事件(推送到前端)
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum AiChatEvent {
|
||||
/// 流式文本片段
|
||||
AiTextDelta { delta: String, conversation_id: Option<String> },
|
||||
/// 工具调用开始
|
||||
AiToolCallStarted { id: String, name: String, args: serde_json::Value, conversation_id: Option<String> },
|
||||
/// 工具调用完成
|
||||
AiToolCallCompleted { id: String, result: serde_json::Value, conversation_id: Option<String> },
|
||||
/// 需要人工审批
|
||||
AiApprovalRequired { id: String, name: String, args: serde_json::Value, reason: String, conversation_id: Option<String> },
|
||||
/// 审批结果
|
||||
AiApprovalResult { id: String, approved: bool, conversation_id: Option<String> },
|
||||
/// AI 响应完成
|
||||
AiCompleted { total_tokens: u32, prompt_tokens: u32, completion_tokens: u32, conversation_id: Option<String> },
|
||||
/// 错误
|
||||
AiError { error: String, conversation_id: Option<String> },
|
||||
/// Agent 循环新一轮(前端需新建 assistant 消息)
|
||||
AiAgentRound { round: u32, conversation_id: Option<String> },
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 会话状态(放 mod.rs,各子文件经 use super::* 拿到)
|
||||
// ============================================================
|
||||
|
||||
/// AI 会话内状态(Mutex 保护)
|
||||
pub struct AiSession {
|
||||
/// 对话历史(ContextManager:唯一消息真相源,裁剪仅影响发送视图,不影响持久化)
|
||||
pub messages: ContextManager,
|
||||
/// 当前提供商 ID
|
||||
pub active_provider_id: Option<String>,
|
||||
/// 当前活跃对话 ID
|
||||
pub active_conversation_id: Option<String>,
|
||||
/// 活跃对话创建时间(懒创建:首条消息落库前仅存内存,upsert 时用作 created_at)
|
||||
pub active_conv_created_at: Option<String>,
|
||||
/// 挂起的审批(tool_call_id → 审批信息)
|
||||
pub pending_approvals: HashMap<String, PendingApproval>,
|
||||
/// 是否正在生成
|
||||
pub generating: bool,
|
||||
/// 当前 agent 循环的语言设置(用于审批后恢复循环)
|
||||
pub agent_language: Option<String>,
|
||||
/// 停止信号:ai_chat_stop 置位,agentic loop / stream_llm 检测后尽快退出
|
||||
pub stop_flag: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl AiSession {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
messages: ContextManager::new(ContextConfig::default()),
|
||||
active_provider_id: None,
|
||||
active_conversation_id: None,
|
||||
active_conv_created_at: None,
|
||||
pending_approvals: HashMap::new(),
|
||||
generating: false,
|
||||
agent_language: None,
|
||||
stop_flag: Arc::new(AtomicBool::new(false)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 待审批的工具调用
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PendingApproval {
|
||||
pub tool_call_id: String,
|
||||
pub tool_name: String,
|
||||
pub arguments: serde_json::Value,
|
||||
pub risk_level: RiskLevel,
|
||||
pub conversation_id: Option<String>,
|
||||
/// 重启恢复的积压审批:无 live loop 持有 session.messages,审批后不 save(防空 messages 污染老对话)、不续跑
|
||||
pub recovered: bool,
|
||||
}
|
||||
|
||||
/// 工具调用草稿(流式收集时的临时结构)
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct ToolCallDraft {
|
||||
pub(crate) id: String,
|
||||
pub(crate) name: String,
|
||||
pub(crate) args: String,
|
||||
}
|
||||
Reference in New Issue
Block a user