4 Commits
Author SHA1 Message Date
胡飞 5236415412 fix(terminal): 修复 PROMPT_COMMAND 钩子在子 shell 报「未找到命令」(#217)
bash 分支把 PROMPT_COMMAND 注册成裸函数名。PROMPT_COMMAND 是 shell 局部机制,
但它的值可能被环境导出并被后续 shell(su、tmux、exec bash、嵌套 ssh)继承,
而那些 shell 里没有本文件定义的函数,于是每个提示符都多输出一行
「bash: __onetcli_precmd_bash:未找到命令」,即 issue #217 的现象。

- 钩子改为自带存在性判断的命令串:`command -v` 是内建命令,函数缺失时静默跳过、
  不产生 fork,也不受继承链路影响;
- 退出码必须在钩子里先取好再显式传给函数:钩子里的 `command -v` 会覆盖 `$?`,
  若仍让函数自己去读 `$?`,上报的 exit code 会恒为 0、`133;D` 失效;
- 补两个回归测试:继承钩子但没有函数的 shell 必须静默、主 shell 退出码必须仍上报;
- 设计文档记录该约束,避免以后被简化回裸函数名。

验证:`cargo test -p terminal`(503 lib 测试通过)、
`cargo clippy -p terminal --all-targets`(改动文件零告警);另在真实交互式 bash 中
对比复现:修复前子 shell 输出 2 行 command not found,修复后 0 行,
主 shell 的 `133;D` 退出码上报仍为 `false`→1、`true`→0。
2026-09-18 17:57:46 +08:00
胡飞 45a75c5be4 fix(terminal): 修复 Shell Integration 握手无兜底导致 SSH 键盘输入被永久暂存 (#206)
运行时 Shell Integration 的就绪握手期间,actor 会把用户键盘输入压入
deferred_actor_inputs 暂存。四个暂存态(WaitingForFirstOutput / Injecting /
AwaitingPrompt / PlainAwaitingOutput)都只能靠远端输出推进,其中三个没有任何
超时兜底:远端一旦不再产出可解除握手的输出(登录 expect 永不匹配导致
should_inject 不触发、prompt 结束标记缺失等),会话就永久停在暂存态——远端
输出照常刷新、提示符与光标都正常,但按键(含 Enter / Ctrl+C)被静默吞掉,
界面没有任何提示。本地终端走 pty_backend、没有这道门禁,因此表现为
「同窗口本地终端正常、SSH 标签输入全死」。

- RuntimeShellIntegration 新增 phase_name() 与 force_release_input():把上述四个
  暂存态强制推进到 Plain(丢弃注入回显缓冲,此后不再抑制输出、不再注入),
  已可输入的阶段返回 false,不干扰正常会话
- actor 新增 30s 看门狗 SHELL_INTEGRATION_HANDSHAKE_TIMEOUT,到期调用
  force_release_input() 并置 shell_ready = true,下一轮循环按序重放 deferred
  队列;输入被暂存时打 terminal.ssh.runtime 的 debug 日志(含 phase 与队列长度),
  看门狗触发时打 terminal.ssh.setup 的 warn 日志
- 抽出 arm_shell_integration_handshake_watchdog() 供测试直接断言武装条件:
  不能写成 accepts_terminal_input().then(..)——bool::then 是「为真才取」,那样只在
  已可输入的会话里武装,握手态反而是 None,看门狗永不触发(等于没接上),且到期
  那侧 force_release_input() 返回 false 属无害空转,既不报错也不失败。状态机推进
  单向,启动时判定一次即可
- 设计与状态表同步更新到 docs/design/ssh-runtime-shell-integration.md

验证(在本提交所覆盖的工作区执行):

- cargo test -p terminal --lib => 491 passed / 0 failed
- 新增 handshake_watchdog_arms_exactly_when_input_is_deferred:把武装条件改回反向
  写法实测 FAILED,修正后 Green
- cargo clippy -p terminal --all-targets -- -D warnings:terminal 自身干净,剩余报错在
  agent_runtime、crates/ssh/src/host_key.rs 等未触碰文件,属既存 lint

已知限制:兜底只放行输入,不补发 init_commands——其发送判定在输出处理分支内,
远端彻底沉默时仍需再来一段输出才会发出。
2026-09-16 16:16:59 +08:00
user.email e92900b425 fix(terminal): SSH 探测致传输层断连后自动降级单通道重连,修复受限设备无法登录 (#183)
华为 USG 等仅允许单个 SSH 会话的嵌入式设备会在 shell integration 探测的
CHANNEL_OPEN 阶段直接回 SSH_MSG_DISCONNECT 掐断整个传输层(日志表现为
Disconnected),随后在死 transport 上开交互通道报 Channel send error,
且不匹配既有的 channel open 降级重连条件,导致整条连接失败。

- establish_channel 探测后检查传输层存活:被掐断时失效该 transport
  generation,重建连接并以单裸交互通道模式重试(跳过探测);
  探测失败仍只降级不注入,零远端写入的行为不变
- 连接表单高级设置新增「禁用 Shell 集成」开关,针对网络设备/工控主机
  从源头跳过探测(复用既有 disable_shell_integration 字段)
- 降级重试后仍被设备断连时,为 russh Disconnect/SendError 补充
  设备 SSH/VTY 会话限制排查提示
- 更新设计文档补充受限设备探测断连降级章节
2026-09-11 17:03:44 +08:00
胡飞 297c6ebca5 docs(terminal): runtime SSH shell integration design notes
Document the no-remote-write injection design: probe, single-line
ANSI-C eval injection, echo suppression state machine, readiness
handshake, timeout fallback, legacy rc detection/cleanup, and the
verification matrix including the live 181-server test.
2026-08-28 14:23:41 +08:00