From 7c9187f7bb255747570c3e2bf485818e7e751743 Mon Sep 17 00:00:00 2001 From: Aaplloo <3155677252@qq.com> Date: Mon, 11 May 2026 17:07:21 +0800 Subject: [PATCH] Fix remote proxy deploy sync --- src-tauri/build.rs | 2 + src-tauri/proxyd/Cargo.lock | 2 +- src-tauri/src/remote_service.rs | 2 + src-tauri/src/utils.rs | 32 ++++++++++++ src/hooks/useCodexController.ts | 91 +++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 19ef66ad..7db29543 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -8,8 +8,10 @@ const REMOTE_BUILD_FILES: &[&str] = &[ "proxyd/Cargo.toml", "proxyd/Cargo.lock", "proxyd/src/main.rs", + "src/app_paths.rs", "src/auth.rs", "src/models.rs", + "src/profile_files.rs", "src/proxy_daemon.rs", "src/proxy_service.rs", "src/state.rs", diff --git a/src-tauri/proxyd/Cargo.lock b/src-tauri/proxyd/Cargo.lock index 599c50dc..ad53b4ce 100644 --- a/src-tauri/proxyd/Cargo.lock +++ b/src-tauri/proxyd/Cargo.lock @@ -187,7 +187,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "codex-tools-proxyd" -version = "1.8.5" +version = "1.8.6" dependencies = [ "async-stream", "axum", diff --git a/src-tauri/src/remote_service.rs b/src-tauri/src/remote_service.rs index 92d61f97..86325d6c 100644 --- a/src-tauri/src/remote_service.rs +++ b/src-tauri/src/remote_service.rs @@ -31,8 +31,10 @@ const PROXYD_BUILD_SOURCE_FILES: &[&str] = &[ "proxyd/Cargo.toml", "proxyd/Cargo.lock", "proxyd/src/main.rs", + "src/app_paths.rs", "src/auth.rs", "src/models.rs", + "src/profile_files.rs", "src/proxy_daemon.rs", "src/proxy_service.rs", "src/state.rs", diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 43bce12c..9fa2cebd 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -282,11 +282,43 @@ fn preferred_executable_dir_candidates() -> Vec { ] { push_unique_candidate(&mut dirs, dir); } + + #[cfg(target_os = "windows")] + add_winget_package_executable_dirs(&mut dirs, &home); } dirs } +#[cfg(target_os = "windows")] +fn add_winget_package_executable_dirs(dirs: &mut Vec, home: &Path) { + let packages_dir = home + .join("AppData") + .join("Local") + .join("Microsoft") + .join("WinGet") + .join("Packages"); + let Ok(packages) = fs::read_dir(packages_dir) else { + return; + }; + + for package in packages.flatten() { + let package_path = package.path(); + let Some(package_name) = package_path.file_name().and_then(|name| name.to_str()) else { + continue; + }; + if !package_name.starts_with("zig.zig_") { + continue; + } + push_unique_candidate(dirs, package_path.clone()); + if let Ok(children) = fs::read_dir(package_path) { + for child in children.flatten() { + push_unique_candidate(dirs, child.path()); + } + } + } +} + fn push_unique_dir(dirs: &mut Vec, candidate: PathBuf) { if candidate.is_dir() && !dirs.iter().any(|existing| existing == &candidate) { dirs.push(candidate); diff --git a/src/hooks/useCodexController.ts b/src/hooks/useCodexController.ts index 7e38cba8..eab0c78d 100644 --- a/src/hooks/useCodexController.ts +++ b/src/hooks/useCodexController.ts @@ -215,6 +215,8 @@ export function useCodexController() { const settingsRef = useRef(DEFAULT_SETTINGS); const apiProxyUsageLoadSeqRef = useRef(0); const apiProxyUsagePollInFlightRef = useRef(false); + const remoteProxyStatusesRawRef = useRef>({}); + const remoteProxyAutoRedeployInFlightRef = useRef(false); const reloginPromptedAccountKeysRef = useRef>(new Set()); const profileIntegrityPromptedRef = useRef(false); @@ -327,6 +329,10 @@ export function useCodexController() { [localizeRemoteProxyStatus, remoteProxyStatusesRaw], ); + useEffect(() => { + remoteProxyStatusesRawRef.current = remoteProxyStatusesRaw; + }, [remoteProxyStatusesRaw]); + const loadAccounts = useCallback(async () => { const data = await invoke("list_accounts"); applyAccounts(data); @@ -523,6 +529,7 @@ export function useCodexController() { const successCount = result.importedCount + result.updatedCount; if (successCount > 0) { await loadAccounts(); + void redeployDeployedRemoteProxiesAfterAccountChange(); } if (successCount > 0 && result.failures.length === 0) { @@ -1042,6 +1049,7 @@ export function useCodexController() { await invoke("import_current_auth_account", { label: null }); await refreshUsage(true); await loadAccounts(); + void redeployDeployedRemoteProxiesAfterAccountChange(); setAddDialogOpen(false); setNotice({ type: "ok", message: copy.notices.currentAccountImportSuccess }); } catch (error) { @@ -1088,6 +1096,7 @@ export function useCodexController() { try { await invoke("create_api_account", { input }); await loadAccounts(); + void redeployDeployedRemoteProxiesAfterAccountChange(); setAddDialogOpen(false); setNotice({ type: "ok", @@ -1404,6 +1413,86 @@ export function useCodexController() { } }, [copy.notices, deployingRemoteProxyId, ensureRemoteLocalDependency, localizeError]); + async function redeployDeployedRemoteProxiesAfterAccountChange() { + if (remoteProxyAutoRedeployInFlightRef.current) { + return; + } + + const statuses = remoteProxyStatusesRawRef.current; + const servers = settingsRef.current.remoteServers.filter((server) => { + const status = statuses[server.id]; + return Boolean( + status?.installed || + status?.serviceInstalled || + status?.running || + status?.enabled, + ); + }); + + if (servers.length === 0) { + return; + } + + remoteProxyAutoRedeployInFlightRef.current = true; + const failures: Array<{ server: RemoteServerConfig; error: string }> = []; + + try { + for (const server of servers) { + if (!(await ensureRemoteLocalDependency(server))) { + continue; + } + + setRemoteDeployProgress({ + serverId: server.id, + label: server.label, + stage: "validating", + progress: 6, + detail: null, + }); + setDeployingRemoteProxyId(server.id); + + try { + const status = await invoke("deploy_remote_proxy", { + input: { + server, + }, + }); + setRemoteProxyStatusesRaw((current) => ({ + ...current, + [server.id]: status, + })); + } catch (error) { + const errorText = String(error); + failures.push({ server, error: errorText }); + setRemoteProxyStatusesRaw((current) => ({ + ...current, + [server.id]: buildRemoteProxyFallback(server, errorText), + })); + } finally { + setRemoteDeployProgress((current) => + current?.serverId === server.id ? null : current, + ); + setDeployingRemoteProxyId((current) => + current === server.id ? null : current, + ); + } + } + } finally { + remoteProxyAutoRedeployInFlightRef.current = false; + } + + if (failures.length > 0) { + const firstFailure = failures[0]; + setNotice({ + type: "error", + message: copy.notices.remoteProxyDeployFailed( + firstFailure.server.label, + localizeError(firstFailure.error), + ), + }); + } + } + const onStartRemoteProxy = useCallback(async (server: RemoteServerConfig) => { if (startingRemoteProxyId === server.id) { return; @@ -1660,6 +1749,7 @@ export function useCodexController() { try { await invoke("delete_account", { id: account.id }); setAccounts((prev) => prev.filter((item) => item.id !== account.id)); + void redeployDeployedRemoteProxiesAfterAccountChange(); setNotice({ type: "ok", message: copy.notices.accountDeleted }); } catch (error) { setNotice({ @@ -1681,6 +1771,7 @@ export function useCodexController() { restartEditorTargets: settings.restartEditorTargets, }); await loadAccounts(); + void redeployDeployedRemoteProxiesAfterAccountChange(); let baseNotice: Notice; if (!settings.launchCodexAfterSwitch) {