Skip to content

feat: terminal per-command blocks with hover add-to-conversation - #421

Open
havoc-rao wants to merge 2 commits into
omdsh-dev:mainfrom
havoc-rao:feat/terminal-blocks
Open

feat: terminal per-command blocks with hover add-to-conversation#421
havoc-rao wants to merge 2 commits into
omdsh-dev:mainfrom
havoc-rao:feat/terminal-blocks

Conversation

@havoc-rao

Copy link
Copy Markdown

Problem

终端是一条连续滚动流,无法把「某条命令 + 它的输出」作为一个整体引用。文本/代码 viewer 已有「添加到对话框」能力(TextEditor 选区浮钮 → appendToDraft),终端完全缺失同款能力;xterm 自身也没有任何块级语义(无命令边界、无聚合提取、无稳定锚点)。

Fix

  • src/client/terminal-blocks.ts(纯逻辑,随终端懒加载 chunk 分发,不进核心 bundle):
    • TerminalBlockTracker:以输入流为界切分 block——onData 逐字符状态机清洗(CSI/OSC/粘贴标记/退格,裸回车不产生空块),Enter 提交命令并锚定 shell echo 行;onSubmit 回调供视图钉锚点。
    • marker 化锚点:视图在每次提交后 term.registerMarker(0)(cursor 行 = echo 行)钉住每个 block 的边界——marker 随 scrollback trim / reflow 平移、滚出 buffer 自动 dispose;blockStartLine / blockEndLine / blockSpanLines 统一走 marker 解析,disposed marker 解析为 +Infinity(行已消失 = block 整体不可见)。
    • blockOutputText:纯文本提取(跳过 echo 行、折行还原、剥尾部空行与半条 pending 命令),marker 解析边界。
    • buildTerminalInsert / blockForSelection:fence payload(info 行 $ <command>、4000 字符截断 + \n…)与选区 → block 归属。
  • src/client/TerminalBlockOverlay.tsx:视觉 block 层——每次 CLI 执行以 echo 行为界画 hairline 分隔线;悬停某 block → 行区间淡色高亮 + 悬停行右侧浮出「添加到对话」药丸(有文本选区时让位给选区 popup);几何 = .xterm-screen rect + (row - viewportY) × cellH(不依赖渲染器内部行元素),rAF 合并 tick(scroll / write-parsed / resize + ResizeObserver)自驱重绘,alt buffer 时整层让位;点击经 appendToDraft 整块插入对话草稿,复用既有 addToConversation i18n key(19 语言零新增)。
  • src/client/TerminalView.tsx / builtins/tabs.tsx / sidebar.module.css:会话 state 驱动 overlay 挂载;提交时 marker 解析边界;替换掉旧的右上角常驻药丸;.terminal 增加定位上下文 + 层/分隔线/高亮/药丸样式(全 token 驱动)。

Regression guard

  • tests/terminal-blocks.spec.ts(27 例):清洗状态机、提交/闭合/裸回车/多行粘贴/上限裁剪 + marker 解析(trim 漂移归属、disposed → +Infinity 不可见、cap 时 dispose 被丢弃 block 的 marker)、提取、归属、payload 形状。
  • tests/terminal-block-overlay.spec.tsx(4 例,jsdom + mock rect + 队列化 rAF):每 block 一条分隔线、hover 高亮 + 药丸点击提交正确的 block、mouseleave 清除、!visible 零渲染。
  • 旧代码下必红的断言:marker 漂移后的选区归属(blockForSelectionmarker.line 而非起始索引)、disposed marker 不可见(blockStartLine 返回 +Infinity)、分割线数量。

Verification

  • pnpm typecheck ✅ / pnpm build ✅(lib/client-terminal.js 545KB,含新代码)/ check:consumer-types
  • 全量单测 1054 passed / 9 skipped(较基线 +10);仅 agent-pty/smoke 26 例 posix_spawnp failed——沙箱禁止 node-pty 拉起真实 shell,git stash 后在干净基线上同样复现(与本次改动无关)
  • 挂载冒烟(CI plugin-mount job)覆盖终端懒加载 chunk 路径;本机沙箱无法起真实 dsh web,未本地跑

关联

  • 设计文档:docs/plans/2026-08-27-terminal-blocks-design.md(决策记录、marker 锚点、hover overlay 设计)
  • 分支:feat/terminal-blocks920549f + d976952 两笔提交)

- terminal-blocks.ts: pure block framework — the input stream (Enter in
  onData) segments the xterm buffer into per-command blocks (cleaned
  command + echo row anchor + output span), with wrap-aware plain-text
  extraction, pending-echo peeling, selection attribution and the fenced
  insert payload builder (mirrors selection-payload.ts).
- TerminalView: ports the TextEditor "add to conversation" capability —
  an xterm selection raises the same floating popup (anchored at the
  .xterm-selection DOM rects), and a top-right pill offers the current
  block (last command + output) as one insertable unit; both go through
  appendToDraft.
- tabs.tsx: terminal descriptor now passes ctx to TerminalView.
- tests: 21 unit tests for the framework; design doc.
- TerminalBlockOverlay: hairline dividers at every CLI block boundary,
  hover span highlight + per-block 'add to conversation' pill at the
  hovered row; geometry from .xterm-screen rect + buffer row math
  (renderer-independent), self-ticking via rAF on scroll/write/resize,
  hover from host mousemove.
- terminal-blocks: blocks pin their echo row with an xterm marker
  (tracker onSubmit hook; marker slides with trims/reflows, disposed
  marker = block gone); blockStartLine/blockEndLine/blockSpanLines
  resolve marker-aware spans for extraction, attribution and the layer.
- TerminalView: session state drives the overlay; block commit resolves
  marker-aware boundaries; old pinned top-right pill removed (hover pill
  replaces it).
- tests: marker-aware span/extraction/attribution + tracker onSubmit +
  overlay behavior (dividers, hover pill, commit, clear); design doc v2.
@Menghuan1918 Menghuan1918 added enhancement New feature or request P2 中:一般功能/优化 area/terminal Terminal tabs, PTY, font fallback labels Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/terminal Terminal tabs, PTY, font fallback enhancement New feature or request P2 中:一般功能/优化

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants