Files
OpenTerminal/docs/PLAN-2026-10-21-backlog.md
T
Bill c0f1cdcecb docs(plan): ROADMAP 勾选已完成里程碑并新增 2026-10-21 backlog
- ROADMAP 修正过期限制说明,M3-A/M3-B/M4/M5 按实际完成勾选
- 新增 docs/PLAN-2026-10-21-backlog.md(W0–W5 波次计划,含核实记录)
2026-10-21 23:02:22 +08:00

228 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenTerminal 下一轮迭代计划(v1.0.32+ 待办整理)
> 本计划整理自 2026-10-21 的三路代码审查(路线图梳理 / 代码缺口扫描 / 竞品对标),
> 所有条目均经源码逐一核实(文件:行号见各项「现状」)。**本文件只是计划,不代表任何代码改动已开始。**
> 执行时按波次进行,每个波次一个版本号;条目内的勾选框在执行阶段回填。
>
> 核实记录(2026-10-21 二轮):文档初稿写完后又逐条回源码验证,修正了 6 处凭印象写错的细节——
> ① `pendingOpens` 在 `pty.ts` 而非 ssh.ts;② ssh2 无官方类型、项目用手写 shim `ssh2.d.ts` 且未声明
> `forwardOut`;③ 本地 PTY 路径没有 ZMODEM sentry(W2-4 需新写检测而非复用);④ 剪贴板图片落临时文件
> 不经过 `localPathGrants`(它只授权对话框选中的路径);⑤ 官网 SFTP 区并无「双栏」宣传;⑥ zh-TW
> 「密碼」32 处 vs「口令」5 处(统一方向确认)。所有测试基建文件名(updater-fallback / settings-store /
> link-rules / zmodem-e2e / ssh-loopback)已确认存在。
## 总览
| 波次 | 主题 | 内容 | 预估工作量 |
|---|---|---|---|
| W0 | 文档债清理 | 计划 checkbox 回填、ROADMAP 过期条目 | 0.5h |
| W1 | 修复:更新器 + 发布脚本 + 预设升级 | 4 项小修,其中 2 项影响存量用户 | 1 天 |
| W2 | 捡漏功能(半成品补全) | 链接规则导入导出、命令库参数、i18n 统一、ZMODEM 提示 | 1–2 天 |
| W3 | 剪贴板与命令感知 | OSC 52、图片粘贴、OSC 133 marks、完成通知 | 2–3 天 |
| W4 | Shell 与 SSH 迁移链 | 本地 shell 配置档、ssh_config 导入、ProxyJump + 端口转发 | 3–5 天 |
| W5 | 差异化(择期) | 远程文件编辑、应用命令面板、终端内 AI 助理 | 各 2–4 天 |
| — | 需决策的取舍项 | 代码签名、多窗口、双栏 SFTP、传输暂停续传 | 见 §6 |
**波次间的依赖**:W3 的「完成通知」依赖同波次的 OSC 133 marks;W4 的 ProxyJump 与端口转发共用 ssh2 通道基建必须同一波次;W5 各项独立。
---
## W0:文档债清理(无代码改动)
### W0-1 回填两份 superpowers 计划的 checkbox
- 现状:`docs/superpowers/plans/2026-10-20-mode-button-double-click-sidebar.md` 12 个、
`docs/superpowers/plans/2026-10-16-theme-overhaul.md` 40 个 `- [ ]` 全部未勾,但对应代码、测试、
CHANGELOG 均已落地(v1.0.29 / v1.0.31)。
- 动作:逐项核对后勾上。
### W0-2 修正 ROADMAP 过期陈述
- 现状:`docs/ROADMAP.md:33`「SSH 面板暂不支持作为分屏参照」已过时——
`src/renderer/src/workspace/Workspace.tsx:880` 起的 `handleSplit` 已实现 SSH dockview 内分屏。
- 动作:删掉该条已知限制;顺带勾掉 M3-A / M5 已完成项的 checkbox,把 M4 真正未做的三项
(双栏 / 压缩解压 / 远程编辑)单列。
---
## W1:修复(目标版本 v1.0.32)
### W1-1 更新器周期定时器不再被高频设置写入重置
- 现状(已核实调用链):每次设置保存走 `mutateSettings`(settingsStore.ts:732)→ `applySystemSettings`(:736)→
`updateScheduleApplier?.(system)`(:575)→ `applyUpdateSchedule`,而后者(`updater.ts:533-537`)无条件
`clearInterval` + 重建。拖 ColorPicker / 打字会把 4h 倒计时无限推迟。
- 改动:`applyUpdateSchedule` 记忆当前 interval 值,仅当 `updateCheckIntervalHours` 实际变化时重建定时器。
- 测试:`tests/updater-fallback.mjs` 已有 schedule 测试段(第 10 节,:586 起),在其内补「连续调用不改变倒计时起点」用例。
### W1-2 「启动检查」中途拨开语义修正
- 现状(已核实文案):设置页开关标签为「启动时自动检查」(`src/shared/i18n/dicts/zh-CN/settings.ts:357`),
但 `updater.ts:543-547` `startupArmed` 只在首次武装时置位——启动时关闭过该开关的用户在会话中途打开,
会在 5s 后立刻跑一次 `runCheck('startup')`,与「启动时」的文案语义矛盾。
- 改动:启动时无论开关状态都消费 `startupArmed`(记录「启动检查已过」),
中途打开只影响周期定时器。
### W1-3 修复 `--channel-only --skip-gitea` 静默上传
- 现状:`scripts/release.cjs:437-441` `CHANNEL_ONLY` 分支在 `SKIP_GITEA` 警告(:442-446)之前 return——
两个参数同用时警告永不打印,且 channel 照样上传,与操作者预期相反。
- 改动:参数解析处直接拒绝该组合(`--channel-only` 的定义就是国内通道,叠加 `--skip-gitea` 无意义),
或把警告移到分支之前并显式确认。
- 测试:`release.cjs` 无测试基建,人工跑一次参数组合验证输出即可。
### W1-4 高亮预设升级机制补全(**影响存量用户,本波次重点**)
- 现状(已核实判定链,settingsStore.ts:243-267):`refreshBuiltinRules` 只在
`LEGACY_BUILTIN_PATTERNS[rule.id].includes(存储pattern)` 成立时把规则升级到新 preset;
该表(:208-213)目前只有 perm/okstate/badstate 三条旧 pattern。追加新预设另有闸门
`LEGACY_BUILTIN_IDS`(:215 起)的「存储集合恰好等于旧预设集」判定。结论:今后改任何预设的 pattern,
若不在改动同时把旧 pattern 登记进 `LEGACY_BUILTIN_PATTERNS`,老用户将永远停在旧 pattern。
- 改动:把历次发布过的预设 pattern 全量补进 `LEGACY_BUILTIN_PATTERNS`(从 git 历史逐版本提取),
并在文档里写明「改预设 pattern 时必须同步登记旧 pattern」的规则(AGENTS.md 高亮一节)。
- 测试:`tests/settings-store.mjs` 表驱动补「旧版 pattern 规则 → 升级到新 pattern、保留用户颜色/启停」用例。
---
## W2:捡漏功能(目标版本 v1.0.33)
### W2-1 可点击链接规则的导入 / 导出 + profile 联动
- 现状:`src/renderer/src/settings/HighlightImportExport.tsx:44,52,155` 只处理 `highlightRules`;
AGENTS.md「可点击链接规则」章末明确「尚未做,属后续可加」。
- 改动:`src/shared/highlightIO.ts` 的信封机制扩展 `kind`(或新建 `linkRulesIO.ts` 同构模块),
UI 侧在 `ClickableLinkRules` 区块复用剪贴板 + FileReader + Blob 方案,**不新增 IPC**;
profile 联动参考 `excludedByProfile` 的现有做法。
- 测试:`tests/link-rules.mjs` 补信封/合并用例。
### W2-2 命令库 `{{param}}` 参数变量落地
- 现状(已核实执行链):`src/shared/commands.ts:11` 定义了 `params?: string[]`,全仓无消费代码。
命令的实际执行路径是 `Workspace.tsx:1215` 的 `runCommand` → `writeBroadcast(sid, \`${cmd}\r\`)`(:1227)
→ 激活面板。参数替换应发生在 `runCommand` 入口处,替换产物继续走 `writeBroadcast`,
各 pane 的 line buffer 语义自然保持。
- 改动:执行命令时若含 `{{name}}` 占位,弹参数输入(antd Modal 表单),替换后写入终端。
- 测试:替换逻辑抽纯函数 + 表驱动测试(占位符转义、未填参数、含 `$` 字符等)。
### W2-3 i18n 两个统一专项
- 现状(已核实计数):zh-TW 词典「密碼」32 处(settings.ts 26 + ssh.ts 4 + workspace.ts 2)为压倒性多数,
「口令」仅 `dicts/zh-TW/ssh.ts` 5 处,统一为「密碼」并通读 指令/命令、伺服器/服务器、預設/默认;
ja `dicts/ja/ssh.ts` 用「フォルダ」而 `settings.ts`/`terminal.ts` 用「フォルダー」。
- 改动:纯文案批量替换 + 通读;不动键名。
- 测试:无测试基建,四语言界面各过一遍设置页与 SSH 面板目检。
### W2-4 本地终端运行 rz/sz 的用户提示
- 现状(已核实数据路径):ZMODEM sentry 只挂在 SSH 流上(`pty.ts:433-438` `handle.stream.on('data')` →
`feedZmodem`);本地 node-pty 会话的数据路径**没有任何 chunk 检测**。本地终端跑 `rz/sz` 只会静默卡住。
- 改动:在本地 PTY 数据路径加轻量 ZMODEM 头检测(只在看到 `rz`/`sz` 启动帧时生效,常态零开销),
命中时在终端里输出一行醒目的不支持说明(走终端数据面,i18n 四语);不要接入完整 sentry。
- 测试:`tests/zmodem-e2e.mjs` 补「本地会话触发 → 提示且不进入传输态」。
---
## W3:剪贴板与命令感知(目标版本 v1.0.34,对位「AI Agent 工作台」核心场景)
### W3-1 OSC 52 远程写剪贴板
- 现状:只装了 fit/search/unicode11/webgl 四个 addon;远程 tmux/vim 复制无法直达本机剪贴板。
- 改动:`term.parser.registerOscHandler(52, ...)` 自实现(比引 `@xterm/addon-clipboard` 可控):
base64 → **UTF-8 安全解码**(`atob` 裸解中文会乱码,用 TextDecoder)→ `navigator.clipboard.writeText`;
新增设置开关「允许远程程序写入剪贴板」(默认开,设上限如 1MB)。
- 测试:解码函数抽纯模块,表驱动测中文/emoji/base64 边界。
- 注意:新依赖规则——自实现则零依赖;若引 addon,渲染层依赖进 devDependencies。
### W3-2 剪贴板图片粘贴进终端
- 场景:截图直接喂给 Claude Code / Kimi Code 这类支持贴图的 AI CLI。
- 改动:渲染层拦截粘贴(现有粘贴逻辑在 `TerminalView.tsx:99-124` 确认弹窗与 :943-946 的 xterm paste 通道),
剪贴板为图片时经 IPC 让主进程 `clipboard.readImage()` → 落临时 PNG(`os.tmpdir()`,定期清理)→
把路径文本写入终端。**不涉及 `localPathGrants`**:该注册表只授权「系统对话框选中的路径」
(`grantPickedFiles`/`grantPickedDirectory`,localPathGrants.ts:110,119),临时文件由主进程自己写入、
应用自身不读它,无需授权。
- 测试:临时文件命名/清理逻辑的单测;实际粘贴行为列入发版手测清单。
### W3-3 OSC 133 命令块感知(marks)
- 现状:`src/main/shellIntegration.ts:8,39,60` 已注入 OSC 7(bash/zsh/PowerShell 三个适配器)——
扩到 133 是同一处注入脚本 + xterm 侧 mark 注册。
- 改动:注入脚本补 `OSC 133;A/B/C/D`(prompt start / command start / output start / finished+exitcode);
渲染层监听 mark 事件建「命令块索引」,提供:
- 滚动条刻度(marks gutter)
- 快捷键跳上/下一条命令
- 「复制本次命令输出」(整块选中复制——整段取 AI agent 输出是核心诉求)
- 测试:注入脚本的字面量生成有现有测试模式可仿;mark 索引纯函数表驱动。
- 风险:OSC 133 在不同 shell/嵌套 tmux 下行为差异大,首版只承诺 bash/zsh/pwsh,tmux 内标注「依赖外层终端透传」。
### W3-4 长任务完成通知(依赖 W3-3)
- 场景:多路分屏跑 AI agent,跑完切走被叫回来——本产品核心场景。
- 改动:OSC 133 D(命令结束)到达且该 pane **不可见**且命令耗时 > 阈值(设置项,默认 10s)时:
托盘气泡(复用 `tray.ts notifyUpdate` 的通道)+ 标签强调态。退出码非零时气泡文案区分成功/失败。
- 测试:判定逻辑抽纯函数(耗时阈值、可见性、退出码),表驱动。
---
## W4:Shell 与 SSH 迁移链(目标版本 v1.0.35,获客向)
### W4-1 本地 Shell 配置档
- 现状:`src/main/pty.ts:220-228` win32 硬编码 `powershell.exe`;`createPty` 的 `opts.shell`/
`opts.shellArgs` 已存在但**无任何调用方传参**——只差最后一公里。
- 改动:设置新增「默认 Shell」下拉(自动探测:`wsl.exe -l -q` 枚举发行版、`git-bash.exe` 常见路径、
cmd/pwsh/powershell),`Workspace.tsx` 的 `createPty()` 调用点传入;工作区「+ 新建终端」沿用默认,
侧栏可提供「以其它 shell 新建」次级菜单。
- 测试:探测函数接受注入的枚举源(测试缝),表驱动覆盖各解析分支;真实 WSL/Git Bash 列入手测清单。
### W4-2 `~/.ssh/config` 导入
- 现状:无任何 ssh_config 解析代码;国内用户从 Xshell/PuTTY 迁移时「几十台机器重录」是弃用理由之首。
- 改动:解析器抽纯模块(Host/HostName/User/Port/IdentityFile/ProxyJump,多 Host 与通配 Host `*`),
映射到 `SshConnection` 并批量追加进 `connections.json`(新增字段时同步三处:
`PUBLIC_KEYS` / `toPublic()` / `saveConnection()` 新记录字面量——AGENTS.md 明确要求)。
ProxyJump 字段在 W4-3 之前先存起来不生效。
- 测试:解析器表驱动(注释、大小写、引号、通配、Include 提示不支持)。
### W4-3 SSH ProxyJump + 端口转发(同一波次,共用通道基建)
- 现状(已核实):`forwardOut|ProxyJump|jumpHost` 全仓零命中;企业内网 bastion 是刚需。
**两个核实到的前置事实**:① 飞行中连接登记表 `pendingOpens` 在 `src/main/pty.ts:155,329,360`
(不在 ssh.ts);② ssh2 不带类型定义,项目用手写 shim `src/main/ssh2.d.ts`,
其中**只声明了 `connect()`,没有 `forwardOut`**(:85-86)——必须扩 shim。
- 改动:
- 连接模型:`SshConnection` 增加 `jumpHostId`(引用另一条连接)与 `forwards[]`(本地/远程/SOCKS)。
- 主进程:`ssh2` 先连跳板 → `forwardOut` 建通道 → 在通道上再握手目标机;复用
`pendingOpens` 的中止与超时体系(每跳独立超时);主机指纹逐跳走现有 host key 队列。
- 类型:扩展 `src/main/ssh2.d.ts` 补 `forwardOut` 等声明。
- 端口转发:连接建立后按 `forwards[]` 起本地监听,断开/失败时面板给出醒目状态。
- 测试:ssh-loopback 测试基建可起两级跳板做端到端;真实服务器场景列入手测清单。
- 风险:这是本计划里架构风险最高的一项,建议单独立项评审后再动。
---
## W5:差异化(择期,各独立立项)
### W5-1 远程文件内置编辑器
- 双击 SFTP 文件 → 面板内打开编辑(轻量 textarea 起步,Monaco 体积与零依赖取向冲突需另行评估);
保存自动回写;处理编码(UTF-8 优先)、CRLF、无写权限提示。改动点:`FilePanel.tsx` +
`sftp.ts` 新增 read/write 文件 IPC(走 per-op 超时 `bounded()`)。
### W5-2 应用级命令面板 + 可自定义快捷键
- `Ctrl+Shift+P`(已核实全仓无占用)动作注册表 + antd 模糊搜索 Modal;快捷键录制器复用
`src/shared/reservedAccelerators.ts` 保留键表(`acceleratorParts`/`isReservedAccelerator`,防抢 Ctrl+L/Ctrl+F)。
价值:功能密度已高,这是「后续功能不再堆 UI」的前置投资。
### W5-3 终端内 AI 助理
- OpenAI 兼容端点(DeepSeek/Kimi/智谱均可接入),「`#` 开头自然语言 → 建议命令」,
**默认只生成、回车前必须人工确认**;报错解释走显式按钮。**红线:任何终端内容不外发**,
与现有「诊断日志不含内容」的隐私原则保持一致。
- 注意:引入网络请求路径,需过安全评审;不绑账号、无云同步(相对 Warp 的国内优势)。
---
## §6 需决策的取舍项(不排期,等拍板)
| 项 | 取舍点 | 建议 |
|---|---|---|
| 代码签名证书 | 外部成本(~数百美元/年);无签名则 SmartScreen 拦截 + 通道完整性缺口 | 用户量到一定规模再做 |
| 多窗口 / 标签拖出 | 与单实例设计冲突,`sessionState`/owner 归属需重构 | 等真实多显示器用户反馈 |
| SFTP 本地↔远程双栏 | 大工程(本地文件树模型 + 传输层重做);官网 SFTP 区从未宣传「双栏」(i18n fs.* 文案只讲远程面板 + 上传下载),无宣传口径包袱 | 观望;拖拽上传先满足大半诉求 |
| 传输暂停/续传 | `TransferState` 无 `paused` 态,需断点续传协议层 | 观望 |
| 性能优化第二阶段(B3/B4) | 项目自定规则:没拿到真实 PERF 日志前不许凭感觉动 | 维持观测,等数据 |
| xterm 解 pin 回 `^` | 锁 `6.1.0-beta.304` 因 IME 修复;解 pin 需同步 addon-unicode11 peer 并重测中文输入法 | 等上游 6.1.0 stable |
| autoWrap=false 固定列宽 | xterm 无原生支持,等于自写列裁剪层 | 不做 |
## 执行约束(所有波次通用,摘自 AGENTS.md 铁律)
1. 新增纯逻辑一律抽零 import 纯模块 + Node 原生类型剥离表驱动测试,测试数随 AGENTS.md 清单同步更新
2. 依赖分类:`src/main|preload` 实际 import 的才进 dependencies;渲染层一律 devDependencies
3. i18n 四语言键必须同步(zh-CN/zh-TW/en/ja),缺键回落简中但属必须修
4. 新增「渲染层构造本地路径传主进程」的调用点必须过 `localPathGrants`
5. CSS 一律 `var(--ot-*)`,新代码禁止裸颜色字面量(`tests/css-theme-vars.mjs` 守门)
6. 每个发版 commit 必须带 `package-lock.json`;发布流程照 AGENTS.md「发布新版本」六步
7. 改 AGENTS.md 已文档化的行为时,同步更新 AGENTS.md