跳至内容

工具预算与插件责任:从“万物皆插件”到可维护生态

这是一张给初学者的总决策卡。它把“万物皆插件”、工具列表过长、非侵入式扩展、源码 patch、Hook bridge 和运行时注入放到同一张地图里。

证据范围仍然是固定上游提交 aa6c361a972c8369148dea7380bb5c21c24e07ec。本篇解释源码和官方文档支持的设计,不声称已经完成真实模型性能实验,也不替任何社区项目背书。

先把你的直觉改成准确说法

直觉更准确的说法
“万物皆插件,所以所有工具都会灌给模型。”插件负责装配能力;工具还要经过作用域、呈现和执行策略,才可能进入当前请求。
“工具越多一定越慢、模型一定变差。”工具名称、description 和 schema 可能增加输入成本与选择负担;幅度必须按模型和 provider 实测。
“非侵入式一定更强。”非侵入式更适合作为默认扩展路线,因为版本、卸载和信任边界更清楚;它不代表所有需求都能完成。
“侵入式工作不能由插件作者做。”普通插件作者不应把宿主级修改藏在安装步骤里;如果维护 patch/fork,他的身份已变成宿主或发行版维护者。
“能 hook 就是插件。”hook 只说明接入点;是否是插件,还要看公开接口、模块边界、生命周期、安装方式、身份和证据。

先记住三层和一条呈现线

不要把下面三层和一条呈现线压缩成一个“工具列表”:

text
运行时已经注册的工具     = 宿主知道它存在的候选集合
当前 agent 可解析的工具  = 这个作用域的 get / execute 查找可以解析的集合
呈现与最终组装            = presentAs(native / code / both) 决定模型收到的工具字段
执行策略允许的工具调用   = 经过 guard、审批、沙箱和宿主权限后的结果

注册集合可以有 20 个工具,而当前 agent 只解析其中一部分;在 native 呈现且最终组装未替换时,模型请求可能只收到 3 个工具的 schema。若使用 code 模式,模型侧可能主要收到 run_code 和 SDK,具体工具仍由代码执行侧按作用域解析。这不表示另外 17 个工具被删除,也不表示可呈现工具获得了无限权限。

在 DSH 的同一 agent 作用域中,restrict() 不只影响 native schema 组装;同一作用域的 get() 与工具分发也会把被排除工具当作未知。这样模型选择面和该 agent 的查找面保持一致。它仍不是操作系统权限开关:一个可解析或可呈现的工具照样要经过 guard、审批、沙箱和宿主能力。

因此,“20 个工具仍注册,当前 agent 只解析其中 3 个,并在 native 模式下向模型呈现这 3 个”是合理的实验组。被排除的 17 个工具仍在注册集合里,也没有任何输入因此获得操作系统级权限;隔离边界的完整表述见第 22 课

工具预算应该怎样定

默认不要问“能不能把所有工具都注册上”,而要按下面顺序问:

  1. 这个 Profile 是否真的需要加载这个 Bundle?不需要的能力先不要默认启动。
  2. 当前 agent 是否真的需要解析并向模型呈现这个工具?用公开的作用域和呈现接口限制解析/呈现集合。
  3. schema 是否只保留模型做选择所需的信息?名称、description、参数和枚举要稳定、清楚、不过度展开。
  4. 执行层是否仍有独立的审批、guard、沙箱和宿主权限?可见性不是安全边界。
  5. 集合变化是否有记录?注册、注销、重排和 schema 修改都可能改变请求前缀,应该可解释、可回滚。

渐进加载是第 3 条的现成范例:技能目录只在提示词里放一行 name+description 摘要,正文等模型精确调用 skill 工具才进入上下文。技能目录实验演示摘要信封、digest 驱动的替换规则和三种工具结局。

教材用三种模式帮助学习。这些名称不是上游已经承诺的内置 Profile 或命令:

模式推荐做法适合谁不能误解成
normal加载常用能力,只让当前任务需要的工具被解析并呈现日常对话和稳定产品没显示就等于没权限
development额外记录注册变化、schema 组装和结果事件插件作者和宿主开发者可以随便改私有 registry
audit固定工具全集,分组改变模型呈现集合并保存快照性能与生态审计一次把所有工具塞给模型

真正的性能结论要看工具可见集合观测与性能实验。当前仓库的离线检查器只比较脱敏 JSON、集合数量和 schema 字节数,不能代替 provider tokenizer、缓存字段、首 token 延迟或模型质量。

把“自进化”先写成实验卡

如果一个项目会自动改 prompt、工具配置、模型、Skill、记忆或压缩策略,不要先问它是否“会自我进化”,先填写下面这张卡:

text
本次改动改了哪一个循环环节:观测、上下文、动作、状态、策略还是评估?
固定的 Harness、模型、Provider、任务集和工具集合是什么?
主指标是什么,护栏指标是什么?
有没有不可见的 holdout 任务,避免只对已看过的样本优化?
是配对 A/B、交错实验,还是只有几个成功案例?
是否记录版本、配置、平台、时间、成本和失败样本?
如果指标变差,怎样自动回滚,谁批准推广?

没有这些信息时,可以说“系统生成了一个候选改动”或“离线样例出现差异”,不能直接说“Agent 已经自我进化”或“效果普遍提升”。小型固定基准可以发现回归;它不能代表所有用户和任务。

一个普通模式的最小例子

换一组更接近真实安装规模的数字(和上文“20 注册、3 呈现”是两个独立例子):假设你装了 10 个插件,共注册 18 个工具,而正在处理的任务只需要“读文件、搜索、查看状态”。一个可维护的普通模式是依次做三件事:不需要的 Bundle 不默认加载;已经加载但不属于当前任务的工具由 agent 作用域排除;剩下 3 个在 native 模式下呈现给模型的工具仍分别走各自的文件、网络或审批策略。这样“18 已注册、3 个可解析、3 个原生呈现、3 个仍可能被拒绝”是正常状态,不是配置失效。

社区生态有六层

典型产物谁负责对外应该怎样称呼
1. 上游核心DSH 源码、官方 Bundle、官方事件和服务上游维护者官方实现
2. 公开扩展ctx.on()ctx.provide()ctx.tools.register()插件作者第三方插件,注明支持版本
3. 组合配置Bundle manifest、cordis.patch.yml、Profile overlay组合包维护者Bundle、配置组合或发行版
4. 协议兼容Hook bridge、旧接口适配器、外部 shell 翻译器bridge 维护者兼容层,不冒称官方实现
5. 源码变体patched build、私有 fork、改过的核心事件fork 或发行版维护者patched fork、发行版或私有扩展
6. 运行时改写私有 registry 改写、模块替换、进程注入、系统配置改写集成或实验维护者非官方运行时补丁或注入器

第 2 层使用公开 API,通常可以按普通插件的生命周期审计。第 5、6 层改变的是宿主或进程本身,必须额外公开基线提交、差异、权限、版本矩阵、回滚和卸载方式。

一个项目可以同时跨越多层。例如它可能先用 Bundle 把 apply(ctx) 装进插件树,再用 Windows 目录链接和私有 Loader 接管模块解析。审计时要拆开两层,不能因为外壳有 manifest,就给整个项目贴上“普通插件”标签。

五问决策卡:我到底在写什么

按顺序回答,不要先看项目自称:

  1. 只调用公开的 Service、Event、Tool API 吗? 是:优先按普通插件设计;否:继续问。
  2. 只是把插件放进 Bundle 或 Profile 吗? 是:这是组合配置层,不是源码 patch;否:继续问。
  3. 只是把外部协议翻译成公开事件吗? 是:这是 Hook bridge 或兼容层;否:继续问。
  4. 是否修改了 DSH 源码、构建产物、私有 registry 或模块缓存? 是:按 patched fork、monkey patch 或运行时补丁审计。
  5. 是否通过进程注入、启动项、Windows 注册表或其他系统机制改写加载? 是:按 OS 级集成或注入器审计,不要包装成普通插件。

“注册表”要特别小心:ctx.tools.register() 是公开工具登记接口;Windows Registry 是操作系统配置。两个词都能翻译成“注册表”,但它们不在同一层,也不共享 DSH 插件生命周期。

普通插件作者和宿主维护者的分界

普通插件作者可以做这些事:

  • 使用公开 Service、Event、Tool API 和 Bundle 入口;
  • 记录自己的注册、执行结果、失败和 dispose;
  • 在宿主提供公开观测接口时导出脱敏快照;
  • 把缺少的扩展点整理成 feature request 或可审阅的 patch。

技术上任何人都能编写读取私有 Map、重建 Loader、替换模块缓存、改构建产物、写 Windows Registry 或向运行中进程注入代码的程序;语言层面做得到;限制在于身份和责任不能被隐瞒。普通插件作者不应为了“让功能出现”而把这些动作藏进普通插件的安装路径。

如果需求确实只能通过这些方式完成,正确做法是改项目身份:维护一份明确的 patched fork 或发行版,公布上游 SHA、补丁范围、权限、失败恢复、回滚和同步策略。

