# dsh-terminal-context 一键将 DeepSeek Harness (DSH) 内置侧栏终端的选中文本,转为对话输入框中的原生 `@file` 引用。 对齐 Cursor 的 `@Terminals` 与 Trae 的「添加到对话」体验:免去手动复制粘贴数百行日志的繁琐操作;引用在输入框中以结构化 chip 显示,可点击预览,发送时自动展开为全文。 [English](README.md) | [简体中文](README.zh.md) --- ## 使用方法 整个交互配合常规提问流,无需寻找浮动按钮: 1. **选中文本**:在右侧栏内置终端中划选需要引用的输出或报错日志。 2. **点击输入框**:点击当前会话的输入框(准备输入问题)。此时「添加到上下文」按钮会固定浮现在输入框上沿右侧。 3. **加入上下文**: - **方式 A(点击)**:单击「添加到上下文」按钮,终端输出即刻以文件引用形式插入输入框。 - **方式 B(快捷键)**:在终端文本保持高亮时直接按下 **`Ctrl+L`**(macOS 为 **`Cmd+L`**)。 > **按钮位置说明**:本插件放弃了「跟随选区浮动」的设计。实测表明,侧栏 xterm 的高亮叠加层在多行折叠场景下无法提供跨环境可靠的视口坐标,浮动按钮容易跳出视口或遮挡文字。固定停靠在输入框上方能够确保位置稳定、不遮挡交互区域。 ### 快捷键行为与取消选中 - **命令标识**:`dsh-terminal-context.add`,可在「设置 → 快捷键」中重新绑定。 - **让渡按键**:当终端没有可用选区时,插件不拦截 `Ctrl+L`,终端原生的清屏功能照常生效;只有在选区有效时才会接管该按键。需要清屏时请输入 `clear`。 - **状态同步**:取消终端选区(灰色高亮消失)后,输入框上方的按钮会立即隐藏,快捷键也不会发送之前缓存的输出。 --- ## 为什么沉淀为文件,而不是直接粘贴文本? 终端输出通常包含数十至数百行日志。直接将大段文本灌入输入框存在明显弊端: - **稀释提问主体**:长日志会淹没你的实际问题,破坏会话的可读性。 - **重复消耗 Token**:多轮重试或追问时,内联的日志会被重复序列化提交,大幅增加上下文消耗。 - **来源断代**:大模型无法区分这段文本是终端产生的客观输出还是用户的手写输入。 本插件采用 **「本地临时捕获 + 原生引用注入」** 方案: 1. 选中文本自动写入 `<工作区>/.dsh/term-captures/terminal-<时间戳>.txt`,文件头部带有来源标识。 2. 通过 DSH 原生机制在输入框插入该文件引用。 3. 发送消息时,引用被序列化为 `@.dsh/term-captures/terminal-….txt`,Agent 可按需调取全文。 > **文本规范化**:落盘时,插件会自动剥除每行行尾的空白符以及整段文本首尾的空行。xterm 默认会用空格将行填满至终端视口宽度,这一清理可移除数百个无意义的填充空格,同时严格保留原本可见的所有字符。 --- ## 安装方式 DSH 目前未设立中心化插件市场,你可以通过 DSH 内置的插件管理能力进行安装。本仓库已内置预构建的客户端产物,无需本地构建,亦不会触发 `allowBuilds` 授权。 ### 方式 1:DSH 桌面版图形界面安装(最推荐) 如果你使用的是 DeepSeek Harness 桌面客户端,直接通过应用界面安装即可,无需打开命令行: 1. 打开 DSH 桌面版,点击左侧栏的 **「插件」** 图标。 2. 点击右上角的 **「添加插件」** 按钮。 3. 在安装来源输入框中直接填入 GitHub 仓库标识: ```text github:ZHOU-ZHIZHEN/dsh-terminal-context ``` 4. 点击安装,等待 DSH 自动拉取完成。 5. **完全重启 DeepSeek Harness** 即可生效。 > **本地开发提示**:如果是本地调试插件代码,也可以在「添加插件」输入框中直接填入本仓库在本地的**绝对路径**进行链接调试。 ### 方式 2:DSH Web 版 / 命令行安装 如果你使用的是 DSH Web 版或通过 CLI 管理 profile,在终端中执行: ```sh dsh plugin --profile web add github:ZHOU-ZHIZHEN/dsh-terminal-context ``` > **注意**:桌面版的 `desktop` profile 由 Electron 客户端独占管理,通过命令行操作会提示 `profile "desktop" is managed exclusively by the Electron application`。桌面版请统一使用上述**方式 1**在图形界面中添加。 ### 方式 3:通过本地 Tarball 安装 在仓库根目录下打包并安装: ```sh pnpm pack dsh plugin --profile web add ./dsh-terminal-context-0.1.0.tgz ``` --- ## 工作原理 ### 1. 结构化引用插入(三层降级) 向输入框注入原生 chip 必须通过会话作用域事件 `slash/input-insert-reference`。该事件要求 `span` 必须携带当前的草稿修订号 `draftRev`(由宿主做 CAS 校验),且 `reference.source` 必须为核心认可的源名。 为了稳定取得光标/插入点上下文,插件按序尝试以下三层路径: 1. **插槽桥(优先)**:向已声明的列表插槽 `conversation.input.dock` 注册无 UI 桥接组件(DSH 官方的 `todo` 与 `queue` 模块同在其中)。该组件必定能收到带有当前会话 `captureInsertion` 与 `insertText` 的标准 `inputActions`。 2. **服务直连**:调用 `ctx.get('conversation').input.for(scope)` 解析当前活动输入会话。 3. **纯文本提及(兜底)**:若上述两层结构化注入因宿主 CAS 拒绝返回 `false`,降级为直接向输入框追加 `@相对路径 ` 纯文本,DSH 仍会对其做高亮渲染。 ### 2. 选区读取与高亮层还原 | 提取路径 | 触发时机 | 精度特性 | |---|---|---| | **xterm DOM 选区** | 浏览器选区尚未折叠、文本可直接读取时 | 精确匹配选中字符 | | **高亮叠加层几何还原** | 鼠标松开后浏览器选区已自动折叠时 | 按行截取,宁多勿少 | 实测中,鼠标在终端松开的瞬间,浏览器的原生选区经常已退化为 `collapsed: true`(矩形尺寸为 0),导致 `window.getSelection()` 与合成的剪贴板探针读数均为空。但此时 xterm 自身绘制在 `.xterm-selection` 的独立绝对定位高亮层依然保留。 插件此时会解析该层的高亮像素矩形,计算出其覆盖的终端行号范围,并提取对应 `.xterm-rows` 的完整行内容。这种策略确保不会截断关键输出(例如因列换算误差误切 `ls -la` 结尾文字),用户若觉得行数偏多可在发送前微调,避免了选区截断导致的重新划选成本。 --- ## 项目结构 | 文件 | 说明 | |---|---| | `lib/client.js` | 浏览器端产物(遵循 `window.__ModuleLoader__.load` 规范):负责选区监听、停靠按钮、快捷键绑定与输入框交互 | | `lib/index.js` | 宿主端(Node.js):提供 `/capture` 落盘、`/sweep` 轮转清理以及 `/diag` 诊断等 HTTP 路由 | | `cordis.patch.yml` | Bundle 声明文件,用于在加载配置时注册插件运行时 | | `test-host.mjs` | 宿主端离线单测(模拟 WebServer、Sessions 及各类边界路径) | | `test-client.mjs` | 浏览器端离线单测(模拟 DOM、Lexical 输入框及 xterm 交互) | --- ## 本地验证 无需启动真实 DSH 环境,本仓库提供完整的离线验证脚本: ```sh node test-host.mjs lib/index.js # 验证路由调度、落盘安全、错误防护及 20 份轮转 node test-client.mjs lib/client.js # 验证 Bundle 契约、事件流、兜底链路与快捷键 ``` --- ## 已知限制与安全说明 - **HTTP 路由鉴权范围**:插件的 `/capture`、`/sweep` 与 `/diag` 路由挂载在 DSH 进程的 `webServer` 上,其内部不重复对请求发起方做独立身份校验。请确保 DSH 的 Web 端口仅监听在本地回环地址(`127.0.0.1`),严禁将该端口直接暴露到公网或未受信任的局域网中。 - **仅限右侧栏内置终端**:识别选择器限定为 `[data-sidebar-terminal]`(支持 DSH 原生终端以及 v0.19.0+ 的 `dsh-better-sidebar` 终端)。插件不依赖第三方终端组件的私有 API。 - **非全自动转录**:DSH 在架构设计上明确将终端执行过程排斥在会话 Transcript 之外(参考 `dsh-api-terminal-controller` 约定)。因此插件不会静默监听所有命令,仅在用户显式选定并触发后生成捕获。 - **捕获轮转机制**:捕获文件保存在 `<工作区>/.dsh/term-captures/`,文件名前缀为带时间戳的 `terminal-.txt`。插件每次写入后会自动扫描该目录,仅保留时间最新的 20 份文件,超额文件将自动销毁。单份捕获体积极小(0.5~6 KB 左右),若工作区受 Git 管理,建议将 `.dsh/` 加入根目录 `.gitignore`。 - **诊断日志存储**:由于打包后的 Electron 桌面版无法直接唤起 DevTools,客户端的关键事件与错误会通过宿主写入 `$DSH_HOME/dsh-terminal-context-diag.json`(保留最近 200 条,单次最大 4MB),用于无控制台环境下的排错。 --- ## 许可证 本项目基于 [MIT License](LICENSE) 开源。