dshbase

插件目录 / Developer / dsh-custom-tool

dsh-custom-tool

已验证 · 实测可装 omdsh-dev

✓ 持续维护 2 位贡献者 基于 8 个官方 DSH 包 纯 TypeScript

查看 GitHub ↗ ← 返回插件目录

23Stars
0Forks
0未关闭 issue
TypeScript语言
2026-08-16最近推送
跨平台平台

功能简介

用 Monaco 编辑器和模型驱动的工具生命周期,为 DeepSeek Harness 创建并管理沙盒 JavaScript 工具。

✅
我们的评价
可用 — 实测通过,社区增长中

用 Monaco 编辑器和模型驱动的工具生命周期,为 DeepSeek Harness 创建并管理沙盒 JavaScript 工具。 实测能干净安装、正常启动。社区在增长,是个稳妥选择。

「已验证」表示我们的自动化 CI 在干净 profile 里实际执行了 dsh plugin add 并启动成功——仅此而已。功能描述与版本兼容性均为作者声明。这不是安全审计,也不代表对第三方代码的背书。

README

dsh-custom-tool

Custom tools for the DeepSeek Harness: users author their own JavaScript tools in the settings UI with a Monaco (VS Code) editor and TypeScript intellisense, and the model grows and prunes the same toolset itself through custom_tool_create / custom_tool_remove / custom_tools_list. Every tool is durable, hot-registered, and written into the model prompt on the next step.

The Custom Tool settings page

The tool editor

Problems it solves

  • Users cannot extend their agent: before this plugin, adding a capability meant shipping a harness package. Now a tool is a form in the settings UI — name, description, parameters, code — saved live and callable by the model immediately.
  • The model cannot grow itself: custom_tool_create lets the model persist tools mid-session (hot-registered, visible on its next step), with the same validation gate the UI uses — the model cannot persist anything the settings UI would refuse.
  • User-authored code runs in a restricted worker: every call executes in a fresh worker thread inside a node:vm realm with an explicit allowlist, Node Permission Model, and hard budgets. The worker receives no inherited environment variables, filesystem access outside its configured scope, or child-process capability.

Features

  • Settings UI (Custom Tool section, own nav glyph): list, create, edit, enable/disable, delete. Model-created and workspace-scoped tools are badged. Every string follows the harness locale (Chinese / English) and switches with the language preference.
  • Monaco editor: VS Code engine + TypeScript language service; args typed from the parameter schema, env/sandbox globals declared, completions and diagnostics live. Editor and TS workers are bundled inline — the client bundle is a single file.
  • Durable store: tools live in the custom-tools settings namespace (schema defaults, composition base, user document — the ordinary settings layering). Edits apply live; restart restores them.
  • Live registration: enabled tools register into ctx.tools the moment the settings write commits; disabled/removed tools unregister immediately. The harness assembles tool schemas into the system prompt automatically.
  • Model self-service: custom_tool_create (upsert by name), custom_tools_list, and custom_tool_remove share the UI's validation gate and the ownership rules below.

Tool scopes and permission boundaries

Every tool declares one of two execution scopes. The boundary is the core security contract of this plugin:

global (default) workspace
Purpose pure computation, external data, workflows recurring file tasks inside the session workspace
fetch (network) per allowNetwork config per allowNetwork config
console, timers, TextEncoder, URL, … yes yes
fs capability no readFile / writeFile / list, confined to the session workspace root
require / import / process never never

Confinement rules for the workspace scope

  • The root is the session workspace directory (the initiating agent's cwd), resolved at call time.
  • Relative paths resolve from the root; absolute paths must stay inside it; any path that escapes the root is rejected with an explicit error.
  • Outside a session (no initiator context) a workspace tool fails with no workspace root rather than running without a boundary.
  • Confinement is lexical (resolve + prefix check). A symlink inside the workspace can still point out of it — workspace scope is trusted code, not a sandbox against a malicious host. The liveness budgets below apply to both scopes.

Storage locations

Every tool also declares where it EXISTS:

  • location: 'global' — stored in the shared settings namespace; available in every workspace until removed.
  • location: 'workspace' — stored in a per-workspace file under <dsh home>/workspace-tools/, keyed by the canonical workspace root; visible only to sessions of that workspace (registered into each matching agent's own tool scope).

The two dimensions combine freely: a global-location tool with workspace scope (a durable file task the user keeps everywhere, like a PDF reader) runs its fs on whichever workspace calls it.

Ownership and authorization rules for the model

  • The model may create, list, and remove model-created tools (source: model).
  • Creating a global-location tool requires the user's explicit approval: custom_tool_create raises a harness approval request (GUI prompt); a declined or unavailable answer fails the creation closed. Workspace-location tools are autonomous.
  • The model may not remove user-created tools (source: user); custom_tool_remove refuses them and the system-prompt guidance says to ask the user to delete them in the settings UI.
  • The settings UI manages everything: both sources, both scopes, both locations, enable/disable, delete.

Execution budgets (both scopes)

  • One worker thread per call; the worker is terminated on timeout, abort, or completion.
  • Wall-clock deadline (timeoutMs), heap cap (memoryLimitMb), result text bound (maxResultChars), code size bound (maxCodeBytes), stored-tool cap (maxTools).

Install

dsh plugin --profile web add https://github.com/omdsh-dev/dsh-custom-tool/archive/refs/tags/v0.1.2.tar.gz
dsh web   # restart the server to pick the plugin up

The package declares dsh.bundle.patch (mounts the host plugin) and dsh.client (serves the browser half at /plugins/dsh-custom-tool/client.js). lib/ is committed, so the GitHub tarball installs without a build step.

Harness requirement: the settings namespace is exposed to web configuration clients through the WEB_SETTINGS_NAMESPACES allowlist in packages/host/apiproxy/src/api-proxy.ts; the string 'custom-tools' must be present there (the upstream harness commit d6ea05b5 adds it). Without it the UI renders but saves are silently refused (settings-not-exposed).

Tool code contract

The code field is the body of an async function async (args, env) => value:

// args is typed from the parameter JSON Schema you declared.
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()
  • Return a JSON value (string, number, boolean, null, array, or plain object); undefined or a non-JSON value fails the call.
  • Parameters: object-rooted JSON Schema in the harness subset — type, properties, required, items, enum, const, oneOf, additionalProperties, description, title, default, examples.
  • Globals: fetch (blocked when allowNetwork: false), console, TextEncoder/TextDecoder, URL/URLSearchParams, atob/btoa, structuredClone, AbortController, setTimeout/setInterval + clears. env is { tool, scope }. Workspace scope adds fs.

Configuration

All tunables are cordis.yml config fields of the dsh-custom-tool entry:

Field Default Meaning
timeoutMs 30000 wall-clock budget per call
memoryLimitMb 128 worker old-generation heap cap per call
maxResultChars 16000 rendered result text budget
maxCodeBytes 65536 UTF-8 byte budget per tool body
maxTools 100 stored-tool cap
allowNetwork true whether tool bodies may call fetch or use network APIs

Development

pnpm install        # links the sibling dsh checkout for types and tests
pnpm run build      # worker bundles -> inline sources -> declarations -> bundles
pnpm run test       # builds workers first (pretest), then vitest
pnpm run typecheck
pnpm run lint
pnpm run check      # typecheck + lint + test + build

Node-env tests alias @deepseek-ai/dsh-client-runtime/client to source and monaco-editor to a mock (see vitest.config.ts).

Known Limitations and Deferred Work

  • Custom tool names cannot shadow tools owned by other packages; a collision surfaces as a per-tool registration failure in custom_tools_list.
  • Workspace confinement is lexical, not symlink-proof (see the scope table).
  • No per-tool test-run button in the UI yet; tools are exercised through model calls or a headless run.

安装

🧩 让 Agent 自动装(推荐)

装一次目录插件,之后本站所有插件都能让 DeepSeek Harness 自动找、自动装:

dsh plugin add dshbase-catalog

然后对 agent 说「帮我装 dsh-custom-tool」,它会在目录里找到并自动安装。文档:dshbase-catalog · 已验证场景包。

该插件是 GitHub 源码(未发 npm)——直接从仓库装:

Web profile:

dsh plugin --profile web add github:omdsh-dev/dsh-custom-tool

Headless(CLI)profile:

dsh plugin --profile headless add github:omdsh-dev/dsh-custom-tool

实测报告

验证通过:从 GitHub 源码完成 L1 安装 + L2 加载 + L3 运行(dsh 0.1.0-rc.6)。

使用场景

用 Monaco 编辑器创建和管理沙箱化的 JS 工具,让模型能调用你定义的函数。

适合谁

想用自己的逻辑扩展 agent 能力、又不想写完整插件的人。

二次开发建议

沙箱 JS 运行时是缝——加权限、npm 依赖和更丰富的工具 schema。

安全:尚未扫描——我们的每日静态扫描将很快覆盖它。

分享徽章

Developer 里更多

浏览全部 7797 个插件 →