Files
freedak f7a720204a Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用
- 添加所有子项目的完整源代码
- 保留原始 .git 为 .git.bak 备份
2026-07-04 19:20:46 +08:00

9.5 KiB
Raw Permalink Blame History

以桌面应用方式运行 NomiFun

桌面应用 (nomifun-desktop) 是一个 Tauri 外壳,在同一进程内链接 Rust 后端 (nomifun-app)。这里没有派生的后端二进制,没有 Electron,也没有捆绑的 nomicore。外壳在一个空闲的 127.0.0.1 端口上将后端启动为异步任务,然后将打包好的 SPA (ui/dist) 加载进 WebView,并使其指向 http://127.0.0.1:<port>/api

桌面 WebView 不显示登录页。嵌入式后端使用 AuthPolicy::TrustLocalToken: 外壳把每次启动生成的本地信任 secret 注入自己的 WebView,只有携带该 secret 的请求会被视为桌面用户。如果你想要登录 + 远程浏览器/手机访问,请参阅 WebUI 远程访问(应用内功能),或 自托管 Web 服务器(独立服务器)。

NomiFun 桌面主窗口

快速开始

前置条件

桌面应用需要:

  • Tauri 支持的平台 (Windows 10+、macOS 11+、主流 Linux 发行版)。
  • WebView 运行时:Windows 上的 WebView2 (Win 11 预装;Win 10 上请安装 Evergreen Bootstrapper)macOS 上的 WKWebView (内置)Linux 上的 WebKitGTK (libwebkit2gtk-4.1-0)。
  • 用于开发:Rust 工具链、Bun ≥ 1.3.13,以及对应平台的 Tauri 构建依赖 (参见 Tauri 前置条件)。

从源码运行 (开发模式)

在仓库根目录:

bun install
bun run dev