研究本身不受限制;这里要做的是把责任放回真正能观察和维护它的人。插件作者负责自己的模块;宿主维护者负责核心一致性;注入器维护者负责系统级风险和版本脆弱性。对用户的关键是他实际改了哪一层、是否锁定版本、怎么回滚、卸载后是否有残留。

“不改源码也能 Hook”应该怎么写

当需求落在公开事件、服务或工具接口上,可以把它写成普通扩展。例如只记录工具结果时,说明:

text
入口:公开的 tools/result 事件
改变范围:只记录,不替换结果
生命周期:监听器属于当前插件 Fiber,dispose 时撤销
权限:不额外获得文件、网络或子进程权限
证据:固定版本源码、最小插件测试、卸载后无残留监听器

当需求要改变“是否允许执行”时,应改写成 pre-executeguard 的决策说明,并写清拒绝的单调性、审批关系和失败路径。不要把一个观察事件包装成“安全 Hook”。

想看完整的注册、schema、取消、结果和卸载契约,接着读官方工具插件完整契约;想接外部命令,读官方 Hook Bridge 与兼容层

社区项目的十分钟审计卡

发现一个 GitHub 项目后,先复制这张卡,不要直接运行安装脚本:

text
项目与仓库所有者:
固定 commit / tag:
项目自称的身份:官方 / 第三方插件 / bridge / fork / 注入器:
实际入口:公开 API / Bundle / 私有对象 / 进程或系统机制:
默认会注册什么工具?默认对哪些 agent 可解析,最终又怎样呈现?
需要哪些文件、网络、子进程、凭据或系统权限?
是否有 preinstall、postinstall、prepare 或下载脚本?
源码是否修改上游?如果是,基线和差异在哪里?
卸载是否撤销监听器、工具、watcher、连接、子进程和临时文件?
我实际核对了哪些源码、测试、安装日志和清理日志?
仍然没有证明什么?

README、GitHub topic、Release 徽章和包名只能证明“项目这样自我介绍”。要看清一个插件的真实面目,按顺序核五层:读固定源码确认结构,看 Loader 组合确认装载,真实启动一次拿到运行证据,抓 provider 返回确认模型实际收到什么,最后从卸载日志确认生命周期收尾干净。

dsh-super-injector 这样的案例已经在社区生态与扩展边界中拆成 Bundle 外壳和运行时注入两层。读者应该学习它的审计方法,而不是把它当作普通插件安装教程。

现在可以做什么,未来还缺什么

条件现在或以后最值得做的事最小验收证据
只需要网页按 00、01、25 学习;用固定链接阅读;用离线快照练习集合差异页面可达、链接正确、学习记录写出源码事实和未验证项
只需要本仓库扩大高风险索引人工抽查;补最小公开 API 插件工作台固定 commit、源码事实、测试事实、dispose 和清理结果
需要宿主维护者增加脱敏的注册/可见/schema/执行四点快照版本、Profile、agent、脱敏规则、权限、回滚和失败日志
需要模型和 provider做“20 个注册 20 个 native 呈现”对比“20 个注册 3 个 native 呈现”的交错 A/Binput/cached tokens、首 token、总延迟、工具错误、盲评质量和成本
需要仓库管理员复核并补充现有 Issue 模板、给 master 加最小保护、分类依赖告警、维护 Actions 运行时设置截图或 API 结果、原始告警、升级测试和 Pages 回归

最后一行是仓库治理,不是 DSH 运行时证明;依赖告警也不能直接写成 DSH 运行时漏洞。完整优先级和前置关系见后续研究路线

读完后的五个自测

  • [ ] 我能用三层和一条呈现线解释注册、解析、模型呈现和执行允许。
  • [ ] 我知道工具 schema 变多可能增加输入成本,但当前教材没有真实 provider 基准。
  • [ ] 我能区分普通插件、Bundle、Hook bridge、patched fork 和注入器。
  • [ ] 我知道“侵入式”可以研究,但不能伪装成普通插件并把宿主责任藏起来。
  • [ ] 我能从一个社区仓库写出固定 commit、入口、权限、卸载和仍未验证项。

如果这五项中有两项说不清,回到工具可见性与非侵入扩展;如果已经说清,继续做工具可见集合观测与性能实验的离线练习,再决定是否需要真实模型。

本篇的证据边界

本篇能证明的是术语、设计层次、公开扩展路线和研究方法;它不能证明某个社区项目当前仍安全、某个注入器一定可卸载、某个工具集合一定让所有模型变快,或上游最新提交仍与固定版本一致。

任何运行结论都要补上命令、平台、输入、输出、版本、时间和清理记录。没有这些记录,就把结论写成“源码支持”“项目自述”或“静态检查发现”,不要写成“已经运行验证”。