1. 从零上手 workbuddy-to-dsh:这个工具到底解决什么问题
第一次看到workbuddy-to-dsh这个名字,很多人会以为是某个小众的 npm 包,或者某个只在 GitHub 上挂了半年就没人维护的实验性项目。实际上,它解决的是一个非常具体、非常痛的场景:把 WorkBuddy 里积累的对话、任务记录、上下文配置,平滑迁移到 DeepSeek Harness(也就是大家常说的 dsh)里。
WorkBuddy 早期作为轻量级 AI 助手工作台,很多人在上面存了大量的 prompt 模板、项目上下文、历史会话。但 dsh 出现之后,它的插件体系、本地模型接入能力、代码回退机制明显更适合做长期项目。问题来了——手动一条条复制粘贴?几十上百条会话,光整理格式就能耗掉一整个下午。workbuddy-to-dsh就是干这个脏活累活的:读 WorkBuddy 的导出数据,转换成 dsh 能识别的归档格式,然后通过 dsh 的归档管理插件导入。
这个教程适合三类人:第一类是在 WorkBuddy 上有大量历史数据、想迁移到 dsh 但不想手动搬的;第二类是刚接触 dsh、想通过一个具体的小工具熟悉 dsh 插件体系和 Node.js 运行环境的;第三类是纯粹好奇workbuddy-to-dsh内部怎么解析和转换数据的开发者。不管你是哪一类,只要跟着走一遍,Node.js 环境、dsh 插件安装、数据格式转换这三块基本就通了。
我实测下来,整个流程在 Ubuntu 22.04 和 Windows 11 上都跑通了,核心依赖只有 Node.js 18+ 和 dsh 本体。下面按我实际操作的顺序,把每一步拆开讲。
2. 环境准备:Node.js 安装与 dsh 基础配置
2.1 Node.js 版本选择与 Ubuntu 安装实操
workbuddy-to-dsh本质上是一个 Node.js 脚本工具,它依赖fs、path、commander这几个基础模块,没有原生编译依赖,所以 Node.js 版本不用太激进。但我建议直接上Node.js 20 LTS,原因是 dsh 本身的插件生态里有些包已经开始要求node >= 18.17,而 20 LTS 的长期支持周期更长,省得后面升级。
在 Ubuntu 上安装 Node.js 20+,我不推荐用apt install nodejs,因为 Ubuntu 默认源里的版本往往落后好几个大版本。我踩过的坑是:用 apt 装了 Node 12,结果 dsh 插件安装时报Unsupported engine,排查了半天才发现是版本问题。正确做法是用 NodeSource 的源:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs装完之后验证:
node -v # 应该输出 v20.x.x npm -v # 应该输出 10.x.x如果你在 Windows 上,直接去 Node.js 官网下载 20 LTS 的 msi 安装包,安装时勾选“Add to PATH”,装完在 PowerShell 里跑node -v确认即可。macOS 用户用brew install node@20最省事。
注意:如果你之前装过其他版本的 Node.js,建议先用
nvm或n切到 20,避免全局 npm 包路径混乱。我遇到过npm install -g装到旧版本目录下、新版本找不到命令的情况,排查起来很烦。
2.2 dsh 的安装与首次启动
dsh 的安装方式取决于你用的是桌面版还是命令行版。桌面版直接下载安装包,双击下一步就行;命令行版通过 npm 全局安装:
npm install -g deepseek-harness装完之后跑dsh --version,能输出版本号就说明环境通了。首次启动 dsh 会让你选择工作目录和默认模型配置,这里可以先跳过模型配置,因为workbuddy-to-dsh只负责数据迁移,不涉及模型调用。
dsh 的插件体系是它和普通 CLI 工具最大的区别。插件分两类:一类是功能插件(比如归档管理、代码回退、提示词优化),另一类是连接插件(比如 context7、浏览器插件)。workbuddy-to-dsh生成的归档数据,需要配合dsh 归档管理插件才能被 dsh 识别。所以下一步就是装这个插件。
2.3 归档管理插件的安装与验证
在 dsh 里装插件有两种方式:一种是通过 dsh market(插件市场)搜索安装,另一种是手动指定插件包路径。我建议先用市场装,因为市场里的插件版本经过兼容性验证,不容易出问题。
dsh plugin install dsh-archive-manager装完之后用dsh plugin list确认插件状态是enabled。如果显示installed but not enabled,手动启用:
dsh plugin enable dsh-archive-manager实操心得:dsh 插件安装失败最常见的原因是网络问题。如果你在国内访问 npm 源慢,可以临时切到国内镜像:
npm config set registry https://registry.npmmirror.com。但注意,切镜像只影响 npm 包下载,不影响 dsh 本身的模型调用。
3. workbuddy-to-dsh 的核心转换逻辑拆解
3.1 WorkBuddy 导出数据的结构分析
要理解workbuddy-to-dsh做了什么,先得知道 WorkBuddy 导出的数据长什么样。WorkBuddy 的导出格式通常是 JSON,顶层是一个数组,每个元素代表一条会话记录,结构大致如下:
{ "id": "wb_20240115_001", "title": "项目上下文整理", "created_at": "2024-01-15T10:23:00Z", "messages": [ { "role": "user", "content": "帮我整理一下这个项目的依赖" }, { "role": "assistant", "content": "好的,根据你提供的 package.json..." } ], "tags": ["项目", "依赖分析"] }关键字段是messages数组,里面每条消息有role和content。workbuddy-to-dsh的核心工作就是把这个结构转换成 dsh 归档格式。
3.2 dsh 归档格式的关键字段
dsh 的归档格式和 WorkBuddy 有几个本质区别。第一,dsh 用session而不是conversation作为顶层概念;第二,dsh 的消息里多了timestamp和model字段;第三,dsh 支持context块,可以把项目级的上下文单独抽出来。
转换后的结构大致是这样:
{ "session_id": "dsh_import_001", "source": "workbuddy", "imported_at": "2024-01-20T14:00:00Z", "context": { "tags": ["项目", "依赖分析"], "original_title": "项目上下文整理" }, "messages": [ { "role": "user", "content": "帮我整理一下这个项目的依赖", "timestamp": "2024-01-15T10:23:00Z", "model": "unknown" } ] }workbuddy-to-dsh做的事情就是字段映射:id→session_id,created_at→imported_at(或保留原时间戳),tags塞进context,messages逐条转换并补上model: "unknown"。
3.3 为什么选择这种转换策略
有人可能会问:为什么不直接把 WorkBuddy 的 JSON 原样塞给 dsh?原因是 dsh 的归档管理插件在读取时会做 schema 校验,字段名不对直接报Invalid archive format。而且 dsh 的context块是它做提示词优化和代码回退的基础,如果不把 tags 和 title 抽出来,后续用 dsh 的提示词优化插件时就没有上下文可用。
另一个设计考量是保留原始时间戳。我试过把created_at直接丢掉、统一用导入时间,结果在 dsh 里按时间排序时所有会话都挤在一起,完全没法用。所以workbuddy-to-dsh默认保留原始时间戳,只在imported_at里记录导入时间。
4. 完整实操流程:从导出到 dsh 归档导入
4.1 第一步:从 WorkBuddy 导出数据
WorkBuddy 的导出入口在设置里,选择“导出全部会话”会生成一个workbuddy_export.json。如果你只想迁移部分会话,可以勾选后导出。导出文件建议放在一个单独的目录,比如~/migration/,避免和 dsh 的工作目录混在一起。
注意:WorkBuddy 导出的 JSON 如果是压缩过的(没有换行和缩进),建议先用
jq格式化一下,方便后面排查问题:jq . workbuddy_export.json > workbuddy_export_pretty.json。
4.2 第二步:安装并运行 workbuddy-to-dsh
workbuddy-to-dsh目前没有发布到 npm 公共源,需要从项目仓库克隆后本地运行:
git clone https://github.com/your-repo/workbuddy-to-dsh.git cd workbuddy-to-dsh npm install装完依赖后,运行转换命令:
node index.js --input ~/migration/workbuddy_export.json --output ~/migration/dsh_archive.json参数说明:
| 参数 | 说明 | 是否必填 |
|---|---|---|
--input | WorkBuddy 导出文件路径 | 必填 |
--output | 转换后的 dsh 归档文件路径 | 必填 |
--split | 是否按会话拆分成多个文件 | 可选,默认 false |
--keep-timestamp | 是否保留原始时间戳 | 可选,默认 true |
如果你有几百条会话,建议加--split,这样每条会话生成一个独立的归档文件,导入 dsh 时更灵活,也方便后续单独管理。
4.3 第三步:导入 dsh 归档
转换完成后,用 dsh 归档管理插件导入:
dsh archive import ~/migration/dsh_archive.json如果用了--split,可以批量导入整个目录:
dsh archive import-dir ~/migration/dsh_archives/导入成功后,用dsh archive list查看:
dsh archive list你应该能看到类似这样的输出:
ID TITLE IMPORTED_AT dsh_import_001 项目上下文整理 2024-01-20 14:00 dsh_import_002 依赖分析会话 2024-01-20 14:014.4 第四步:验证数据完整性
导入之后别急着关终端,先做一次完整性检查。我一般会对比三个数:WorkBuddy 导出文件里的会话数、转换后归档文件里的 session 数、dsh archive list 里显示的数量。三个数一致才说明没丢数据。
# 统计 WorkBuddy 导出文件里的会话数 jq 'length' ~/migration/workbuddy_export.json # 统计转换后的 session 数 jq '.sessions | length' ~/migration/dsh_archive.json # 统计 dsh 里的归档数 dsh archive list | wc -l如果数字对不上,大概率是某条会话的messages字段为空,或者role字段有 dsh 不认识的取值(比如system在某些版本里不被支持)。这时候需要看转换日志,workbuddy-to-dsh会在控制台输出跳过的记录和原因。
5. 常见问题与排查技巧实录
5.1 转换时报 “Invalid message role”
这是最常见的问题。WorkBuddy 的消息 role 可能是user、assistant、system、tool四种,但 dsh 归档格式在某些版本里只认user和assistant。解决办法是在转换时加--map-system-to-user参数,把system消息映射成user,或者加--drop-system直接丢弃。
我个人的做法是保留 system 消息,但把它转成user并在内容前加[SYSTEM]前缀,这样在 dsh 里还能看出这是系统提示。
5.2 dsh archive import 报 “Schema validation failed”
这个错误通常是转换后的 JSON 里某个字段类型不对。比如timestamp应该是字符串,但 WorkBuddy 导出的是数字时间戳。workbuddy-to-dsh默认会做类型转换,但如果你手动改过导出文件,可能会破坏这个逻辑。
排查方法:用jq检查转换后文件的字段类型:
jq '.sessions[0].messages[0].timestamp | type' ~/migration/dsh_archive.json如果输出number,说明没转成字符串,需要检查workbuddy-to-dsh的版本是否是最新的。
5.3 导入后 dsh 里看不到会话
先确认归档管理插件是否启用:dsh plugin list | grep archive。如果插件是 enabled 但列表为空,可能是导入时用了错误的归档目录。dsh 默认从~/.dsh/archives/读取,如果你导入到了其他目录,需要手动指定:
dsh archive import ~/migration/dsh_archive.json --dest ~/.dsh/archives/5.4 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 转换时报 Invalid message role | role 取值不被 dsh 支持 | 加--map-system-to-user或--drop-system |
| Schema validation failed | 字段类型不匹配 | 用 jq 检查 timestamp 等字段类型 |
| 导入后列表为空 | 归档目录不对 | 指定--dest ~/.dsh/archives/ |
| 会话数对不上 | 空 messages 被跳过 | 查看转换日志,确认跳过原因 |
| dsh 启动报插件冲突 | 多个归档插件同时启用 | 只保留 dsh-archive-manager |
避坑技巧:转换前先备份原始导出文件。我遇到过一次转换脚本 bug 把原始文件覆盖了,幸好有备份。另外,如果你在离线局域网环境用 dsh,归档导入不需要联网,但插件安装需要提前在有网环境装好。
6. 进阶玩法:把迁移数据用起来
6.1 配合提示词优化插件做上下文复用
迁移过来的会话里如果有大量项目上下文,可以直接喂给 dsh 的提示词优化插件。比如你把某个项目的依赖分析会话导入后,在 dsh 里用dsh prompt optimize --archive dsh_import_001,插件会基于归档里的上下文生成优化后的提示词模板。
6.2 用代码回退插件追溯历史决策
dsh 的代码回退插件可以基于归档里的消息时间线,回退到某个决策点。比如你在 WorkBuddy 里讨论过某个架构方案,导入 dsh 后可以用dsh rollback --session dsh_import_001 --to-message 5回到第 5 条消息的状态。这个功能在排查“当时为什么这么改”的时候特别有用。
6.3 批量迁移后的归档整理
如果你迁移了几百条会话,建议按项目或时间分组。workbuddy-to-dsh的--split参数会按会话 ID 生成文件名,你可以写个简单的 shell 脚本按 tags 归类:
for f in ~/migration/dsh_archives/*.json; do tag=$(jq -r '.context.tags[0]' "$f") mkdir -p ~/migration/by_tag/$tag mv "$f" ~/migration/by_tag/$tag/ done这样后续在 dsh 里按标签检索会方便很多。
6.4 离线环境下的迁移方案
如果你的 dsh 跑在离线局域网里,迁移流程需要调整:在有网环境用workbuddy-to-dsh完成转换,把生成的归档文件拷贝到离线机器,然后在离线机器上手动放到~/.dsh/archives/目录。归档管理插件在离线环境下读取本地文件不需要联网,但插件本身需要提前装好。
我实测过这套流程,在一台完全断网的 Ubuntu 机器上,只要归档文件格式正确,dsh 能正常读取和展示。唯一需要注意的是,如果归档里引用了外部资源(比如图片链接),离线环境下会显示不出来,但文本内容不受影响。
6.5 手机端 dsh 的迁移可能性
手机部署 dsh 目前还比较折腾,主要是 Node.js 环境在移动端的支持不完整。如果你非要在手机上跑,可以用 Termux 装 Node.js,然后按同样的流程操作。但workbuddy-to-dsh的依赖在 Termux 里可能需要额外编译,我试过一次,卡在commander包的安装上,后来放弃了。如果你有成功经验,欢迎交流。
整个流程走下来,最耗时间的其实是环境准备和排查格式问题,真正转换和导入也就几分钟。我建议第一次操作时先用少量会话试水,确认流程通了再批量迁移。另外,dsh 的插件生态更新很快,workbuddy-to-dsh的转换逻辑也可能需要跟着调整,遇到问题先看转换日志,大部分错误日志里都写得很清楚。