cc-switch 本地路由重构:显式开关 × 持久化意图全解
cc-switch 本地路由重构显式开关 × 持久化意图全解【免费下载链接】cc-switchA cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build Hermes Agent. Only official website: ccswitch.io项目地址: https://gitcode.com/GitHub_Trending/cc/cc-switch本次改动把「本地路由随启动隐式拉起、关掉又被悄悄打开」换成了「按应用持久化的enabled意图是唯一启动依据」。读完你能带走三点启动时到底依据什么决定是否恢复路由、start/stop如何把意图先落库再收敛、以及哪些契约目前还没有测试兜底。旧行为的代价想象一个场景你在设置里关闭了本地路由端口随即释放。可重启 CC Switch 后127.0.0.1:15721又自动听了起来——你那次「关闭」从未真正生效。这正是变更记录里被点名的缺陷v3.9.0-1的修复项「Disable auto-start on app launch by resetting enabled flag on stop」CHANGELOG.md以及v3.9.0-2的「remove global auto-start flag」CHANGELOG.md。根因是运行时状态与持久化意图脱节停止操作只清掉了内存里的服务句柄却把持久化的proxy_enabled意图静默留在了true。于是形成三条因果链停止只take()服务句柄、不回写意图 → 数据库里意图仍是true下次启动读取该意图 → 判定「应该运行」→ 端口被重新打开用户反复关闭、反复复活 → 开关「关了又开」本地端口始终无法保持关闭。新契约行为边界表改动后持久化的enabled/proxy_enabled成为「期望状态」的唯一来源。启动、停止都先写意图、再收敛运行态二者不再各走各的。触发条件期望行为持久化影响启动时某应用proxy_config.enabled true恢复该应用接管并拉起路由不改写意图只读用户手动启动路由监听端口置proxy_enabled true意图落库为开启用户手动停止stop停止服务置proxy_enabled false意图落库为关闭跨重启保持用户关闭路由stop_with_restore恢复 Live 配置 清除各应用enabled意图清除下次不自动恢复仍有应用处于接管态时调用停止拒绝停止并返回提示无任何持久化影响某应用enabledtrue但恢复失败清除该应用状态避免下启重试该应用意图回滚不变量默认监听端口仍固定为15721src-tauri/src/proxy/types.rs接管依旧是按应用粒度的独立控制stop仅停服务与stop_with_restore停服务并恢复 Live 配置的语义分离保持不变异常退出后的残留恢复recover_from_crash路径也未改动。这些都不随本次显式开关的重构而变化。机制拆解从意图到运行态读取持久化意图以划定恢复范围启动时不猜测、不默认只从数据库读每个应用的enabled布尔值收集出「本次需要恢复接管」的白名单。没有任何应用为true就直接返回端口保持关闭。async fn enabled_proxy_apps_on_startup(db: Database) - Vecstatic str { let mut apps Vec::new(); for app_type in PROXY_STARTUP_APP_TYPES { if db.get_proxy_config_for_app(app_type).await .is_ok_and(|config| config.enabled) { apps.push(app_type); } } apps }该函数位于 src-tauri/src/lib.rs它是「启动依据什么」的唯一答案意图为false的应用永远不会被恢复直接否定了旧行为里「隐式拉起」的前提。按应用收敛接管状态拿到白名单后逐个恢复接管任何一项失败就回滚该应用避免下一次启动又重试同一个坏状态。for app_type in apps_to_restore { match state.proxy_service.set_takeover_for_app(app_type, true).await { Ok(()) { log::info!(✓ 已恢复 {app_type} 的代理接管状态); } Err(e) { log::error!(✗ 恢复 {app_type} 的代理接管状态失败: {e}); // 失败时清除该应用状态避免下次启动再次尝试 let _ state.proxy_service.set_takeover_for_app(app_type, false).await; } } }见 src-tauri/src/lib.rs。这段把「意图 → 运行态」的收敛做成了幂等循环且失败即回滚正是边界表中「恢复失败 → 意图回滚」一行的落点。启动即把意图先落库start()的第一步不是绑端口而是把proxy_enabled写成true并落库。意图先于运行态固化因此「启动了」这件事必然留下持久痕迹。let mut global_config self.db.get_global_proxy_config().await.map_err(...)?; if !global_config.proxy_enabled { global_config.proxy_enabled true; self.db.update_global_proxy_config(global_config.clone()).await.map_err(...)?; } // … 随后才读取配置、绑定端口见 src-tauri/src/services/proxy.rs。落库失败会直接向调用方报错而非继续绑端口杜绝了旧式「运行时起来了、意图却没写进去」的漂移。停止即回写关闭意图stop()在take()服务句柄、等任务结束后把proxy_enabled回写为false。关闭这一次是「真的关了」。if let Some(server) self.server.write().await.take() { server.stop().await.map_err(...)?; let mut global_config self.db.get_global_proxy_config().await.map_err(...)?; if global_config.proxy_enabled { global_config.proxy_enabled false; self.db.update_global_proxy_config(global_config).await...; } }见 src-tauri/src/services/proxy.rs。意图与运行态在同一函数里成对变更从结构上堵住了「停止只清运行时、意图残留true」这条复活路径。而stop_with_restore进一步清除各应用enabled保证手动关闭后下次启动不再自动恢复src-tauri/src/services/proxy.rs。异常路径与用户感知拒绝停止stop_proxy_server会先查接管状态只要还有任一应用处于接管态就返回中文提示「仍有应用处于代理接管状态请先…再停止」不产生任何持久化副作用src-tauri/src/commands/proxy.rs。端口绑定失败start()在TcpListener::bind失败时返回BindFailed错误如实呈现而非静默重试。停止超时服务停止带 5 秒超时保护超时返回StopTimeout并「强制继续」不会挂死整个退出流程src-tauri/src/proxy/server.rs。启动残留恢复检测到异常退出残留时先recover_from_crash再进入正常启动序列恢复与显式开关互不干扰src-tauri/src/lib.rs。用户需要做什么想关掉路由设置里关闭一次即可保持关闭想让某应用走路由对该应用单独开启接管停止被拒先逐应用关闭接管再停止升级后端口仍为15721无需改动测试如何守住契约src-tauri/tests/proxy_commands.rs当前只锁住「成本倍率」与「定价来源」两条命令的往返round-trip对proxy_enabled/enabled意图的落库与跨重启契约没有测试覆盖——这是本次重构最需要补的回归缺口。src-tauri/tests/proxy_commands.rs 中default_cost_multiplier_commands_round_trip仅断言倍率读写不涉及启停意图「停止后意图为 false」无断言。src-tauri/tests/provider_commands.rs涉及代理相关命令面但聚焦供应商命令未覆盖「启动按enabled恢复」这一收敛路径。一句话结论启停意图的持久化契约在仓库里当前无测试覆盖读者若要验证「关闭即持久」需自行以集成测试补断言。资料索引docs/user-manual/zh/4-proxy/4.1-service.md补充本地路由代理服务的用途与使用入口。src-tauri/src/services/proxy.rsstart/stop/stop_with_restore的完整实现比正文片段更全。src-tauri/src/lib.rs启动序列、recover_from_crash与恢复调用的完整上下文。src-tauri/src/commands/proxy.rs前后端命令边界看清「拒绝停止」等前端可见行为从哪来。CHANGELOG.md定位v3.9.0-1/v3.9.0-2两条自动启动相关变更的原始记录。【免费下载链接】cc-switchA cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build Hermes Agent. Only official website: ccswitch.io项目地址: https://gitcode.com/GitHub_Trending/cc/cc-switch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Codex CLI 指定 GPT-5-Codex,动态思考任务的 Base URL 走 TaoToken 通道

Codex CLI 指定 GPT-5-Codex,动态思考任务的 Base URL 走 TaoToken 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/6 10:34:53 阅读更多 →
600美元以内DIY开源四足机器人:树莓派+舵机方案全解析

600美元以内DIY开源四足机器人:树莓派+舵机方案全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 20:39:50 阅读更多 →
nn-zero-to-hero 神经网络教程:如何手写反向传播、从零搭语言模型

nn-zero-to-hero 神经网络教程:如何手写反向传播、从零搭语言模型

nn-zero-to-hero 神经网络教程:如何手写反向传播、从零搭语言模型 【免费下载链接】nn-zero-to-hero Neural Networks: Zero to Hero 项目地址: https://gitcode.com/GitHub_Trending/nn/nn-zero-to-hero 这是 "Neural Networks: Zero to Hero" 课…

2026/10/15 20:39:54 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/5 12:28:00 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/6 9:29:27 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/5 12:28:01 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/5 12:28:02 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/6 8:08:42 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/5 19:38:59 阅读更多 →

日新闻

周新闻

月新闻