Skip to content

终端诊断 Phase 2: Shell Integration 与 Auto Beta 落地 #525

@pionxe

Description

@pionxe

关联 RFC / 架构

  • 提案/架构 issue:终端诊断设计 (V5 终极落地版 - 严格依从现有网关协议)
  • 对应用户场景:实现了【场景一:Auto 模式(即时纠错,无缝顺滑)】完整交互体验,并将【场景二】由 Mock 雏形升级为对接真实大模型。
  • 当前问题:作为整体落地路线的 Phase 2,核心目标是基于 PTY 桥接实现“基于原生命令退出的精准自动触发(Auto Beta)”以及连通真实的 AI 大模型工具诊断。由于 PTY 代理本身只看得到字节流,无法可靠获取内部 Shell 的命令退出码,因此必须引入 Shell Integration(如 OSC 133)来精确感知命令的开始、结束和状态,从而做到“不阻断 stdout、在 Prompt 再次出现后再渲染诊断”的无缝体验。

实现设计(How)

  • 关键改动点

    1. PTY 代理稳定性加固 (前置技术债修复):在代理入口极早期加入 defer term.Restore() 兜底防线;扩大信号量捕获范围,不仅透传 SIGTSTP/SIGCONT (作业控制),必须强制拦截并透传 SIGHUP (窗口关闭) 和 SIGINT (中断),防止退出窗口时产生大量孤儿僵尸进程或吞噬用户的 Ctrl+C。
    2. 稳健的 Shell Integration 注入与 Active Probe (动态探针):提供 neocode shell --init 脚本。
      • 兼容性挂载:通过追加或 add-zsh-hook 注入 OSC 133,兼容主流主题。
      • Tmux 穿透:处于 tmux 时,包裹 \ePtmux;...\e\ 透传指令。
      • 首屏动态探针:启动 PTY 后开启 1.5s 倒计时。若超时未拦截到 \e]133;A\a,先暂且降级为 Manual 模式。但状态不写死——如果在后续用户的任意命令交互中,Ring Buffer 突然捕捉到了完整的 C+D+A (命令开始-结束-Prompt) 序列,则说明缓慢的终端已就绪,代理必须动态将其重新平滑升级回 Auto 模式。
    3. OSC 133 解析器 (internal/ptyproxy/shell_events.go):在代理端拦截并剥离这些专门用于通信的 OSC 133 字节流。当收到 D;{exit_code}(命令结束状态)时,不能盲目见非零即触发。
    4. 精准触发过滤引擎 (Trigger Filter):建立严格的防误触状态机规则,避免刷屏骚扰:
      • 排除中断信号:明确忽略因用户 Ctrl+C (130)、SIGKILL (137) 等导致的非零退出。
      • 常见命令豁免:对于 grep, find, test, false 等常因未命中或逻辑判断而返回非零(但不属异常)的命令,建立本地豁免名单。
      • 输出质量检查:判定缓存的 Stderr 或终端输出内容是否为空/太短,无实际报错内容的坚决不触发诊断。
    5. 全方位安全清洗与智能截断 (Sanitization & Truncation):在向网关发送前,执行两步清洗。第一步降噪:剥离 ANSI 色彩与折叠 \r 进度条,再通过 Head-Tail 截断防 Token 爆炸。第二步安全脱敏(从 Phase 4 强制提前):用核心正则库双向扫描截取到的 Output(日志)与 Input(输入命令),强制打码 AWS AKIA、JWT 等极高危凭证,绝不允许敏感数据在 Phase 2 的 Auto 触发中发生任何出网裸奔风险。
    6. 延迟安全渲染机制:满足触发条件后,代理挂起触发动作,绝不阻断命令输出。等待下一个表示 Prompt 就绪的 OSC 133 指令后,才发起诊断,避免插队破坏排版。
    7. 认证屏障(已实现):认证屏障已在 Gateway 及 Phase 1 中完整实现,直接沿用。
    8. 真实 SubAgent 闭环 (internal/tools/diagnose):正式调用 SpawnSubAgent,解析 JSON Schema 模型输出并渲染 ANSI。
    9. Socket IPC 协议 JSON-Lines 升级:为彻底解决 \n 换行符破坏 Payload 边界的问题,废弃简单的 <CMD>:<PAYLOAD>\n,直接将底层协议升级为基于 JSON-Lines ({"cmd":"...","payload":"multi\nline"}\n) 的通信格式,为 Phase 3 的多行交互打下坚实基础。
    10. 全局路径规范与平滑升级 (EADDRINUSE 防御):统一收口 Socket 至 ~/.neocode/run/neocode-diag-<PID>.sock。若客户端找不到该路径,MUST 添加对旧版 $TMPDIR 路径的 fallback 探测,并在成功回退时输出 Warning,防止 Phase 1 遗留环境升级直接断裂。启动 net.Listen 前强制 os.Remove(sockPath)
    11. 信号量并发拦截设计 (AUTO off 响应时机):Socket 监听 MUST 在独立 Goroutine 运行并修改 atomic.Bool。网关 RPC 诊断完成后,输出渲染前必须二次校验该标志位。若发现被关闭,直接 Drop 诊断结果,实现零延迟切断。
  • 影响模块ptyproxy(新增 OSC 事件解析与流状态机、IPC 扫地僧)、tools/diagnose(对接真实大模型)、cli(增加 hook 输出脚本)。

  • 边界与非目标:本阶段不包含针对 vim/ssh 等交互式长任务的 TUI 防干扰过滤(该能力属于 Phase 4);不包含 IDM 沙盒的多轮交互支持(该能力属于 Phase 3)。关于环境兼容性,禁止使用高延迟的超时等待,必须通过首屏探针机制(Active Probe)主动检测 OSC 133 握手回声,若不支持则瞬间无感降级为 Manual 模式。

