From f1aa7ac33d65bedc1ed99b8e6f399818058dacad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Fri, 19 Jun 2026 03:26:44 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84:=20commands=E6=8B=86?= =?UTF-8?q?=E5=88=86config+skills=E5=9F=9F=C2=B7commands.rs=2092KB?= =?UTF-8?q?=E6=8B=86=E5=88=86=E5=AE=8C=E6=95=B4(strategy)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新建 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四批); 零调用方预留保留 --- src-tauri/src/commands/ai/commands/config.rs | 89 +++++++++++++++++++ src-tauri/src/commands/ai/commands/mod.rs | 92 +++----------------- 2 files changed, 103 insertions(+), 78 deletions(-) create mode 100644 src-tauri/src/commands/ai/commands/config.rs diff --git a/src-tauri/src/commands/ai/commands/config.rs b/src-tauri/src/commands/ai/commands/config.rs new file mode 100644 index 0000000..91b94e3 --- /dev/null +++ b/src-tauri/src/commands/ai/commands/config.rs @@ -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, 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, + per_conv_limit: Option, +) -> 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(()) +} diff --git a/src-tauri/src/commands/ai/commands/mod.rs b/src-tauri/src/commands/ai/commands/mod.rs index 507f12e..32a8e87 100644 --- a/src-tauri/src/commands/ai/commands/mod.rs +++ b/src-tauri/src/commands/ai/commands/mod.rs @@ -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, 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, - per_conv_limit: Option, -) -> 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::*;