重构: commands拆分config+skills域·commands.rs 92KB拆分完整(strategy)
- 新建 commands/config.rs(89行, 4 IPC: ai_list_skills/ai_set_concurrency_config/ai_set_agent_max_iterations/ai_set_agent_max_retries) - commands/mod.rs 99→34行(收敛re-export only, 无IPC函数体) - re-export三级透传(chat/conversation/provider/config),lib.rs invoke_handler+前端零改动 commands.rs 92KB拆分完整: 原1829行God→5文件(chat 1147+conversation 336+provider 348+config 89+mod.rs 34 re-export) 主代兜底: cargo check --workspace 0 + test 98 + cat mod.rs re-export only印证 strategy全程: 分批1-2文件原子操作(chat→conv→provider→config四批); 零调用方预留保留
This commit is contained in:
89
src-tauri/src/commands/ai/commands/config.rs
Normal file
89
src-tauri/src/commands/ai/commands/config.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
//! skills + config 域 IPC — 4 个 `#[tauri::command]` 函数
|
||||
//!
|
||||
//! 原 `commands/ai/commands/mod.rs` 收敛到 re-export only 后,本文件承接最后一批 IPC:
|
||||
//! - `ai_list_skills` — 列出本机 Claude 技能(skills + commands + plugins),供前端 `/` 联想
|
||||
//! - `ai_set_concurrency_config` — LLM 并发上限运行时调整(global/per-conv,立即生效)
|
||||
//! - `ai_set_agent_max_iterations` — Agentic 循环最大轮次(下次发消息生效)
|
||||
//! - `ai_set_agent_max_retries` — 流式对话失败自动重试次数(下次发消息生效)
|
||||
//!
|
||||
//! re-export 链:本文件经 `commands/ai/commands/mod.rs` 的 `pub use self::config::*`
|
||||
//! → `commands::*` → `ai/mod.rs` 的 `pub use self::commands::*` 透传到 `commands::ai::*`
|
||||
//! → `lib.rs` invoke_handler + 前端 `api/ai.ts` 零改动。
|
||||
//!
|
||||
//! 注:`ai_list_skills` 复用 `super::super::skills::{skills_cached, SkillInfo}`(skills.rs
|
||||
//! 模块提供进程内缓存 + 扫盘逻辑,本文件仅做 IPC 包装,不重复实现)。
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use tauri::State;
|
||||
|
||||
// skills_cached(进程内缓存命中即 clone,不重复扫盘)/SkillInfo(技能统一返回结构)
|
||||
// 来自 commands/ai/skills.rs,本域 IPC 复用,不重复定义。
|
||||
use super::super::skills::{skills_cached, SkillInfo};
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
/// 列出本机 Claude 技能(skills + commands + plugins 三类),供前端 `/` 联想
|
||||
#[tauri::command]
|
||||
pub async fn ai_list_skills() -> Result<Vec<SkillInfo>, String> {
|
||||
// 命中进程内缓存,命中后仅 clone,不重复扫盘
|
||||
Ok(skills_cached().clone())
|
||||
}
|
||||
|
||||
/// 设置 LLM 调用并发上限(运行时调整,立即生效)
|
||||
///
|
||||
/// 软收敛:缩并发时已持有旧 permit 的任务继续执行不受影响,待其释放后新限制完全生效。
|
||||
/// None 表示该层不变(前端可单独调一层)。值下限为 1。
|
||||
#[tauri::command]
|
||||
pub async fn ai_set_concurrency_config(
|
||||
state: State<'_, AppState>,
|
||||
global_limit: Option<u32>,
|
||||
per_conv_limit: Option<u32>,
|
||||
) -> Result<(), String> {
|
||||
// 下限 1,无上限;同时给 global 时约束 per-conv 不超过 global
|
||||
if let Some(g) = global_limit {
|
||||
state.llm_concurrency.set_global(g.max(1) as usize).await;
|
||||
}
|
||||
if let Some(p) = per_conv_limit {
|
||||
let mut p = p.max(1);
|
||||
if let Some(g) = global_limit {
|
||||
p = p.min(g.max(1));
|
||||
}
|
||||
state.llm_concurrency.set_per_conv(p as usize).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 设置 Agentic 循环最大轮次(运行时调整,立即生效)
|
||||
///
|
||||
/// 与并发配置不同:max_iterations 是 loop 入口 load 快照的值,热改后当前 loop 不受影响
|
||||
/// (已锁定边界),下次发消息生效。范围双 clamp(command 端 1-50 + 前端 input min/max),
|
||||
/// 防越界输入致 loop 过早结束(值过小)或失控(值过大)。
|
||||
#[tauri::command]
|
||||
pub async fn ai_set_agent_max_iterations(
|
||||
state: State<'_, AppState>,
|
||||
value: u32,
|
||||
) -> Result<(), String> {
|
||||
// clamp 1-50:下限防 agent 失能(一轮即截断无法调任何工具),
|
||||
// 上限防失控烧 token(50 轮足够覆盖复杂多步任务)
|
||||
let clamped = value.clamp(1, 50) as usize;
|
||||
state.agent_max_iterations.store(clamped, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 设置流式对话失败自动重试次数(F-260616-07 / 决策 a1:运行时调整,下次发消息生效)
|
||||
///
|
||||
/// 只重试流前失败(Init Err:未输出任何 token);流中途失败(MidStream Partial)保文不重试。
|
||||
/// 退避复用 retry::backoff_delay(1s→2s→4s+jitter) + is_status_retryable Fatal 分类 +
|
||||
/// 30s 总预算(详见 agentic.rs 流前重试循环)。
|
||||
/// 范围 clamp 0-10:0 表示不重试(直接报错),上限 10 防过度重试烧 token/拖慢体验。
|
||||
/// 默认 3(复用 retry.rs backoff_delay + 错误分类,详见 agentic.rs 重试循环)。
|
||||
#[tauri::command]
|
||||
pub async fn ai_set_agent_max_retries(
|
||||
state: State<'_, AppState>,
|
||||
value: u32,
|
||||
) -> Result<(), String> {
|
||||
let clamped = value.clamp(0, 10) as usize;
|
||||
state.agent_max_retries.store(clamped, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,16 +1,23 @@
|
||||
//! 所有 `#[tauri::command]` IPC 函数 — 由 ai/mod.rs 重导出供 invoke_handler 引用
|
||||
//!
|
||||
//! 原单文件 commands.rs(1829 行 God 文件)按域拆分为 `commands/` 子目录:
|
||||
//! 原单文件 commands.rs(1829 行 God 文件)按域拆分为 `commands/` 子目录,本文件收敛到 re-export only:
|
||||
//! - [`chat`] — chat 域 13 个 IPC(发送/重新生成/编辑/强制发送/停止/审批/上下文分段与压缩/循环控制)
|
||||
//! + chat 专用 helper(`finalize_pending_placeholders`)+ `PendingToolCallInfo`
|
||||
//! - [`conversation`] — conversation 域 8 个 IPC(创建/列出/切换/删除/重命名/归档/置顶/导出)
|
||||
//! - [`provider`] — provider 域 7 个 IPC(提供商 CRUD/池配置/模型拉取探测)+ provider 专用 helper
|
||||
//! (`mask_api_key` api_key 脱敏、`normalize_provider_type_for_fetch` 类型归一)
|
||||
//! - 本文件(`mod.rs`)保留其余域 IPC:skills/config(后续批按域继续拆分)。
|
||||
//! - [`config`] — skills + config 域 4 个 IPC(ai_list_skills + ai_set_concurrency_config
|
||||
//! + ai_set_agent_max_iterations + ai_set_agent_max_retries);`ai_list_skills` 复用
|
||||
//! `super::super::skills::{skills_cached, SkillInfo}`(skills.rs 缓存+扫盘,config 仅 IPC 包装)
|
||||
//!
|
||||
//! re-export 链:`commands/mod.rs` → `pub use self::{chat,conversation,provider}::*` 把各域 IPC
|
||||
//! 拉到 `commands::*` → `ai/mod.rs` 的 `pub use self::commands::*` 透传到 `commands::ai::*`
|
||||
//! re-export 链:`commands/mod.rs` → `pub use self::{chat,conversation,provider,config}::*`
|
||||
//! 把各域 IPC 拉到 `commands::*` → `ai/mod.rs` 的 `pub use self::commands::*` 透传到 `commands::ai::*`
|
||||
//! → `lib.rs` invoke_handler + 前端 `api/ai.ts` 零改动。
|
||||
//!
|
||||
//! 注:本文件仅 mod + pub use 声明(re-export only),不含任何 IPC 函数体。
|
||||
//! config/skills 域外的 helper(mask_api_key/finalize_pending_placeholders 等)随各域就近安置,
|
||||
//! skills 域共享的 skills_cached/SkillInfo 仍由 commands/ai/skills.rs 提供,config.rs 通过
|
||||
//! `super::super::skills` 路径引用,保持单一来源(DRY)。
|
||||
|
||||
// 各域子模块 + glob 重导出(拉到 commands::* 经 ai/mod.rs 透传到 commands::ai::*)
|
||||
pub mod chat;
|
||||
@@ -22,77 +29,6 @@ pub use self::conversation::*;
|
||||
pub mod provider;
|
||||
#[allow(unused_imports)]
|
||||
pub use self::provider::*;
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use tauri::State;
|
||||
|
||||
// skills 域(ai_list_skills)仍用 skills_cached/SkillInfo,保留。
|
||||
use super::skills::{skills_cached, SkillInfo};
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
/// 列出本机 Claude 技能(skills + commands + plugins 三类),供前端 `/` 联想
|
||||
#[tauri::command]
|
||||
pub async fn ai_list_skills() -> Result<Vec<SkillInfo>, String> {
|
||||
// 命中进程内缓存,命中后仅 clone,不重复扫盘
|
||||
Ok(skills_cached().clone())
|
||||
}
|
||||
|
||||
/// 设置 LLM 调用并发上限(运行时调整,立即生效)
|
||||
///
|
||||
/// 软收敛:缩并发时已持有旧 permit 的任务继续执行不受影响,待其释放后新限制完全生效。
|
||||
/// None 表示该层不变(前端可单独调一层)。值下限为 1。
|
||||
#[tauri::command]
|
||||
pub async fn ai_set_concurrency_config(
|
||||
state: State<'_, AppState>,
|
||||
global_limit: Option<u32>,
|
||||
per_conv_limit: Option<u32>,
|
||||
) -> Result<(), String> {
|
||||
// 下限 1,无上限;同时给 global 时约束 per-conv 不超过 global
|
||||
if let Some(g) = global_limit {
|
||||
state.llm_concurrency.set_global(g.max(1) as usize).await;
|
||||
}
|
||||
if let Some(p) = per_conv_limit {
|
||||
let mut p = p.max(1);
|
||||
if let Some(g) = global_limit {
|
||||
p = p.min(g.max(1));
|
||||
}
|
||||
state.llm_concurrency.set_per_conv(p as usize).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 设置 Agentic 循环最大轮次(运行时调整,立即生效)
|
||||
///
|
||||
/// 与并发配置不同:max_iterations 是 loop 入口 load 快照的值,热改后当前 loop 不受影响
|
||||
/// (已锁定边界),下次发消息生效。范围双 clamp(command 端 1-50 + 前端 input min/max),
|
||||
/// 防越界输入致 loop 过早结束(值过小)或失控(值过大)。
|
||||
#[tauri::command]
|
||||
pub async fn ai_set_agent_max_iterations(
|
||||
state: State<'_, AppState>,
|
||||
value: u32,
|
||||
) -> Result<(), String> {
|
||||
// clamp 1-50:下限防 agent 失能(一轮即截断无法调任何工具),
|
||||
// 上限防失控烧 token(50 轮足够覆盖复杂多步任务)
|
||||
let clamped = value.clamp(1, 50) as usize;
|
||||
state.agent_max_iterations.store(clamped, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 设置流式对话失败自动重试次数(F-260616-07 / 决策 a1:运行时调整,下次发消息生效)
|
||||
///
|
||||
/// 只重试流前失败(Init Err:未输出任何 token);流中途失败(MidStream Partial)保文不重试。
|
||||
/// 退避复用 retry::backoff_delay(1s→2s→4s+jitter) + is_status_retryable Fatal 分类 +
|
||||
/// 30s 总预算(详见 agentic.rs 流前重试循环)。
|
||||
/// 范围 clamp 0-10:0 表示不重试(直接报错),上限 10 防过度重试烧 token/拖慢体验。
|
||||
/// 默认 3(复用 retry.rs backoff_delay + 错误分类,详见 agentic.rs 重试循环)。
|
||||
#[tauri::command]
|
||||
pub async fn ai_set_agent_max_retries(
|
||||
state: State<'_, AppState>,
|
||||
value: u32,
|
||||
) -> Result<(), String> {
|
||||
let clamped = value.clamp(0, 10) as usize;
|
||||
state.agent_max_retries.store(clamped, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
pub mod config;
|
||||
#[allow(unused_imports)]
|
||||
pub use self::config::*;
|
||||
|
||||
Reference in New Issue
Block a user