studyzy/dsh-lazy-tools

dsh-lazy-tools

仓库尚未提供可用的公开描述。

未分類

dsh-lazy-tools

为 DeepSeek Harness 提供的 CodeBuddy 风格延迟工具加载插件。

一个 tool_search + defer_execute_tool 覆盖层,让工具 schema 在真正需要之前 不会进入模型上下文。

*减少 token 消耗 · 缩小上下文窗口 · 保持工具可发现*

它是做什么的

大多数编码 Agent 会把每一个可用工具的 JSON Schema 都塞进提示词—— 包括模型最终根本不会用到的工具。dsh-lazy-tools 颠覆了这个模型:工具 默认被延迟(deferred),只有当模型主动请求时才进入上下文。

装上即用、零配置:默认延迟长尾工具,同时保留一组常驻编码核心 (read/write/edit/bash/glob/grep/web_search/web_fetch/ ask_user_question/skill,详见默认行为)。这个核心只是起点: 开启自动调优后,插件会按项目统计真实使用情况,把每个项目里最常用的工具设为 常驻、其余全部延迟——所以每个项目最终拿到的是适合它自己的那份配置。

被延迟的工具会从模型可见的工具列表里剔除,因此它们的 schema(乃至名字) 永远不会进入模型上下文。模型通过 tool_search 按需发现它们,激活后 即可直接调用。

剔除发生在 system-prompt/assemble 这条 waterfall 上——也就是 agent loop 真正发给模型的那份 per-scope 工具表(它同时决定请求头与提供商的工具声明)。 本插件不修改工具注册表,所以它不关心工具来自哪个平面。

这是一个纯粹的暴露控制层:

  • 它不拥有、也不实现任何工具。
  • 被延迟的工具是注册表里的普通工具(宿主 composition、agent preset、MCP 等

第三方工具皆可);本插件只从模型可见列表里观察它们的 name / description / parameters 用于发现。

  • 它不代理执行——tool_search / defer_execute_tool 只负责*激活*,激活后

模型直接调用该工具本身。

因为完全实现在 agent 层,它适用于任何模型与任何提供商(DeepSeek、 OpenAI、Anthropic、Gemini……),不依赖提供商原生的延迟工具协议(如 Anthropic tool_reference 或 OpenAI 的 deferred-tool input items)。

特性

  • 🔍 按需发现 — tool_search 通过精确工具名(tool_names)或关键词

(queries,中英文均可)查找工具,命中即激活。

  • ⚡ 懒激活 — 命中的工具记入该 agent 的激活集合,下一轮模型请求即可

直接调用。

  • ⚡ 按名激活 — defer_execute_tool 按精确工具名直接激活一个已知工具。
  • 🧭 无侵入 — 不碰注册表:只在 system-prompt/assemble 上对模型可见的

工具列表做减法,因此与任何其他 restrict、任何工具来源、任何平面天然共存, 绝不放宽其他策略。

  • 🎛️ 灵活配置 — CodeBuddy 风格 Defer(...) / NoDefer(...) 模式,支持 *

通配符。

  • 🛡️ 自保守卫 — tool_search 与 defer_execute_tool 注册在 agent 自身作用域,

永不被延迟;保留传输 run_code 同样被钉住,Defer(*) 无法把系统锁死。

  • 📊 按项目自动调优 — 启动后第一个汇报工作目录的会话会扫描该项目最近

30 天的会话历史,统计 tool/call 频率,把最常用的 20 个工具设为常驻、其余 全部延迟。

  • 🗂️ 全局 + 项目级两层配置 — 你手写的全局 defer/noDefer 对所有项目

生效;自动调优的结果只写进独立的项目级存储,按项目覆盖全局。优先级 项目级 > 全局。全局配置永远不会被扫描结果改写。

安装

从 GitHub 仓库安装为外部 bundle:

dsh plugin --profile <profile> add github:studyzy/dsh-lazy-tools
git:github.com/... 不是合法的 pnpm 语法——它会被当成 SSH 远端,在没配
GitHub SSH key 的机器上报 Could not read from remote repository。用
github:user/repo(或 git+https://github.com/user/repo.git)走 HTTPS。
安装后需要重启 DSH:bundle 层只在启动时加载,当前进程不会热加载。
也可以先 git clone 到本地,再从本地目录安装。该 bundle 通过
cordis.patch.yml 注入一个名为 lazy-tools 的插件。

兼容性

本插件面向 DeepSeek Harness 0.2.0-rc.2(@deepseek-ai/dsh-* 0.2.0-rc.2、 @deepseek-ai/cordis 4.0.4、@deepseek-ai/schemastery 3.18.4)。 package.json 的 peerDependencies 声明了这些精确版本,与 DSH 内置的 运行时依赖一致,因此安装时 pnpm peers check 不会报出本插件的 peer 缺失:

# 本地目录安装(开发时更新依赖后刷新 profile 依赖树)
dsh plugin --profile <profile> add link:/path/to/dsh-lazy-tools
升级 DSH 后若 pnpm peers check 提示本插件 peer 版本不匹配,把
package.json 的 peerDependencies / devDependencies 对齐到新的
@deepseek-ai/dsh-* 版本,重新 pnpm install && pnpm run check,
再执行一次上面的 add 即可。

配置

零配置即可用:不写任何 config 时插件使用内置预设,装完就是这样。

默认行为

· 内容 延迟 · Defer(*) —— 除守卫外全部延迟,模型按需 tool_search 常驻可用 · read、write、edit、bash、glob、grep、web_search、web_fetch、ask_user_question、skill 守卫(永不被延迟) · tool_search、defer_execute_tool、run_code

上表是全局默认,也就是每个项目在还没被自动调优前的起点。开启自动调优
(默认开启)后,某个项目一旦积累够历史,就会用该项目自己的统计结果覆盖它
——详见"配置分层"与"按项目自动调优"。想让所有项目都固定用这套默认,设
autoTune: false。

一旦显式写了 `defer` 或 `noDefer` 中的任意一个键,预设就被完全替换,一切按你写的来: defer: [] 仍然是"不延迟任何工具",defer: ['glob'] 就是只延迟 glob (不会因为 glob 在默认核心里而被重新保护)。

需要改默认时才写配置,位置是 profile 的 cordis.patch.yml(用户 patch 层) 中该插件的 config 字段,使用 CodeBuddy 风格语法:

- id: lazy-tools
  name: '@studyzy/dsh-lazy-tools'
  config:
    defer: ['glob', 'web_search', 'Defer(fetch_*)']
    noDefer: ['bash']

键 · 类型 · 默认 · 说明 defer · string[] · 见"默认行为" · 要延迟的工具名或 Defer(pattern) 条目。裸名等价于 Defer(name)。* 是唯一通配符——Defer(*) 延迟除守卫工具外的所有工具。 noDefer · string[] · 见"默认行为" · 必须保持可直接调用的工具名或 NoDefer(pattern) 条目。裸名等价于 NoDefer(name)。始终优先于 `defer`。 autoTune · boolean · true · 是否按本项目会话历史自动生成 defer/noDefer,见"按项目自动调优"。 autoTuneWindowDays · number · 30 · 统计窗口天数。 autoTuneTopN · number · 20 · 自动调优保留多少个最常用工具常驻。 autoTuneMinSamples · number · 200 · 窗口内调用总数达到该值才允许改写配置。

修饰符大小写不敏感(defer(bash) ≡ Defer(bash))。优先级(从高到低): noDefer > defer。

想彻底关掉延迟加载? 写 defer: [] 就行,不需要额外的开关——空列表本身
就表示"不延迟任何工具",再挂一个布尔开关只会和它互相矛盾。

在界面里配置

Web / 桌面版还有一块可视化配置页,不用手写 YAML:打开 设置(Settings)→ 插件 (Plugins),然后从下面任意一个入口都能进:

  • 官方插件 分组里的 懒加载工具(Lazy tools) 卡片 —— 与 子智能体(Subagent)

插件的配置入口一致;

  • 已安装 分组里的 `@studyzy/dsh-lazy-tools` 包卡片(点进去后,配置表单就在

「包含的组件」列表上方)。

两处渲染的是同一个表单、同一份草稿:在哪边改都一样,保存也是一次写入。

为什么有两个入口:本插件是 profile 的依赖(link: 声明),插件页因此把它当作
「已安装的包」列出一张包卡片,同时又作为「官方插件」列出一张配置卡片。子智能体
不存在这个问题,因为它是应用自带的(未安装),根本不会有包卡片。两个入口都注册,
是为了让用户点进哪一张都能配置。

页面上六个字段与上表一一对应:defer 和 noDefer 是逗号分隔的输入框(例如 Defer(*), web_fetch, glob;也接受换行分隔,两者可混用。留空=清除该键、回退到 组合层提供的值,而不是写入空数组);autoTune 是开关;其余三个是数字输入。 改动点保存才生效,离开页面即丢弃草稿。

未配置时,defer / noDefer 两个框会直接显示当前实际生效的内置预设 (Defer(*) 与那一串常驻工具),而不是空框——它们不算"已覆盖",因此不带覆盖标记。 这样你看到的就等于插件真正在执行的值。

想彻底关掉延迟加载? 把 defer 框清空保存即可(等价于 defer: [])。
为什么用逗号而不是"一行一个":DSH 共用的 SettingsValueField 渲染的是单行
,浏览器会把渲染值里的换行去掉。若用换行分隔,bash, read`
会显示成 bashread,保存时被当成一个工具名写回去,直接破坏列表。

保存写进的是该插件在 profile patch 里的 config,也就是全局层;项目级覆盖仍由 自动调优写入 ~/.dsh/lazy-tools/projects.json,界面上不会被改写。保存后配置当场 生效,不需要重启:插件每次都从实时配置重新解析延迟规则,保存会触发一次重新排名, 下一次请求就用新规则。

页面由插件自带的浏览器端一半提供(dsh.client 声明 + lib/client.js),只在 Host