Skip to content

桌面应用 ​

每个版本的 Release 都会附带 Electron 桌面应用构建产物,覆盖 macOS(Apple silicon 与 Intel)、Windows 和 Linux(x86_64 与 arm64)。

它是什么 ​

桌面应用 = 一个 Electron 窗口 + 一个控制台的后端。窗口里的界面始终是安装包里自带的这一份,后端只决定数据从哪来:内置在同一个安装包里的网关服务,或者你自己已经部署好的服务。

  • 后端为「本机」时,主进程会拉起网关(与 Docker 镜像中运行的 Next.js standalone 服务完全相同),等 /health 通过后再打开控制台窗口。
  • 网关只监听 127.0.0.1,不会暴露到局域网。
  • 后端为「本机」时,默认端口 8001,可以在首次启动的对话框、菜单里的「设置…」或「设置 → 桌面应用」里修改;填的是部署地址时只问地址,端口保持已保存的值。端口一旦被确定下来(在这里保存过,或用 CODEBUDDY_DESKTOP_PORT 指定过),被占用时就不会自动换,而是问你要用哪个。
  • 关闭窗口后(macOS)网关仍在后台运行,/v1/* 继续可用;退出应用才会停止网关。
  • 同一时间只有一个窗口、一个网关:再次启动应用或点击菜单栏图标,都只是把已经打开的窗口带到前台。macOS 上应用保留 Dock 图标,控制台就是众多窗口中的一个:除了菜单栏图标,也能从 Dock 或 Cmd+Tab 回到它。
  • 后端是本机时无需登录:控制台只监听回环地址,而且只认应用自己的那个窗口,登录页和「安全」设置都不会出现。后端是你自己部署的服务时两者都会回来,见下文。
  • 控制台只给应用自己的窗口:主进程每次启动时临时生成一个令牌,经环境变量交给网关、经 cookie 交给窗口,不带它的请求一律得到 404——所以浏览器打开 127.0.0.1 看不到控制台。/v1/* 与 /health 不在此列,它们是网关对外提供的接口。

后端 ​

首次启动会用系统自己的对话框来问后端:macOS 上是 AppKit 的对话框,Windows 上是 WinForms 窗体,Linux 上是 zenity 画出的那个。端口属于本机的网关,所以只有答案是「这台机器」时才会在同一个对话框里问端口——填的是部署地址,控制台用的端口保持已保存的值不变。屏幕上没有一处是本应用自己画的,所以外观、按钮、语言都跟着系统和控制台走。之后可以随时在菜单栏图标的菜单里用「设置…」改。没有给出任何答案,应用会直接退出——网关正是这个选择要决定的东西,替你选一个再启动不算答案。没有可以画对话框的桌面时(无头会话),应用不会改用自己画的页面,而是用这台电脑自己的消息框说明这一点;首次启动则直接退出。CODEBUDDY_DESKTOP_ASK=window 会改用应用自己的窗口来问,那是为了跑测试——原生对话框是测试点不到的。

  • 本机:启动安装包里内置的网关,数据都存在本机,不设登录。这是默认选项。
  • 我自己部署的服务:填一个 http:// 或 https:// 地址。桌面端照旧启动本机网关来渲染控制台,只是把 /admin-api/* 与 /v1/* 转发到那个服务:窗口里出现的始终是本应用自带的界面,不是那个服务返回的网页。首次连接会先探测 /health,确认它确实是 CodeBuddy2API 的部署;探测不通过时会弹出窗口说明是哪一种情况(没有响应,或者响应了但不是本服务),可以重试、改后端或在浏览器里打开它。它可能要求登录,登录由那个服务自己处理,桌面端不保存你的密码。
  • 断网或地址填错时,桌面端不会显示一个空白窗口:它会弹出上面那个窗口说明原因。

选了远端后端后,菜单里的「后端」一行显示它的地址;「复制地址」复制的是本机控制台的地址——/v1/* 会被转发,把它当作 API 端点同样可用。端口是本机网关服务控制台用的那一个,所以无论后端是本机还是远端,设置里都能改。

设置 ​

菜单栏图标的菜单里,「设置…」打开的是这台电脑自己的一个对话框,里面是这台电脑自己的标签页:macOS 上是 AppKit 的标签视图(放在 AppKit 画的 alert 里),Windows 上是 WinForms 的 TabControl。两者都是这台电脑上其它对话框用的那个控件,所以外观、按钮、语言都跟着系统和控制台走;屏幕上没有一处是本应用自己画的。Linux 上 zenity 没有标签页可用:先在一个列表里选一节,再用 zenity 自己的对话框问这一节,只用来说明的节则显示为一个信息框。

三个标签页:

  • 通用:与首次启动问的是同一个问题——后端是「本机」还是「我自己部署的服务」,以及本机网关服务控制台用的端口。上一次的答案没能用时(比如地址填得不对),这句话显示在这一页的顶部。
  • 数据:本机后端时列出数据目录与数据库文件的路径,下面还有一个链接——点它会在系统的文件管理器里打开那个目录,对话框不会因此关掉。远端后端时数据在那边的部署上,这一页因此只说明这一点,并给出那个部署的地址。
  • 关于:应用版本、当前后端(后端是远端时还有那个服务的版本),以及项目仓库的链接——点它在浏览器里打开仓库。菜单里因此不再单独列一行 GitHub。

只有点「保存」才会写入:改了后端或端口,网关会重启,窗口被带到新地址。取消则什么都不改。CODEBUDDY_DESKTOP_ASK=window 下会用应用自己的窗口来问,那是为了跑测试——原生对话框是测试点不到的。

登录 ​

桌面端不设管理员密码。网关只监听 127.0.0.1,控制台又只认应用自己的窗口,加一道密码只会把你自己锁在外面。

自行部署时才需要设置管理员密码,桌面端的 /admin-api/auth/setup 会返回 404。

后端是你自己部署的服务时,登录页与密码都属于那个服务。在桌面端输入密码是可以的:密码会转发给那个服务,控制台保存的是它下发的会话 cookie。

但那个服务的通行密钥(passkey)在桌面端用不了,浏览器或系统为它保存的密码也一样:它们都属于那个服务的地址,而这个控制台来自 127.0.0.1——浏览器只会为当前来源提供凭据,而且也不会与那个服务配置的 rpId 对上。登录页因此不会给出一个注定失败的按钮,而是说明情况并给出链接;点这个链接会在浏览器中打开那个服务自己的页面,在那里 passkey 和已保存的密码都能用。

用设备码登录 ​

所以桌面端还有一条从浏览器登录进来的路:后端是你自己部署的服务时,菜单里会有一行「登录…」。它向那个服务要两个码——一个应用自己拿着等,一个显示给你——然后在浏览器里打开那个服务自己的页面,码已经填好。在那里用那个服务要求的任何方式登录(passkey、浏览器保存的密码,或两者都用),批准这个码,应用会自己取回一个令牌:自始至终没有密码被输入 127.0.0.1 的那个窗口。

等待期间菜单里显示正在等待,不会再给出第二个码。批准的有效期是十分钟;码过期只是这一次机会结束,再登录一次就行。登录之后菜单显示「已登录」,并给出「退出登录」——它会在本机忘掉这个令牌,也会请那个服务忘掉它。

令牌保存在 userData 里、设置文件旁边,只有运行这个应用的用户能读,而且只属于当初给它那个地址:把应用指向另一个部署,就要重新登录一次。转发给那个部署的每个请求都带着它,所以窗口一直处于登录状态,直到你退出。不要求登录的部署会直接被告知这一点,而不是给一个谁也批准不了的码。

菜单栏状态 ​

macOS 顶部菜单栏会常驻一个状态图标,图标旁显示今日的 token 用量(输入 / 输出,每分钟刷新一次)。点开菜单可以看到当前后端与地址、打开控制台、复制地址、打开「设置…」,或退出应用。Windows 与 Linux 的托盘图标把状态与用量放在悬浮提示里,点击图标直接打开控制台。

菜单里的文案跟随控制台界面的语言。

版本与更新 ​

菜单底部列出桌面端版本;后端是你自己部署的服务时,还会列出那个服务的版本——它可能与桌面端不同。使用内置网关时不列服务端版本:那个网关就是桌面端本身。

「设置…」的「关于」一页列出同样的版本,并给出项目仓库的链接;菜单里因此不再单独列一行 GitHub。

同一个菜单里的「检查更新…」会去 GitHub 上问最新的发布版本:有新版本时先问你是否安装,确认后下载这台机器对应的安装包并交给系统打开(macOS 挂载 dmg,Windows 运行安装程序,Linux 打开 AppImage)。没有适用于这台机器的安装包时,会打开发布页让你自己挑。应用不会在后台替换自己。

端口 ​

改端口在首次启动的对话框、菜单「设置…」的「通用」一页,或控制台的「设置 → 桌面应用」里完成:保存后桌面端会重启网关,并把窗口带到新地址。已经被保存过或指定过的端口不会再被自动改用下一个,被占用时会在同一个对话框里问你要换到哪个端口,或者让你停掉占用它的程序后再重试——菜单里此时也显示被占用的那个端口号。还没保存过任何设置的安装则会向上寻找空闲端口,这样在已经占用 8001 的部署旁边也能直接用。

首次启动前也可以用 CODEBUDDY_DESKTOP_PORT 指定端口;一旦在设置里保存过,保存的值优先于环境变量。

存储 ​

桌面端固定使用 SQLite,没有其它后端可选:它只服务于本机,没有需要共享数据库的第二个进程。因此 CODEBUDDY_STORAGE_BACKEND、DATABASE_URL、CODEBUDDY_STORAGE_PG_URL 在桌面端会被忽略,设置页里的存储后端是不可修改的。

首次启动会生成加密密钥,凭据和 API key 都是加密存储的。删除 storage-encryption-key 会导致已加密的数据无法解密,这与自行部署时的契约一致,备份时请连数据库一起备份。

数据存放位置 ​

所有数据都写在 Electron 的 userData 目录里,而不是安装目录:

路径说明
data/文件存储目录,默认放置 storage.sqlite
credentials/CodeBuddy 凭据文件
storage-encryption-key首次启动生成的存储加密密钥(权限 0600)
desktop-settings.json桌面端自身的设置:后端与端口
desktop-device-token.json你批准后那个服务下发给本应用的令牌(权限 0600)

签名说明 ​

Release 中的 macOS 构建已签名并经过 Apple 公证,下载后双击 dmg 即可打开。Windows 构建会提示 SmartScreen,选择「仍要运行」即可。

如果 macOS 提示「已损坏,无法打开」,把应用拖进「应用程序」后执行:

sh
xattr -cr /Applications/CodeBuddy2API.app