Files
OpenTerminal/docs/ROADMAP.md
T
Bill 2653ab1820 feat(i18n): tab auto titles follow the UI language
Titles are stored display text (layout templates, session snapshot,
broadcast registry), so a pane used to keep the wording of the language it
was opened in, and nextTerminalTitle could not even parse the number back
out of another language's pattern (numbering restarted, duplicates).

New pure module src/shared/terminalTitle.ts: resolution tries all four
languages' patterns, rendering uses the active one; i18n gains tFor(lang)
for off-language rendering. Workspace retitles auto-numbered local tabs in
place on language switch, snapshot restore and template apply; SSH panels
(user-typed connection names) are never touched. dockview's title-change
event propagates the new title to the broadcast registry and the snapshot
save with no extra wiring.

New test terminal-title.mjs (16 writer/reader language pairs, non-auto
title boundaries, gap filling); offline suite grows 17 -> 18.
2026-10-08 00:11:20 +08:00

14 KiB
Raw Blame History

OpenTerminal 长期路线图

目标:以开源组件组合构建现代化的本地 + SSH 终端应用,按里程碑推进,每个里程碑可独立交付使用。

里程碑总览

阶段 内容 状态
M1 本地终端 + 分屏 + 主题/字体 + 设置持久化 ✅ 已完成(v0.1)
M2 SSH 远程会话 + 连接管理器 ✅ 已完成(v0.2)
M2.5 关键词高亮(提前自 M4)+ 系统设置(自启动/阻止休眠)+ UI 打磨 ✅ 已完成(v0.2.1)
M3 SSH 产品化:Terminal/SSH 分离 + 服务器硬件监控(Wave 风格) ✅ 已完成(v0.3)
M4 SFTP 文件管理 + 传输面板 + 权限/属主/chmod ✅ 已完成(v0.4)
M5 命令历史/命令库/补全 + 会话日志 ✅ 已完成(v0.5)
M6 广播输入 + ZMODEM + 快捷输入面板 + 快捷键系统 ✅ 已完成(v0.6)
M7 打包分发(MSI + NSIS + 自动更新) ✅ 已完成(v0.7,Release 已发布)
M8 工作区分离(Terminal/SSH 双工作区)+ SSH 底部文件面板 + 右键菜单 + 监控美化 + 补全修复 ✅ 已完成(v0.8)
M9 体验打磨:系统托盘 + 关闭行为 + 单实例 + 主题联动标题栏 + 布局菜单重做 + 补全交互修正 + 应用图标 ✅ 已完成
M10 多语言界面(zh-CN / zh-TW / en / ja)+ 离线多语言更新日志 + 快捷键录制 + 可配终端工具条 + 设置健壮性 ✅ 已完成(v1.0.13)
M11 审查修复第二轮:渲染层性能 + asar 瘦身 + 安全纵深 + 测试补全 + 文档刷新 ✅ 已完成(2026-10,Dev_20261001)

M2 — SSH 远程会话 ✅

  • src/main/ssh.ts:ssh2 连接池(connect/shell/resize/close),PTY_DATA/PTY_EXIT 广播通道统一复用(本地与 SSH 会话同数据面)
  • 连接配置模型(shared/connections.ts):host/port/username、密码 vs 私钥(keyPath/keyContent)vs Agent、keepalive
  • 凭据加密存储:safeStorage(DPAPI) + plain: 兜底;渲染层只见 savedAuth 标志
  • 连接管理器 UI:书签侧栏(分组手风琴)+ 新建/编辑对话框 + 双击连接
  • Host key 校验:known_hosts 固定、首次确认、变更告警、30s 超时拒绝
  • 测试:tests/ssh-loopback.mjs(ssh2 回环)+ tests/ssh-session-e2e.mjs(真实会话路由层 e2e)
  • 待解锁后的 GUI 验收:双击书签连接、指纹弹窗交互、断线提示
  • 已知限制:SSH 面板暂不支持作为分屏参照(总在新标签打开);连接中 Modal 不可取消;agent 认证未在本机验证

M3 — SSH 产品化:Terminal/SSH 分离 + 服务器硬件监控 ✅