任务拆解

  • T0. PTY 稳定性前置加固:在原 RunManualShell 或代理核心入口补充 defer 恢复机制,并编写信号量透传器拦截转发 SIGHUPSIGINTSIGTSTPSIGCONT
  • T1. 注入钩子开发:实现一份轻量级的 bash/zsh 兼容脚本,确保在命令执行前后静默打印 \e]133;A\a (Prompt 出现), \e]133;C\a (命令开始执行), \e]133;D;{exit_code}\a (命令结束附带状态码)。
  • T2. 事件监听器开发:在 internal/ptyproxy 实现状态流拦截器,截获并吃掉这些 OSC 133 序列信号,避免将其漏到用户的真实终端屏幕上变成乱码。
  • T3. 延迟触发与防误判状态机:利用捕获的 D (退出码) 结合防误判规则进行综合评估,并在收到下一个 A (Prompt) 后安全发起 Auto 诊断。
  • T4. 日志清洗、脱敏与截断器开发:编写极速降噪清洗函数(去 ANSI/折叠 \r)、对 UTF-8 安全的 Head-Tail 截断算法,以及核心数据脱敏器(正则拦截 Token/密码等),确保发往模型的数据不仅体积受限,更要绝对安全合规。
  • T5. 对接真实模型:完善 tools/diagnose 工具,编写 Prompt,调用 SpawnSubAgent 进行推理,并引入 JSON 强校验器转 ANSI 输出。
  • T6. IPC 协议重构:将 CLI 与 Proxy 间的 Socket 通信全面升级为 JSON-Lines ({"cmd":"...","payload":"..."}\n) 结构,彻底解决多行截断问题,并实现对 AUTO: off 等指令的监听处理。
  • T7. 基建路径治理:统一全局配置加载(config.yaml)及 Socket 路径(~/.neocode/run/...),并实现 net.Listen 前的静默清理防御逻辑。

测试与验证(Done)

  • 单元测试 (覆盖率目标 100%)
    • 编写 internal/ptyproxy/shell_events_test.go:送入包含大量随机中英文字符与合法 OSC 133 序列的混合字节流,测试状态机是否能正确剔除 OSC 字符且准确剥离出命令的退出码与执行边界。
    • 编写 internal/ptyproxy/filter_test.go:穷举并断言 Trigger Filter 的各种判定场景,确保按 Ctrl+C 退出或执行 grep 失败等常见操作必定会被判定为 Skip(豁免触发)。
    • 编写 internal/ptyproxy/sanitizer_test.go:断言清洗函数在处理包含假 Token 和中英文字符串时 0 泄漏且不破坏排版。
    • 编写 internal/tools/diagnose/agent_test.go:针对断网、大模型返回内容损坏等场景,验证工具安全 Fallback(静默降级)不 panic。
    • 核心契约测试(已完成):验证客户端正确处理鉴权策略(此测试已随 Phase 1 完成验证,本阶段无需重复覆盖)。
  • 并发混沌测试 (Chaos/Race Testing)
    • 编写针对 Ring Buffer 的高压读写轰炸测试:起多个 Goroutine 模拟千兆字节的高速 stdout 灌入,同时在另一个线程并发读取截断快照,要求跑通 go test -race,保证 0 死锁、0 指针异常、提取出的文本无截断乱码。
  • 人工验证 (集成演示)
    • 正常路径:配置好 Shell Hook 的环境下启动代理,运行一段必失败的命令(如 cat 不存在的文件)。终端首先正常打印原生报错并返回系统的命令输入符,随即在下一行自动打印出带颜色的 AI 根因分析。
    • 边界条件:执行耗时较长(如需编译 1 分钟)且最终报错的命令时,Auto 模型须耐心等待其完全结束并返回 Prompt 后再触发,不得在中途插队截断原程序输出。
    • 异常降级验证:检测不到 hook/OSC 时,自动切入 Manual 模式。执行错误命令不触发 Auto,不报错刷屏,无误触发死锁。

风险与回滚

  • 风险:极少数深度定制终端(未按规范实现 OSC/ANSI)或极端网络 SSH 环境下,探针可能误判或注入失效。此外,庞大的正则匹配脱敏(Sanitization)若在终端日常打印时执行,极易成为 CPU 瓶颈导致卡顿。
  • 缓解/回滚方案:得益于动态探针机制,绝大多数不支持环境会自动切回手动模式。脱敏计算严格限制在向网关发起 RPC 的那一刻仅对截断后的几 KB 切片执行。若发现逻辑严重误判或阻碍终端刷新,用户可通过 neocode diag auto off 实时关闭自动触发,或直接退出 neocode shell

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions