diff --git a/src-tauri/src/agents/windows_probe.rs b/src-tauri/src/agents/windows_probe.rs index fc8eb39..6b69feb 100644 --- a/src-tauri/src/agents/windows_probe.rs +++ b/src-tauri/src/agents/windows_probe.rs @@ -337,16 +337,6 @@ pub(crate) fn parse_windows_zcode_registration(kind: &str, value: &str) -> Optio .then_some(executable) } -pub(crate) fn parse_windows_zcode_discovery_output(output: &str) -> Option { - let candidates: Vec = serde_json::from_str(output.trim()).ok()?; - candidates.into_iter().find_map(|candidate| { - parse_windows_zcode_registration( - candidate.get("kind")?.as_str()?, - candidate.get("value")?.as_str()?, - ) - }) -} - pub(crate) fn find_windows_registered_zcode_executable() -> Option { collect_windows_zcode_registrations() .into_iter() @@ -639,65 +629,6 @@ pub(crate) fn read_windows_claude_desktop_store_version() -> Option { .find_map(|package| normalize_detected_agent_version(&package.version)) } -pub(crate) fn parse_windows_claude_desktop_version_output(output: &str) -> Option { - output.lines().find_map(|line| { - line.trim() - .strip_prefix("VERSION:") - .and_then(normalize_detected_agent_version) - }) -} - -pub(crate) fn parse_windows_codex_version_output(output: &str) -> Option { - output.lines().find_map(|line| { - line.trim() - .strip_prefix("VERSION:") - .and_then(normalize_detected_agent_version) - }) -} - -pub(crate) fn parse_windows_codex_app_discovery_output(output: &str) -> Option { - output.lines().find_map(|line| { - let line = line.trim(); - if let Some(app_id) = line.strip_prefix("APPID:").map(str::trim) { - return (!app_id.is_empty()) - .then(|| DesktopAppTarget::WindowsAppId(app_id.to_string())); - } - line.strip_prefix("EXE:") - .map(str::trim) - .filter(|path| !path.is_empty()) - .map(|path| DesktopAppTarget::Application(PathBuf::from(path))) - }) -} - -pub(crate) fn parse_windows_codex_app_id_from_registry(output: &str) -> Option { - const PACKAGE_MARKER: &str = "\\AppModel\\Repository\\Packages\\"; - output.lines().find_map(|line| { - let line = line.trim(); - let (_, package_full_name) = line.split_once(PACKAGE_MARKER)?; - if package_full_name.contains('\\') { - return None; - } - windows_codex_app_id_from_package_full_name(package_full_name) - }) -} - -pub(crate) fn windows_codex_app_id_from_package_full_name( - package_full_name: &str, -) -> Option { - let package_name = package_name_from_full_name(package_full_name)?; - if !matches!( - package_name, - "OpenAI.Codex" | "OpenAI.CodexBeta" | "OpenAI.ChatGPT" - ) { - return None; - } - let publisher_id = publisher_id_from_full_name(package_full_name)?; - if publisher_id == package_name { - return None; - } - Some(format!("{package_name}_{publisher_id}!App")) -} - pub(crate) fn find_windows_codex_app_id_via_registry() -> Option { find_windows_appx_app_id(&["OpenAI.Codex", "OpenAI.CodexBeta", "OpenAI.ChatGPT"]) } diff --git a/src-tauri/src/network_proxy.rs b/src-tauri/src/network_proxy.rs index bf01335..4249184 100644 --- a/src-tauri/src/network_proxy.rs +++ b/src-tauri/src/network_proxy.rs @@ -47,6 +47,7 @@ fn parse_detected_proxy(value: &str) -> Result { } } +#[cfg(any(target_os = "macos", target_os = "linux", test))] fn parse_env_proxy(name: &str, value: &str) -> Result { let value = value.trim().trim_matches('\'').trim_matches('"'); if value.is_empty() { diff --git a/src-tauri/src/tests/agent_paths.rs b/src-tauri/src/tests/agent_paths.rs index b7d9186..8ed796e 100644 --- a/src-tauri/src/tests/agent_paths.rs +++ b/src-tauri/src/tests/agent_paths.rs @@ -109,11 +109,10 @@ fn zcode_windows_finds_custom_installations_from_registered_paths() { format!("{} /allusers", uninstaller.display()), ), ] { - let output = serde_json::json!([{ "kind": kind, "value": value }]).to_string(); assert_eq!( - parse_windows_zcode_discovery_output(&output), + parse_windows_zcode_registration(kind, &value), Some(executable.clone()), - "{output}", + "kind={kind}, value={value}", ); } fs::remove_dir_all(home).unwrap(); @@ -138,26 +137,27 @@ fn zcode_windows_skips_stale_and_unrelated_registration_entries() { let executable = home.join("valid/ZCode.exe"); fs::create_dir_all(executable.parent().unwrap()).unwrap(); fs::write(&executable, []).unwrap(); - let mut candidates = vec![ - serde_json::json!({ "kind": "directory", "value": home }), - serde_json::json!({ "kind": "executable", "value": unrelated }), - serde_json::json!({ "kind": "executable", "value": home.join("missing/ZCode.exe") }), - serde_json::json!({ "kind": "executable", "value": "ZCode.exe" }), - serde_json::json!({ "kind": "executable", "value": "\"unterminated" }), - serde_json::json!({ "kind": "unknown", "value": executable }), - serde_json::json!({ "kind": "executable", "value": null }), - ]; + for (kind, value) in [ + ("directory", path_to_string(&home)), + ("executable", path_to_string(&unrelated)), + ( + "executable", + path_to_string(&home.join("missing/ZCode.exe")), + ), + ("executable", "ZCode.exe".to_string()), + ("executable", "\"unterminated".to_string()), + ("unknown", path_to_string(&executable)), + ] { + assert_eq!( + parse_windows_zcode_registration(kind, &value), + None, + "kind={kind}, value={value}", + ); + } assert_eq!( - parse_windows_zcode_discovery_output(&serde_json::to_string(&candidates).unwrap()), - None, - ); - candidates.push(serde_json::json!({ "kind": "executable", "value": executable })); - assert_eq!( - parse_windows_zcode_discovery_output(&serde_json::to_string(&candidates).unwrap()), + parse_windows_zcode_registration("executable", &path_to_string(&executable)), Some(executable), ); - assert_eq!(parse_windows_zcode_discovery_output("[]"), None); - assert_eq!(parse_windows_zcode_discovery_output("invalid JSON"), None); fs::remove_dir_all(home).unwrap(); } diff --git a/src-tauri/src/tests/platform.rs b/src-tauri/src/tests/platform.rs index 1a991b6..f3ed130 100644 --- a/src-tauri/src/tests/platform.rs +++ b/src-tauri/src/tests/platform.rs @@ -60,58 +60,6 @@ fn app_locale_normalization_has_a_stable_chinese_fallback() { assert_eq!(GuiConfigFile::default().locale, "zh-CN"); } -#[cfg(target_os = "windows")] -#[test] -fn windows_chatgpt_discovery_parser_accepts_registered_app_and_executable() { - let app = parse_windows_codex_app_discovery_output("APPID:OpenAI.Codex_2p2nqsd0c76g0!App\r\n") - .unwrap(); - match app { - DesktopAppTarget::WindowsAppId(app_id) => { - assert_eq!(app_id, "OpenAI.Codex_2p2nqsd0c76g0!App"); - } - DesktopAppTarget::Application(_) => panic!("expected Store application ID"), - } - - let executable = parse_windows_codex_app_discovery_output( - "warning\r\nEXE:C:\\Program Files\\OpenAI\\ChatGPT\\ChatGPT.exe\r\n", - ) - .unwrap(); - match executable { - DesktopAppTarget::Application(path) => { - assert_eq!( - path, - PathBuf::from(r"C:\Program Files\OpenAI\ChatGPT\ChatGPT.exe") - ); - } - DesktopAppTarget::WindowsAppId(_) => panic!("expected desktop executable"), - } - - assert!(parse_windows_codex_app_discovery_output("MSEdgePWA:ChatGPT\r\n").is_none()); - assert_eq!( - parse_windows_claude_desktop_version_output("VERSION:1.2.3\r\n").as_deref(), - Some("1.2.3") - ); - assert_eq!( - parse_windows_codex_version_output("VERSION:26.901.51231\r\n").as_deref(), - Some("26.901.51231") - ); - - let registry_output = r"HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\Repository\Packages\OpenAI.Codex_26.715.4045.0_x64__2p2nqsd0c76g0"; - assert_eq!( - parse_windows_codex_app_id_from_registry(registry_output).as_deref(), - Some("OpenAI.Codex_2p2nqsd0c76g0!App") - ); - assert_eq!( - windows_codex_app_id_from_package_full_name("OpenAI.ChatGPT_1.2.3.4_arm64__2p2nqsd0c76g0") - .as_deref(), - Some("OpenAI.ChatGPT_2p2nqsd0c76g0!App") - ); - assert!(windows_codex_app_id_from_package_full_name( - "Microsoft.MicrosoftEdge_1.0.0.0_x64__8wekyb3d8bbwe" - ) - .is_none()); -} - #[cfg(target_os = "windows")] #[test] fn codex_owl_version_uses_app_metadata_not_package_or_runtime_version() {