DeepSeek Harness 插件开发实战:从设计理念到 npm 发布

引言:为什么插件是 dsh 的灵魂

上一篇文章介绍了 DeepSeek Harness 的安装与上手。如果说 dsh 是一台可组装的机器,那么插件就是它的每一个零件——界面、模型接入、工具调用,乃至官方 UI 本身,全都是插件。

这篇文章将带你完整走一遍插件开发的实战路径:从理解设计理念和架构组成,到安装别人的插件、自己动手写两个 demo,最后发布到 npm 让全世界都能安装。

本文是实战向教程,代码会尽量精简,重点讲清"为什么这么做"以及我踩过的坑。


一、设计理念:一切皆插件

dsh 的整个架构建立在一条简单的信念上:

Everything is a Plugin(一切皆插件)。

这意味着框架本身只提供"组装"能力(由 Cordis 驱动),具体功能全部由插件以模块化的方式提供。对开发者来说,这个理念带来三个直接好处:

  • 可插拔:想要什么功能,装一个插件;不想要了,卸掉即可
  • 可替换:同一个能力有多个实现?换一个插件就行,互不干扰
  • 可学习:官方功能也是插件实现的——源码就摆在仓库里,是最好的教材

理解这一点,是进入插件开发的第一把钥匙。


二、插件的架构组成

一个 dsh 插件本质上是一个 npm 包,通过 package.json 里的声明"激活"成插件。它由两大部分组成:

1. 声明(让 dsh 认识这个包)

package.json 中声明两件事:

  • dsh.bundle.patch:声明本包是 bundle,并指向 cordis.patch.yml——安装后该 patch 会自动挂进配置层栈
  • dsh.client:声明浏览器半侧的注入依赖与平台(web)

2. 两个半侧(插件实际运行的代码)

半侧 位置 职责 形态
宿主半侧(服务端) lib/index.js 注册路由、服务、权限等 标准 Cordis 插件:{ name, inject, apply(ctx, config) }
浏览器半侧(前端) lib/client.js 渲染界面、交互逻辑 window.__ModuleLoader__.load({ id, factory })

浏览器半侧有几个硬性规则,是新手最容易踩的坑:

  • 不能自己打包 React:factory 接收同步 require,React 等运行时依赖必须从 DSH 外壳的平台模块表获取
  • CSS 内联注入:以字符串形式插入 <style> 标签,而不是引外部样式文件
  • 插件 ID 唯一id 必须与 package.json 声明一致

三、插件是什么:一个生活化的类比

如果还是觉得抽象,可以把插件想象成 App Store 里的应用

  • dsh 是操作系统,提供运行环境和接口
  • 插件是应用,各自提供一项能力
  • dsh plugin 命令就是应用商店/包管理器

装一个插件 = 往商店里加一个应用;写一个插件 = 开发一个新应用上架。


四、安装别人的插件

安装插件非常简单,本质上是 pnpm add$DSH_HOME/profiles/web/node_modules

# 安装
dsh plugin --profile web add <包名>

# 卸载
dsh plugin --profile web remove <包名>

# 更新
dsh plugin --profile web update

# 查看已安装
dsh plugin --profile web list

前置条件:需要 pnpm 环境;--profile web 指定安装到 Web profile。

实战踩坑提醒:如果你用本地路径(file:)安装自己正在开发的插件,要特别注意——pnpm 的 file: 依赖是复制而不是链接。也就是说,你改了源码,已安装的那份不会自动更新,必须 removeadd 一次(或重启服务),否则跑的还是旧代码。这个坑在开发期会反复遇到。


五、自己写插件:整体流程

自己写一个插件,大致分四步:

  1. 建包:初始化 npm 包,写好 package.json 的声明(bundle patch + client)
  2. 写宿主半侧:用 Cordis 三件套注册插件主体
  3. 写浏览器半侧(如果要界面或前端逻辑):按 __ModuleLoader__ 形态注册客户端
  4. 本地验证dsh plugin --profile web add . 装上,重启看效果

从 hello world 开始

我的第一个插件是 dsh-hello——一个工具类插件:它注册了一个"打招呼"工具,你在聊天里和 AI 说"你好",AI 识别到这个意图后,就会自动调用插件提供的问候工具。

这个 demo 虽然简单,但它的意义不小:

  • 验证整条链路是通的:声明能被 dsh 识别、安装后能挂进配置层栈、宿主半侧能正常激活、工具能被 AI 自动调用
  • 跑通"AI 调用工具"的核心机制:模型判断意图 → 触发工具 → 拿到结果 → 继续对话,这整个闭环在 hello 里就完整走了一遍
  • 工具描述怎么写,直接影响 AI 会不会正确调用:hello 阶段就开始体会"给模型写说明书"这件事

不要小看这一步。插件开发的绝大多数挫败感都来自"链路没通"——装上了但没生效、激活了但看不到、改了代码但跑的还是旧的。先用 hello world 把链路跑通,后面所有功能都是在这条已验证的链路上叠加。

而且 dsh-hello 就是下面 Demo 01(AI 可调用工具)的最初原型——工具类插件从 hello 一路演化成了更复杂的能力。

下面用两个 demo 展示最常见的两种插件能力。


六、Demo 01:AI 可以调用的工具

目标:让模型在对话时能自动调用插件提供的工具(类似其他 Agent 软件的 Skill)。

这正是 dsh-hello 走过的路——只是把"打招呼"换成真正的能力。

思路:插件向运行时注册一个工具——定义一个名字、一段描述(让模型知道何时用)、和一个执行函数。模型在对话中判断"这个任务需要调用工具"时,会自动触发它并拿到结果,继续推理。

关键点

  • 工具的描述要写清楚:模型靠它决定是否调用
  • 执行函数要返回结构化结果:模型靠它继续推理
  • 工具可以是任何能力:读文件、查网页、执行命令、访问你的私有 API……

这个 demo 的价值在于:它把"让 AI 干活"从对话扩展到了真实世界——模型不再是只聊天,而是能真正动手。


七、Demo 02:自定义 Web UI

目标:往 dsh 界面里注入自己的 UI 组件(比如一个桌面宠物、一个侧边栏、一个浮窗)。

思路:dsh 的界面是"槽位 + 注入"的架构。官方定义了一些插槽(如 shell.overlay 浮动层),插件可以把自己的组件注入到这些槽位里,与官方 UI 共存而不互相覆盖。

关键点

  • 找到合适的槽位(如浮动层、侧边栏、状态栏)
  • 组件在浏览器半侧渲染,用 DSH 提供的 React
  • 注意竞态与生命周期:界面组件经常异步加载,要做好防重入、防过期回调

我实战做的"桌面宠物"就是挂在浮动层上的自定义 UI:动画链式播放、屏幕漫游、点击/拖拽交互、窗口缩放跟随——整个就是一个通过槽位注入的独立应用。


八、发布插件:让全世界都能安装

开发完成后,发布到 npm 即可让任何人 dsh plugin --profile web add <包名> 安装。

1. 登录 npm(官方源)

npm login --registry=https://registry.npmjs.org/

注意用官方源,而不是镜像源。如果账号开了两步验证(2FA),登录/发布时可能需要 OTP 验证码,或使用 npm tokens 页面 创建的访问令牌。

2. 发布前自查

  • 健康检查脚本:在 package.json 里配置 prepack,发布前自动校验必需文件、bundle 形态、包体积
  • 收窄 files:只发布运行时需要的文件(代码 + 播放资源),文档/预览图等不需要进包
  • 版本号:语义化版本,发新版记得 npm version patch/minor/major

3. 发布

npm publish --registry=https://registry.npmjs.org/

发布成功后,任何人都可以一条命令安装你的插件了。


九、总结

从"一切皆插件"的理念,到写出第一个能跑的插件、再到发布到 npm,这条路径比想象中顺滑:

  • 理念:插件 = npm 包 + 声明,宿主半侧管能力、浏览器半侧管界面
  • 安装dsh plugin 一条命令
  • 开发:hello world 跑通链路 → 工具 demo 让 AI 动手 → UI demo 让界面长出自己的样子
  • 发布:npm login + publish,全球可装

插件开发最迷人的地方在于:官方功能也是插件。遇到任何不懂的实现,直接读官方插件源码就是最好的学习路径。

如果你也在写 dsh 插件,欢迎分享你的作品——记得在 GitHub 仓库打上 dsh-plugin 话题,让更多人发现它。🚀

posted @ 2026-08-14 17:55  PC2005-cloud  阅读(56)  评论(0)    收藏  举报