diff --git a/src-tauri/src/commands/agent_infra.rs b/src-tauri/src/commands/agent_infra.rs index b261898..3477f65 100644 --- a/src-tauri/src/commands/agent_infra.rs +++ b/src-tauri/src/commands/agent_infra.rs @@ -128,12 +128,7 @@ fn detect_contracts(root: &Path) -> Vec { let cargo_content = std::fs::read_to_string(root.join("Cargo.toml")) .or_else(|_| std::fs::read_to_string(root.join("src-tauri/Cargo.toml"))) .unwrap_or_default(); - // Tauri 项目:commands 目录在 src-tauri/src/commands/ - let tauri_commands_path = if path_exists(root, "src-tauri/src/commands") { - "src-tauri/src/commands" - } else { - "src/commands" - }; + // ── Node.js 框架层 ──────────────────────────────────────────────────────── @@ -226,6 +221,37 @@ fn detect_contracts(root: &Path) -> Vec { }); } + // React(前端组件层) + if pkg_deps.iter().any(|k| k == "react") { + contracts.push(DetectedContract { + label: "前端组件类型(React/TypeScript)".into(), + paths: vec!["src/**/*.tsx".into()], + doc: "组件 Props 类型变更需检查所有消费方".into(), + confidence: "medium".into(), + }); + } + + // Vite 构建配置 + if pkg_deps.iter().any(|k| k == "vite") { + let p = "vite.config.ts"; + contracts.push(DetectedContract { + label: "构建配置(Vite)".into(), + paths: vec![p.into()], + doc: "Vite 配置变更影响构建输出和 dev 行为(Tauri 项目尤其注意)".into(), + confidence: confidence(root, p), + }); + } + + // Zustand 状态层 + if pkg_deps.iter().any(|k| k == "zustand") { + contracts.push(DetectedContract { + label: "前端状态类型(Zustand store)".into(), + paths: vec!["src/store/**".into()], + doc: "Store 类型变更影响所有消费组件,需同步更新".into(), + confidence: "medium".into(), + }); + } + // pnpm monorepo 共享类型 if path_exists(root, "pnpm-workspace.yaml") { // 优先已知命名约定;否则列出 packages/ 下实际存在的子包目录 @@ -300,21 +326,23 @@ fn detect_contracts(root: &Path) -> Vec { }); } - // Tauri(自身的 command 层) - let tauri_frontend_ts = if path_exists(root, "src/lib/commands.ts") { - "src/lib/commands.ts" - } else { - "src/commands.ts" - }; - if cargo_has(&cargo_content, "tauri") && path_exists(root, tauri_commands_path) { + // Tauri(command 层) + // 注意:不要求 commands/ 目录已存在——新项目初始化时只有 lib.rs,但契约路径应预先声明 + if cargo_has(&cargo_content, "tauri") { + let tauri_cmd_dir = "src-tauri/src/commands"; + let tauri_frontend_ts = if path_exists(root, "src/lib/commands.ts") { + "src/lib/commands.ts" + } else { + "src/commands.ts" + }; contracts.push(DetectedContract { label: "Tauri command 接口(前后端契约)".into(), paths: vec![ - format!("{tauri_commands_path}/**/*.rs"), + format!("{tauri_cmd_dir}/**/*.rs"), tauri_frontend_ts.into(), ], doc: "新增 command 时前后端必须同步".into(), - confidence: "high".into(), + confidence: if path_exists(root, tauri_cmd_dir) { "high".into() } else { "medium".into() }, }); } }