这会执行 tauri dev --config apps/desktop/tauri.conf.json。它启动 Vite 开发服务器 (http://localhost:5173) 来托管 SPA,构建并启动 nomifun-desktop,并在每次启动时在一个全新的空闲 localhost 端口上启动嵌入的后端。

构建发布包

bun run build

输出包按平台落到 target/release/bundle/ 下 (Windows 上是 NSIS 安装器 + MSImacOS 上是 .app + .dmgLinux 上是 .deb + .AppImage)。要生成签名的更新器构件 (额外的 .sig 文件),请在配置好签名密钥后使用 bun run build:updater (参见下方更新器状态)。

构建成功后会打印包的位置,例如在 macOS 上:

$ bun run build
   Compiling nomifun-app v0.1.0
    Finished `release` profile [optimized] target(s)
    Bundling NomiFun.app (macos)
    Bundling NomiFun_0.1.0_aarch64.dmg (macos)
    Finished 2 bundles at:
      target/release/bundle/macos/NomiFun.app
      target/release/bundle/dmg/NomiFun_0.1.0_aarch64.dmg

窗口与标题栏

主窗口在 Windows 和 Linux 上是无边框的:React 标题栏组件在与应用内导航同一行绘制最小化/最大化/关闭按钮。在 macOS 上,原生的红绿灯按钮通过 Tauri 的 Overlay 标题栏样式得以保留,内容延伸至栏底之下。

  • 默认尺寸:1280 × 832,最小 880 × 600
  • 各处都可调整大小 (即使没有 OS 绘制的装饰,Windows 上的边缘调整和 Snap 仍然可用)。
  • 标题栏:NomiFun

窗口边框因系统而异:Windows / Linux 上是带应用内控件的无边框标题栏,macOS 上保留原生红绿灯按钮(内容延伸至 Overlay 栏下)。

单实例

tauri-plugin-single-instance 在 Windows 和 Linux 上强制应用只运行一个副本。试图启动第二个 nomifun-desktop 不会在另一个端口上启动新的后端,而是会静默地聚焦到已有的窗口。

深度链接

应用注册了 nomifun:// URL 协议 (在 apps/desktop/tauri.conf.jsonplugins.deep-link.desktop.schemes 下配置)。当操作系统通过 nomifun://... URL 启动 Nomi 时,外壳会通过 Tauri 事件 deep-link://received 将 URL 转发给渲染进程。渲染进程可以使用 @tauri-apps/api/event 中的 listen('deep-link://received', ...) 订阅以处理负载。

启动时会调用 register_all() 来安装该协议;在需要带外注册步骤的平台上 (某些 Linux 桌面、开发环境),该调用是尽力而为的,失败会被忽略。

自启动

外壳附带 tauri-plugin-autostart,使得渲染进程可以通过插件的 invoke API 让应用加入 "登录时启动"。在 macOS 上这使用 LaunchAgent;在 Windows 上使用注册表的 Run 键;在 Linux 上则使用 autostart 文件夹中的 .desktop 文件。面向用户的开关位于应用设置中。

通知

tauri-plugin-notification 已启用。渲染进程可以显示 OS 级别的通知 (例如,当 agent 完成一个长任务或 AutoWork 有结果时)。在 macOS 上,第一次会请求用户授权;在 Windows 上,通知使用现代的操作中心;在 Linux 上则通过 libnotify

数据存储位置

桌面应用将 SQLite 数据库、agent 状态、日志和 Bun 运行时缓存持久化到按用户的应用数据目录下 —— Windows 上是 %LOCALAPPDATA%\NomiFun\NomimacOS 上是 ~/Library/Application Support/NomiFun/NomiLinux 上是 $XDG_DATA_HOME/NomiFun/Nomi (由共享的 nomifun_app::cli::default_data_dir() 解析)。这与 nomifun-web 宿主和开发脚本使用的是同一个默认目录,因此在一个宿主里配置的 provider 或伙伴在其他宿主里同样可见。

在启动应用前设置 NOMIFUN_DATA_DIR=<absolute path>,数据目录就会变为 $NOMIFUN_DATA_DIR/Nomi。后端启动时会对数据目录取排他的 server.lock;若启动失败 (例如该目录已被另一个实例占用),桌面外壳会弹出原生错误对话框并退出。

旧版本默认使用 <system temp>/nomifun-data/Nomi。在那里发现的安装会在启动时自动迁移到按用户位置 (一次性):数据被复制,数据库中存储的绝对路径会被改写,旧目录保留作为备份。可再生的缓存 (解压出的 Bun 运行时、日志、浏览器配置 …) 不会带过去 —— 它们会在首次使用时重建。

要重新开始,退出应用并删除该目录。要迁移,将该目录复制到新机器上即可。

~/Library/Application Support/NomiFun/Nomi/    # macOSWindows/Linux 路径见上文)
├── nomifun-backend.db        # SQLite 状态(会话、设置、session 等)
├── logs/                     # nomicore.log
├── companion/                # 伙伴 + 共享记忆中枢
├── knowledge/                # 受管理的知识库
├── runtime/                  # 解压出的 Bun 运行时缓存(可再生)
└── server.lock               # 后端运行期间持有的排他锁

认证与本地信任

桌面外壳不会把旧式完全无鉴权后端暴露给所有 localhost 调用者。它以 TrustLocalToken 启动嵌入式后端,向 WebView 注入 window.__nomiLocalTrust 渲染端在 HTTP 与 WebSocket 请求中呈递该 secret。只知道 127.0.0.1:<port>/api 的其他进程不会自动被信任。

桌面应用仍是单用户工具:启动它的 OS 账户拥有 agent 能做的一切,包括 shell 和文件访问。

如果你想从另一台设备访问同一个安装,不要直接暴露嵌入的端口。请使用以下之一:

  • WebUI 远程访问 (一个按实例启用的功能,参见 WebUI 远程访问) —— 启动一个独立的认证服务器并提供二维码登录。
  • 自托管 Web 服务器 (Web 服务器部署) —— 在 nomifun-web 下以无头方式运行同一个后端,并要求认证。

更新器状态

Tauri 更新器插件 (tauri-plugin-updater) 已接入,渲染进程暴露了 invoke('check_for_updates') (返回新版本字符串,若已是最新则返回 null)。然而:

  • apps/desktop/tauri.conf.json 中配置的端点 (plugins.updater.endpoints) 是一个占位符 (https://REPLACE-WITH-YOUR-HOST/...)。在你将其替换为一个提供已签名的 latest.json 的真实 HTTPS URL 之前,更新器检查会失败。
  • 包含的 pubkey 是一个为本地测试生成的开发密钥在任何公开发布前请替换它,并将私钥存储在 CI 密钥中。
  • bun run build:updater 会生成已签名的更新构件 (在每个安装器旁边附带 .sig 文件)。

完整 updater 流程(签名环境变量、latest.json schema、支持的平台键)在 apps/desktop/updater/README.md 中。OS 级别代码签名/公证是另一层:macOS Developer ID 签名与公证已通过 bun run build:signedapps/desktop/signing/README.md 接好;Windows 签名仍需要外部代码签名证书。

故障排查

窗口打开后是空白白屏。 确保已安装 WebView 运行时 (Windows 10 上的 WebView2 需要 Evergreen Bootstrapper)。在 Linux 上需要 libwebkit2gtk-4.1-0

"Failed to bind backend port"。 另一个进程占用了 127.0.0.1 临时端口。后端会尝试 pick_free_port(),失败时回退到 8799 —— 退出任何其他 NomiFun 实例后再试。

Agent 命令失败并报 bun: command not found Agent 引擎会派生 Bun 作为子进程来执行工具。请安装 Bun (curl -fsSL https://bun.sh/install | bash) 并确保它在系统 PATH 上,或者使用 NOMIFUN_EMBED_BUN=1 构建桌面包以将其嵌入。

另请参阅