修复: 全库走查 P0+P1(df-mcp 数据丢失/evaluate 拆 + df-execute probe_pwsh 死缓存/超时/单源 + ai_self_review 注入隔离)
- df-mcp P0: update_idea/project/task 缺省回退 existing(治部分更新清空 title 丢数据)+ P1: evaluate_idea 拆只读(Low)+score_idea(Medium 写),read-only 不再改库 - df-execute P0: probe_pwsh 死缓存(两 OnceLock 合并 PWSH_CACHE 单源,治 Windows 永走 PS5)+ P1: probe_pwsh 3s 超时防挂起 + detect_shell 复用 shell.rs 单源(探测与执行对齐) - df-nodes P1: ai_self_review prompt 注入隔离(truncate + XML 标签 <task_output> 数据/指令隔离 + system 声明) - generate_image: SSRF 集成测试 + b64 OOM 估算纯函数测试(走查测试增强)
This commit is contained in:
@@ -221,18 +221,27 @@ fn read_windows_version() -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// 探测默认 shell(复用 shell.rs 的 pwsh 探测语义)。
|
||||
/// 探测默认 shell(Windows 走 shell.rs 单源,Unix 读 SHELL 环境变量)。
|
||||
///
|
||||
/// 单源语义(2026-08 修复):Windows 分支不再独立 probe pwsh/powershell,而是:
|
||||
/// 1) 先调 `shell::probe_pwsh_blocking()` 填充模块级 `PWSH_CACHE`(与 `shell::probe_pwsh()` 异步路径
|
||||
/// 共用同一 OnceLock + 同一阻塞探测实现,杜绝两套逻辑漂移);
|
||||
/// 2) 再调 `shell::current_shell()`(同步读 `PWSH_CACHE`),映射 ShellType → prompt 字符串。
|
||||
/// 后续 `execute()` → `probe_pwsh().await` 直接命中缓存,跳过重复探测。
|
||||
/// Unix 分支保留原 SHELL 环境变量读取(与执行侧 ShellType::Sh 默认一致,无漂移风险)。
|
||||
fn detect_shell() -> String {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// 优先 pwsh(PS7,支持 &&),其次 powershell(PS5),兜底 cmd。
|
||||
if probe_command_success("pwsh", &["-NoProfile", "-Command", "exit 0"]) {
|
||||
return "pwsh".to_string();
|
||||
// 单源填充 PWSH_CACHE(本函数运行在 EnvSnapshot::detect 的 spawn_blocking 内,
|
||||
// 通常先于首次 execute(),故常是缓存的首次写入者)。
|
||||
crate::shell::probe_pwsh_blocking();
|
||||
// 单源读取并映射为 prompt 字符串。
|
||||
match crate::shell::current_shell() {
|
||||
crate::shell::ShellType::Pwsh => "pwsh".to_string(),
|
||||
crate::shell::ShellType::PowerShell => "powershell".to_string(),
|
||||
crate::shell::ShellType::Cmd => "cmd".to_string(),
|
||||
crate::shell::ShellType::Sh => "sh".to_string(),
|
||||
}
|
||||
if probe_command_success("powershell", &["-NoProfile", "-Command", "exit 0"]) {
|
||||
return "powershell".to_string();
|
||||
}
|
||||
return "cmd".to_string();
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
@@ -301,17 +310,6 @@ fn extract_codepage(text: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 执行 `tool args`,成功(true)即工具可用。Windows 加 CREATE_NO_WINDOW 防黑窗。
|
||||
#[allow(dead_code)] // 仅 Windows 路径调用,非 Windows 静态裁掉
|
||||
fn probe_command_success(tool: &str, args: &[&str]) -> bool {
|
||||
let mut cmd = std::process::Command::new(tool);
|
||||
cmd.args(args);
|
||||
cmd.stdout(Stdio::null()).stderr(Stdio::null());
|
||||
#[cfg(windows)]
|
||||
cmd.creation_flags(0x0800_0000); // CREATE_NO_WINDOW
|
||||
cmd.status().map(|s| s.success()).unwrap_or(false)
|
||||
}
|
||||
|
||||
/// 执行 `tool --version`,解析首行返回版本串。失败/超时返回 None,不阻塞调用方。
|
||||
///
|
||||
/// 例:python --version 输出 "Python 3.11.5" → 返回 "3.11.5";git --version 输出
|
||||
@@ -429,6 +427,27 @@ mod tests {
|
||||
assert_eq!(a, b, "detect() 应返回同一静态引用");
|
||||
}
|
||||
|
||||
/// 单源不变量回归:prompt 期 shell(env_snapshot.shell)与执行期 shell(current_shell)必须一致。
|
||||
///
|
||||
/// 历史 bug:detect_shell 持独立 probe_command_success 探测,与 shell.rs::probe_pwsh 各填各的
|
||||
/// OnceLock → prompt 告诉 LLM 用 pwsh,执行却走 powershell(或反之)。根本修:二者共用
|
||||
/// shell.rs 的 probe_pwsh_blocking + PWSH_CACHE 单源。本测试锁定「无漂移」不变量。
|
||||
#[cfg(windows)]
|
||||
#[tokio::test]
|
||||
async fn detect_shell_matches_shell_rs_current_shell() {
|
||||
// detect() 内 detect_shell → probe_pwsh_blocking 填 PWSH_CACHE,再读 current_shell 映射。
|
||||
let snap = EnvSnapshot::detect().await;
|
||||
let current = crate::shell::current_shell();
|
||||
// 二者必须一致(同一 PWSH_CACHE 单源读出)。
|
||||
match snap.shell.as_str() {
|
||||
"pwsh" => assert_eq!(current, crate::shell::ShellType::Pwsh),
|
||||
"powershell" => assert_eq!(current, crate::shell::ShellType::PowerShell),
|
||||
"cmd" => assert_eq!(current, crate::shell::ShellType::Cmd),
|
||||
"sh" => assert_eq!(current, crate::shell::ShellType::Sh),
|
||||
other => panic!("未知 shell 字符串: {}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_prompt_contains_os_and_shell() {
|
||||
let snap = EnvSnapshot {
|
||||
|
||||
Reference in New Issue
Block a user