前言¶
给 DeepSeek Harness(以下简称 DSH)加一项能力,常规路径是写一个 harness 包:声明工具 schema、实现 execute、打进 profile。这套流程适合正式插件,但对「今天临时要调一个天气接口」「这个工作区反复做同一类文件整理」来说,成本偏高。改完还要重启、重新挂载,模型这一侧也不能在会话中途自己补一把工具。
官方仓库把架构写成「一切皆插件」:模型、工具、技能、会话、沙箱、UI 都可以在配置层装卸,不必改 Harness 源码。社区里有人把「写工具」这件事收进设置页:用 Monaco 编辑器填名字、描述、参数和 JavaScript 代码,保存后热注册进 ctx.tools;同一套工具,模型也可以通过 custom_tool_create / custom_tools_list / custom_tool_remove 增删。这个插件叫 dsh-custom-tool,收录在独立的社区插件目录 deepseek-harness-plugin.com 中。该目录与 DeepSeek / 幻方没有官方从属关系,不是官方应用商店。
本文按插件目录页、GitHub 仓库 README / README.zh.md、package.json、dsh.plugin.json 交叉核对后整理:它是什么、装哪条命令、工具代码怎么写,以及沙箱边界和 harness 前置条件。
这是什么¶
dsh-custom-tool 是一款面向 DeepSeek Harness 的开发与运行时插件,由 GitHub 组织 omdsh-dev 维护,仓库地址为 omdsh-dev/dsh-custom-tool。当前版本为 0.1.2(package.json 与 dsh.plugin.json 一致;仓库在 2026-08-16 打了 git tag v0.1.2)。许可证为 MIT,LICENSE 版权声明写的是 2026 FSMargoo。主要语言是 TypeScript;仓库已提交 lib/,按 README 用 GitHub tarball 安装时不必本地构建。截至 2026-08-17 查询,GitHub API 显示 24 stars(社区目录页当时标注为 23)。package.json 要求 Node.js ^22.19 || >=24。
目录页给它的一句话是:用 Monaco 编辑器创建和管理沙箱 JavaScript 工具,模型驱动工具生命周期。仓库 README 写得更具体:用户在设置界面的「Custom Tool」页编写工具;模型通过上述三个工具接口扩展和修剪同一套工具集。工具持久化、热注册,并在下一步写入模型提示词。
它要填的坑,README 列了三条:以前加能力要发布 harness 包,现在一张表单保存即生效;模型可以在会话中途持久化工具,且与 UI 共用同一道校验门;用户写的代码在受限 worker 里跑,而不是直接进当前 Node 进程。
核心功能¶
下面几条都来自当前仓库 README、README.zh.md 与 dsh.plugin.json,不额外发挥。
1. 设置页里的 Custom Tool¶
插件在 Web 设置里加了一个「Custom Tool」分区,带专属导航图标。可以列表、新建、编辑、启用 / 停用、删除。模型创建的工具、以及工作区作用域的工具会打徽章。文案接入 harness 的中文 / English 语言体系,随界面语言切换。
编辑器是 Monaco(VS Code 引擎)加 TypeScript 语言服务:args 按你声明的参数 schema 生成类型,env 和沙箱全局量有声明,补全与诊断即时出现。编辑器和 TS worker 内联打包,客户端是单文件 bundle。package.json 声明浏览器半通过 dsh.client 提供,README 写明路径是 /plugins/dsh-custom-tool/client.js。
2. 持久化与热注册¶
工具存在 custom-tools 设置命名空间,分层方式和 harness 其他设置一样:schema 默认值、组合 base、用户文档。改动提交后立刻生效,重启后按存储恢复。
启用的工具在设置写入提交的瞬间注册进 ctx.tools;停用或删除会立即注销。工具 schema 由 harness 自动汇入系统提示词,模型下一步就能看见。
3. 模型自助:创建、列出、删除¶
dsh.plugin.json 声明贡献的工具是:
custom_tool_create:按名字 upsertcustom_tools_listcustom_tool_remove
这三条与设置 UI 共用校验门。归属规则 README 写得很清楚:
- 模型可以创建、列出、删除 自己创建 的工具(
source: model) - 创建 global 位置 的工具需要用户明确授权:
custom_tool_create会发起 harness 审批请求(GUI 弹窗);拒绝或审批不可用则创建失败关闭 - workspace 位置的工具,模型可以自主创建
- 模型 不能 删除用户创建的工具(
source: user):custom_tool_remove会拒绝,提示词会引导模型请用户在设置界面删除
设置界面管理全部来源、作用域、位置,以及启停和删除。
4. 两套作用域、两套存放位置¶
每个工具声明一种执行作用域。这是插件的核心安全契约:
global(默认) |
workspace |
|
|---|---|---|
| 用途 | 纯计算、外部数据、工作流 | 工作区内重复性的文件任务 |
fetch |
受 allowNetwork 控制 |
受 allowNetwork 控制 |
console、定时器、TextEncoder、URL 等 |
有 | 有 |
fs |
无 | readFile / writeFile / list,限定在本会话 workspace 根目录内 |
require / import / process |
永不 | 永不 |
workspace 作用域的根目录是发起 agent 的 cwd,调用时解析。相对路径从根解析;绝对路径必须落在根内;越界路径会被显式拒绝。没有会话上下文时,workspace 工具直接报 no workspace root,不会在无边界下运行。
隔离是词法级的(resolve + 前缀检查)。README 明确写了:工作区内的符号链接仍可能指向外部——workspace 作用域按可信代码处理,不是对抗恶意宿主的沙箱。
存放位置是另一维:
location: 'global':存在共享设置命名空间,所有工作区都可用,直到被删除location: 'workspace':存在按工作区根路径哈希命名的独立文件里(README 写在workspace-tools/目录下),只对该工作区的会话可见
两维可以自由组合。README 举的例子是:location 为 global、scope 为 workspace 的文件类工具(例如 PDF 读取),在任意被调用的工作区上执行 fs。
5. 沙箱执行与预算¶
每次调用在独立 worker 线程里跑,环境是全新的 node:vm 领域,配合白名单、Node Permission Model 和硬预算。worker 不继承环境变量,也不能访问配置范围之外的文件或创建子进程。超时、取消或完成后,该 worker 被终止。
README 给出的可调预算(cordis.yml 里 dsh-custom-tool 条目的 config 字段)默认值如下:
| 字段 | 默认值 | 含义 |
|---|---|---|
timeoutMs |
30000 | 单次调用墙钟上限(毫秒) |
memoryLimitMb |
128 | 单次调用 worker 老年代堆上限(MB) |
maxResultChars |
16000 | 结果渲染文本字符上限 |
maxCodeBytes |
65536 | 单个工具代码的 UTF-8 字节上限 |
maxTools |
100 | 可存储的工具数上限 |
allowNetwork |
true | 是否允许工具代码调用 fetch |
安装与启用¶
插件目录页给出的安装命令是:
dsh plugin add github:omdsh-dev/dsh-custom-tool
目录页同时提醒:插件以当前 dsh 进程的权限运行,安装时可能执行代码。安装前请检查源代码仓库和许可证。若需要可复现安装,固定 commit 哈希:
dsh plugin add github:omdsh-dev/dsh-custom-tool#<commit>
把 <commit> 换成仓库里实际的提交哈希,不要照抄占位符。当前 tag v0.1.2 指向提交 7cb95649dca9b380c9a30af96bdbef87a76a2259。
仓库 README 面向 Web 界面,写法是按 web profile 安装固定版本的 tarball,然后重启:
dsh plugin --profile web add https://github.com/omdsh-dev/dsh-custom-tool/archive/refs/tags/v0.1.2.tar.gz
dsh web
包声明了 dsh.bundle.patch(挂载 host 插件)与 dsh.client(提供浏览器半)。lib/ 已提交,因此这份 tarball 安装后无需再构建。
Harness 前置条件(README 原文):设置命名空间要通过 packages/host/apiproxy/src/api-proxy.ts 中的 WEB_SETTINGS_NAMESPACES 白名单暴露给 web 配置客户端,名单里必须有 'custom-tools'。上游 harness 提交 d6ea05b5 已加入该项。缺少它时界面能渲染,但保存会被静默拒绝,错误为 settings-not-exposed。
典型用法¶
在设置页新建工具¶
启动 Web 界面并打开设置里的 Custom Tool:
- 新建一条工具,填写名字、描述、参数 schema、作用域和存放位置。
- 在 Monaco 里写代码。代码字段是 一个异步函数体,契约是
async (args, env) => value,不是完整的源文件。 - 保存。启用状态下,工具立刻注册进
ctx.tools,下一步会出现在模型提示词里。 - 不需要时可以停用或删除;停用会立即注销。
README 给出的示例是按城市拉天气(需要 allowNetwork 为 true,这是默认值):
// args 按你声明的参数 JSON Schema 生成类型。
const url = `https://api.example.com/weather?city=${encodeURIComponent(args.city)}`
const response = await fetch(url)
if (!response.ok) throw new Error(`upstream returned ${response.status}`)
return await response.json()
返回值必须是 JSON 值:string、number、boolean、null、array 或普通对象。undefined 或非 JSON 值会使调用失败。
参数是 object 根的 JSON Schema,且只接受 harness 子集:type、properties、required、items、enum、const、oneOf、additionalProperties、description、title、default、examples。
沙箱全局量包括:fetch(allowNetwork: false 时被禁)、console、TextEncoder / TextDecoder、URL / URLSearchParams、atob / btoa、structuredClone、AbortController、setTimeout / setInterval 及对应的 clear。env 为 { tool, scope }。workspace 作用域额外提供 fs。
界面目前没有「试运行」按钮。README 写明:工具通过模型调用或 headless 运行来验证。
让模型自己补工具¶
会话里可以直接要求模型创建一条可复用的工具。模型会走 custom_tool_create。若目标是 global 位置,界面会弹出 harness 审批;拒绝则创建失败。workspace 位置不走这道审批。
查看当前自定义工具用 custom_tools_list。自定义工具名不能遮蔽其他包已经注册的工具;冲突会以逐工具注册失败的形式出现在这份列表里。
删除时,模型只能删 source: model 的条目。用户在设置页写的工具,需要人在 UI 里删。
适用场景与注意事项¶
比较适合这些情况:
- 已经在用
dsh web,希望给当前环境加几条小工具,又不想为此发一个正式插件包 - 需要模型在会话中途把反复出现的步骤沉淀成可调用工具,并在下一步立刻看见
- 工具逻辑是纯计算或受控的
fetch;若要碰文件,明确使用 workspace 作用域,并接受词法隔离的边界 - 希望用户写的工具和模型写的工具分权:人删人的,模型只能动自己创建的那批
使用前注意下面几条,均来自目录页或仓库 README,不是额外发挥:
- 先看源码和许可证再装。 目录页写明:插件以当前 dsh 进程权限运行,安装时可能执行代码。这是社区插件,不是 DeepSeek 官方组件。
- 确认
custom-tools已进入 harness 白名单。 否则设置页能打开,保存会静默失败(settings-not-exposed)。需要上游提交d6ea05b5或等价改动。 - 沙箱不是万能隔离。
require/import/process不可用;global 作用域没有fs;workspace 的路径检查不防符号链接。README 把 workspace 代码按可信代码对待。 - 网络默认是开的。
allowNetwork默认true。不希望工具访问外网时,要在cordis.yml里关掉。 - 预算有上限。 单次 30 秒、堆 128 MB、结果 16000 字符、代码 64 KiB、最多 100 条工具,都是文档给出的默认硬限制。
- 不要把目录页当成官方商店。 deepseek-harness-plugin.com 是社区目录;DSH 本体以 deepseek-ai/deepseek-harness 为准。安装命令以目录页原文为准;Web 固定版本安装以仓库 README 的 tarball 写法为准,不要凭插件名自行拼接路径。
小结¶
dsh-custom-tool 做的事情很集中:把「写一个 JavaScript 工具」放进 DSH 设置页,用 Monaco 编辑、热注册、持久化;同时把同一套生命周期交给模型,但用审批和归属规则把用户工具保护起来。执行侧是带白名单和预算的 worker,不是把任意脚本直接跑进当前进程。
目录页与仓库:
- 插件目录:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-custom-tool/
- GitHub:https://github.com/omdsh-dev/dsh-custom-tool
- DeepSeek Harness:https://github.com/deepseek-ai/deepseek-harness
- 官方介绍:https://www.deepseek.com/harness/