A. Terminal 与 SSH 功能分离(产品形态)

  • 侧栏双分区:「终端」(本地)与「SSH 服务器」各自独立区块(独立折叠、独立头部、独立计数)
  • SSH 会话标识:标签页带服务器图标/主机名前缀,本地与 SSH 标签视觉区分
  • 新建入口分离:图标条「+」只建本地终端;SSH 会话仅从服务器列表发起(双击连接,右键:连接/编辑/删除/复制主机)
  • SSH 区增加「最近会话」(按 lastConnectedAt 排序,一键重连)
  • (可选增强)工作区模式:本地/SSH 两个独立工作区布局,互不混排
  • 验收:不开侧栏也能一眼区分标签是本地还是 SSH;图标条「+」只出本地终端

B. 服务器硬件监控(参考 Wave Terminal 的 sysinfo 块)

技术可行性:✅ 高,零部署方案已在真实服务器上验证。

  • 零部署路线:ssh2 exec 读 Linux 标准接口——CPU /proc/stat(双采样算占用率)、内存 /proc/meminfo、负载 /proc/loadavg、磁盘 df -kP、网络 /proc/net/dev(双采样算速率)、运行时间 /proc/uptime
  • 增强路线(部署脚本):首次连接部署 ~/.openterminal/sysinfo.sh(纯 shell 输出 JSON,Linux/macOS 通用),解锁进程 Top 列表

数据面:ssh2 conn.exec → stdout JSON → 主进程解析 → STATS:{id, stats} 广播 → 渲染层

  • src/main/sysinfo.ts:按会话轮询(默认 3s,可配置),会话关闭/断线自动停止;解析容错
  • 契约:shared/sysinfo.ts(SysinfoSample + STATS 通道 + 面板开关事件)
  • UI:SSH 会话右侧可折叠监控面板——CPU 多核条形、内存/磁盘用量条、网络上下行、负载/运行时间
  • (增强路线)进程 Top 列表 + 结束进程
  • 验收:连接后 ≤3s 看到实时 CPU/内存;断开会话监控自动停止;服务器跑 stress 曲线明显上升

M4 — SFTP 文件管理 ✅

  • src/main/sftp.ts:ssh2 SFTP 封装(readdir/stat/rename/mkdir/rm/mv,大文件分块传输 + 进度事件)
  • 双栏界面(本地 ↔ 远程)+ 拖拽上传/下载 + 传输面板(队列/暂停/取消)
  • 右键菜单:压缩/解压(tar.gz)、编辑远程文件(Monaco,下载-编辑-回传)
  • 验收:100MB 文件传输进度流畅、可取消续传

M5 — 命令系统与会话日志 ✅

  • 命令历史(sqlite + better-sqlite3,按会话去重)
  • 命令库(分组 + 参数变量 {{param}} + 一键运行/粘贴)
  • 终端补全:历史 + 命令库 + 内置命令表(内置命令文档可从 tldr 页面生成)
  • 会话日志:手动启停、纯文本落盘、断线暂停指示
  • 关键词高亮(✅ 已提前完成:highlightEngine 流式 ANSI 注入 + 22 条预设 + 设置页管理,见 M2.5;状态类预设不分大小写、覆盖 ✓/✗ 符号,删除/新建操作单独着色,百分比/退出码/HTTP 状态码/耗时按数值分级取色,含密钥泄露提醒与危险管道,旧安装的预设规则在加载时按「未被用户改动过」升级)
  • 验收:补全 ↑↓ 选择 / Tab 接受 / Esc 关闭 / 回车直接执行,交互流畅

M6 — 多终端协同 ✅

  • 广播输入(broadcastStore):选中 ≥2 个会话同步键入;标签广播标记 + 按钮计数徽标;目标 <2 自动关闭
  • 快捷输入面板(Quick Input)(已移除:全局单例开关与面板不对一一对应,功能与行内补全/侧边栏命令面板重叠)
  • ZMODEM(rz/sz):主进程引擎(zmodem.js,仅 SSH 会话;本地 ConPTY 不支持二进制),文件选择/保存目录对话框 + 传输面板进度 + 看门狗超时;双向 e2e(tests/zmodem-e2e.mjs)
  • 快捷键系统:Ctrl+=/-/0 字号(持久化)、Ctrl+PgUp/PgDn 切换终端、全局唤起/隐藏(设置页可配 globalShowHide)
  • 验收:3 个分屏同步执行命令 ✅(活体验证:终端 3 键入扇出到终端 4);rz 传输 ✅(e2e 双向内容一致;真实服务器 rz/sz 待用户复测)

M7 — 打包与分发 ✅

  • electron-builder:MSI(固定 upgradeCode,手动/企业部署)+ NSIS(x64),npm run dist / dist:dir
  • 原生模块:@lydell/node-pty 预编译 + asarUnpack(node-pty/ssh2),npmRebuild=false,win-unpacked 冒烟通过
  • 自动更新(electron-updater,generic feed = Gitea generic package 稳定地址,公网可读;仅 packaged 启用,OT_UPDATE_URL/OT_UPDATE_TOKEN 可覆盖)
  • 应用图标(build/icon.png)已补齐,MSI/NSIS 桌面与开始菜单快捷方式已启用
  • 代码签名(可选,未做)

M9 — 体验打磨 ✅

  • 系统托盘:托盘图标 + 右键菜单(显示窗口/关闭行为/退出);关闭按钮行为可设「每次询问/最小化到托盘/直接退出」,询问对话框支持记住选择(settings.closeAction)
  • 单实例运行:requestSingleInstanceLock,二次启动唤出已有窗口(托盘隐藏也可恢复)
  • 主题联动标题栏:titleBarOverlay 自定义标题栏,颜色跟随终端主题实时刷新;窗口背景同色
  • 布局菜单重做:弃用 antd Dropdown 传送门(与 dockview 全局指针处理冲突导致闪退),改为侧栏内联弹出面板
  • 补全交互修正:回车不再接受建议(此前会把建议拼接到已输入内容后,如 kimi → kimikimi);与已输入完全相同的建议自动过滤;新增「输入建议」设置开关
  • 标签页视觉打磨:圆角胶囊 + 描边 + 独立关闭按钮
  • 本地 PTY 声明终端能力(TERM/COLORTERM/TERM_PROGRAM),TUI 程序不再降级配色

M10 — 多语言与体验细节 ✅

  • 界面语言(zh-CN / zh-TW / en / ja):全应用文案抽到 src/shared/i18n/dicts,设置 → 系统 → 界面语言,切换即时生效并持久化;antd 组件内置文案随语言切换
  • 更新日志随安装包内置(CHANGELOG*.md?raw),「关于」页离线可看,按界面语言显示、缺翻译回退简体中文
  • 全局唤起快捷键改为按键录制(Esc 取消 / 退格清空;必须带修饰键或功能键,避免误占普通按键)
  • 终端右上角工具条可配置:打开工作区目录(随 cd 跟踪)、记录会话日志、打开日志目录
  • 设置健壮性:清洗器修复而不丢弃(priority 字符串、0/1 布尔、缺前景色),异常写 settings-warnings.log;设置写入串行化;「每次询问」关闭行为不再被静默改回
  • 「输入建议」「记录命令历史」默认关闭;浅色主题标签栏/设置弹窗对比度修复;会话日志改为每文件缓冲写入

M11 — 审查修复第二轮 ✅

背景:2026-10 全面审查(6 个子代理分域审查 + 逐条核实)已在 Dev_20261001 落地两轮修复(第一轮:store 损坏兜底、zmodem 错误/节流/终结、release 降级护栏、主进程加固、模板应用恢复、锁屏 portal inert、设置页/SFTP 界面、背景图浅色主题可读性 + 压暗 scrim;第二轮即下列各项)。

1. 渲染层性能 ✅

  • TerminalView settings 字段级订阅:5 组 useShallow 分组订阅,主题写 options 不再 refit;useResolvedTheme 改 shallow + memo
  • FilePanel 虚拟化:自实现固定行高(24px)windowing,>200 条目启用;无新依赖
  • per-panel ErrorBoundary:pane 崩溃只显示该 pane 占位 + 重试,不再卸载整个工作区
  • SshBottomPanel 拖动:React.memo(FilePanel)(唯一 prop 恒定)
  • TransferPanel 改 ref+version 增量更新 + memo 行;MonitorPanel ResizeObserver 只建一次

