大家好,我是【考拉搞AI】,我又来啦!
这几天AI 圈子爆火的莫过于
DeepSeek Harness了,从8月13日到今天才4天,Github 都暴增到15万星了,恐怖如斯。
更让人惊叹的是:已经有人搓了客户端,并且插件也呈现疯狂生长趋势。这波潮流让我想起了最开始 AI 兴起,
SKILL爆火的时代。
之前的文章大致介绍了一下安装与使用,相信小伙伴们也有所了解。
作为一名AI圈子的博主,这波流量,阿不,这波最新技术,咱必须不能落后,必须好好体验一波,这不,最近几天好好研究了一番,并且将一些
VibeCoding项目移动了上去,用起来感觉很顺手,下面两点是Claude Code、Codex 等 无可比拟的:
1、web端打开,不用下载客户端 2、可以自由切换模型,可以自由搭配插件、甚至可以配置loop Agent,完全可自定义自己的Agent,这是最吸引我的地方,未来肯定是各种插件满天飞,自由搭建自己智能体的时代即将开启

于是,博主研究决定从其
插件系统入手,这也是这个技术的核心。
废话不多说,下面详细介绍插件系统,并安装一个 侧边栏插件【这几天用下来,发现缺失的东西有点多,用起来还是不够丝滑,比如左侧菜单没有文件和git等】,让小伙伴理解插件,同时也能更好的使用web agent。

二、插件底层内核:Cordis
2.1 Cordis
DSH 插件完全基于自研 Cordis 元框架,三个核心概念:
Context 上下文 inject 依赖注入 apply 插件入口
Context:全局共享上下文对象,所有服务(tools、systemPrompt、webview 等)挂载在这里。插件之间不直接互相 import,全部通过 Context 获取服务。
inject 数组:声明当前插件依赖哪些服务,框架等待依赖全部就绪,才执行插件逻辑。
apply(ctx):插件唯一入口函数,Cordis 内核自动调用,传入上下文。插件在这里注册工具、注册 web 插槽、监听事件、注册配置项。
副作用自动回收:插件卸载时,ctx.effect()注册的所有监听、工具注册会自动清理,避免内存泄漏。
2.2 DSH 插件两大分类
2.3 插件加载流程
dsh 启动读取 profile 配置,解析bundles插件清单; profile 配置存放目录:~/.dsh/profiles/web,插件实际安装到 profile 下面的 node_modules 中DeepS...。 Cordis 内核解析每个插件inject依赖,拓扑排序确定启动顺序; 依次调用每个插件apply(context),注册工具 / UI / 事件; Agent‑loop 插件启动,大模型就可以调用插件注册的全部工具。
三、安装 dsh‑workspace‑enhance 插件
前置条件 已经全局安装 dsh:
npm install -g @deepseek‑ai/dsh
DeepSeek Harness + H5 射击塔防小游戏有没有搞头? 从 下载安装 到 项目实战 全程跑通 DeepSeek 官方 web Agent 框架
直接 让deepseek 帮我们安装:
帮我安装插件 https://github.com/luis1232023/dsh‑workspace‑enhance
安装成功提示输出类似:
plugin dsh‑workspace‑enhance installed into profile web
Please restart dsh web service to load new plugin
重启 dsh 服务访问 http://127.0.0.1:3080


卸载插件
dsh plugin --profile web remove dsh‑workspace‑enhance

四、dsh‑workspace‑enhance 源码深度解读
我们来研究下 这个插件,触类旁通,然后就可以编写我们自己的插件。
目录结构
dsh‑workspace‑enhance
├── package.json # dsh插件标识,dsh字段声明插件元信息
├── src
│ ├── index.ts # Host侧插件入口 apply(ctx)
│ └── client.ts # Client浏览器侧UI插件入口
└── tsconfig.json
4.1 package.json 关键片段(DSH 插件识别标记)
{
"name": "dsh‑workspace‑enhance",
"dsh": {
"bundles": {
"host": "./lib/index.js",
"client": "./lib/client.js"
}
}
}
dsh.bundles是 DSH 识别插件的核心标记:
host:Node 后端插件编译产物 client:浏览器 Web 前端插件编译产物
4.2 Host 侧 src/index.ts 核心逻辑
import type { Context } from '@deepseek‑ai/cordis'
// 声明依赖,需要systemPrompt服务,用于注入系统提示词片段
export const inject = ['systemPrompt','workspace']
export function apply(ctx: Context) {
// 监听工作区变更事件
ctx.on('workspace:change', async (workspacePath)=>{
// 读取目录结构,生成精简的文件树摘要
const fileTree = await scanDirectory(workspacePath)
// 将文件树摘要注入系统Prompt,模型自动感知当前项目结构
ctx.systemPrompt.section('workspace‑context',`
【当前工作区文件摘要】
${JSON.stringify(fileTree,null,2)}
不要反复调用ls扫描目录,优先使用上面给出的文件列表
`)
})
}
async function scanDirectory(path:string){
// 递归扫描本地目录,过滤node_modules、.git等忽略目录
}
Host 插件做两件事:
监听workspace:change事件,工作区切换时扫描本地目录; 将精简文件树注入systemPrompt,给大模型直接提供项目概览,减少工具调用次数。
4.3 Client 侧 src/client.ts 前端 UI 逻辑
import type { Context } from '@deepseek‑ai/cordis/client'
// 前端依赖webview服务,用于注册侧边栏tab
export const inject = ['webview']
export function apply(ctx: Context) {
// 向DSH Web侧边栏注册新Tab标签页
ctx.webview.registerSidebarTab({
id:"workspace‑files",
label:"Workspace Files",
async render(el){
// el是DOM容器,在这里渲染文件树组件
el.innerHTML = `<div id="file‑tree"></div>`
// 监听后端推送过来的文件树数据,渲染到页面
ctx.events.on('workspace‑enhance:file‑tree',(tree)=>{
renderFileTree(el.querySelector('#file‑tree'),tree)
})
}
})
}
Client 插件只负责 UI 展示,不直接读取本地磁盘;文件扫描全部交给 Host 后端,通过事件总线把数据推送到前端渲染。
五、手写极简插件
接下来,我们可以写一个极简插件:注册一个 host 工具demo_echo,同时在 web 侧边栏新增一个简单 tab。
步骤 1:初始化插件项目
mkdir dsh‑plugin‑demo
cd dsh‑plugin‑demo
pnpm init
pnpm add @deepseek‑ai/cordis @deepseek‑ai/dsh‑tools typescript
tsconfig.json
{
"compilerOptions": {
"target":"ES2022",
"module":"CommonJS",
"outDir":"./lib",
"strict":true
},
"include":["src/**/*"]
}
package.json 核心配置
{
"name":"dsh‑plugin‑demo",
"scripts":{"build":"tsc"},
"dsh":{
"bundles":{
"host":"./lib/index.js",
"client":"./lib/client.js"
}
}
}
步骤 2:编写 Host 插件 src/index.ts
import type { Context } from '@deepseek‑ai/cordis'
import { defineTool } from '@deepseek‑ai/dsh‑tools'
import z from 'schemastery'
// 声明依赖:需要tools工具注册服务
export const inject = ['tools']
export function apply(ctx: Context) {
// 注册工具给大模型调用
ctx.tools.register(defineTool({
name:"demo_echo",
description:"测试回显工具,把输入内容原样返回",
schema: z.object({
msg:z.string().describe("输入消息")
}),
async invoke({msg}){
return { result:`demo插件收到消息:${msg}` }
}
}))
}
步骤 3:编写 Client 前端插件 src/client.ts
import type { Context } from '@deepseek‑ai/cordis/client'
export const inject = ['webview']
export function apply(ctx: Context){
ctx.webview.registerSidebarTab({
id:"demo‑tab",
label:"Demo插件面板",
render(el){
el.innerHTML = `<h3>我的第一个DSH插件</h3>`
}
})
}
当然,我们直接让DeepSeek 帮我们写:
帮我写一个DeepSeek Harness 插件,主要功能是:
1、给右侧项目文件添加右键菜单;
2、右键菜单包含本地打开、浏览器打开、删除以及重命名等
八、总结
Deepseek Harness 地址:
https://github.com/deepseek-ai/deepseek-harness
插件地址:
https://github.com/luis1232023/dsh-workspace-enhance
博主认为接下来一段时间,这种 自定义插件式Agent 将会是一种AI Agent 规范和潮流,AI 大厂 如腾讯、阿里等都会相继推出的自己的 Harness 系统,直接对标Claude、Codex。
作为我们个体 VibeCoder 来说,利用好这些开源资源完成好我们自己的任务才是重中之重。
其次要好好研究插件,编写或者安装更多更好用的插件,让自己的 Harness 用起来更加丝滑即可。
比如,现在还欠缺这些插件:
皮肤插件,必须整上花里胡哨 上下文监控插件; SKILL 仓库插件; 右键菜单;
今天的分享到这里,接下来会继续分析更多VibeCoding实战技能和经验,欢迎点赞和关注!
更多内容,欢迎加入:

夜雨聆风