Skip to content

HomeSense Studio v2 终端与设备控制台重构交接文档

🕒 Published at:

HomeSense Studio v2 终端与设备控制台重构交接文档 ​

本文件总结了当前终端重构的进展、核心设计思路、技术架构及后续接班开发计划。


1. 核心目标与当前状态 ​

当前任务是移除 Mock 配置,转向真实、解耦的本地/SSH/ADB 终端适配。目前已完成大部分后端与前端的基础链路改造,完成了本地 SSH 通道与按需凭证解析。

当前主要变动与状态: ​

  • 后端端口移至 3100:为了避免与前端常规端口冲突,NestJS 后端默认端口由 3000 改为 3100(apps/server/src/main.ts 中通过 process.env.PORT || 3100 指定)。
  • 前端配置环境变量:apps/web/.env 文件配置了 VITE_API_BASE=http://localhost:3100,Vite 开发服务器当前在 5181 端口运行。
  • Mock 服务白名单:前端 mock-server.ts 已将 /api/terminal 加入到 REAL_API_PREFIXES 白名单,保证所有终端相关请求均穿透 Mock 直达真实 NestJS 后端。
  • 密钥安全存放(Git-ignored):私钥和 ADB 配对密钥被安全地存放在后端的本地文件系统中:
    • apps/server/runtime-keys/ssh/
    • apps/server/runtime-keys/adb/
    • 避免将敏感的认证信息(如 n8n_watchdog 密钥)提交到公共 Git 仓库。

2. 数据库与后端架构 ​

2.1 数据库设计 (terminal_targets 表) ​

在 SQLite 中实现了配置数据库,独立存储设备的接入通道和认证凭证:

sql
CREATE TABLE IF NOT EXISTS terminal_targets (
    id INTEGER NOT NULL,
    name TEXT NOT NULL,
    kind TEXT NOT NULL,         -- 'ssh' | 'adb' | 'local'
    target_json TEXT NOT NULL,  -- 存储主机、端口、用户名、私钥文件名等配置 JSON
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    PRIMARY KEY (id AUTOINCREMENT)
)

2.2 核心模块关系 ​

  1. KeyStore (keystore.ts):负责读写 runtime-keys/ 下的文件,不对前端暴露密钥文件内容,仅对内提供解析。
  2. TargetResolver (target-resolver.ts):将前端请求的配置 ID 或设备 ID 解析为包含主机地址、端口、凭证名称的 ProtocolTarget 对象。
  3. SSHProtocol / LocalProtocol / AdbProtocol:
    • 适配不同类型的终端通道。
    • LocalProtocol 在 Windows 上使用 node-pty / ConPTY 跑本地 PowerShell/CMD。
    • SSHProtocol 基于 ssh2 模块建立远程加密 shell 会话。
  4. TerminalGateway (terminal.gateway.ts):WebSocket 网关(绑定路径为 /api/terminal/ws),升级 HTTP 并处理输入输出流,将 WebSocket 数据流通过 Subject 泵送到具体的协议处理器。

3. 前端重构架构 ​

前端去除了原来的单页面强制铺满设计,改为高可复用的终端卡片组件:

  1. TerminalPanel.vue (通用组件):
    • 封装 xterm.js 及 fit-addon 插件。
    • 通过 ResizeObserver 动态计算宽高,并向后端发送 resize 消息调节伪终端的行/列数。
    • 管理 WebSocket 状态的开启与清理,统一处理 stdout、session_opened、exit 等控制帧。
  2. DeviceDetailView.vue (设备详情页整合):
    • 在设备详情页中提供控制台展开区,直接内嵌 TerminalPanel.vue,实现快速操作。
  3. SessionView.vue (全屏独立会话页面):
    • 负责承载全屏长会话终端,同样内嵌 TerminalPanel.vue,支持通过 URL 参数 target_id 连接特定凭据的目标。
  4. AuthorizationsView.vue (凭据授权管理页):
    • 完全实现了 SSH 配置卡片的增删改查。
    • 用户可以新建通道(SSH/Local)、选择并配置私钥别名、测试连接并实时验证握手结果。

4. 接下来的工作规划 (待办事项) ​

开发已基本贯通真实物理连接链路,下一步应该集中力量解决会话持久化与生命周期管理:

  1. 后端 Session 存储 (TerminalSessionStore):
    • 当前 WebSocket 刷新或断开会导致 PTY 进程被直接 Kill。
    • 需要引入内存 Session 管理器:当连接断开时,保持 PTY 进程存活;等待客户端重新 attach。
    • 实现 Ring Buffer 环形缓冲区:每个活动 Session 在后端保留最近的(如 1000 行)输出历史,在新连接重新 attach 时主动下发以恢复终端视窗。
  2. 终端生命周期控制 UI:
    • 前端应允许用户自主选择终端的关闭方式:
      • “暂离 / 保持运行” (Detach):关闭面板但保持 PTY 活跃。
      • “彻底终止” (Kill / Terminate):向后端发送退出码,彻底销毁 PTY 进程并断开 WebSocket。
  3. 多标签终端支持 (Tabs):
    • 允许单个设备面板中并存多个 Shell 会话(例如左侧跑 ADB Shell 调试,右侧通过本地 PowerShell 查看日志)。
  4. 未来演进(流媒体与 Agent 接管):
    • 保证底层 Protocol 具备可拦截和可读取的流接口,使得未来的 Agent (比如 Coding Agent) 可以直接作为虚拟客户端,挂载到同一个 Session ID 旁听或发送指令。

交接日期:2026/06/08主分支:master / main开发环境端口:Vite(5181) | NestJS(3100)