2. asar 瘦身 ✅(98MB → 8.1MB,↓91.7%)

  • 10 个纯渲染层依赖移到 devDependencies,顺手删死依赖 @xterm/addon-serialize;dependencies 只剩 main 实际 import 的 5 个(node-pty/ssh2/zmodem.js/font-list/electron-updater)
  • 验收:dist:dir 后 asar 内零渲染层包,asarUnpack 原生件完好,win-unpacked 冒烟通过
  • undici 显式 devDependencies

3. 安全纵深 ✅

  • 本地路径准入层 src/main/localPathGrants.ts:SFTP/zmodem/keyPath 只接受对话框授权路径,realpath+stat 双重校验,防符号链接逃逸;keyPath 限普通文件 ≤1MB
  • webPreferences 显式 contextIsolation/nodeIntegration/webSecurity
  • 代码签名(M7 遗留可选项,仍未做;更新通道完整性缺口随之保留)

4. 测试补全 ✅(离线测试 12 → 17)

  • updater.ts(feed 回退/超时预算,82 断言)、ipc.ts(sender guard 真实注册路径灌伪造帧,43)、logSanitizer.ts(ANSI 状态机 + 字节切分 fuzz,71)
  • 保留键判定抽纯函数 src/shared/reservedAccelerators.ts,渲染层/主进程两表合一(56 断言)
  • SFTP per-op 超时(元数据 30s/传输块 60s/open 10s,驱逐半死通道重试一次,39 断言)
  • ssh-loopback.mjs 改加载真实 ssh.ts bundle(50 断言:TOFU/认证门/连接预算)
  • 渲染层测试框架评估:结论暂不引入 vitest/jsdom,纯逻辑继续抽函数走 bundle 测试

5. 文档与杂物 ✅

  • README 测试清单/锁屏补录;docs/STATE.md 刷新到 v1.0.20 现行发布流程
  • CI 缓存 Electron 二进制;.gitignore 补 .env.*(保留模板豁免)
  • 归档脚本入 scripts/,KEEP_TAG 改必传参数
  • isPanicLockChord 改判 input.code(物理键位,Dvorak/非拉丁布局正确)
  • P3:设置页「更新通道」死控件移除、layoutMenu/IconRail memo + onOpenSettings useCallback、TerminalHandle 死 API 移除
  • 面板标题存已翻译字符串(切语言错位)——✅ 已修:不改持久化格式,改多语言反解 + 语言切换/快照恢复/模板应用三处原地重渲染(src/shared/terminalTitle.ts,18 号测试 terminal-title)

工程约定(贯穿各阶段)

  1. 契约先行:新增功能先在 src/shared/ 定义通道与模型,再实现两端
  2. 原生依赖:优先选带预编译二进制的包(@lydell/node-pty 模式),避免用户机器装构建链
  3. 测试:main 进程服务(pty/ssh/sftp/commands/settings/zmodem)先用 esbuild 打成 CJS/ESM bundle,再由 tests/*.mjs 以纯 Node 断言跑(npm test;无 vitest、无需服务器);渲染层交互靠 dev 手测
  4. 里程碑验收后打 git tag

已知待办(M1 遗留)

  • 布局塌陷(v0.2.1 修复:antd <App> 包裹层 .ant-app 无高度导致百分比高度链断裂)
  • 关闭标签页整窗崩溃(v0.2.1 修复:xterm IDisposable 对象被当函数调用;并新增 ErrorBoundary 兜底 + 渲染层报错转发主进程日志)
  • 首启动空屏(v0.2.1:启动自动打开一个终端)
  • autoWrap=false 的固定列宽模式(xterm.js 无原生 wrapMode,需自定义列数控制)
  • 终端标题跟随 OSC 序列(窗格标题显示当前目录/命令)
  • 内置等宽字体打包(OFL 许可:JetBrains Mono / Fira Code 等)
  • rendererMode webgl 的终端数量上限自动降级(大量终端实例时回退 DOM 渲染)
  • 会话数据在面板间拖拽迁移(dockview 原生支持面板拖动,已具备)
  • 界面语言切换(✅ v1.0.13:zh-CN / zh-TW / en / ja,文案抽到 src/shared/i18n/dicts,设置 → 系统 → 界面语言)