mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-06 13:44:21 +08:00
feat: 支持 Linux 平台使用(CA 安装适配 + 静默启动),并修复 api_key 泄漏
CA 适配: - 移除 CA 模块对 macOS/Windows 的硬性限制,Linux 走完整初始化流程 - 按发行版自动选择安装命令:Debian 系 update-ca-certificates, Fedora/RHEL/Arch 系 update-ca-trust extract;已安装检测比对信任锚文件 - 删除不可达的 CaState::Unsupported 分支及前端"请使用 macOS 或 Windows"提示 静默启动(参考 cc-switch 实现逻辑): - 新增 DesktopSettings 持久化(service_settings 表)及 GET/PUT /api/settings/desktop - 主窗口统一以 visible(false) 创建,启动时读取配置决定是否显示 - 应用设置页:开启"开机启动"后显示"静默启动"子开关 安全修复: - ProviderEndpoint.api_key 增加 serde(skip_serializing), 避免明文 API Key 随 JSON 响应泄漏(provider_console 测试恢复通过) 其他: - Linux 补齐 open_terminal_with_command:按序探测 x-terminal-emulator / gnome-terminal / konsole 等并在新终端窗口执行命令 - "打开终端安装 CA"失败信息不再被前端静默吞掉 - 顺手修复上游遗留问题:desktop.rs 未使用导入、output.rs 测试模块位置、providers.rs 格式
This commit is contained in:
@@ -15,12 +15,11 @@ export function CursorCaGate({ busy, waitingForRefresh, onInitialize, onRefresh,
|
||||
const ready = useContext(CaReady);
|
||||
const { cursorHarness } = useAppStore();
|
||||
if (ready) return children;
|
||||
const unsupported = cursorHarness?.ca === "unsupported";
|
||||
const installedLocally = cursorHarness?.ca === "untrusted";
|
||||
return <div className={styles.gate}>
|
||||
<strong>{unsupported ? t("当前系统暂不支持安装 CA") : installedLocally ? t("需要在系统中信任本地 CA") : t("需要先初始化本地 CA")}</strong>
|
||||
<span>{unsupported ? t("请使用 macOS 或 Windows。") : installedLocally ? t("请在终端中粘贴授权命令并输入密码,完成后点击下方按钮") : t("CA 仅保存在本机,用于安全解析 Cursor 的 HTTPS 请求。")}</span>
|
||||
{!unsupported && <button className={controls.primary} disabled={busy} onClick={waitingForRefresh ? onRefresh : onInitialize}>{busy ? t("刷新中…") : waitingForRefresh ? t("我已初始化,刷新") : installedLocally ? t("打开终端安装 CA") : t("初始化 CA")}</button>}
|
||||
<strong>{installedLocally ? t("需要在系统中信任本地 CA") : t("需要先初始化本地 CA")}</strong>
|
||||
<span>{installedLocally ? t("请在终端中粘贴授权命令并输入密码,完成后点击下方按钮") : t("CA 仅保存在本机,用于安全解析 Cursor 的 HTTPS 请求。")}</span>
|
||||
<button className={controls.primary} disabled={busy} onClick={waitingForRefresh ? onRefresh : onInitialize}>{busy ? t("刷新中…") : waitingForRefresh ? t("我已初始化,刷新") : installedLocally ? t("打开终端安装 CA") : t("初始化 CA")}</button>
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ import {
|
||||
currentAppVersion,
|
||||
hasNativeAppLifecycle,
|
||||
readAutostart,
|
||||
readSilentStart,
|
||||
writeAutostart,
|
||||
writeSilentStart,
|
||||
} from "../../native/appLifecycle";
|
||||
import { updateStore, useUpdateStore } from "../../store/updateStore";
|
||||
import { Button } from "../ui/Button";
|
||||
@@ -19,6 +21,8 @@ export function AppLifecycleSettingsCard() {
|
||||
const [version, setVersion] = useState("…");
|
||||
const [autostart, setAutostart] = useState(false);
|
||||
const [loadingAutostart, setLoadingAutostart] = useState(native);
|
||||
const [silentStart, setSilentStart] = useState(false);
|
||||
const [loadingSilentStart, setLoadingSilentStart] = useState(native);
|
||||
|
||||
useEffect(() => {
|
||||
let disposed = false;
|
||||
@@ -28,6 +32,10 @@ export function AppLifecycleSettingsCard() {
|
||||
.then((enabled) => { if (!disposed) setAutostart(enabled); })
|
||||
.catch((cause) => message(cause instanceof Error ? cause.message : String(cause)))
|
||||
.finally(() => { if (!disposed) setLoadingAutostart(false); });
|
||||
void readSilentStart()
|
||||
.then((silent) => { if (!disposed) setSilentStart(silent); })
|
||||
.catch(() => {})
|
||||
.finally(() => { if (!disposed) setLoadingSilentStart(false); });
|
||||
}
|
||||
return () => { disposed = true; };
|
||||
}, [message, native]);
|
||||
@@ -45,6 +53,19 @@ export function AppLifecycleSettingsCard() {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleSilentStart = async (enabled: boolean) => {
|
||||
try {
|
||||
setLoadingSilentStart(true);
|
||||
await writeSilentStart(enabled);
|
||||
setSilentStart(await readSilentStart());
|
||||
message(enabled ? t("已开启静默启动") : t("已关闭静默启动"));
|
||||
} catch (cause) {
|
||||
message(cause instanceof Error ? cause.message : String(cause));
|
||||
} finally {
|
||||
setLoadingSilentStart(false);
|
||||
}
|
||||
};
|
||||
|
||||
const checkUpdate = async () => {
|
||||
try {
|
||||
const nextVersion = await updateStore.check();
|
||||
@@ -75,6 +96,18 @@ export function AppLifecycleSettingsCard() {
|
||||
onChange={(enabled) => void toggleAutostart(enabled)}
|
||||
/>
|
||||
</div>
|
||||
{autostart && <div className={styles.row}>
|
||||
<div>
|
||||
<strong>{t("静默启动")}</strong>
|
||||
<small>{t("开机启动时不显示主窗口,仅保留系统托盘图标。")}</small>
|
||||
</div>
|
||||
<Switch
|
||||
checked={silentStart}
|
||||
disabled={!native || loadingSilentStart}
|
||||
label={t("静默启动")}
|
||||
onChange={(enabled) => void toggleSilentStart(enabled)}
|
||||
/>
|
||||
</div>}
|
||||
<div className={styles.row}>
|
||||
<div>
|
||||
<strong>{t("软件更新")}</strong>
|
||||
|
||||
Reference in New Issue
Block a user