DeepSeek Harness plugin

dsh-foreground-stream

前台命令执行实时输出流式展示——对话历史命令卡片实时输出 + 底部流条(Host 镜像旁路 subprocess collect 游标 + 只读轮询路由 + WebUI 设置栏目)

Jump to install

Source facts

Repository
XiaoYuOvO/dsh-foreground-stream
Latest update
Aug 18, 2026
Category
Memory
GitHub stars
0
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/XiaoYuOvO/dsh-foreground-stream
Plugin: dsh-foreground-stream
Author: XiaoYuOvO

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer2 files
README.mdSource · read only

dsh-foreground-stream

DeepSeek Harness Web bundle 插件:前台命令执行(bash / pwsh 工具、非后台模式)期间的实时输出流式展示——对话页输入区上方出现一条"命令输出流条",随命令执行实时滚动显示 stdout/stderr,而不是等命令结束后才一次性看到。

  • 不修改任何官方工具包:tool/result 内容与执行路径逐字节不变,模型语义零改动。
  • 只旁路展示:命令完成后官方工具卡片照常呈现最终结果;本条只负责"执行期间"的增量画面。
  • 纯内存缓冲,进程重启即清,不做任何跨会话持久化。

安装

从 GitHub 一键添加(推上仓库后)

包已按可分发结构打包(dependencies 声明了 host 依赖、files/.gitignore 排除了开发期 junction):

# 在任意位置执行(git 需走本地代理 127.0.0.1:7800):
node "G:\Deepseek Harness Desktop\dependencies\dsh\node_modules\@deepseek-ai\dsh\lib\bin.js" plugin --profile web add github:<owner>/<repo>
# 或带版本:add github:<owner>/<repo>#<tag|commit>

dsh plugin 会自动把声明了 dsh.bundle.patch 的包追加进 dsh.profile.bundles(自动 reconcile)。

安装后必做一步(settings 白名单补丁,幂等脚本)

node "G:\Deepseek Harness Desktop\data\dsh\plugins\dsh-foreground-stream\scripts\patch-allowlist.mjs"
# 或:npm run patch:allowlist

> 原因:Web 客户端读写 settings 命名空间受 harness dsh-host-apiproxy 的 > WEB_SETTINGS_NAMESPACES 硬编码白名单过滤,插件侧无注册逃生通道;本脚本把 > dsh-foreground-stream 幂等加入该白名单。harness 升级/重装会覆盖补丁,需重跑。

然后重启 DSH web 宿主(Host half 改动不热更新;Client 刷新页面即可)。

本地目录安装(开发中)

# 在插件目录(含 package.json 的目录)下执行:
node "G:\Deepseek Harness Desktop\dependencies\dsh\node_modules\@deepseek-ai\dsh\lib\bin.js" plugin --profile web add .

> 等价于 pnpm 在 profile 目录里 add file:<插件绝对路径>。Windows 路径含空格时 > CLI 可能拆参,可改为:在 profile 目录 pnpm add "file:<插件绝对路径>",再手动把包名 > 追加进 dsh.profile.bundlesprofiles/web/package.json)。

验证安装:

node "G:\Deepseek Harness Desktop\dependencies\dsh\node_modules\@deepseek-ai\dsh\lib\bin.js" --profile web --dump-config | Select-String -Pattern 'dsh-foreground-stream'

应出现:

- id: dsh-foreground-stream
  name: dsh-foreground-stream

重启后如何确认效果

1. 重启 DSH web(新组合在启动时加载)。 2. 让 agent 跑一条长时间前台命令,例如:

- pwsh(Windows):1..1000 | ForEach-Object { Write-Output "line $_"; Start-Sleep -Milliseconds 200 }

- bash(POSIX):for i in $(seq 1 1000); do echo "line $i"; sleep 0.2; done - 或 ping -t 8.8.8.8(需注意默认 timeout)。 3. 观察对话页输入框上方:出现"pwsh · <命令>"条,命令输出随执行逐行滚动; 命令结束显示"命令完成 · 退出码 N"约 4 秒后自动收起,官方工具卡片照常呈现最终结果。

设计说明

为什么是"镜像旁路"而不是改官方包

官方链路(已读源码确认):

dsh-tool-bash/pwsh.execute → ctx.shell.run(spec) → 执行器 runArgv
  → ctx.subprocess.spawn(spec)   (stdio 恒为 collect 模式,无增量回调)
  → await handle.done → readFrom(0) 一次性汇总

dsh-subprocess 服务契约明确:collect-mode reader 是 offset-based 非消耗式的 (readFrom(fromByte) 返回 { text, nextOffset, lossy, spillPath },独立读者互不消耗)。 因此插件用自己的游标增量读取 handle.collected.stdout/stderr,官方最终 readFrom(0) 完全不受影响——这就是 task-status "镜像补丁保证零竞争" 哲学的同一个缝。

callId 关联(把输出挂到具体工具调用)

  • agent-loop 在 execute 之前同步 append tool/call{turn, step, callId, name, arguments}),

session/event 派发 → 插件记录"当前前台命令"并建立 per-callId 缓冲。

  • 真实事件形态(源码 + 实测确认,勿想当然):

- tool/callarguments 是模型侧原始 JSON 字符串(agent-loop 直接落 block.arguments,只有 exec.arguments 经过 parseArguments)——插件 先 JSON.parse 再读 command / run_in_background。 - tool/resultmessage.content嵌套形态 [{ type:'tool-result', content:[{type:'text', text}] }]createToolResultMessage 包装)——退出码提取需穿透包装层。

  • 前台 shell 调用在 agent-loop 中严格串行(startCall await dispatch 直到进程结束),

因此"当前前台命令"是单槽;subprocess.spawn 包装器在 spawn 时校验 argv 包含该命令字符串(bash:["bash","-c",cmd];pwsh:["pwsh",...,"-Command",<preamble>cmd]; win32 sandbox 的 runner argv 同样内嵌原 argv)才挂 tap——MCP / skill / worker 等 其他工具的 spawn 因 argv 不匹配而绝不会被误挂。

  • tool/resultmessage.source.callId)收尾:running=false、尽力恢复退出码/信号、

清 pending。

数据通道与节流

  • Host 注册只读路由 GET /plugins/dsh-foreground-stream/active?sessionId=...

(流条用,返回当前/最近命令 + 全文 + dock 配置位)与 GET /plugins/dsh-foreground-stream/output?callId=...(历史卡片实时轮询用); 客户端整段替换渲染(tail 效果)。

  • 增量 tap 统一 120ms 心跳 drain(不随输出量放大);缓冲 64KB 保尾截断;

完成后保留 120s 供展示,之后清理;缓冲条目上限 100。

  • 客户端运行中 400ms / 空闲 1s 轮询;输出区 max-height 180px 滚动 + 自动跟随底部

(用户上翻暂停跟随,回底恢复);ANSI 转义防御性清洗。

  • 长命令行展开:命令行超过 64 字符(或含换行)时,流条标题变为可点击

(带 ▾/▴ 指示与 aria-expanded),点击展开完整命令(等宽字体块、 max-height 120px 可滚动),再点收起;调用切换时自动复位。短命令保持单行省略。

  • 历史卡片实时输出:运行中的前台命令,其对话历史卡片自动展开终端面板,

面板输出区按 callId 轮询 /plugins/dsh-foreground-stream/output 实时更新 (400ms/次),无需底部流条即可在记录里直接看到命令输出;命令结束后停止 轮询,改由官方最终结果呈现。

  • 自动展开/收起(config.autoExpand,默认开):运行中的新命令面板自动展开、

运行完成后自动收起;用户手动展开/收起后不再自动干涉(手动状态优先)。

  • 复制命令按钮:历史卡片终端面板内命令行右侧有复制按钮,悬停卡片时显示

点击一键复制完整命令行(短暂显示 ✓)。

  • 面板展开/收起动画(config.animMs,默认 150ms):终端面板展开播

dshfs-panel-in、收起先播 dshfs-panel-out 再卸载(opacity + 轻微位移); 时长由设置项"面板动画速度"控制(关闭 0 / 快 80 / 标准 150 / 慢 300), animMs: 0 时无动画、即时展开/收起。

  • WebUI 设置栏目(命令输出)通用设置 → 外观 → 命令输出,两个开关——

"显示底部命令流条"(showDock)、"命令面板自动展开/收起"(autoExpand) 与动画速度下拉(animMs)。 值存 Host settings 命名空间 dsh-foreground-stream(settings.yaml 持久化), 即时生效(流条/卡片随下一次轮询应用),无需改组合行配置。 注册方式:Host 在 apply 时经 ctx.get('settings') 直连注册,服务未就绪时 500ms 轮询重试(最多 60s)——不依赖嵌套 ctx.inject(真实宿主上该路径 对部分插件不触发)。诊断:GET /plugins/dsh-foreground-stream/settings-state 返回 { state, source, registered }

  • ⚠️ harness 依赖:Web 客户端能否读写某命名空间由 dsh-host-apiproxy

WEB_SETTINGS_NAMESPACES 硬编码白名单决定(代码注释明说:未列入即 settings-not-exposed,即使命名空间已注册)。本插件已把 dsh-foreground-stream 加入该白名单(dependencies/dsh/node_modules/ @deepseek-ai/dsh-host-apiproxy/lib/index.js)。升级/重装 harness 会覆盖 该修改,需重新打补丁,否则设置栏目会退回"设置服务暂不可用"。

  • 组合行配置作为默认层cordis.patch.ymlconfig.showDock /

config.autoExpand 仍是 base 默认值;UI 里手动开关后以 settings 用户值为准。

``yaml - id: dsh-foreground-stream config: showDock: false # base 默认层(UI 可再覆盖) autoExpand: false ``

槽位选择

候选槽结论
conversation.input.dock(list)✅ 流条官方既有 additive 座位(task-status 同款),对 bash/pwsh/任何 shell 工具统一生效;负责"执行期间"的实时滚动展示
tool.call.toolview(keyed)✅ 历史卡片接管 bash + pwsh 两个 key(priority: -1 最低者胜出,替换官方 bash-toolview-sample 与 pwsh 的通用回退行),原版面板形态:标题行 = 命令执行图标(悬停/已展开变箭头)+ 工具名标题(Bash/PowerShell)· 描述摘要 + 状态;点击行展开终端面板,面板内命令行单行省略、点击命令行本身原位展开为完整多行(无第二面板),下方为输出(等宽、滚动)。数据取自 block 的 callView/resultViewcard:'terminal'),缺失回退 parseArgs(argsRaw)/resultText
conversation.details.tool(single)接管 = 渲染所有工具的输出详情面板,太重,未采用
settings.general.item(list)✅ 设置栏目通用设置页的"命令输出"行(id command-output,order 15,紧随"外观"行):标题 + 两个开关(showDock / autoExpand),经 settingsScope 绑定 Host 命名空间读写

> 两处都只读展示:官方 execute 行为与模型可见的 tool/result 内容零改动。

局限

  • 只覆盖经 ctx.shell 的前台 bash/pwsh 工具调用;run_code 内部子调度、终端

(PTY)路径、tool-bash-persistent 不经此链路,无流式旁路(不影响其正常执行)。

  • 输出缓冲是"插件视角的镜像",与官方最终 tool/result 在超长输出截断边界上可能有

细微差异(各用各的 64KB 上限),但展示用途完全够用。

开发与自检

node --check lib/index.mjs   # Host half 语法
node --check lib/client.js   # Client half(浏览器 bundle)语法
node scripts/smoke.mjs       # Host 逻辑冒烟:补丁/关联/增量/跳过/隔离/dispose

文件

package.json        # dsh.bundle.patch + dsh.client(web platform + inject)
cordis.patch.yml    # 挂载行:- id: dsh-foreground-stream
lib/index.mjs       # Host half:镜像 spawn 补丁 + session/event 关联 + /active 路由
lib/client.js       # Client half:dock 流条 + 历史命令卡片(手写 ModuleLoader bundle)
scripts/smoke.mjs   # Host 逻辑冒烟:补丁/关联/增量/跳过/隔离/dispose
scripts/smoke-client.mjs  # Client 冒烟:bundle 结构/槽注册/展开交互/卡片渲染
README.md

> Client half 是手写 plain-JS window.__ModuleLoader__.load({ id, factory }) bundle > (与 dsh-message-edit 同款格式),无需 tsdown 构建步骤,提交的产物即源码; > 安装时无 build 脚本,pnpm 不会触发 allowBuilds 拦截。