From 1054c2a6619d6e6a52e6a74475837c23340eac84 Mon Sep 17 00:00:00 2001 From: Bill Date: Sun, 20 Sep 2026 20:27:08 +0800 Subject: [PATCH] docs: sync STATE/ROADMAP/AGENTS/README with reality version 1.0.13, M10 milestone, release steps matching release.cjs (incl. the sync-changelog pre-step), removed QuickInputPanel mentions, real test mechanism instead of vitest, full test list --- AGENTS.md | 18 +++++++++++------- README.md | 17 +++++++++++++++-- docs/ROADMAP.md | 14 ++++++++++++-- docs/STATE.md | 32 ++++++++++++++++++-------------- 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c8292e9..4c5310e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,8 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。 - 开发:`npm run dev`(主进程改动不热重建,需重启) - dev 实例使用独立用户数据目录 `%APPDATA%\OpenTerminal-dev` 与独立单实例锁(`src/main/index.ts` 顶部 `!app.isPackaged` 分支),窗口标题带 `(dev)`:**可与已安装的正式版同时运行,互不干扰**,也不会把测试设置/会话写进真实配置 -- 类型检查:`npx tsc --noEmit -p tsconfig.web.json` +- 类型检查:`npm run typecheck`(tsconfig.node.json + tsconfig.web.json;只看渲染层可单跑 `npx tsc --noEmit -p tsconfig.web.json`) +- 测试:`npm test`(先 `node tests/build-bundles.cjs` 重建 esbuild bundle,再依次跑可离线运行的 7 个测试;真实服务器测试需 JD_* 凭据,不在此列) - 打包:`npm run dist`,产物在 `release/`(msi + exe + latest.yml + blockmap) - 国内网络需镜像:`ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ ELECTRON_BUILDER_BINARIES_MIRROR=https://npmmirror.com/mirrors/electron-builder-binaries/ npm run dist` @@ -23,14 +24,17 @@ Electron + electron-vite + React 终端工具(本地终端 / SSH / SFTP)。 ## 发布新版本 -1. `package.json` 版本号 +1,写 `RELEASE_NOTES.md`(仓库根,已 gitignore) -2. `npm run dist` 构建 -3. `node scripts/release.cjs <版本号> --skip-github`,例如 `node scripts/release.cjs 1.0.11 --skip-github` - - **只发国内**(2026-09-15 起的产品决定):Gitea release(含 msi/exe 资产)→ Gitea 更新通道(`api/packages/admin/generic/openterminal-update/stable`,更新 latest.yml/blockmap/exe/release-notes.md) +1. `package.json` 版本号 +1,写 `RELEASE_NOTES.md`(仓库根,已 gitignore;可选 `.zh-TW/.en/.ja` 译文,缺译文回退简体) +2. `node scripts/sync-changelog.cjs` 把发布说明并入 `CHANGELOG*.md` —— **必须在 `npm run dist` 之前**:更新日志以 `?raw` 打进安装包(「关于」页离线读),`release.cjs` 也校验 `CHANGELOG.md` 已含该版本号 +3. `npm run dist` 构建 +4. `node scripts/release.cjs <版本号> --skip-github`,例如 `node scripts/release.cjs 1.0.14 --skip-github` + - **只发国内**(2026-09-15 起的产品决定):Gitea release(msi + exe 资产)→ Gitea 更新通道(`api/packages/admin/generic/openterminal-update/stable`:exe.blockmap → exe → release-notes.md → **latest.yml 最后**) + - 通道不再先删旧版:新版本文件全部传完、latest.yml 生效后才清掉上一版 exe/blockmap,中途失败不会把通道打空;同一版本可重复运行(release 复用、已传资产跳过) + - 只补通道:`node scripts/release.cjs <版本号> --channel-only`(不建 release、不发 GitHub) - 国内通道全程直连,**不需要设代理**;代理只在显式补发 GitHub 时才用(`HTTPS_PROXY=http://127.0.0.1:7897`,脚本只把它用于 GitHub 请求) - GitHub 那一步的状态:`README` 与更新机制里仍保留 GitHub 作为更新回退源,但**release 资产不再随版本发布同步**;若某天需要补,跑一次 `node scripts/release.cjs <版本号> --skip-gitea` 即可 -4. 验证更新通道:`curl https://git.codingplan.site/api/packages/admin/generic/openterminal-update/stable/latest.yml` 应返回新版本号 -5. `git tag v<版本号>` 并推送两个远程(代码/tag 的镜像保持同步,仅 release 资产不发 GitHub) +5. 验证更新通道:`curl https://git.codingplan.site/api/packages/admin/generic/openterminal-update/stable/latest.yml` 应返回新版本号 +6. `git tag v<版本号>` 并推送两个远程(代码/tag 的镜像保持同步,仅 release 资产不发 GitHub) ## 更新机制 diff --git a/README.md b/README.md index 7199a73..6172309 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ npm install # 已安装可跳过 npm run dev # 开发模式(热更新) npm run build # 生产构建到 out/ npm run typecheck # 全量类型检查 +npm test # 重建测试 bundle 后依次跑离线测试(详见「测试」) ``` > Electron 二进制下载失败时:`ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ node node_modules/electron/install.js` @@ -42,7 +43,7 @@ npm run typecheck # 全量类型检查 **效率工具** - 广播输入:勾选 ≥2 个终端后同步键入,标签带广播标记 -- 快捷输入面板:右下角浮层,命令历史 + 命令库(支持 `{{param}}` 变量)+ 一键执行 +- 命令面板:侧边栏「命令」标签分「历史」/「命令库」两页,历史按会话去重,命令库支持分组与一键运行 - 输入建议:历史 + 命令库来源,Tab 接受、回车始终直接执行(可在设置中整体关闭) - 会话日志:手动启停、纯文本落盘 - 快捷键:Ctrl+=/-/0 字号、Ctrl+PgUp/PgDn 切换面板、全局唤起/隐藏(可配) @@ -55,9 +56,21 @@ npm run typecheck # 全量类型检查 - 单实例运行:重复启动唤出已有窗口 - 设置持久化(userData/settings.json,原子写入)+ 多窗口实时同步 +**界面与语言** +- 四种界面语言:简体中文 / 繁體中文 / English / 日本語(设置 → 系统 → 界面语言,切换即时生效并持久化;antd 组件内置文案一并跟随) +- 更新日志随安装包内置,「关于」页离线可看,并按当前界面语言显示(某版本缺翻译时回退简体中文) + **测试** + +`npm test` 会先重建 esbuild bundle,再依次跑下列测试(无需服务器与凭据): + - `node tests/ssh-loopback.mjs` — ssh2 客户端/服务端回环(认证、shell、数据、resize、指纹) -- `node tests/ssh-session-e2e.mjs` — 真实会话路由层端到端(需先跑 esbuild 打包命令,见脚本头注释) +- `node tests/ssh-session-e2e.mjs` — 会话路由层端到端(SSH 数据面、replay、resize、kill) +- `node tests/sysinfo-e2e.mjs` — 服务器监控轮询端到端(META、采样速率、stopPolling) +- `node tests/zmodem-e2e.mjs` — ZMODEM 双向传输(与第二个 zmodem.js Sentry 对接,内容一致性) +- `node tests/commands-store.mjs` / `node tests/settings-store.mjs` — 命令库/历史/会话日志与设置清洗器 +- `node tests/.hl-split-smoke.cjs` — 关键词高亮流分块回归(bundle 由 `node tests/build-bundles.cjs` 生成) +- 真实服务器测试(需 `JD_HOST/JD_USER/JD_PASS`,不在 `npm test` 内):`tests/sftp-real.mjs`、`tests/sftp-chmod.mjs` ## 架构 diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 57aff84..67cec9c 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -16,6 +16,7 @@ | M7 | 打包分发(MSI + NSIS + 自动更新) | ✅ 已完成(v0.7,Release 已发布) | | M8 | 工作区分离(Terminal/SSH 双工作区)+ SSH 底部文件面板 + 右键菜单 + 监控美化 + 补全修复 | ✅ 已完成(v0.8) | | M9 | 体验打磨:系统托盘 + 关闭行为 + 单实例 + 主题联动标题栏 + 布局菜单重做 + 补全交互修正 + 应用图标 | ✅ 已完成 | +| M10 | 多语言界面(zh-CN / zh-TW / en / ja)+ 离线多语言更新日志 + 快捷键录制 + 可配终端工具条 + 设置健壮性 | ✅ 已完成(v1.0.13) | ## M2 — SSH 远程会话 ✅ @@ -96,11 +97,20 @@ - [x] 标签页视觉打磨:圆角胶囊 + 描边 + 独立关闭按钮 - [x] 本地 PTY 声明终端能力(TERM/COLORTERM/TERM_PROGRAM),TUI 程序不再降级配色 +## M10 — 多语言与体验细节 ✅ + +- [x] 界面语言(zh-CN / zh-TW / en / ja):全应用文案抽到 `src/shared/i18n/dicts`,设置 → 系统 → 界面语言,切换即时生效并持久化;antd 组件内置文案随语言切换 +- [x] 更新日志随安装包内置(`CHANGELOG*.md?raw`),「关于」页离线可看,按界面语言显示、缺翻译回退简体中文 +- [x] 全局唤起快捷键改为按键录制(Esc 取消 / 退格清空;必须带修饰键或功能键,避免误占普通按键) +- [x] 终端右上角工具条可配置:打开工作区目录(随 `cd` 跟踪)、记录会话日志、打开日志目录 +- [x] 设置健壮性:清洗器修复而不丢弃(priority 字符串、0/1 布尔、缺前景色),异常写 `settings-warnings.log`;设置写入串行化;「每次询问」关闭行为不再被静默改回 +- [x] 「输入建议」「记录命令历史」默认关闭;浅色主题标签栏/设置弹窗对比度修复;会话日志改为每文件缓冲写入 + ## 工程约定(贯穿各阶段) 1. **契约先行**:新增功能先在 `src/shared/` 定义通道与模型,再实现两端 2. **原生依赖**:优先选带预编译二进制的包(@lydell/node-pty 模式),避免用户机器装构建链 -3. **测试**:main 进程服务(pty/ssh/sftp)用 vitest 单测;渲染层交互靠 dev 手测 +3. **测试**:main 进程服务(pty/ssh/sftp/commands/settings/zmodem)先用 esbuild 打成 CJS/ESM bundle,再由 `tests/*.mjs` 以纯 Node 断言跑(`npm test`;无 vitest、无需服务器);渲染层交互靠 dev 手测 4. **里程碑验收后打 git tag** ## 已知待办(M1 遗留) @@ -113,4 +123,4 @@ - [ ] 内置等宽字体打包(OFL 许可:JetBrains Mono / Fira Code 等) - [ ] rendererMode webgl 的终端数量上限自动降级(大量终端实例时回退 DOM 渲染) - [ ] 会话数据在面板间拖拽迁移(dockview 原生支持面板拖动,已具备) -- [ ] 界面语言切换(中/英):需先把全应用文案抽为 i18n 资源目录(一次完整重构),设置页预留「系统」分区 +- [x] ~~界面语言切换~~(✅ v1.0.13:zh-CN / zh-TW / en / ja,文案抽到 `src/shared/i18n/dicts`,设置 → 系统 → 界面语言) diff --git a/docs/STATE.md b/docs/STATE.md index 4b2727c..a2908e7 100644 --- a/docs/STATE.md +++ b/docs/STATE.md @@ -4,7 +4,7 @@ ## 当前版本与仓库 -- v0.1.0(版本重置:作为全新开源项目从 0.1.0 起步),远程 `git.codingplan.site/admin/OpenTerminal.git`(国内仓)+ `github.com/billowliu2/OpenTerminal.git`(GitHub 镜像仓);凭据存于 `.env`(已 git 忽略),凭据助手按 host 自动读取 +- v1.0.13,远程 `git.codingplan.site/admin/OpenTerminal.git`(国内仓)+ `github.com/billowliu2/OpenTerminal.git`(GitHub 镜像仓);凭据存于 `.env`(已 git 忽略),凭据助手按 host 自动读取 - 开源协议:MIT(LICENSE) - 更新通道 = `https://git.codingplan.site/api/packages/admin/generic/openterminal-update/stable/`(公网可读,含 latest.yml/exe/blockmap) - 技术栈:Electron + electron-vite + React 19 + TS strict + antd 6(全局深色)+ zustand + dockview-react 8 + @xterm/xterm 6 + @lydell/node-pty + ssh2 + zmodem.js + electron-updater + electron-builder @@ -24,6 +24,7 @@ | M7 打包分发(MSI+NSIS+自动更新) | ✅(v0.7.0 已发布 Release) | | M8 工作区分离+底部文件面板+右键菜单+监控美化+补全修复 | ✅(v0.8.0) | | M9 体验打磨(托盘+关闭行为+单实例+主题联动标题栏+布局菜单重做+补全修正+图标) | ✅ | +| M10 多语言界面(zh-CN/zh-TW/en/ja)+离线多语言更新日志+按键录制+可配工具条+设置健壮性 | ✅(v1.0.13) | ## M8 实现要点(v0.8.0,已落地) @@ -42,31 +43,34 @@ - **广播输入**:渲染层 zustand(broadcastStore)维护 enabled/targets/sessions;TerminalView 全部写路径(onData/补全/粘贴/Workspace runCommand)走 writeBroadcast 扇出;目标 <2 自动禁用;tab 目标圆点 + 按钮计数徽标 - **ZMODEM**:主进程引擎(src/main/zmodem.ts,仅 SSH 会话;本地 pty 走 ConPTY 只给 UTF-8 字符串,二进制会损坏——不支持,注释已说明);Sentry 常驻分流非 zmodem 字节;offer→渲染层选文件/目录→respond;传输期抑制 PTY_DATA/replay/日志并丢弃用户键入;offer 120s/传输 90s 看门狗;进度复用 TransferPanel(kind=zmodem-upload/download);测试 tests/zmodem-e2e.mjs 用第二个 zmodem.js Sentry 模拟远端,双向内容一致性断言 -- **快捷输入面板**:QuickInputPanel 右下 fixed 浮层(bottom:44 避让 TransferPanel),发送经 writeBroadcast(广播感知),列表打开沿刷新 - **快捷键**:Ctrl+=/-/0 字号(main.tsx capture 监听,xterm-helper-textarea 放行——隐藏 textarea 曾被误判为输入框导致终端聚焦时失效,已修);globalShowHide accelerator(globalShortcuts.ts,设置页系统分区可配,注册失败仅 warn);Ctrl+PgUp/PgDn 面板循环(Workspace capture 监听) - **打包**:electron-builder.yml(msi 固定 upgradeCode 5ab9f79e-e4eb-4052-9df6-3af3a301ab0a + nsis;asarUnpack @lydell/node-pty + ssh2;npmRebuild false);updater.ts(仅 packaged 启用,OT_UPDATE_URL/OT_UPDATE_TOKEN env,默认 feed=上述 generic package 地址) ## 发布流程(下一版本照抄) -1. package.json version 升位 → `npm run dist`(env:ELECTRON_MIRROR + ELECTRON_BUILDER_BINARIES_MIRROR=npmmirror;dist:dir 后先删 release/win-unpacked 避免占用 EPERM) -2. `git tag vX.Y.Z && git push origin main vX.Y.Z` -3. Gitea API 建发布:POST /api/v1/repos/admin/OpenTerminal/releases(中文 body 必须走 UTF-8 文件 --data-binary @file,shell 内联会坏) -4. 附件:POST .../releases/{id}/assets?name=(msi/exe/blockmap/latest.yml,实测 141MB 可传) -5. 更新通道:DELETE .../api/packages/admin/generic/openterminal-update/stable(旧版)→ PUT 同 URL 依次上传 latest.yml / exe.blockmap / exe -6. 校验:curl 无 token 拉 latest.yml 应 200 且 version 正确 +1. `package.json` version 升位 + 写 `RELEASE_NOTES.md`(可选 `.zh-TW/.en/.ja` 译文)→ `node scripts/sync-changelog.cjs`(**在 dist 之前**:更新日志会打进安装包)→ `npm run dist`(env:ELECTRON_MIRROR + ELECTRON_BUILDER_BINARIES_MIRROR=npmmirror;dist:dir 后先删 release/win-unpacked 避免占用 EPERM) +2. `node scripts/release.cjs <版本号> --skip-github`:脚本自己建 Gitea release(msi/exe 资产)→ 传更新通道 `exe.blockmap → exe → release-notes.md → latest.yml`(**latest.yml 最后**);不再先删旧版,latest.yml 生效后才清掉上一版 exe/blockmap +3. 通道传坏了只补通道:`node scripts/release.cjs <版本号> --channel-only`(同一版本可重复运行:release 复用、已传资产跳过) +4. 校验:无 token `curl .../generic/openterminal-update/stable/latest.yml` 应 200 且 version 正确 +5. `git tag vX.Y.Z && git push origin main vX.Y.Z`(GitHub 镜像只推代码/tag,不随版本发 release 资产) ## 测试(全部通过,改动后必跑) ```bash -npx tsc --noEmit -p tsconfig.node.json && npx tsc --noEmit -p tsconfig.web.json +npm run typecheck # tsconfig.node.json + tsconfig.web.json npm run build +npm test # = node tests/build-bundles.cjs && 下面 7 个测试(依次,全部离线可跑) node tests/ssh-loopback.mjs -npx esbuild src/main/pty.ts --bundle --platform=node --format=cjs --outfile=tests/.session-e2e.cjs --external:@lydell/node-pty --external:ssh2 --alias:electron=./tests/electron-stub.cjs && node tests/ssh-session-e2e.mjs -node tests/sysinfo-e2e.mjs -npx esbuild tests/hl-split-smoke.mjs --bundle --platform=node --format=cjs --outfile=tests/.hl-split-smoke.cjs && node tests/.hl-split-smoke.cjs node tests/commands-store.mjs +node tests/settings-store.mjs # 设置清洗器(closeAction/高亮规则修复/告警日志) +node tests/.hl-split-smoke.cjs node tests/zmodem-e2e.mjs -# 真实服务器测试(需 JD 环境变量凭据,旧凭据已过期): +node tests/ssh-session-e2e.mjs +node tests/sysinfo-e2e.mjs +# `node tests/build-bundles.cjs` 单独重建全部 6 个 esbuild bundle(别名只存在于该脚本): +# .session-e2e.cjs(pty.ts) .sftp-svc.mjs(sftp.ts,ESM) .commands-store.cjs .settings-store.cjs +# .zmodem-e2e.cjs .hl-split-smoke.cjs —— 少 --alias:@shared=./src/shared 会编译失败 +# 真实服务器测试(需 JD 环境变量凭据,旧凭据已过期,不在 npm test 内): # JD_HOST=... JD_USER=root JD_PASS=... node tests/sftp-real.mjs / tests/sftp-chmod.mjs # 打包:npm run dist(产物 release/) ``` @@ -94,4 +98,4 @@ node tests/zmodem-e2e.mjs 1. ~~应用图标~~(已完成:build/icon.png,程序生成的原创图标) 2. 用户实测项:Ctrl+PgUp/PgDn 真实键盘(合成键盘无法验证修饰键)、真实服务器 rz/sz 一轮、全局唤起快捷键 -3. 小项:autoWrap=false 固定列宽、OSC 标题跟随、内置 OFL 字体打包、WebGL 终端数上限降级、i18n(中英切换)、最近命令历史出现两条命令拼接的记录(广播键入时行捕获合并,低优先级修) +3. 小项:autoWrap=false 固定列宽、OSC 标题跟随、内置 OFL 字体打包、WebGL 终端数上限降级、最近命令历史出现两条命令拼接的记录(广播键入时行捕获合并,低优先级修)