Skip to content

design(ssh): 抽象统一 SSH 诊断与修复层(覆盖 connect/install/doctor/health) #89

@Akane-CN

Description

@Akane-CN

背景

当前 ClawPal 里 SSH 相关逻辑分散在多个层(UI/Tauri/core/install/doctor)。用户遇到连接失败时,报错常常是“点状”的:某一步失败但缺少统一诊断链路,导致修复建议不一致、重复重试成本高。

目标:抽象一个统一的 SSH Diagnostic & Repair Layer,让所有 SSH 入口共享同一套“分层诊断 + 可执行修复建议 + 错误码语义”。


一、调研结果:哪些环节依赖 SSH

1) 连接与会话生命周期(基础层)

  • src-tauri/src/commands/mod.rs
    • ssh_connect
    • ssh_connect_with_passphrase
    • ssh_disconnect
    • ssh_status
    • ssh_exec
  • src-tauri/src/ssh.rs
    • 连接池/重连/并发控制/semaphore
    • exec / sftp_read / sftp_write / sftp_remove

2) 实例接入与管理

  • connect_ssh_instance(实例级接入)
  • SSH Host registry CRUD:list_ssh_hosts / upsert_ssh_host / delete_ssh_host
  • clawpal-core/src/ssh/registry.rs, clawpal-core/src/instance.rs

3) 安装与初始化流程(高频失败点)

  • src-tauri/src/install/commands.rs
    • run_remote_ssh_step(...)
    • precheck/install/init/verify 阶段均通过 SSH 执行远端命令

4) Doctor 远端诊断与修复

  • src-tauri/src/doctor_commands.rs
    • collect_doctor_context_remote
    • doctor file/config/... 远端读写与执行
    • openclaw path 修复、远端日志抓取、gateway 状态探测等

5) 健康检查/轮询

  • clawpal-core/src/health.rs
    • remote ssh health check 依赖 ssh command
  • 前端自动轮询(Start/Home)会触发远端状态请求,间接打到 SSH

6) 前端交互与错误提示

  • src/App.tsx 内有 SSH_ERROR_MAP(字符串正则映射)
  • 多处页面(Start/Doctor/Home)有“重连/检查/提示”逻辑
  • 目前前后端错误语义尚未统一(regex 文案驱动为主)

二、核心问题

  1. 诊断逻辑分散:连接失败、认证失败、主机指纹、远端命令失败等分散处理。
  2. 错误语义不统一:前端 regex + 后端原始错误混杂,缺少稳定错误码。
  3. 修复建议不可复用:同类错误在 install/doctor/connect 场景下提示不一致。
  4. 重试策略不一致:有的环节自动重连,有的直接失败;缺少统一 backoff 策略。
  5. 可观测性弱:缺少跨模块、分阶段的 SSH 诊断事件和统计。

三、设计:SSH Diagnostic & Repair Layer

3.1 新增统一领域模型(建议放 clawpal-core/src/ssh/diagnostic.rs

SshDiagnosticReport {
  stage: SshStage,
  status: ok | degraded | failed,
  errorCode: Option<SshErrorCode>,
  summary: String,
  evidence: Vec<SshEvidence>,
  repairPlan: Vec<SshRepairAction>,
  confidence: f32,
}
  • SshStage(建议)
    • ResolveHostConfig
    • TcpReachability
    • HostKeyVerification
    • AuthNegotiation
    • SessionOpen
    • RemoteExec
    • SftpRead
    • SftpWrite
    • SftpRemove
  • SshErrorCode(稳定枚举)
    • SSH_HOST_UNREACHABLE
    • SSH_CONNECTION_REFUSED
    • SSH_TIMEOUT
    • SSH_HOST_KEY_FAILED
    • SSH_KEYFILE_MISSING
    • SSH_PASSPHRASE_REQUIRED
    • SSH_AUTH_FAILED
    • SSH_REMOTE_COMMAND_FAILED
    • SSH_SFTP_PERMISSION_DENIED
    • SSH_SESSION_STALE
    • SSH_UNKNOWN

3.2 统一诊断入口

新增接口(core 或 tauri facade):

  • diagnose_ssh(host_id, intent)
    • intent: connect | exec | sftp_read | sftp_write | install_step | doctor_remote

输出统一 SshDiagnosticReport,上层不再直接拼接散乱字符串。

3.3 修复动作抽象(可执行计划)

SshRepairAction 示例:

  • PromptPassphrase
  • RetryWithBackoff
  • SwitchAuthMethodToSshConfig
  • SuggestKnownHostsBootstrap(先手动 ssh 一次确认 host key)
  • SuggestAuthorizedKeysCheck
  • SuggestPortHostValidation
  • ReconnectSession

注意:默认只给建议,不做高风险自动修改(authorized_keys/sshd_config)。

3.4 与现有模块集成方式

  1. ssh_connect* / ssh_exec / sftp_*:失败时统一转换为 SshDiagnosticReport
  2. install/commands.rs:每个 remote step 附带 ssh 诊断上下文
  3. doctor_commands.rs:远端诊断输出叠加 sshDiagnostic
  4. App.tsx:由 errorCode -> i18n,逐步替换 regex 文案映射

3.5 事件与可观测性

新增事件(建议):

  • ssh:diagnostic
  • ssh:repair-suggested
  • ssh:repair-applied(若后续支持自动修复)

指标:

  • ssh 失败按 stage/errorCode 分布
  • 首次修复成功率
  • 连接建立耗时 / 重试次数

四、实施拆解

Phase 0:模型与兼容层

  • 定义 SshStage / SshErrorCode / SshDiagnosticReport
  • 提供 from_any_error(...) 适配器(兼容旧错误文本)

Phase 1:连接链路接入

  • ssh_connect / ssh_connect_with_passphrase / ssh_status 接入诊断层
  • src-tauri/src/ssh.rs 的 reconnect/exec 失败统一产出 errorCode

Phase 2:SFTP/命令执行接入

  • sftp_read/write/remove + ssh_exec 接入
  • 区分权限/不存在/超时/会话断开等错误码

Phase 3:Install + Doctor 接入

  • run_remote_ssh_step 输出结构化 ssh 诊断
  • collect_doctor_context_remote 增加 sshDiagnostic

Phase 4:前端语义统一

  • UI 从 regex 映射迁移到 errorCode 渲染
  • 增加“建议修复动作”展示区

Phase 5:测试与CI

  • 单测:错误映射、stage 分类、repair plan 生成
  • 集成测试:模拟 key missing / host key failed / auth failed / timeout
  • E2E:SSH 断连后重连 + doctor 远端诊断路径

五、验收标准

  • 同一类 SSH 错误在 connect/install/doctor 场景下输出一致 errorCode
  • Doctor 远端诊断包含结构化 sshDiagnostic
  • 前端不再依赖主要 regex 做 SSH 主判断(可保留兜底)
  • 至少 8 类常见 SSH 故障有明确 repairPlan
  • CI 覆盖映射与关键路径回归

预期收益

  • 降低 SSH 相关排障时间
  • 提升 install + doctor 场景的修复成功率
  • 为后续“自动修复(受控)”打基础

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions