mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-04 02:52:55 +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,7 +15,7 @@ use axum::{
|
||||
};
|
||||
use tauri::{
|
||||
async_runtime::JoinHandle, webview::Color, AppHandle, Manager, RunEvent, WebviewUrl,
|
||||
WebviewWindowBuilder,
|
||||
WebviewWindow, WebviewWindowBuilder,
|
||||
};
|
||||
use tauri_plugin_opener::OpenerExt;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
@@ -52,12 +52,30 @@ fn open_terminal_with_command(command: String) -> tauri::Result<()> {
|
||||
.spawn()?;
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let _ = command;
|
||||
const TERMINALS: &[(&str, &[&str])] = &[
|
||||
("x-terminal-emulator", &["-e"]),
|
||||
("gnome-terminal", &["--"]),
|
||||
("konsole", &["-e"]),
|
||||
("xfce4-terminal", &["--execute"]),
|
||||
("alacritty", &["-e"]),
|
||||
("kitty", &[]),
|
||||
];
|
||||
let script = format!("{command}; exec bash");
|
||||
for (terminal, separator) in TERMINALS {
|
||||
let mut process = Command::new(terminal);
|
||||
process.args(*separator);
|
||||
process.arg("bash").arg("-c").arg(&script);
|
||||
match process.spawn() {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => continue,
|
||||
Err(error) => return Err(error.into()),
|
||||
}
|
||||
}
|
||||
Err(tauri::Error::from(std::io::Error::new(
|
||||
std::io::ErrorKind::Unsupported,
|
||||
"terminal guidance is unsupported on this platform",
|
||||
std::io::ErrorKind::NotFound,
|
||||
"no supported terminal emulator found",
|
||||
)))
|
||||
}
|
||||
}
|
||||
@@ -96,7 +114,10 @@ fn desktop_api_router(app: AppHandle) -> Router {
|
||||
.layer(Extension(app))
|
||||
}
|
||||
|
||||
fn create_main_window(app: &AppHandle, address: std::net::SocketAddr) -> tauri::Result<()> {
|
||||
fn create_main_window(
|
||||
app: &AppHandle,
|
||||
address: std::net::SocketAddr,
|
||||
) -> tauri::Result<WebviewWindow> {
|
||||
let url = format!("http://{address}/__byok-api__/")
|
||||
.parse()
|
||||
.expect("local frontend URL");
|
||||
@@ -108,15 +129,15 @@ fn create_main_window(app: &AppHandle, address: std::net::SocketAddr) -> tauri::
|
||||
.background_color(Color(20, 20, 20, 255))
|
||||
.decorations(cfg!(target_os = "macos"))
|
||||
.shadow(true)
|
||||
.resizable(true);
|
||||
.resizable(true)
|
||||
.visible(false);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let builder = builder
|
||||
.title_bar_style(tauri::TitleBarStyle::Overlay)
|
||||
.hidden_title(true);
|
||||
|
||||
builder.build()?;
|
||||
Ok(())
|
||||
builder.build()
|
||||
}
|
||||
|
||||
pub fn run() {
|
||||
@@ -160,6 +181,9 @@ pub fn run() {
|
||||
let listener = tauri::async_runtime::block_on(server.bind())?;
|
||||
let address = listener.local_addr()?;
|
||||
tauri::async_runtime::block_on(server.harness().cleanup_stale_settings())?;
|
||||
let silent_start = tauri::async_runtime::block_on(server.store().desktop_settings())
|
||||
.map(|settings| settings.silent_start)
|
||||
.unwrap_or(false);
|
||||
let shutdown = CancellationToken::new();
|
||||
let server_shutdown = shutdown.clone();
|
||||
let app_handle = app.handle().clone();
|
||||
@@ -176,7 +200,13 @@ pub fn run() {
|
||||
server: Mutex::new(Some(task)),
|
||||
exiting: AtomicBool::new(false),
|
||||
});
|
||||
create_main_window(app.handle(), address)?;
|
||||
let window = create_main_window(app.handle(), address)?;
|
||||
if silent_start {
|
||||
tracing::info!("silent start enabled; keeping the main window hidden");
|
||||
} else {
|
||||
window.show()?;
|
||||
window.set_focus()?;
|
||||
}
|
||||
tray::create(app)?;
|
||||
Ok(())
|
||||
})
|
||||
|
||||
@@ -66,7 +66,7 @@ export interface ModelConnectivityResult {
|
||||
output: string;
|
||||
}
|
||||
|
||||
export type CaState = "missing" | "untrusted" | "ready" | "invalid" | "unsupported";
|
||||
export type CaState = "missing" | "untrusted" | "ready" | "invalid";
|
||||
export type IntegrationState = "disabled" | "enabled" | "degraded";
|
||||
export interface CursorHarnessStatus {
|
||||
platform: string;
|
||||
@@ -114,6 +114,10 @@ export interface TabSettings {
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface DesktopSettings {
|
||||
silent_start: boolean;
|
||||
}
|
||||
|
||||
export interface OverviewMetrics {
|
||||
llm_calls: number;
|
||||
successful_calls: number;
|
||||
@@ -310,4 +314,6 @@ export const api = {
|
||||
setProxySettings: (settings: ProxySettingsInput) => request<ProxySettings>("/settings/proxy", { method: "PUT", body: JSON.stringify(settings) }),
|
||||
tabSettings: () => request<TabSettings>("/settings/tab"),
|
||||
setTabSettings: (settings: TabSettings) => request<TabSettings>("/settings/tab", { method: "PUT", body: JSON.stringify(settings) }),
|
||||
desktopSettings: () => request<DesktopSettings>("/settings/desktop"),
|
||||
setDesktopSettings: (settings: DesktopSettings) => request<DesktopSettings>("/settings/desktop", { method: "PUT", body: JSON.stringify(settings) }),
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -431,8 +431,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 22,
|
||||
"column": 107
|
||||
"line": 21,
|
||||
"column": 65
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -484,7 +484,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 38,
|
||||
"line": 37,
|
||||
"column": 59
|
||||
},
|
||||
{
|
||||
@@ -576,7 +576,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 87,
|
||||
"line": 120,
|
||||
"column": 27
|
||||
}
|
||||
]
|
||||
@@ -789,7 +789,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 51,
|
||||
"line": 72,
|
||||
"column": 29
|
||||
}
|
||||
]
|
||||
@@ -803,7 +803,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 83,
|
||||
"line": 116,
|
||||
"column": 13
|
||||
}
|
||||
]
|
||||
@@ -1320,6 +1320,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"47d1c20aa017ff05": {
|
||||
"source": "开机启动时不显示主窗口,仅保留系统托盘图标。",
|
||||
"kind": "text",
|
||||
"placeholders": [],
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 102,
|
||||
"column": 17
|
||||
}
|
||||
]
|
||||
},
|
||||
"48b970b568a7f8f9": {
|
||||
"source": "代理设置",
|
||||
"kind": "text",
|
||||
@@ -1355,7 +1367,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 82,
|
||||
"line": 115,
|
||||
"column": 13
|
||||
}
|
||||
]
|
||||
@@ -1514,8 +1526,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 23,
|
||||
"column": 222
|
||||
"line": 22,
|
||||
"column": 205
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1665,7 +1677,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 40,
|
||||
"line": 48,
|
||||
"column": 40
|
||||
}
|
||||
]
|
||||
@@ -1789,7 +1801,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "api.ts",
|
||||
"line": 290,
|
||||
"line": 294,
|
||||
"column": 43
|
||||
}
|
||||
]
|
||||
@@ -1801,7 +1813,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 80,
|
||||
"line": 113,
|
||||
"column": 18
|
||||
}
|
||||
]
|
||||
@@ -1844,7 +1856,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 36,
|
||||
"line": 35,
|
||||
"column": 14
|
||||
}
|
||||
]
|
||||
@@ -1974,7 +1986,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 51,
|
||||
"line": 72,
|
||||
"column": 78
|
||||
}
|
||||
]
|
||||
@@ -2015,18 +2027,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"722e156c20650a3f": {
|
||||
"source": "请使用 macOS 或 Windows。",
|
||||
"kind": "text",
|
||||
"placeholders": [],
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 22,
|
||||
"column": 26
|
||||
}
|
||||
]
|
||||
},
|
||||
"7392e20d61abaa07": {
|
||||
"source": "额外保存完整请求和流响应;默认只保存时间、状态与用量。",
|
||||
"kind": "text",
|
||||
@@ -2082,7 +2082,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "api.ts",
|
||||
"line": 285,
|
||||
"line": 289,
|
||||
"column": 43
|
||||
}
|
||||
]
|
||||
@@ -2185,8 +2185,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 23,
|
||||
"column": 138
|
||||
"line": 22,
|
||||
"column": 121
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2197,7 +2197,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 91,
|
||||
"line": 124,
|
||||
"column": 37
|
||||
}
|
||||
]
|
||||
@@ -2221,7 +2221,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "api.ts",
|
||||
"line": 231,
|
||||
"line": 235,
|
||||
"column": 21
|
||||
}
|
||||
]
|
||||
@@ -2250,12 +2250,12 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 68,
|
||||
"line": 89,
|
||||
"column": 18
|
||||
},
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 74,
|
||||
"line": 95,
|
||||
"column": 16
|
||||
}
|
||||
]
|
||||
@@ -2272,6 +2272,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"864597982c308d72": {
|
||||
"source": "已开启静默启动",
|
||||
"kind": "text",
|
||||
"placeholders": [],
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 61,
|
||||
"column": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
"86b7355ec3bd55ef": {
|
||||
"source": "隐藏 API Key",
|
||||
"kind": "text",
|
||||
@@ -2508,18 +2520,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"95f76d30c25d5eda": {
|
||||
"source": "当前系统暂不支持安装 CA",
|
||||
"kind": "text",
|
||||
"placeholders": [],
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 21,
|
||||
"column": 28
|
||||
}
|
||||
]
|
||||
},
|
||||
"966498853d801a52": {
|
||||
"source": "TAB 选择",
|
||||
"kind": "text",
|
||||
@@ -2558,8 +2558,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 23,
|
||||
"column": 205
|
||||
"line": 22,
|
||||
"column": 188
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2616,6 +2616,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"9e356080c56877f8": {
|
||||
"source": "已关闭静默启动",
|
||||
"kind": "text",
|
||||
"placeholders": [],
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 61,
|
||||
"column": 40
|
||||
}
|
||||
]
|
||||
},
|
||||
"9e46da6923836182": {
|
||||
"source": "如:2026-08-23 09:00、1小时前",
|
||||
"kind": "text",
|
||||
@@ -2683,11 +2695,28 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 65,
|
||||
"line": 86,
|
||||
"column": 29
|
||||
}
|
||||
]
|
||||
},
|
||||
"a1b8c98f29374a2f": {
|
||||
"source": "静默启动",
|
||||
"kind": "text",
|
||||
"placeholders": [],
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 101,
|
||||
"column": 18
|
||||
},
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 107,
|
||||
"column": 16
|
||||
}
|
||||
]
|
||||
},
|
||||
"a2901cd2743c1921": {
|
||||
"source": "模型服务的 API 根地址;修改后会同步更新该上游模型的路由身份。",
|
||||
"kind": "text",
|
||||
@@ -2734,8 +2763,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 23,
|
||||
"column": 170
|
||||
"line": 22,
|
||||
"column": 153
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2906,7 +2935,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 40,
|
||||
"line": 48,
|
||||
"column": 25
|
||||
}
|
||||
]
|
||||
@@ -2918,7 +2947,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 87,
|
||||
"line": 120,
|
||||
"column": 39
|
||||
}
|
||||
]
|
||||
@@ -3561,7 +3590,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 69,
|
||||
"line": 90,
|
||||
"column": 17
|
||||
}
|
||||
]
|
||||
@@ -3962,8 +3991,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 21,
|
||||
"column": 68
|
||||
"line": 20,
|
||||
"column": 33
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -4121,7 +4150,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 37,
|
||||
"line": 36,
|
||||
"column": 12
|
||||
}
|
||||
]
|
||||
@@ -4296,7 +4325,7 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/settings/AppLifecycleSettingsCard.tsx",
|
||||
"line": 91,
|
||||
"line": 124,
|
||||
"column": 25
|
||||
}
|
||||
]
|
||||
@@ -4308,8 +4337,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 21,
|
||||
"column": 89
|
||||
"line": 20,
|
||||
"column": 54
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -4422,8 +4451,8 @@
|
||||
"refs": [
|
||||
{
|
||||
"file": "components/cursor/CursorGates.tsx",
|
||||
"line": 22,
|
||||
"column": 73
|
||||
"line": 21,
|
||||
"column": 31
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"43cb41d62de2d179": "Proxy requires authentication",
|
||||
"461d6a57900c2ed7": "Connectivity test failed: {error}",
|
||||
"470049252e54de6a": "Success rate: {rate}",
|
||||
"47d1c20aa017ff05": "Hide the main window on startup and keep only the tray icon.",
|
||||
"48b970b568a7f8f9": "Proxy settings",
|
||||
"48d8db17bae06246": "{count} total",
|
||||
"492042ed1fdc29ed": "Version {version} is ready to install",
|
||||
@@ -137,7 +138,6 @@
|
||||
"6e86570183c3cdd0": "You're up to date",
|
||||
"7005693f4f050bce": "Cache I/O {cost}",
|
||||
"71eb2c6fce991a29": "Add provider",
|
||||
"722e156c20650a3f": "Use macOS or Windows.",
|
||||
"7392e20d61abaa07": "Also store complete requests and streamed responses; by default only timing, status, and usage are stored.",
|
||||
"75844712d53a24de": "Values must be strings; when editing, null keeps the original value of the corresponding sensitive Header.",
|
||||
"788db1cfec2a3db5": "Theme",
|
||||
@@ -157,6 +157,7 @@
|
||||
"83fcfb4c1f2c1641": "Fetch models",
|
||||
"842b9f11cdd96bda": "Launch at login",
|
||||
"84924374710e03bd": "Base URL must be a valid URL",
|
||||
"864597982c308d72": "Silent start enabled",
|
||||
"86b7355ec3bd55ef": "Hide API Key",
|
||||
"8716e1344b0daddb": "Cursor official",
|
||||
"878a8ab176429a86": "View instructions",
|
||||
@@ -174,7 +175,6 @@
|
||||
"946b3ffc02f026c0": "Delete this model?",
|
||||
"94803f35c825e47a": "Full request URL",
|
||||
"94df1e7f04815daf": "Used only for display; does not change the model name sent to the provider.",
|
||||
"95f76d30c25d5eda": "CA installation is not supported on this system",
|
||||
"966498853d801a52": "TAB connection",
|
||||
"9850ed41a5bfbb0c": "{count} selected",
|
||||
"997ec8201c2adeda": "Open terminal to install CA",
|
||||
@@ -182,12 +182,14 @@
|
||||
"9ac0ac940982895d": "Select provider",
|
||||
"9c41b3a9e12ac994": "Reasoning effort",
|
||||
"9d8f2ef4e85ea665": "Custom context tokens",
|
||||
"9e356080c56877f8": "Silent start disabled",
|
||||
"9e46da6923836182": "For example: 2026-08-23 09:00, 1 hour ago",
|
||||
"9f6fee1aba17a565": "Language",
|
||||
"9fb48101d237ff96": "Last week",
|
||||
"a026f37e613cf48b": "Output Tokens",
|
||||
"a03a1a0cb35414f8": " must be an integer from 0 to 65535",
|
||||
"a1a42cd9b16e2162": "Application",
|
||||
"a1b8c98f29374a2f": "Silent start",
|
||||
"a2901cd2743c1921": "The API root URL for the model service. Changing it also updates the routing identity of this provider's models.",
|
||||
"a3030bf8f16dc63c": "Save",
|
||||
"a363743025795ec7": "I've initialized it — refresh",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"43cb41d62de2d179": "代理需要认证",
|
||||
"461d6a57900c2ed7": "连通性测试失败:{error}",
|
||||
"470049252e54de6a": "成功占比:{rate}",
|
||||
"47d1c20aa017ff05": "开机启动时不显示主窗口,仅保留系统托盘图标。",
|
||||
"48b970b568a7f8f9": "代理设置",
|
||||
"48d8db17bae06246": "共 {count} 条",
|
||||
"492042ed1fdc29ed": "版本 {version} 可以安装",
|
||||
@@ -137,7 +138,6 @@
|
||||
"6e86570183c3cdd0": "当前已是最新版本",
|
||||
"7005693f4f050bce": "缓存读写 {cost}",
|
||||
"71eb2c6fce991a29": "添加上游",
|
||||
"722e156c20650a3f": "请使用 macOS 或 Windows。",
|
||||
"7392e20d61abaa07": "额外保存完整请求和流响应;默认只保存时间、状态与用量。",
|
||||
"75844712d53a24de": "值必须是字符串;编辑时 null 表示保留对应敏感 Header 的原值。",
|
||||
"788db1cfec2a3db5": "主题",
|
||||
@@ -157,6 +157,7 @@
|
||||
"83fcfb4c1f2c1641": "获取模型",
|
||||
"842b9f11cdd96bda": "开机启动",
|
||||
"84924374710e03bd": "Base URL 必须是有效地址",
|
||||
"864597982c308d72": "已开启静默启动",
|
||||
"86b7355ec3bd55ef": "隐藏 API Key",
|
||||
"8716e1344b0daddb": "Cursor 官方",
|
||||
"878a8ab176429a86": "查看说明",
|
||||
@@ -174,7 +175,6 @@
|
||||
"946b3ffc02f026c0": "确定删除这个模型吗?",
|
||||
"94803f35c825e47a": "请求完整地址",
|
||||
"94df1e7f04815daf": "仅用于界面展示,不会改变发送给上游的模型名称。",
|
||||
"95f76d30c25d5eda": "当前系统暂不支持安装 CA",
|
||||
"966498853d801a52": "TAB 选择",
|
||||
"9850ed41a5bfbb0c": "已选 {count} 项",
|
||||
"997ec8201c2adeda": "打开终端安装 CA",
|
||||
@@ -182,12 +182,14 @@
|
||||
"9ac0ac940982895d": "选择上游",
|
||||
"9c41b3a9e12ac994": "思考强度",
|
||||
"9d8f2ef4e85ea665": "自定义上下文 tokens",
|
||||
"9e356080c56877f8": "已关闭静默启动",
|
||||
"9e46da6923836182": "如:2026-08-23 09:00、1小时前",
|
||||
"9f6fee1aba17a565": "语言",
|
||||
"9fb48101d237ff96": "近一周",
|
||||
"a026f37e613cf48b": "输出 Token",
|
||||
"a03a1a0cb35414f8": "必须是 0–65535 之间的整数",
|
||||
"a1a42cd9b16e2162": "应用设置",
|
||||
"a1b8c98f29374a2f": "静默启动",
|
||||
"a2901cd2743c1921": "模型服务的 API 根地址;修改后会同步更新该上游模型的路由身份。",
|
||||
"a3030bf8f16dc63c": "保存",
|
||||
"a363743025795ec7": "我已初始化,刷新",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { isTauri } from "@tauri-apps/api/core";
|
||||
import { disable, enable, isEnabled } from "@tauri-apps/plugin-autostart";
|
||||
import { relaunch } from "@tauri-apps/plugin-process";
|
||||
import { check, type Update } from "@tauri-apps/plugin-updater";
|
||||
import { api } from "../api";
|
||||
|
||||
export function hasNativeAppLifecycle(): boolean {
|
||||
return isTauri();
|
||||
@@ -20,6 +21,14 @@ export async function writeAutostart(enabled: boolean): Promise<void> {
|
||||
await (enabled ? enable() : disable());
|
||||
}
|
||||
|
||||
export async function readSilentStart(): Promise<boolean> {
|
||||
return (await api.desktopSettings()).silent_start;
|
||||
}
|
||||
|
||||
export async function writeSilentStart(silentStart: boolean): Promise<void> {
|
||||
await api.setDesktopSettings({ silent_start: silentStart });
|
||||
}
|
||||
|
||||
export async function checkForUpdate(): Promise<Update | null> {
|
||||
return check();
|
||||
}
|
||||
|
||||
@@ -170,7 +170,11 @@ export function CursorSettingsPage() {
|
||||
}
|
||||
};
|
||||
const openCaTerminal = () => {
|
||||
if (caCommand) void api.openCursorCaInstallTerminal(caCommand);
|
||||
if (caCommand) {
|
||||
api
|
||||
.openCursorCaInstallTerminal(caCommand)
|
||||
.catch((cause) => message(cause instanceof Error ? cause.message : String(cause)));
|
||||
}
|
||||
setCaCommand(null);
|
||||
setWaitingForCaRefresh(true);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user