Skip to content

feat(ssh): apply host setting changes to active connections#247

Merged
su-fen merged 2 commits into
mainfrom
features
Jul 23, 2026
Merged

feat(ssh): apply host setting changes to active connections#247
su-fen merged 2 commits into
mainfrom
features

Conversation

@su-fen

@su-fen su-fen commented Jul 23, 2026

Copy link
Copy Markdown
Member

问题

在设置页修改已有活跃连接的 SSH 主机信息后,已建立的连接继续用旧配置运行:SSH 保存只写库、无任何联动钩子,配置只在下一次连接或断线自动重连时才被重新读取,用户既得不到提示,也没有让新配置立即生效的手段(会话 UI 只有"关闭",没有手动重连)。

方案

保存时弹窗询问

  • 编辑已有主机且改动了影响连接的字段(host/端口/用户名/认证方式/代理/输入了新密钥;name、描述不算)时,检测该主机的活跃会话并弹窗二选一:「立即用新配置重连 N 个会话」或「保持旧连接(下次重连时生效)」。
  • 立即重连严格等待设置落库(saveState 屏障)后执行;结果以卡片上的瞬态状态行汇总(成功数/需交互认证/需确认指纹)。

手动重连按钮(双端)

  • SSH 隧道面板会话行与终端 overlay 头部新增重连按钮;disconnected 会话也可点,兼做断线复活。chat SSHManager 工具创建的会话在同一 registry,天然覆盖。

删除主机警告并断开

  • 删除确认弹窗明示「将断开 N 个活跃连接」,确认后先逐会话关闭再删除主机。

Rust 核心:TerminalSessionRegistry::ssh_reconnect

  • 占用与自动重连相同的 reconnect_runner 互斥位后直接 disconnect + clear 拆除旧连接(绝不走 shutdown 通道——writer 任务会 disconnect 共享槽内"当前"句柄,新连接装入后会被误杀);随后复用 reconnect_ssh_session(本就重读最新配置)即时单次重连。孤儿 IO 泵依靠互斥位与连接代次守卫自然退出。
  • 顺手加固预存在竞争:reconnect_ssh_sessioninstall_connection 后复查 is_closing,防止批量关闭与进行中的重连交叠时装回幽灵连接。

网关:零 proto 改动

  • 新 terminal action "ssh_reconnect",Rust 端进 session-scoped SSH 门控组,Go relay 进 WebSshTerminalEnabled 组;web 端经 terminal.<action> 通用编码透传。

kbi(keyboardInteractive)降级

  • 重连路径没有交互提示通道,无法原地重连:设置页降级为纯提示弹窗;面板重连失败后引导「关闭+新建」(完整 prompt 链路);overlay 提示前往面板。

镜像纪律

  • pages/settings/SshSection.tsxlib/terminal/types.tscomponents/ui/confirm-dialog.tsx 保持双端字节一致并新入 mirror-manifest;平台差异收敛在 web 的 invoke shim(新增 terminal_list/terminal_close/terminal_ssh_reconnect 三个映射)。SshTunnelPanelWorkspaceSshTerminalOverlay 仍为手动镜像差异版,已逐块同步。

本 PR 同时携带 features 分支上此前未合入的一个提交:1bcec99a feat(gui): persist window size and maximized state across restarts

验证

  • node scripts/check-mirror.mjs:100 个镜像文件全部一致
  • Rust:cargo test 557 通过(含新增 3 个 ssh_reconnect 并发守卫测试:missing session / closing / 互斥占用不误释放)
  • GUI 前端:npm run test:frontend 1176 通过;Web 前端:npm test 403 通过
  • Go:go build ./...go test ./internal/protocol/... 通过
  • 双端 tsc --noEmit 与 biome 对改动文件零错误

手动验证建议(自动化覆盖不到真实连接):

  1. 密码主机开 2 个会话 → 仅改 name 保存应无弹窗;改 port 为错误值 → 选"立即重连" → 两会话重连失败报错(证明用了新配置);改回正确值 → 重连成功,SFTP 面板继续可用(缓存按连接代次自动重开)。
  2. 面板/overlay 重连按钮:连接中点击输出 [SSH] Reconnected after attempt 1;对 disconnected 会话点击可复活。
  3. kbi 主机:保存弹提示;面板重连失败 → 引导关闭+新建 → 弹交互认证。
  4. 删除有活跃连接的主机 → 弹窗含"断开 N 个" → 确认后会话关闭、主机移除、终端 tab 级联关闭。
  5. WebUI 重复 1/4;关闭 Remote 的 web SSH 终端权限后验证降级(列表滤空、不弹窗)。

🤖 Generated with Claude Code

su-fen and others added 2 commits July 23, 2026 14:54
Register tauri-plugin-window-state with SIZE|MAXIMIZED flags only:
POSITION would fight multi-monitor layouts, VISIBLE would re-show a
tray-hidden window on startup, and DECORATIONS would override the
per-platform window chrome. app_restart bypasses RunEvent::Exit where
the plugin normally flushes to disk, so it saves state explicitly
before restarting.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Editing an SSH host used to leave established connections running on the
old configuration with no feedback and no way to apply the update short
of closing the session.

- Saving connection-affecting changes (host/port/username/auth/proxy/new
  secrets) now detects active sessions for that host and offers to
  reconnect them immediately or keep them until the next reconnect; the
  reconnect waits for the settings save to land before running.
- New manual reconnect action on SSH tunnel panel rows and the terminal
  overlay header (also revives sessions whose automatic reconnect
  attempts were exhausted).
- Deleting a host with active connections now warns with the count and
  closes those sessions before removing the host.
- Rust: TerminalSessionRegistry::ssh_reconnect tears down the current
  connection directly (never via the shutdown channel, which would kill
  a freshly installed handle) under the reconnect-runner mutex, then
  reuses reconnect_ssh_session so the latest stored config is picked up;
  reconnect_ssh_session now re-checks closing after install to avoid
  resurrecting a session closed mid-reconnect.
- Gateway: new terminal action "ssh_reconnect" (no proto changes),
  gated with the session-scoped SSH permission group on both the Rust
  handler and the Go relay.
- keyboard-interactive hosts cannot re-auth inside the reconnect path:
  the settings dialog degrades to a notice, the tunnel panel offers
  close-and-recreate through the full prompt flow, and the overlay
  points at the panel.
- SshSection.tsx, lib/terminal/types.ts and confirm-dialog.tsx are now
  registered in the mirror manifest; platform differences stay in the
  web invoke shim.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@su-fen
su-fen merged commit b1a599b into main Jul 23, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant