working-activity

649Star231Fork1Issue51Watching

DeepSeek Harness 的实时"工作状态行"插件:把会话事件折叠成俏皮思考文案、正在运行的工具与已耗时,同时投递给 TUI 提示符与 Web 客户端。

语言
TypeScript
License
MIT
分支
main
deepseek-harnessdsh-pluginpi-coding-agentpi-pluginstatuslineworking-line

安装

$ dsh plugin --profile web add github:ccch1mneyyy/working-activity

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

一句话定位

DeepSeek Harness 的实时"工作状态行"插件,把模型会话里的事件折叠成一条普通用户看得懂的进度文字——思考时是俏皮短句、跑工具时是"动作 + 文件/命令 + 已耗时"、收尾给一句搞定加汇总——同时投递给 TUI 提示符和 Web 客户端的输入区上方。

核心能力

  • 把会话事件(turn/start / assistant/chunk / tool/call / tool/result / turn/end)与 agent/status 折叠成 idle/waiting/thinking/tool/done 五段状态,按 500ms tick 刷新
  • 自动识别工具名映射成俏皮动词(翻翻文档/改改/跑个命令/搜搜东西/派个小弟 等),参数细节从 path/command/query/url 自动抽取并截断
  • 思考文案池约 95 句中文口语化短句 + 面无表情的英文(lol/hm/ok),每约 4 秒轮换;本地时间 00:00–06:00 混入深夜文案;想久了自动分档(30s / 1min / 5min)
  • TUI 侧:在 ctx.tuiPrompt 注册 ${activity} 模板值,加入 theme.leftPrompt 即显示
  • Web 侧:作为 slot 插件挂到 conversation.input.dock,composer 上方渲染一行带阶段色呼吸点的状态行 + 工具计数徽标
  • 可选注入"⏵ 模型自述"约定到 system prompt:让模型在回复首行写"⏵ 你在做什么",状态行实时抽取这一行展示,并在聊天正文里过滤
  • 收尾摘要:搞定 ✓ · N 工具 · 想Xs 干Ys,最后一格短暂钉住最近工具的片段

技术实现

  • 语言: TypeScript(ESM,"type": "module"),Node 端 tsc 编译到 lib/,Web 端走 tsdown 出 closure-factory bundle 到 lib/client.js
  • 关键依赖: @deepseek-ai/cordis@^4.0.1@deepseek-ai/dsh-session@^0.1.0-rc.6@deepseek-ai/dsh-agent@^0.1.0-rc.6@deepseek-ai/schemastery@^3.18.1
  • 架构模式: Cordis 宿主插件(name: 'working-activity')+ Web slot 插件(注册到 conversation.input.dock,order 15)+ invariant 伴生插件(./invariant,用 dsh-invariants 服务校验 activity/status 形状);自挂载由 dsh.bundle.patch → cordis.patch.yml- insert: 实现
  • 入口文件: packages/activity/working-activity/src/index.ts(宿主插件 apply(ctx, config))→ src/status.ts(纯状态机 ActivityTracker,clock-injected)→ src/client/index.ts(Web slot apply(ctx),注册 WorkingLine)→ src/invariant.ts(校验伴生)

适用场景

DSH 用户在长任务里想看到模型当下到底在干什么——是还在想、卡在思考、还是在跑 npm install——而不是只盯着转圈。等长工具执行时一眼看到已耗时和操作的文件/命令;收尾时看到思考与执行时间拆分,心里有数。配 dsh-cc 终端的状态栏或官方 Web 端使用最直接,也支持自定义任何消费端订阅 activity/status 事件。

前置依赖与兼容性

依赖最低版本说明
DeepSeek Harness0.1.0-rc.6+peerDependencies 中多个 @deepseek-ai/dsh-*@^0.1.0-rc.6 锁定
Node.js^22.19.0 || >=24.0.0engines.node 声明;CI 使用 Node 24
pnpm10+(推荐 11+)dsh plugin add 转发给 pnpm;pnpm 9 传递依赖提升问题会导致模块解析失败
平台macOS / Windows / Linux跨平台,纯 JS/TS 实现,无原生模块
原生模块不依赖 node-gyp 构建
Web 端额外要求官方 rc.6 源码仓库打上 patches/webui-working-activity.patchWeb 端需要这条 runtime 补丁把 activity/status 接进 ConversationSnapshot;不打卡也装但状态行恒空
必需凭证状态行纯本地推导,不读 API key、不发网络请求

安装方式

dsh plugin --profile web add github:ccch1mneyyy/working-activity

安装命令本身只在仓库根 npm 包发布时填写 GitHub shortlink。dsh-working-activity 实际包名固定(被 dsh-cc-tui 依赖),发布前请确认 package.json#repository 指向本仓库。

配置项

所有可调参数都集中在 Config Schema(packages/activity/working-activity/src/index.ts:36),在 profile 用户补丁层按 id 覆盖:

