1. 项目概述一个桌面端AI模型网关的诞生如果你同时在使用 Claude Code、Codex 和 Gemini CLI 这几个AI编程工具那你大概率和我一样被一堆琐碎又恼人的问题困扰过。服务商突然限流代码写到一半就断了手里有好几个账号每次切换都得手动改配置麻烦得要死想看看刚才的请求到底花了多少Token或者想回顾一下某个项目的完整对话历史却发现无从下手。更别提那些MCP服务器、预设提示词、Skill插件每个CLI都得配一遍简直是重复劳动的重灾区。CCG Gateway 这个项目就是在这种“忍无可忍”的状态下诞生的。它本质上是一个运行在你本地的智能网关和管理中心专门为 Claude Code、Codex 和 Gemini CLI 这三款工具服务。它的核心目标不是替代它们而是让它们变得更好用、更稳定、更透明。你可以把它想象成一个智能的“交通指挥中心”和“后勤大管家”。所有来自CLI的请求先经过这个网关由它来决定走哪条“路”哪个服务商或账号并记录下每一次“出行”的详细日志。同时它还把那些分散在各个CLI里的配置——账号、模型映射、MCP、插件——全部集中起来统一管理一次设置多处生效。我选择用 Rust Tauri Vue 3 这套技术栈来构建它是经过深思熟虑的。Rust 负责后端的网关核心逻辑它的高性能和内存安全对于需要处理并发请求、进行故障转移的网关服务至关重要能确保服务稳定不崩溃。Tauri 则用来构建跨平台的桌面应用外壳它比 Electron 更轻量打包出来的应用体积小启动快。前端用 Vue 3 和 TypeScript能快速构建出复杂且交互流畅的管理界面。这套组合拳保证了应用既强大可靠又拥有良好的用户体验。这篇文章我会带你深入这个项目的里里外外。不仅会拆解它的核心架构和那些解决痛点的巧思比如如何实现服务商的智能切换和故障拉黑还会手把手教你如何从零开始配置和使用它让它真正融入你的开发工作流。最后我还会分享开发过程中踩过的坑和总结出的实战经验无论你是想直接使用这个工具还是对如何构建一个类似的桌面端网关应用感兴趣相信都能从中获得启发。2. 核心痛点与设计思路拆解在动手写代码之前我花了大量时间梳理这些CLI工具在实际使用中到底有哪些“反人类”的设计。只有精准地定义问题解决方案才不会跑偏。下面这几个是我认为最核心、也最值得用技术手段去优化的痛点。2.1 服务商稳定性从“手动救火”到“自动容灾”这可能是最影响体验的一点。无论是使用官方API还是第三方中转服务都难免遇到问题官方API有调用频率限制Rate Limit可能突然就返回429错误中转服务商可能因为负载过高而响应变慢甚至短暂宕机还有些服务商会对特定模型比如最新的、能力最强的模型进行限额。当你在IDE里专注编码依赖AI实时补全或解释代码时请求突然失败工作流就被打断了。传统的做法是什么要么忍着等它自己恢复要么手动去修改CLI的配置文件把请求切换到另一个备用服务商或账号上。这非常低效而且破坏心流。CCG Gateway 的解决方案是引入“智能网关”和“故障转移”机制。它的工作流程是这样的请求拦截与路由将所有CLI配置中的API端点指向本地运行的CCG Gateway。这样任何请求都先到达网关。服务商池与健康检查网关背后维护着一个可配置的服务商列表包括多个中转服务商。网关会定期例如每分钟并发地向所有服务商发送一个轻量的“探针”请求比如请求一个简单模型列表来检测它们的可用性和响应延迟。智能路由决策当收到一个真实的模型调用请求时网关会根据预设的优先级从当前健康的服务商池中选择一个最优的通常是优先级最高且延迟最低的来转发请求。故障自动拉黑与恢复如果某个服务商连续失败N次可配置比如3次网关会将其暂时“拉黑”在接下来的M分钟可配置比如5分钟内不再向其发送请求避免持续冲击一个已经故障的节点。拉黑期结束后网关会再次尝试使用它如果恢复成功则重新加入健康池。这个过程对用户是完全透明的。你无需任何操作网关就像一个有经验的运维工程师在后台默默帮你处理好了所有故障切换保障你的请求始终有路可走。2.2 配置管理的碎片化从“四处奔波”到“中央集权”Claude Code、Codex、Gemini CLI 各自为政它们的配置API密钥、端点、模型参数分散在各自的应用目录或配置文件中。管理多个账号比如个人账号、团队账号、不同区域的账号或者使用多个中转服务商时切换成本极高。更麻烦的是那些“增强功能”的配置MCPModel Context Protocol服务器每个CLI都要单独配置MCP服务器的地址和密钥。预设提示词Custom Instructions你精心调校的一套用于代码生成的提示词需要在每个CLI里重复设置。Skill / 插件社区开发的第三方扩展安装和管理同样分散。CCG Gateway 的思路是“配置中心化”和“配置即服务”。统一配置仓库在CCG Gateway内部建立一个统一的数据库用来存储所有与CLI相关的配置项。配置与CLI解耦CLI本身不再直接保存完整的配置而是通过环境变量或启动参数告知CCG Gateway自己的身份例如CLI_TYPEclaude-code。动态配置下发当CLI启动或向网关发起请求时网关可以根据CLI的身份从中央仓库中读取对应的配置使用哪个服务商、启用哪些MCP、加载哪些提示词并动态地影响或补充CLI的行为。对于账号凭证等敏感信息网关可以提供一种安全的注入机制或者让CLI按需从网关获取。一处修改处处生效你在CCG Gateway的界面上添加了一个新的中转服务商或者启用了一个新的Skill。这个改动会立刻对所有关联的CLI生效无需你分别打开三个工具进行配置。2.3 可观测性缺失从“黑盒”到“全景仪表盘”原始的CLI工具对于请求的细节几乎不提供任何观察窗口。你发出了一个请求等了很久最后可能只得到一个简单的错误信息。你不知道这次请求实际使用了哪个服务商请求和响应的具体内容是什么对于调试复杂的提示词或工具调用至关重要消耗了多少输入/输出Token成本是多少整个请求的链路耗时分布网络传输、服务端处理是怎样的历史会话如何按项目归档和检索CCG Gateway 通过全面的日志记录和可视化界面来解决这个问题。全量请求日志网关作为所有流量的必经之路可以完整地记录下每一个请求和响应的原始数据经过脱敏处理如隐藏API密钥。这包括URL、请求头、请求体、响应状态码、响应体、耗时等。结构化存储与展示这些日志不是简单的文本文件而是被结构化地存储到数据库如SQLite中。前端界面可以提供强大的查询和过滤功能比如按时间范围、按CLI类型、按模型、按状态成功/失败进行筛选。会话项目管理网关可以解析请求中的上下文信息如果CLI支持传递会话或项目标识将属于同一个对话序列的请求归组形成完整的“会话历史”。你可以像使用聊天软件一样按项目浏览过去的所有对话查看AI的思考过程如果模型支持并返回了Chain-of-Thought和工具调用结果。统计与图表基于日志数据可以聚合生成丰富的统计数据总请求数、成功率、各服务商的使用量和成功率趋势、Token消耗总量与成本估算等并以图表形式直观展示在仪表盘上。2.4 模型兼容性与映射解决“方言”问题不同的服务商对同一个AI模型的命名可能不同。例如Claude 3.5 Sonnet这个模型在官方API中可能叫claude-3-5-sonnet-20241022而在某个中转服务商那里它可能被命名为claude-3.5-sonnet甚至是内部代号gml-5。如果你在CLI里配置的模型名是官方的直接转发到中转服务商就会导致“模型不存在”的错误。CCG Gateway 引入了“模型映射”规则。你可以在网关中为每个服务商配置一套映射规则。规则支持通配符非常灵活claude-3-5-sonnet* - gml-5将所有以claude-3-5-sonnet开头的模型名映射到该服务商的gml-5模型。gpt-4o - gpt-4将gpt-4o映射到服务商支持的gpt-4模型作为降级方案。*opus* - gml-5将任何包含opus字符的模型名都映射到gml-5。当网关收到一个请求比如模型是claude-3-5-sonnet-20241022它会先根据配置的映射规则将其转换为目标服务商能识别的名称如gml-5然后再转发。这样你在CLI里可以使用一套统一的、标准的模型名称而网关负责处理与不同服务商之间的“方言”转换。3. 架构设计与技术选型深度解析一个桌面应用既要承担高并发的网络代理任务又要提供复杂的配置管理界面这对架构设计提出了挑战。CCG Gateway 采用了典型的前后端分离架构但通过 Tauri 将其紧密集成在一个桌面应用中。3.1 整体架构前后端分离的桌面应用整个应用可以清晰地分为三层前端层Frontend基于 Vue 3 TypeScript Vite 构建的用户界面。负责所有可视化交互展示仪表盘、管理配置、查看日志和会话。它通过 HTTP 或 WebSocket 与后端通信。后端层Backend / Core这是应用的心脏由 Rust 编写。它又包含两个主要部分网关引擎Gateway Engine一个高性能的 HTTP 代理服务器负责接收来自各个 CLI 的请求执行路由、负载均衡、故障转移、模型映射、请求/响应日志记录等核心逻辑。应用后端Application Backend提供 RESTful API 或 RPC 接口用于处理前端的配置管理、数据查询日志、会话、统计等请求。它管理着 SQLite 数据库持久化所有配置和日志数据。通信层IPC在 Tauri 框架下前端WebView与后端Rust通过安全的进程间通信IPC机制进行交互。前端调用由tauri-apps/api封装的函数这些调用被 Tauri 核心路由到后端对应的 Rust 命令Command处理函数中执行完毕后将结果返回给前端。对于网关引擎需要主动向前端推送日志或状态更新的场景则可以使用 Tauri 的事件Event系统或建立一个独立的 WebSocket 连接。为什么选择 Tauri 而不是 Electron这是项目初期一个关键的技术决策。Electron 很流行但它的一个主要缺点是打包体积大因为要嵌入完整的 Chromium 浏览器和内存占用高。Tauri 采用了不同的思路它使用操作系统自带的 WebView在 Windows 上是 WebView2在 macOS 上是 WKWebView在 Linux 上是 WebKitGTK来渲染前端界面后端则是独立的 Rust 二进制文件。这带来了显著的优势打包体积极小一个简单的 Tauri 应用打包后可能只有几 MB而功能相似的 Electron 应用动辄 100MB 以上。启动速度更快利用系统原生 WebView启动和渲染速度有优势。内存占用更低避免了多个 Electron 应用共用同一份 Chromium 内存的浪费问题。安全性Rust 的内存安全特性减少了后端出现内存漏洞的风险Tauri 的 IPC 机制也经过了严格的安全沙箱设计。对于 CCG Gateway 这种需要常驻后台、对资源占用敏感的工具类桌面应用Tauri 是更优的选择。3.2 后端核心Rust 实现的网关引擎网关引擎是后端最复杂的部分我将其设计为一个独立的库ccg_gateway_lib以便于测试和复用。它的核心职责是高效、可靠地转发 HTTP 请求。核心数据结构与流程Gateway结构体这是网关的主入口持有所有关键状态。http_client: reqwest::Client一个配置了连接池、超时、重试等策略的 HTTP 客户端用于向上游服务商发起请求。使用reqwest这个强大的 Rust HTTP 客户端库。providers: VecArcProvider服务商列表。每个Provider包含服务商的配置名称、API端点、鉴权信息、模型映射规则、黑名单等和实时状态是否健康、最近错误次数、被拉黑直到何时等。Arc原子引用计数用于在多线程间安全共享。health_checker: HealthChecker健康检查器定期并发地对所有Provider进行健康检查更新其状态。db_pool: sqlx::SqlitePool数据库连接池用于异步写入请求日志和系统事件日志。请求处理流水线Pipeline当一个请求到达网关引擎会经过一系列步骤async fn handle_request(self, mut request: Request) - ResultResponse, GatewayError { // 1. 解析与验证提取模型名、CLI标识等信息 let (model, cli_id) self.parse_request(request)?; // 2. 路由决策根据CLI配置和模型筛选出可用的服务商列表 let candidate_providers self.select_candidates(model, cli_id)?; // 3. 故障转移循环尝试候选服务商直到成功或全部失败 for provider in candidate_providers { // 3.1 模型映射将请求中的模型名映射到服务商支持的名称 let mapped_model provider.map_model(model); // 3.2 修改请求将目标URL指向服务商添加鉴权头等 let upstream_request self.build_upstream_request(request, provider, mapped_model); // 3.3 发送请求并记录耗时 let start Instant::now(); match self.http_client.execute(upstream_request).await { Ok(response) { // 3.4 成功记录成功日志更新服务商状态返回响应 self.record_success(provider, model, start.elapsed()).await; return Ok(response); } Err(e) { // 3.5 失败记录失败日志更新服务商错误计数 self.record_failure(provider, model, e, start.elapsed()).await; // 如果错误次数达到阈值拉黑该服务商 if provider.should_blacklist() { self.blacklist_provider(provider, Duration::from_secs(300)).await; } // 继续尝试下一个服务商 continue; } } } // 4. 所有服务商都失败返回错误 Err(GatewayError::NoAvailableProvider) }注意以上是高度简化的伪代码用于说明逻辑。实际代码中需要考虑请求体的克隆、流式响应Streaming的处理、更精细的错误分类网络错误、4xx/5xx状态码等复杂情况。健康检查与故障拉黑HealthChecker会启动一个后台异步任务定时例如每30秒遍历所有服务商并发地发送一个轻量级请求比如GET /v1/models。根据响应时间和状态码判断其健康状态。Provider结构体内部维护一个错误计数器和一个拉黑截止时间。连续失败N次后状态被标记为“拉黑”在拉黑期间路由决策会跳过该服务商。拉黑时间到期后健康检查器会再次尝试如果成功则将其恢复。为什么用 Rust性能与并发网关需要处理潜在的并发请求Rust 的async/await异步编程模型和零成本抽象能轻松构建出高性能、高并发的网络服务。内存安全与可靠性没有垃圾回收GC的停顿更重要的是其所有权系统和借用检查器能在编译期杜绝数据竞争和大部分内存错误这对于需要长时间稳定运行的后台服务至关重要。丰富的生态系统reqwestHTTP客户端、tokio异步运行时、sqlx异步数据库访问、serde序列化等库成熟且高效能极大提升开发效率。3.3 前端架构模块化与状态管理前端采用 Vue 3 的 Composition API 和script setup语法搭配 TypeScript保证了代码的类型安全和良好的开发体验。状态管理由于应用状态比较复杂服务商列表、当前配置、日志数据、UI主题等我没有使用 Pinia 或 Vuex而是利用了 Vue 3 的reactive和computed结合自定义的 Composition 函数创建了多个逻辑清晰的状态模块。例如useProviderStore()管理服务商的增删改查、优先级调整、健康状态。useLogStore()管理请求日志和系统日志的查询、过滤和分页。useConfigStore()管理应用设置如主题、数据目录路径等。这种基于组合式函数的“去中心化”状态管理在中等复杂度的桌面应用中往往更灵活模块边界更清晰。UI 组件库为了保持轻量和自定义自由度我没有引入庞大的 UI 框架如 Element Plus 或 Ant Design Vue而是基于 Naive UI 或 PrimeVue 这类相对灵活、样式可塑性强的组件库进行开发并进行了大量的自定义样式以实现项目简介中提到的“古法调色”和独特的视觉体验。与后端通信所有与后端的交互都封装在独立的api.ts模块中内部使用 Tauri 的invoke函数调用对应的 Rust 命令。这样前端业务逻辑与通信细节解耦便于维护和测试。3.4 数据持久化SQLite 的轻量之选对于桌面应用数据存储方案需要满足轻量、无需单独部署服务、读写性能好、支持复杂查询。SQLite 是完美选择。数据库设计核心表providers存储所有服务商配置。accounts存储官方账号凭证加密存储。request_logs存储每一次网关转发的详细日志请求URL、方法、头、体响应状态码、体、耗时、Token用量等。注意请求/响应体可能很大需要考虑使用TEXT类型并做好压缩或分页查询优化。system_events存储系统事件服务商切换、拉黑、恢复等。sessions和messages关联存储会话历史按项目分组。mcp_servers,prompt_templates,skills,plugins分别存储对应的配置信息。使用sqlx库进行数据库操作它支持编译时检查 SQL 语句能有效避免运行时 SQL 错误并且完全异步与tokio运行时无缝集成。4. 核心功能实现与配置详解理解了架构我们来看看具体怎么用。CCG Gateway 的设计目标是开箱即用但充分的配置能让它更贴合你的个人工作流。4.1 服务商与账号管理智能路由的基石这是网关的核心配置区域。你需要在这里告诉网关有哪些可用的“道路”。添加中转服务商在“服务商管理”界面点击“添加服务商”。基本信息填写服务商名称自定义用于识别、API 基础地址例如https://api.your-provider.com/v1。鉴权信息通常是 API Key。网关支持在请求头中注入Authorization: Bearer your-key。重要为了安全网关会加密存储你的 API Key。模型映射规则这是关键。点击“添加映射”输入规则。例如模式claude-3-5-sonnet*目标gml-5这意味着当请求的模型名匹配claude-3-5-sonnet-20241022或claude-3-5-sonnet-latest时实际会请求该服务商的gml-5模型。模型黑名单如果该服务商明确不支持某些模型比如不支持gpt-4可以将其加入黑名单。当请求这些模型时网关会直接跳过此服务商尝试列表中的下一个。高级设置故障拉黑阈值连续失败多少次后拉黑默认3次。拉黑时长拉黑多少分钟默认5分钟。自定义 User-Agent有些服务商可能对 UA 有要求可以在这里覆盖。拖拽调整优先级服务商列表的顺序就是网关的优先级顺序。当多个服务商都健康时网关会优先选择排在最上面的。你可以直接用鼠标拖拽列表项来调整顺序非常直观。官方账号管理 出于安全考虑官方账号OpenAI, Anthropic, Google AI Studio的请求不经过网关转发。网关在这里的角色是“凭证管理器”。你可以添加多套官方账号的凭证API Key。通过拖拽可以快速切换当前CLI所使用的“活跃”账号。一键读取这是一个便利功能。如果你已经在 Claude Code 的配置文件中配置了 API Key可以点击“从当前 CLI 读取”网关会尝试解析对应的配置文件自动填充表单。实操心得模型映射的“通配符”技巧通配符*(匹配任意多个字符) 和?(匹配单个字符) 非常强大。例如一个服务商可能将所有 Claude 3 系列模型都统一用一个内部模型claude-v3来处理。你可以设置规则claude-3* - claude-v3。但要注意模糊匹配可能带来的意外映射尽量让模式更精确比如claude-3-5-*比claude-3*更好。4.2 日志与会话一切尽在掌握请求日志 所有经过网关的请求都会被记录在这里。表格通常包含以下列时间戳请求发生的时间。CLI发起请求的客户端Claude Code / Codex / Gemini。模型请求的原始模型和映射后的模型。状态成功✅或失败❌及状态码。耗时从网关发出请求到收到完整响应的总时间。输入/输出 Token从响应头或响应体中解析出的 Token 使用量。操作点击“详情”可以展开查看完整的请求和响应内容JSON 格式化便于阅读。你可以利用顶部的过滤栏快速定位问题。比如过滤“状态为失败”的日志查看失败原因或者按模型过滤分析某个模型的调用情况。系统日志 记录网关自身的运行事件例如INFO - Provider ProviderA marked as unhealthy after 3 consecutive failures.INFO - Provider ProviderB blacklisted until 2023-10-27 15:30:00.INFO - Health check passed for Provider ProviderC, restored to healthy pool.当遇到请求异常时结合请求日志和系统日志可以快速判断是某个服务商出了问题还是网络、或请求本身的问题。会话管理 这是提升开发体验的重要功能。要实现会话管理需要CLI客户端的配合在请求中携带一个唯一的“会话ID”或“项目ID”。CCG Gateway 会据此对消息进行分组。按项目浏览界面左侧是项目列表右侧是该项目的所有会话。每个会话包含一次完整的问答交互。搜索支持在项目名和会话内容中进行全文搜索快速找到历史对话。查看详情点击一个会话可以展开看到完整的消息流包括用户的提问、AI的回复、以及AI在回复过程中可能进行的“思考过程”Chain-of-Thought和“工具调用”Function Calling的细节。这对于复现问题、分析AI行为模式非常有价值。4.3 MCP、提示词与插件统一配置中心这是解决“配置碎片化”的核心体现。所有配置在网关中集中管理然后通过某种机制同步或应用到各个CLI。MCP 服务器管理在网关界面添加 MCP 服务器的配置名称、地址、认证信息。为每个 MCP 服务器选择要启用它的 CLI可多选。网关会生成对应的配置文件片段或环境变量。你需要根据不同的 CLI采取不同的应用方式对于 Claude Code可能需要将网关生成的配置写入到 Claude Code 的特定配置目录下的mcp_servers.json文件中。对于 Codex / Gemini CLI可能需要通过设置环境变量MCP_SERVERS来指定网关提供的一个动态配置URL或者由网关直接修改其配置文件。注意具体的集成方式取决于各个 CLI 对 MCP 的支持程度和配置方式。CCG Gateway 需要提供相应的“适配器”或“插件”来实现无缝集成。在项目初期可能需要一些手动的配置步骤。预设提示词与 Skill/插件管理 操作逻辑类似。在网关中创建或导入你的提示词模板、Skill通常是一组脚本或配置或插件。然后通过勾选将其分配给一个或多个 CLI。网关负责将这些资源文件同步到各个 CLI 的预期目录下或者在 CLI 启动时通过环境变量告知其资源位置。从 Git 仓库安装 Skill/插件这是一个非常实用的功能。你只需要输入 Git 仓库的 URL网关可以自动执行git clone并将仓库克隆到本地指定目录同时完成必要的依赖安装或构建步骤。这大大简化了社区扩展的安装流程。4.4 备份与恢复数据无忧你的所有配置、日志、会话历史都存储在本地 SQLite 数据库文件中。定期备份非常重要。本地备份/恢复 在设置界面直接点击“导出数据库”会生成一个.db.backup或.zip文件。恢复时选择该文件即可。这个过程本质上是 SQLite 的VACUUM INTO命令或文件复制。WebDAV 云备份 这是实现“跨设备同步配置”的关键。在设置中配置你的 WebDAV 服务器地址、目录、用户名和密码支持加密存储。点击“立即备份”网关会将本地数据库打包、加密可选然后上传到配置的 WebDAV 路径下文件名可能包含时间戳如ccg_gateway_backup_20231027_153000.zip。在另一台设备上安装 CCG Gateway配置相同的 WebDAV 信息然后从“备份列表”中选择最新的备份文件进行恢复。自动备份可以设置定时任务如每天凌晨3点自动执行备份到 WebDAV。踩坑记录WebDAV 兼容性不同的 WebDAV 服务实现如坚果云、Nextcloud、各种NAS可能有细微差异。在开发时需要使用一个兼容性较好的 Rust WebDAV 客户端库如dav-client并处理好各种异常情况比如服务器返回的非标准状态码、目录不存在时的自动创建等。务必在设置界面提供“测试连接”按钮让用户先验证配置是否正确。5. 开发、构建与部署实战如果你想从源码运行或参与贡献这部分是为你准备的。5.1 环境准备与项目结构环境要求Rust: 1.80。建议使用rustup安装和管理。Node.js: 18。建议使用nvm或fnm安装。包管理器:pnpm推荐速度更快或npm。Tauri CLI: 全局安装cargo install tauri-cli。项目结构概览ccg-gateway/ ├── src-tauri/ # Tauri 后端 (Rust) │ ├── Cargo.toml │ ├── src/ │ │ ├── main.rs # 应用入口Tauri 构建设置 │ │ ├── cmd.rs # 定义供前端调用的 Rust 命令 │ │ ├── gateway/ # 网关引擎核心模块 │ │ ├── db/ # 数据库操作模块 │ │ └── ... │ └── ... ├── frontend/ # 前端 (Vue 3 TypeScript) │ ├── package.json │ ├── vite.config.ts │ ├── src/ │ │ ├── main.ts │ │ ├── App.vue │ │ ├── components/ # Vue 组件 │ │ ├── views/ # 页面组件 │ │ ├── stores/ # 状态管理 │ │ ├── api/ # 后端 API 调用封装 │ │ └── ... │ └── ... ├── dev.bat / dev.sh # 一键启动脚本 └── README.md5.2 从源码运行两种方式方式一使用一键启动脚本推荐适合开发项目根目录下的dev.bat(Windows) 或dev.sh(macOS/Linux) 脚本封装了完整的开发命令。# Windows (PowerShell) .\dev.bat # macOS/Linux ./dev.sh这个脚本会同时启动前端开发服务器Vite通常运行在http://localhost:5173支持热重载HMR。Tauri 应用窗口其内部 WebView 会加载前端开发服务器的地址。任何前端代码的修改会立即在窗口中反映出来。修改后端 Rust 代码后需要手动重启 Tauri 应用关闭窗口再运行脚本或 Tauri 可能支持部分热重载。方式二手动启动更灵活# 1. 启动前端开发服务器 cd frontend pnpm install # 首次运行需要 pnpm dev # 2. 在新的终端中启动 Tauri 后端 cd src-tauri cargo run这种方式让你可以更清晰地看到前后端各自的日志输出。5.3 配置详解环境变量CCG Gateway 使用环境变量进行基础配置这比硬编码在代码中更灵活也便于不同环境开发/生产的切换。环境变量默认值说明与建议CCG_GATEWAY_HOST127.0.0.1后端API监听地址。除非你想让同一网络下的其他设备也能访问网关的管理界面有安全风险否则保持127.0.0.1localhost即可。CCG_GATEWAY_PORT7788后端API监听端口。如果端口冲突可以修改。记得在CLI配置中也要对应修改网关地址的端口。CCG_DATA_DIR~/.ccg-gateway数据目录。所有配置文件、数据库文件、日志文件都存储在这里。可以修改到一个更合适的位置比如D:\AI-Tools\ccg-data或/opt/ccg-data。CCG_LOG_FILEfalse文件日志开关。默认日志只输出到控制台。设为true或1后日志会额外写入到CCG_DATA_DIR下的ccg-gateway.log文件中便于长期排查问题。CCG_LOG_LEVELinfo,ccg_gatewaydebug,ccg_gateway_libdebug日志级别。这是最常用的配置项。格式为全局级别,模块1级别,模块2级别。CCG_LOG_LEVEL配置详解日志级别从低到高有error,warn,info,debug,trace。级别越高输出信息越详细。默认值解释info,ccg_gatewaydebug,ccg_gateway_libdebug全局默认级别是info会输出一般性的信息、警告和错误。将ccg_gateway主程序和ccg_gateway_lib核心网关库这两个模块的级别单独设置为debug。这意味着你会看到这两个模块更详细的调试信息比如每个请求的转发详情、健康检查结果等这对于开发和调试非常有用。示例CCG_LOG_LEVELwarn只输出警告和错误非常安静。CCG_LOG_LEVELdebug全局输出debug及以上级别信息量很大。CCG_LOG_LEVELinfo,ccg_gateway_libtrace全局info但核心网关库输出最详细的trace日志包括每个HTTP请求的头部、体等用于深度调试网络问题。如何设置环境变量临时设置当前终端有效# macOS/Linux export CCG_GATEWAY_PORT8080 export CCG_LOG_LEVELdebug # 然后运行 cargo run 或 ./dev.sh # Windows PowerShell $env:CCG_GATEWAY_PORT8080 $env:CCG_LOG_LEVELdebug永久设置推荐macOS/Linux将export语句添加到你的 shell 配置文件~/.bashrc,~/.zshrc末尾然后执行source ~/.zshrc。Windows通过系统属性 - 高级 - 环境变量 进行设置或使用 PowerShell 命令[System.Environment]::SetEnvironmentVariable(CCG_GATEWAY_PORT, 8080, User)为用户级设置。5.4 构建与分发当开发完成需要打包成可分发应用时使用 Tauri 的构建命令cd src-tauri cargo tauri build这个过程会编译 Rust 后端为 Release 版本。构建前端生产版本pnpm build。将前端资源打包进可执行文件并生成对应平台的安装包。Windows: 生成.msi安装包和.exe可执行文件。macOS: 生成.app应用包和.dmg磁盘映像。Linux: 生成.AppImage和.deb等包。构建输出位于src-tauri/target/release/bundle/目录下。构建优化提示在构建前确保前端代码已经过 Tree Shaking 和压缩。Vite 在生产模式下默认会做这些优化。Rust 编译可以使用cargo build --release进行优化但tauri build已经包含了这一步。如果应用图标等资源文件有更新需要同步更新src-tauri/tauri.conf.json中的相关配置。6. 常见问题与故障排查即使设计得再完善在实际使用中也可能遇到各种问题。这里记录了一些常见场景和排查思路。6.1 网关服务无法启动症状启动应用后界面空白或提示“无法连接到后端服务”。检查端口占用默认端口7788可能被其他程序占用。通过命令lsof -i :7788(macOS/Linux) 或netstat -ano | findstr :7788(Windows) 查看。如果被占用修改CCG_GATEWAY_PORT环境变量并重启应用。检查环境变量确保CCG_DATA_DIR指向的目录存在且有读写权限。特别是 Windows 下如果路径包含空格或特殊字符建议用英文引号包裹或换用简单路径。查看日志这是最重要的手段。启动应用时查看控制台输出的日志如果从终端启动或者开启文件日志CCG_LOG_FILEtrue然后去数据目录下查看ccg-gateway.log文件。日志通常会明确指示错误原因如数据库连接失败、配置文件损坏等。6.2 CLI 无法通过网关访问 AI症状CLI 工具报错如连接超时、认证失败等。第一步确认 CLI 配置确保你的 Claude Code/Codex/Gemini CLI 的配置中API 端点Base URL已经修改为http://127.0.0.1:7788或你自定义的CCG_GATEWAY_HOST:PORT。API Key 可以留空或填写任意值因为网关会用自己的配置进行替换。有些 CLI 可能不允许 Key 为空可以填一个占位符如gateway-key。第二步检查网关日志在 CCG Gateway 的“请求日志”界面查看是否有对应的请求记录。如果没有说明请求根本没到达网关问题出在 CLI 配置或网络层面。如果有记录但状态是失败的查看详情中的错误信息。第三步分析网关日志详情连接失败/超时可能是网关到上游服务商的网络问题或者服务商地址配置错误。检查服务商的“API 基础地址”是否正确。认证失败 (401/403)检查服务商配置中的 API Key 是否正确是否有过期。对于官方账号检查账号凭证是否正确。模型不存在 (404)检查请求的模型名是否在该服务商的支持列表中或者检查“模型映射”规则是否正确配置。可以在服务商管理页面使用“模型测试”功能验证该服务商对目标模型的实际支持情况。速率限制 (429)网关触发了服务商的速率限制。考虑在网关中为该服务商配置请求速率限制如果功能支持或者添加更多服务商进行负载均衡。第四步检查服务商状态在“服务商管理”界面查看目标服务商的状态是否是“健康”或“已拉黑”。如果被拉黑可以手动点击“恢复”或等待自动恢复。6.3 模型映射不生效症状请求日志显示使用了原始模型名而不是映射后的名字导致服务商返回模型不存在错误。确认映射规则在服务商编辑界面仔细检查模型映射规则。规则是“模式 - 目标”的格式。确保“模式”能匹配到你请求中的完整模型名。例如请求模型是claude-3-5-sonnet-20241022规则claude-3-5-sonnet是无法匹配的需要写成claude-3-5-sonnet*或claude-3-5-sonnet-20241022。规则优先级如果有多个规则可以匹配同一个模型网关通常会使用第一个匹配的规则。检查规则顺序。通配符转义如果你的模型名中确实包含*或?字符需要确认映射引擎是否支持转义。通常这类字符被保留为通配符。查看日志在CCG_LOG_LEVEL中为ccg_gateway_lib模块设置debug或trace级别可以在日志中看到模型映射的详细过程包括原始模型、尝试匹配的规则、以及最终映射结果。6.4 备份与恢复失败症状本地备份文件无法生成或 WebDAV 备份/恢复操作失败。本地备份失败检查CCG_DATA_DIR目录的磁盘空间和写入权限。备份操作通常需要复制或导出整个数据库文件。WebDAV 连接失败URL 格式确保 WebDAV 地址格式正确通常是https://your-webdav-server.com/remote.php/dav/files/username/或https://your-server:port/dav/。尾部斜杠有时很重要。认证信息用户名和密码是否正确。有些服务如坚果云需要使用应用密码而非账号密码。网络与防火墙确认网络可以访问 WebDAV 服务器且端口通常是 HTTPS 的 443 或自定义端口未被防火墙阻挡。使用“测试连接”务必先使用配置界面提供的“测试连接”功能确认基本信息无误。恢复失败恢复文件损坏或不兼容。确保备份文件是从相同或兼容版本的 CCG Gateway 中导出的。恢复前建议先关闭 CCG Gateway 应用。6.5 性能问题症状感觉请求变慢或者网关界面卡顿。请求延迟高在“请求日志”中查看耗时。如果耗时主要花在“网关处理”阶段可能是网关本身性能瓶颈如数据库查询慢。可以尝试清理旧的日志数据。如果耗时主要在“上游服务”那就是服务商响应慢。考虑使用“模型测试”功能对比不同服务商对同一模型的响应速度调整服务商优先级。界面卡顿如果日志数据量非常大几十万条在打开“请求日志”页面时一次性加载和渲染所有数据可能导致前端卡顿。确保前端实现了虚拟滚动或分页加载。检查电脑资源占用。Tauri 应用本身资源占用很低但如果同时打开过多其他应用也可能有影响。尝试重启应用。开发这个工具的过程是一个不断与自己使用的痛点对话并用代码去“平坑”的过程。从最初只是一个简单的代理脚本到如今集成配置管理、日志分析、会话回溯的完整桌面应用每一次功能迭代都源于实际使用中的不便。技术选型上Rust Tauri 的组合给了我很大的信心尤其是在性能和打包体积上的优势让最终的产品显得非常轻巧和敏捷。最大的体会是工具的价值在于无缝融入现有工作流。CCG Gateway 没有试图重新发明轮子而是选择成为 Claude Code、Codex、Gemini CLI 这些优秀工具背后的“增强层”和“连接器”。它解决的不是“从无到有”的问题而是“从有到优”的问题——让稳定的更稳定让方便的更方便让不可见的变得可见。如果你也在使用多个AI编程工具并且被切换、配置、调试这些问题困扰不妨试试 CCG Gateway。它的目标就是让你能更专注地回到代码本身而不是折腾工具。项目完全开源如果你有新的想法或遇到了 Bug非常欢迎在 GitHub 上提交 Issue 或 Pull Request。