Files
nyaterm/docs-site/docs/development/architecture.md
T
Kang 264b7b298a docs: describe the child-window model and drop the deleted WindowRuntimeStore
The layout guide claimed NyaTerm remembers child-window position, size and modal
relationships. The Tauri implementation did, through a `stateKey` and
`load_child_window_state`; the GPUI port dropped it and this change does not add
it back, so the guide now says what actually happens: where a child window opens,
which ones block the main window and why, which one stays on top, and the
keyboard. Both languages.

`WindowRuntimeStore` was deleted in 15994ef6 along with the global runtime tick
it drove, but `AGENTS.md`, both architecture pages and the `entities` module doc
still listed it as one of the Entity stores.
2026-08-26 15:15:10 +08:00

6.5 KiB

架构说明

NyaTerm 是一个基于 GPUI 构建的原生 Rust 桌面应用。应用界面、终端模拟、连接传输和持久化均位于同一个 Cargo workspace 中,不依赖浏览器运行时或 IPC 桥接层。

整体分层

nyaterm-app
  └─ 启动 GPUI、注册资源、创建根窗口
       └─ nyaterm-desktop
            ├─ AppShell / NyaTermApp / feature state / views
            ├─ nyaterm-ui                共享 GPUI 控件和主题
            ├─ nyaterm-terminal-gpui     终端布局、输入和绘制
            ├─ nyaterm-terminal          终端状态机、解析和快照
            ├─ nyaterm-transport         PTY、SSH、SFTP 和其他协议
            ├─ nyaterm-remote-desktop    RDP/VNC 会话管理与 helper IPC 合约
            ├─ nyaterm-store             redb、事务和兼容性读取
            └─ nyaterm-core              纯模型、格式和策略

  独立进程(通过 IPC 通信,不被应用链接)
       ├─ nyaterm-rdp-helper            IronRDP 解码
       └─ nyaterm-vnc-helper            vnc-rs 解码

各 crate 的主要职责如下:

Crate 职责
nyaterm-app 可执行入口、日志、嵌入资源和根窗口创建
nyaterm-desktop GPUI 应用组合、状态、视图、平台适配和后台任务协调
nyaterm-ui 共享控件、主题 token 和 gpui-component 集成边界
nyaterm-terminal 与 UI 无关的终端状态机、控制序列、编码和图形协议
nyaterm-terminal-gpui GPUI 终端输入、布局、选区、高亮、图片和绘制
nyaterm-transport PTY、SSH、Telnet、串口、SFTP、隧道、远程操作和传输协议
nyaterm-store redb 数据库、事务、加密适配和兼容性读取
nyaterm-core 领域模型、兼容格式、解析、策略及纯逻辑
nyaterm-remote-desktop 与 UI 无关的 RDP/VNC 会话管理、framebuffer 与输入模型、证书策略、剪贴板状态和 helper IPC 合约
nyaterm-rdp-helper 隔离的 IronRDP helper 进程
nyaterm-vnc-helper 隔离的 VNC helper 进程,持有 fork 的 vnc-rs 解码器、重连梯度和服务端策略门控
nyaterm-otp HOTP/TOTP 兼容实现

启动流程

crates/nyaterm-app/src/main.rs 是应用入口:

  1. 解析运行目录并初始化日志。
  2. 向 GPUI 注册嵌入资源和共享组件。
  3. 创建原生根窗口和 AppShell Entity。
  4. AppShell 启动 StoreRuntime,异步加载启动快照。
  5. 数据验证成功后创建 NyaTermApp,再恢复窗口布局和会话。

AppShell 还负责加载、恢复、退出前 flush 等应用级生命周期。数据库启动失败时会进入恢复界面,而不是用未验证的数据继续创建主应用状态。

状态所有权

NyaTermApp 是 GPUI 组合中心,但主要 UI 域由 focused feature state 管理,例如连接、会话、终端、传输、设置、安全、AI、同步和远程操作。

每份状态只有一个可写 owner。当前独立 Entity store 只拥有 NyaTermApp 不拥有的状态:

  • StartupRestoreStore:启动恢复队列
  • OverlayStore:快速切换 overlay

视图直接读取权威状态构造 GPUI element。不要建立同帧 publish/read-back 的只读镜像,也不要在 feature state 和 Entity 中同时保存可变副本。

后台任务与事件

文件系统、数据库、网络、SSH、SFTP、子进程和图片解码等阻塞工作不在 render 路径中执行。

后台任务通过有类型的结果或事件返回 GPUI 状态层。例如会话运行时使用 nyaterm_transport::SessionEvent 传递输出、工作目录变化、命令确认、退出和错误;桌面层在窗口运行时 pump 中消费事件、更新 feature state 并通知 GPUI 重绘。

终端数据流

PTY / SSH / Telnet / Serial
        │
        ▼
nyaterm-transport typed events
        │
        ▼
nyaterm-desktop event drain and session state
        │
        ▼
nyaterm-terminal state machine and snapshots
        │
        ▼
nyaterm-terminal-gpui layout, input and painting

nyaterm-terminal 使用 Alacritty 的终端组件维护网格和控制序列状态,同时负责搜索、编码、Kitty graphics 和 Sixel 等与 UI 无关的逻辑。GPUI 尺寸计算、键盘适配、选区、高亮、图片及逐帧绘制均留在 nyaterm-terminal-gpui

持久化与兼容性

nyaterm-store 通过专用 StoreRuntime 执行数据库工作,桌面层使用 UI client 或 blocking client 提交有类型的请求。GPUI 视图不直接访问 redb。

配置模型、备份格式、云同步文档和加密策略等 schema-neutral 合约位于 nyaterm-core。数据库实现与旧数据读取位于 nyaterm-store。现有 table 名、key、字段名、加密前缀、.nya 备份和 Dragonfly fallback 都属于兼容性边界。

RDP / VNC 的进程隔离

RDP 和 VNC 的协议解码器解析的是服务器控制的字节流,因此它们不在应用链接的任何 crate 里,而是各自跑在独立的 helper 进程中,通过 nyaterm-remote-desktop 里的类型化 IPC 协议与应用通信。

这条边界的含义:

  • 解码器崩溃不会带走应用。两个 helper 都必须把解码器 panic 转换成一个致命 IPC 错误上报,而不是静默退出
  • nyaterm-remote-desktop 自己不含任何解码器。它只负责会话管理、framebuffer 与输入模型、证书策略和剪贴板状态
  • VNC 的服务端策略门控(view_onlyshared、剪贴板启用)必须在 helper 里强制执行,而不是只在应用侧判断
  • 应用在自己的可执行文件旁边解析 helper 路径,NYATERM_RDP_HELPER / NYATERM_VNC_HELPER 可覆盖

两个 helper crate 各自带一个 tests/lifecycle.rs,覆盖握手、正常断开和崩溃 / 挂起回收。IPC 合约变更时必须同步更新两边。

依赖规则

  • nyaterm-corenyaterm-terminalnyaterm-transportnyaterm-remote-desktop 不依赖 GPUI。
  • 解析服务器控制字节的协议解码器只放在 helper crate 里,不放进应用链接的 crate。
  • 桌面功能通过 nyaterm-ui 使用普通输入、选择、菜单、开关和对话框。
  • 模块使用正常 Rust module tree 和显式 import。
  • 新功能优先放入已有 focused feature state;只有需要独立生命周期时才新增权威 Entity。

更具体的界面层规则见 GPUI 桌面开发,运行时与持久化规则见 运行时、传输与存储开发