Skip to content

Latest commit

 

History

History
216 lines (192 loc) · 14.9 KB

File metadata and controls

216 lines (192 loc) · 14.9 KB

EternalTerminal (ET) 集成清单 — 按 Mosh 方式重做

目标:在上游最新架构(分支 feat/et-history-reapply,基于 031bf0ee)上, 完全照搬 Mosh 的方式重新集成 EternalTerminal:

  1. 打包客户端 —— 像 mosh-client 那样,把 et 客户端二进制构建 + 下载 + 捆绑进安装包,运行时只用捆绑的二进制(不依赖系统安装的 et)。
  2. 接入协议 —— 把旧分支 feat/eternal-terminal(tip 67e81616)里的 ET 后端 + UI 重新落到上游重构后的目录结构上,并让它启动捆绑的 et

旧实现参考:git show 67e81616(共 7 个 ET 提交,见 feat/eternal-terminal)。 Mosh 模板参考:resources/mosh/README.mdscripts/*mosh*electron/bridges/terminalBridge/moshSession.cjs.github/workflows/build-mosh-binaries.yml

关键设计差异(ET vs Mosh)

  • 协议:Mosh 需要 Node 重写 Perl 包装器(SSH bootstrap + 抓 MOSH CONNECT + 换 PTY)。ET 不需要 —— et 客户端自己完成 SSH 引导 + 协议握手,我们只要 把 et 当作普通 PTY 进程 pty.spawn 即可。所以没有 etHandshake.cjs
  • 凭证注入:Mosh 自己驱动 ssh、直接往 PTY 里敲密码;ET 内部驱动 ssh,需用 SSH_ASKPASS + 临时 ~/.ssh 环境把保存的密码/密钥/跳板/算法喂给 et 内部的 ssh (旧实现 prepareEtSshEnvironment 已完整实现,直接搬运)。
  • terminfoet 是纯传输客户端、本地不渲染终端,无需 捆绑 terminfo (Mosh 因静态 ncurses 才需要)。打包目录里只放 et[.exe](+ Windows DLL)。
  • 构建系统:Mosh 用 autotools;ET 用 CMake + Ninja + vcpkgcmake -DDISABLE_TELEMETRY=ON -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo), 产物是单个 et(Windows et.exe)。

命名约定(镜像 Mosh)

Mosh ET
resources/mosh/<plat-arch>/mosh-client[.exe] resources/et/<plat-arch>/et[.exe]
打包后 <Resources>/mosh/mosh-client 打包后 <Resources>/et/et
scripts/build-mosh/ scripts/build-et/
scripts/fetch-mosh-binaries.cjs scripts/fetch-et-binaries.cjs
scripts/resolve-mosh-bin-release.cjs scripts/resolve-et-bin-release.cjs
scripts/mosh-extra-resources.cjs scripts/et-extra-resources.cjs
env MOSH_BIN_RELEASE / 仓库 Netcatty-mosh-bin / tag mosh-bin-* env ET_BIN_RELEASE / 仓库 Netcatty-et-bin / tag et-bin-*
npm run fetch:mosh[:dev] npm run fetch:et[:dev]
bundledMoshClient() / resolveBareMoshClient() bundledEtClient() / resolveBareEtClient()
.github/workflows/build-mosh-binaries.yml .github/workflows/build-et-binaries.yml

Phase 1 — 打包基础设施(构建/下载/捆绑)

  • 1.1 resources/et/README.md —— 镜像 resources/mosh/README.md:说明 二进制来源、Netcatty-et-bin 发布仓库、et-bin-* tag、许可证(ET 为 Apache-2.0,与 GPL-3.0 兼容)、可复现构建命令。
  • 1.2 .gitignore —— 追加 ET 段(镜像 mosh 段): /resources/et/*/et/resources/et/*/et.exe/resources/et/*/*.dll/resources/et/*/et-win32-*-dlls/。保留 resources/et/README.md
  • 1.3 scripts/build-et/build-linux.sh —— manylinux2014 + vcpkg 静态三元组 构建 et(x64/arm64),产物 et-linux-<arch>.tar.gz(+.sha256),内含单个 et。 校验非系统动态库(同 mosh 的 ldd 白名单)。
  • 1.4 scripts/build-et/build-macos.sh —— arm64 + x86_64 分别构建后 lipo 成 universal,MACOSX_DEPLOYMENT_TARGET=11.0,产物 et-darwin-universal.tar.gz
  • 1.5 scripts/build-et/build-windows.ps1(或 .sh)—— MSVC + vcpkg x64-windows-static,产物 et-win32-x64.tar.gz(含 et.exe;若动态链接 CRT 则随附 DLL 目录 et-win32-x64-dlls/,否则纯静态无 DLL)。
  • 1.6 scripts/et-extra-resources.cjs —— 镜像 mosh-extra-resources.cjs: 按平台/arch 仅当 resources/et/<plat-arch>/et[.exe] 存在时才产出 extraResources 指令(to: "et/");Windows 额外处理可选 DLL 目录。去掉 terminfo 分支
  • 1.7 scripts/resolve-et-bin-release.cjs —— 镜像 resolve-mosh-bin-release.cjsTAG_RE=/^et-bin-.../,默认仓库 Netcatty-et-bin,env ET_BIN_RELEASE 优先。
  • 1.8 scripts/fetch-et-binaries.cjs —— 镜像 fetch-mosh-binaries.cjsTARGETS 四项(linux-x64/arm64、darwin-universal、win32-x64),全部 tar.gz; SHA256SUMS 校验;解包到 resources/et/<plat-arch>/Windows 用自建产物 (ET 官方有 Windows 构建,无需 FluentTerminal 那种 fallback)。去掉 terminfo 校验。
  • 1.9 单元测试:scripts/fetch-et-binaries.test.cjsscripts/resolve-et-bin-release.test.cjsscripts/et-extra-resources.test.cjs (镜像对应 mosh 测试,改名/改路径)。
  • 1.10 package.json scripts:新增 "fetch:et": "node scripts/fetch-et-binaries.cjs""fetch:et:dev": "node scripts/fetch-et-binaries.cjs --host --resolve-release"; 把 dev 脚本改成先 fetch:mosh:dev && fetch:et:devtest glob 已覆盖 scripts/*.test.cjs(确认即可)。
  • 1.11 electron-builder.config.cjs:引入 etExtraResources,在 darwin/win32/ linux 三处把 etExtraResources(plat) 合并进 extraResources(与 mosh 数组拼接)。
  • 1.12 .github/workflows/build-et-binaries.yml —— 镜像 build-mosh-binaries.yml:四个构建 job + 一个 release job(dispatch 且 release_tag 非空时发布到 Netcatty-et-bin,附 SHA256SUMS)。paths 过滤 指向 scripts/build-et/**scripts/fetch-et-binaries.cjsscripts/et-extra-resources.cjs。 env 用 ET_REF(默认 ET release tag,如 et-v6.2.x)。 > 注:实际二进制由用户手动 workflow_dispatch 触发产出;本地/CI 未设 > ET_BIN_RELEASE 时 fetch 步骤安静跳过(同 mosh)。

Phase 2 — 运行时定位捆绑客户端

  • 2.1 electron/bridges/terminalBridge.cjs 新增 bundledEtClient(opts) —— 镜像 bundledMoshClient:打包路径 <Resources>/et/et[.exe];dev 回退 <projectRoot>/resources/et/<plat-arch>/et[.exe];导出到 module.exports。

Phase 3 — ET 协议后端(搬运旧实现到新架构)

  • 3.1 新建 electron/bridges/terminalBridge/etSession.cjs —— 用上游 moshSession.cjscreateXxxSessionApi(ctx) + with(ctx) 工厂模式,封装: ET_ASKPASS_SCRIPTwriteSecureFileprepareEtSshEnvironmentcreateEtAskpassArtifactscleanupStaleEtTempDirscleanupSessionExternalAuthArtifactsexecOnEtSessionstartEtSession改动点etCmdfindExecutable('et') 改为 resolveBareEtClient() (取捆绑二进制);找不到时抛错(同 mosh:提示跑 npm run fetch:et:dev)。 Windows 若有 DLL 目录,复用 prependEnvPath 思路把 DLL 目录加进 PATH。
  • 3.2 terminalBridge.cjs 接线 createEtSessionApi(ctx)(镜像 moshSessionApi 的 ctx),传入 bundledEtClienttempDirBridgeexecFile/execFileSync 等; 解构出 startEtSessionexecOnEtSessioncleanupStaleEtTempDirscleanupSessionExternalAuthArtifactsresolveBareEtClient
  • 3.3 init()cleanupStaleEtTempDirs()registerHandlersipcMain.handle("netcatty:et:start", startEtSession)closeSessioncleanupAllSessionscleanupSessionExternalAuthArtifacts(session)module.exports 导出 startEtSessionexecOnEtSessionbundledEtClient
  • 3.4 测试:terminalBridge.bundledEt.test.cjs(路径解析)+ terminalBridge/etSession.test.cjs(prepareEtSshEnvironment 的端口/密钥/ askpass/跳板/legacy 算法分支)。可参考旧分支是否已有 ET 测试并搬运。

Phase 4 — domain / 类型 / preload 接口面

  • 4.1 domain/models.tsHostProtocol'et'ProtocolConfig.etPort?Host/GroupConfigetEnabled?/etPort?/etTerminalPath?TerminalSession.etEnabled?ConnectionLog.protocol'et'。 (照搬 git show 794eecdf -- domain/models.ts
  • 4.2 domain/groupConfig.ts:加 etEnabled 默认项(照搬旧 diff)。
  • 4.3 global.d.tsNetcattyBridgestartEtSession?(options): Promise<...> 及相关 options 类型(照搬 git show 794eecdf -- global.d.ts,并补齐后续 ET 提交 新增的 etPort/terminalPath/jumpHosts/legacyAlgorithms 字段)。
  • 4.4 electron/preload/api.cjs:加 startEtSession(镜像第 26 行的 startMoshSession)→ ipcRenderer.invoke("netcatty:et:start", options)注意:上游已把 preload 重构成 createPreloadApi,落点在 preload/api.cjs, 不是旧的 preload.cjs 内联对象。

Phase 5 — 渲染层 + UI + i18n

  • 5.1 application/state/useTerminalBackend.ts:加 etAvailable(查 bridge?.startEtSession)+ startEtSession,并在返回对象/依赖数组里登记 (镜像 mosh 的第 10/42/198/205 行处)。
  • 5.2 application/state/useSessionState.ts:路由 ET 会话(照搬旧 diff,+6 行)。
  • 5.3 components/terminal/runtime/createTerminalSessionStarters.ts:加 startEt(term)(镜像 startMosh,组装 options:etPort/terminalPath/ jumpHosts/legacyAlgorithms/凭证/identityFilePaths)。 注意:上游把它从旧的 infrastructure/runtime/ 移到了 components/terminal/runtime/ —— 落点以上游为准。
  • 5.4 UI 组件(照搬 git show b1a306f8 6c0d5bf3 55caa268 的相应文件, 映射到上游同名组件): - [ ] components/ProtocolSelectDialog.tsx —— 新增 ET 选项 - [ ] components/QuickConnectWizard.tsx - [ ] components/HostDetailsPanel.tsx —— ET 设置(启用、ET 端口、etterminal 路径) - [ ] components/GroupDetailsPanel.tsx - [ ] components/VaultView.tsx - [ ] components/Terminal.tsx / components/TerminalLayer.tsx - [ ] components/terminal/TerminalConnectionDialog.tsx / TerminalToolbar.tsx - [ ] App.tsx
  • 5.5 i18n:application/i18n/locales/en.tszh-CN.ts 加 ET 文案 (照搬旧 diff,键名对齐上游现有 mosh 文案结构)。

Phase 6 — 校验

  • 6.1 npm run lint(确保新 .cjs 在 scripts/ 下不受 ESLint 限制, 或按需加 eslint-disable,与 mosh 脚本一致)。
  • 6.2 npm test(新增的 fetch/resolve/extra-resources/etSession 测试全绿)。
  • 6.3 npm run build(渲染层 TS 编译通过,无类型错误)。
  • 6.4 手动冒烟(需先有发布的二进制): ET_BIN_RELEASE=et-bin-... npm run fetch:etnpm run start → 新建 ET 会话连一台装了 etserver 的主机,验证连接/输入/退出/凭证注入。

进度记录

  • 状态:Phase 1–5 已完成并通过校验(仅余 1 个可选项 + CI 产二进制)
  • 验证结果:
    • npx eslint <所有改动文件> → 干净(0 错 0 警)
    • npx tsc --noEmit → 我的改动 0 个新增类型错误TerminalConnectionDialogcase 'mosh' 的 TS2678 是既有问题,行号因我插入 ET 早返回从 60→64,非新增)
    • node --test(ET 相关)→ etSession/bundledEt/3 个脚本测试 全绿
    • npm test → 1383 通过 / 16 失败,16 个全是既有的 Windows 环境失败 (mosh 打包测试的 GNU-tar C: 问题、isExecutableFile 无 x 位、ACP execPath、SKILL.md 权限、Comware DH 等;均在我未改动的文件里)
    • npm run build(Vite)→ 构建成功(8.55s),渲染层打包通过

已完成

  • Phase 1scripts/et-extra-resources.cjs / resolve-et-bin-release.cjs / fetch-et-binaries.cjs(+3 测试,27 通过)、scripts/build-et/{build-linux.sh, build-macos.sh,build-windows.ps1}.github/workflows/build-et-binaries.ymlresources/et/README.md.gitignorepackage.jsonelectron-builder.config.cjs
  • Phase 2terminalBridge.cjs 新增并导出 bundledEtClient
  • Phase 3terminalBridge/etSession.cjs(startEtSession + prepareEtSshEnvironment + SSH_ASKPASS 机制 + execOnEtSession + 清理),接线进 terminalBridge.cjs(ctx/IPC netcatty:et:start/init 清理/close/quit 清理/导出),+2 测试(13 通过)。 et 指向捆绑二进制(resolveBareEtClient→bundledEtClient),找不到则报错。
  • Phase 4:domain connection.ts/history.ts/terminal.tsgroupConfig.tstypes/global/netcatty-bridge-session.d.ts(startEtSession + NetcattyJumpHost[])、 electron/preload/api.cjsdomain/vaultImport.ts(排除 'et' 导入协议)。
  • Phase 5
    • 启动派发:useTerminalEffects.tsTerminal.tsx(×3) → startEt
    • 运行时 starter:createTerminalSessionStarters.ts 新增 startEt(含单跳板/凭证/ legacy 算法/askpass 路径),.types.tsetAvailable/startEtSession
    • 后端 hook:useTerminalBackend.ts(etAvailable + startEtSession)
    • 会话透传 etEnabled:sessionFactories.tsuseSessionState.ts(×6)、 TerminalLayer.tsx(×3)、TerminalLayerSupport.tsxAppHandlers.ts(协议解析/日志/选择)
    • UI:HostDetailsAdvancedSections.tsx(ET 开关+端口+etterminal 路径,与 Mosh 互斥)、 HostDetailsPanel.tsxProtocolSelectDialog.tsx(ET 选项)、 TerminalConnectionDialog.tsx(ET 标签)、TerminalToolbar.tsx(编码菜单门控)、 GroupSshSettingsSection.tsx + GroupDetailsPanel.tsx(组级 ET)、VaultView.tsx
    • i18n:en/zh-CN 的 hostDetails.section.ethostDetails.et.*terminal.connection.protocol.etterminal.et.*

剩余(可选 / 非阻塞)

  • QuickConnectWizard.tsx:把 ET 加为“快速连接”协议按钮(type/端口/建主机映射 + UI 按钮)。当前快速连接未列 ET;保存主机后开启 ET 再连即可,故仅为便利项。

  • 产出二进制:手动 workflow_dispatchbuild-et-binaries.yml(带 release_tag=et-bin-<ver>-1)发布到 Netcatty-et-bin,并配 ET_BIN_RELEASE_TOKEN secret。之后 ET_BIN_RELEASE=... npm run fetch:et 即可本地/打包捆绑 et。 build-et 脚本本机无法编译 C++,需在 CI 验证。

  • 端到端冒烟:有二进制后 npm run dev,对装有 etserver 的主机建 ET 会话验证。

  • 当前分支:feat/et-history-reapply(基于上游 031bf0ee

  • 旧 ET 实现参考分支:feat/eternal-terminal(tip 67e81616,7 个 ET 提交)