配置类型说明默认值
phrases布尔俏皮文案池开关;关闭后渲染朴素功能标签(思考中 · 总1m23strue
publish布尔追加 activity/status 会话事件供 Web / dsh-cc 消费。默认关闭:开启后含状态行的会话无法 resume(session.append() 不支持 ignorable)false
tickMs数字状态行渲染 tick 间隔(ms),范围 100–5000500
publishIntervalMs数字状态行稳定时两次发布的最小间隔(ms),范围 500–30000;dsh-cc 推荐 5002000
detailLimit数字工具细节展示最大长度(路径/命令/搜索模式字符数),范围 8–12040
customActions对象工具名精确映射到动作文案池,如 {"my_deploy":["部署一下","上线中"]}(大小写不敏感){}
narrate布尔向 system prompt 注入"⏵ 模型自述"约定;关闭后只由事件推导true

常见问题

Q: 我看 dsh 官方 README 装了 Web 端,但 composer 上方没出现工作状态行。

A: 本包的 slot 插件只贡献注册到 conversation.input.dock,要让 Web 真正渲染还需要一条 runtime 补丁把 activity/status 事件接进 ConversationSnapshot.activity 字段。在你的官方 rc.6 源码仓库根目录 git apply <本仓库>/patches/webui-working-activity.patch(已通过 git apply --check 验证)即可。补丁没合入前 Web 端不会报错,只是 WorkingLine 组件恒返回 null。

Q: TUI 里看不到 ${activity} 显示,怎么办?

A: 模板里没加 ${activity} 槽位值会被模板渲染器省略。需要在 profile 用户补丁层($DSH_HOME/profiles/<profile>/cordis.patch.yml)里给 dsh-tuitheme.leftPrompt 加上:'${cwd}${git/worktree}${activity}${model}${token_meter/cache_hit_rate}${context}'。同时确认 profile 装了 dsh-tui 和本插件两个包。

Q: 开启 publish: true 后历史会话 resume 失败,为什么?

A: DSH 当前版本的 session.append() 不能把事件标记为 ignorable,resume 读取路径对未知不可忽略事件类型会拒绝。开启 publish 后凡是渲染过状态行的会话都打了一个 activity/status,整条日志 resume 报错。仅在宿主支持 ignorable append、且你的消费端是基于日志重放的 UI 时再开启;普通 Web UI 用 conversation.input.dock 槽位走实时事件,不需要 publish。

Q: 我有自己的工具(比如内部 deploy 工具),想让状态行显示"部署一下 staging"。

A: 在 customActions 里按工具精确名配动作池:{"my_deploy":["部署一下","上线中"]}。匹配按工具名大小写不敏感精确匹配,没匹配上就走内置的"翻翻文档/改改/跑个命令/派个小弟"等映射,识别不出的工具回退到"干活/调用/整一下"。

Q: 状态行秒数跳动太迟钝,跟手不上长工具。

A: 把 publishIntervalMs 调到 500(默认 2000),让"稳定行"也能 0.5s 重发一次——耗时数字就连续跳动了。改 profile 用户补丁层对应 id 的 config 即可:{ id: working-activity, config: { publishIntervalMs: 500 } },别再 insert 同 id 的行(会双实例)。

Q: 卸载插件会改动 DSH 核心吗?会丢会话吗?

A: 不会。本插件是纯挂载,不修改 DeepSeek Harness 任何源码;卸载即还原。会话日志保留在 profile 的 sessions 目录下原路径。activity/status 事件不影响其他事件类型——只是它本身的存在会让启用 publish 期间的会话 resume 失败(见上条)。

Q: macOS / Windows / Linux 都能用吗?需要装额外系统依赖吗?

A: 跨平台可用,无原生模块、不依赖 node-gyp。在三个系统上 pnpm install && pnpm run build 都能跑通。Windows 上注意 dsh plugin 转发的 pnpm 命令走 cmd,不要用 Git Bash 直接调用。

上手难度

入门 — dsh plugin add 一行命令装上即工作;TUI 端默认配置即可看到状态行,Web 端再补一条 git apply。常用调参只涉及 publishIntervalMs 一项。

已知问题与限制

  • publish 默认关闭:开启后渲染过状态行的会话无法 resume(session.append() 不支持 ignorable;src/index.ts:38-46 / registration.ts:9-13)。
  • 单一活跃状态行:插件按会话维护一条状态行;TUI 槽位显示最近活跃会话,多会话并行时只看到最新一条(README.md:118)。
  • 无工具进度百分比:DSH 没有工具进度事件,长工具只显示已耗时,没有像 pi 版那样的"还剩 ~11s"(README.md:120)。
  • 无动画帧:TUI 槽位渲染静态文本片段;pi 版的 moon/comet/braille 动画预设需等 prompt 槽位契约支持帧回调后再做(README.md:121)。
  • Web 端需 runtime 补丁ConversationSnapshot.activity 字段由 patches/webui-working-activity.patch 接入官方 rc.6 runtime;官方若把该字段合入发布线,补丁即退役,宿主升级后保持兼容(src/client/activity.ts:8-15)。
  • Web 双入口:输入区 WorkingLine 与聊天区 TurnStatus 渲染同一快照;dock 条目覆盖全部阶段,旧补丁的回合级标签不再单独存在(README.md:122 / docs/dsh-working-activity.md:205-206)。
  • narration 是注入约定不是协议:模型自述的"⏵ 你在做什么"依赖模型遵守 before_agent_start 时追加的 system prompt 段;不支持该约定或不输出的模型看不到这一行(src/index.ts:93-94 / src/status.ts:472-480)。
  • 不区分 DSH 提示词面:插件向 system prompt 注入自述约定会增加少量 token;固定且小(单段文本),对缓存稳定性无影响,但每轮都重发(README.md:103-105)。