DeepSeek Harness:三步跑通第一个插件
【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness
[hello-plugin] plugin loaded!这是你跟着本文操作完、会在终端里看到的一行输出。DeepSeek Harness 是一个"万物皆插件"的开源智能体框架——本文将带你亲手写一个插件挂进 Web UI,顺手得到一个可被模型调用的工具。
先看懂扩展机制:一条排插式框架
把框架想象成一条排插:框架本身是插排,每一项能力——模型适配器、工具、文件访问,甚至驱动整个 agent loop——都是插在上面的电器。电器之间共享的那条总线就是ctx(上下文对象,工具、模型路由、会话日志各占其中一格);插件则是一个导出apply(ctx)的模块,靠它把自己的能力注册进总线。
途中还会遇到两个术语:
- patch 覆盖层:一层不改原配置的 YAML,只在启动时"插入"一个条目。本文用它把插件挂进去。
inject:依赖声明,表示"某服务就绪后再启动我"。顺序由框架排,不用你编排。
还有一点值得记住:插件注册的一切都是可逆副作用,卸载时框架自动回滚,叠加、替换、热卸载都不用担心污染全局。
DeepSeek Harness Web UI 怎么安装与启动
做什么。确认 Node.js 22.19 以上(或 24 以上)可用,然后克隆、安装、构建、启动,五条命令一次走完:
git clone https://gitcode.com/gh_mirrors/de/deepseek-harness cd deepseek-harness pnpm install pnpm run build pnpm dsh webpnpm run build负责准备仓库产物;pnpm dsh web直接使用这些已构建产物,不会重新构建。
应该看到什么。浏览器自动打开http://127.0.0.1:3080,出现 dsh 主界面。
怎么确认做对了。终端打印出启动 URL,且页面里能打开设置页。另外注意:运行命令所在的目录会被用作默认 workspace 根目录,建议在一个干净目录里启动。
DeepSeek Harness 模型如何配置
做什么。打开页面左侧设置 → 模型,在 DeepSeek 卡片的 API 密钥输入框填入密钥,点击保存。
应该看到什么。保存后输入框不再回显明文,只剩脱敏引用——密钥本体落在$DSH_HOME/.credentials.yaml,设置项只保留对它的引用。
怎么确认做对了。模型变更在下一次请求时生效,无需重启服务器。如果接的是公司网关或自建服务,选择添加模型提供商并切到自定义页:填全小写 Provider ID、带/v1前缀的 Base URL 和协议(多数网关选openai-completions)。配置完成后在页面里添加并选中一个工作区,会话输入框才可用。
第一个插件怎么写并挂载
做什么。在仓库根目录先建一个临时项目:
mkdir -p scratch-plugin/src往scratch-plugin/src/my-plugin.ts写一个导出apply的模块。name是可选的显示元数据,apply是框架加载时调用的入口:
import type { Context } from '@deepseek-ai/cordis' export const name = 'hello-plugin' export function apply(ctx: Context) { console.log('[hello-plugin] plugin loaded!') }再写 patch 覆盖层scratch-plugin/cordis.yml,把插件插进来(路径换成仓库绝对路径,pwd查看):
- insert: - id: hello name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'插件路径必须是绝对路径,否则 loader 解析不到模块。最后带覆盖层启动:
pnpm dsh web --patch ./scratch-plugin/cordis.yml应该看到什么。启动过程中,终端打印出本文开头那一行:
[hello-plugin] plugin loaded!怎么确认做对了。确认这行日志出现、浏览器页面照常打开——patch 覆盖层被读取、插件模块被挂载、apply被执行,整条链路都走通了,且框架源码一行未动。
从"能跑"到"能用":让模型调用你的工具
打日志只是验证机制,下面注册一个真工具。用这段最小可用版替换my-plugin.ts:
import type { Context } from '@deepseek-ai/cordis' import { defineTool } from '@deepseek-ai/dsh-tools' export const name = 'greet-tool' export const inject = ['tools'] export function apply(ctx: Context) { ctx.tools.register(defineTool({ name: 'greet', description: 'Greet someone by name.', parameters: { name: { type: 'string', required: true, description: 'Name to greet' }, }, output: { schema: { type: 'string' }, render: (_args, value) => [{ type: 'text', text: value }], }, async execute(args) { return `Hello, ${args.name}!` }, })) }这里引入两个新东西:inject = ['tools']声明"工具注册表就绪后再启动我",是依赖声明而非手写顺序;defineTool把parameters推导成模型可理解的 schema,并校验execute收到的参数。如果插件还要开定时器、挂监听器,用ctx.effect()包住并在回调里返回清理函数,卸载时框架会自动调用,无需手写clearInterval。
怎么验证。用同一条--patch命令重启,在对话里输入Use the greet tool to greet Ada.——如果模型返回工具结果Hello, Ada!,说明它已经能调度你写的代码。
排障速查:DeepSeek Harness 常见报错处理
| 报错现象 | 常见原因 | 自救动作 |
|---|---|---|
| 加了插件"没反应",启动却无报错 | 模块路径非绝对路径或文件名拼错 | 模块解析失败只进日志、不崩溃进程;先核对拼写与绝对路径 |
| 进程启动即退出 | apply内抛出异常 | 加载失败会被明确报告,修掉抛错处再启动 |
| 页面打不开 | 3080 被占用或进程已退出 | 确认pnpm dsh web存活;用--port换端口 |
| 模型一直报错 | 密钥未保存 | 回 设置 → 模型 确认已保存;变更下次请求生效,无需重启 |
| 发送图片被拒绝 | 模型输入类型默认纯文本 | 在模型页的模型选项里勾选图片输入类型 |
跑通之后去哪走
- 想深入:第一个插件教程 覆盖对象/类形态与依赖声明;插件配置 讲如何让你的插件接受用户配置。
- 想拓宽:Cordis 入门 是精简概念参考,可一次看完插件形态全貌;架构文档 解释各层如何组合。
- 不想申请密钥:Cordis 教程 每章都是一个可运行示例,在临时目录里无密钥也能全部跑通。
开头那行日志现在出自你自己的终端,greet成了模型能调用的第一个能力。下一个插件,写什么由你定。
【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考