资讯详情

资讯详情

DeepSeek Harness 逐预设常驻挂载:基于作用域父链让每个 preset 每进程只组装一次

DeepSeek Harness 逐预设常驻挂载基于作用域父链让每个 preset 每进程只组装一次【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness导读在 DeepSeek Harnessdsh中一个进程可以同时服务多个会话而每个会话的 agent 由一份 preset一个存放agent.cordis.yml的目录决定其工具、人设、提示词段落与委派后端。本文剖析 2026-08-08 落地的一项关键架构决策preset 从按会话挂载改为每进程常驻挂载——一个 preset 在进程生命周期内只组装一次所有命名它的 agent 通过把自己的 scope key 绑定到常驻挂载的 key 上加入。读完本文你将理解为什么按会话挂载会打破三个宿主读取方的静态假设、dsh-scope的作用域父链如何同时承载注册视图继承与事件向上分发两个方向以及常驻挂载在selfCtx、文件 stamp 代际、peek()不看链、ScopeParentBinding重链等承重细节上的取舍。一、问题按会话挂载 preset 让静态注册这个隐含前提破裂在逐预设常驻挂载之前的方案见 2026-08-03 会话 agent 由 preset 组装的设计 note中preset 是按会话挂载的agent 工厂的setup(agentCtx)把 preset 作为 Cordisinclude子树挂到该 agent 的 scope 上下文下注册随 agent 卸载。这套方案让面向模型的注册视图变成了按 agent的——每个会话看到的是自己那份组装。问题在于进程里有三个独立的宿主读取方它们仍然假设这个注册视图是静态的、不需要任何 agent 就能解析的。按会话挂载让这三个读取方逐个失效读取方按会话挂载后的失效表现冷读session.history找不到 presenter每张工具卡都静默退化成通用渲染器——这与工具本来就没有 presenter无法区分投影块projections block丢掉 preset 注册的键客户端把缺失键当作能力不存在并清掉那一行Typert 网关在宿主根上解析goals得到service-unavailable逐个给读取方打补丁只是拿一种静默降级换另一种例如为了拿到 presenter 而 resume 会话会把投影折叠从 detached 翻到 livetoken 计数随之被抹掉——修好了渲染弄坏了投影与计费。二、决策一个 preset 是每进程一份组装而不是每会话一份核心决策用一句话概括一个 preset 是每进程一份组装而不是每会话一份。roster名单服务在一个合成的常驻 scope 下把它挂载一次每个 agent 通过把自己的 scope key 绑定到挂载的 key 上bindScopeParent(agentKey, standingKey)加入。这一决策修的是这一类问题而非其中个例读取方需要的注册在进程生命周期内始终存在按 preset id 索引不需要任何 agent。全部承载落在dsh-scope的两条机制上实现见 packages/core/scope/src/index.ts注册视图沿父链解析agent → preset → global近者遮蔽远者。ScopedLayers.merge()在解析注册时沿 scope 链合并一个子 scope 能看到其所有祖先的层。带作用域的分发只向上放行监听器以载体键的祖先为标签时被放行——只向上兄弟 preset 的监听器保持失聪。事件永远沿链向上流动绝不向下。2.1 源码证据bindScopeParent与 scope 父链dsh-scope用一张WeakMapScopeKey, ScopeKey存父链一条关系驱动两个方向packages/core/scope/src/index.ts/** 绑定 parent 作为 key 的上级 scope仅一次。 */ export function bindScopeParent(key: ScopeKey, parent: ScopeKey): ScopeParentBinding { if (scopeParents.has(key)) { throw new Error(dsh-scope: scope key is already bound to a parent; re-linking requires the binding returned by the original bind) } linkScopeParent(key, parent) // 带环检测 return { rebind(next) { linkScopeParent(key, next) } } } /** 从 key 到根祖先的完整链近者优先[key, parent, grandparent, …] */ export function scopeChainOf(key: ScopeKey | undefined): ScopeKey[] { … }注意linkScopeParent会做环检测cursor key即抛错因为每个链消费者都要沿父链走到根。而scopeTarget(base, key)构造的载体carrier在过滤监听器时先保留基过滤器的判定再看调用方上下文的 scope tag——tag 是分派 key 本身或其祖先则放行packages/core/scope/src/index.ts。三、常驻挂载的实现roster 的ensureStanding与 agent 加入3.1 单飞single-flight的常驻挂载roster 服务AgentPresetspackages/preset/agent-presets/src/index.ts维护一张standing: Mapstring, PromiseStandingMount按 preset id 单飞两个 agent 竞争同一个 preset 的首次使用时共享一份组装一次失败的挂载会被移除后续会话在文件被修复后可重试packages/preset/agent-presets/src/index.ts。private async ensureStanding(preset: AgentPreset): PromiseStandingMount { const pending this.standing.get(preset.id) if (pending ! undefined) { const mounted await pending const current await compositionStamp(preset.path) // mtime size if (current undefined || sameStamp(mounted.stamp, current)) return mounted if (this.standing.get(preset.id) pending) this.standing.delete(preset.id) return this.ensureStanding(preset) // 开启下一代际 } const created (async () { const key: ScopeKey { agentPreset: preset.id } const scope createScope(this.selfCtx, key) // 挂在 selfCtx 上见 5.1 const stamp await compositionStamp(preset.path) await mountPreset(scope.ctx, preset) return { key, scope, stamp } })() this.standing.set(preset.id, created) return created }关键点常驻 scope 的 key 是{ agentPreset: preset.id }——纯数据对象不引用任何 agentscope 挂在 roster 自己的selfCtx上因此它不属于任何会话只随整树卸载whole-tree teardown回收。3.2 agent 加入的三条路径mount(agentCtx, id)agent 工厂setup(agentCtx)的唯一受支持调用点。先ensureStanding再bindScopeParent(agentKey, standing.key)并把绑定存进bindings: WeakMapScopeKey, ScopeParentBinding。之所以必须在setup里做是因为只有在那里 agent 尚未发布一次被拒绝的组装会让整个创建回滚packages/preset/agent-presets/src/index.ts。composeFrom(agentCtx, parentCtx)子 agentsubagent加入父 agent 所在的同一个常驻组装。它是一次 bind 而非 mount子 agent 拿到的是父 agent 的代际——相同的插件对象、相同的工具注册、相同的提示词段落。同步执行、无自己的失败模式因此子 agent 创建窗口可以使用它packages/preset/agent-presets/src/index.ts。recompose(agentCtx, id)空白会话切换 preset。走bindings.get(agentKey)返回的ScopeParentBinding.rebind(standing.key)并发出tools/change让 scope 分层的工具视图重新对齐packages/preset/agent-presets/src/index.ts。3.3 从任意 agent 反查常驻挂载standingMountFor(agentCtx)packages/preset/agent-presets/src/mount.ts不沿 fiber 向上走——常驻挂载不在agent 的 fiber 之下——而是读scopeOf(agentCtx)再scopeParentOf(agentKey)然后在livePresetMounts()里按 key 匹配。livePresetMounts()会先剪枝prunefiberuid已清空的记录避免死记录把整棵已 dispose 的子树保留在内存里packages/preset/agent-presets/src/mount.ts。四、为什么它便宜状态本就按 Session/Agent 分键常驻挂载之所以不是每会话一份的性能回归核心在于有状态的 preset 插件早于 preset 就存在而且本来就是按Session/Agent分键存状态的plan-mode、token-meter、compaction-basic在 preset 出现之前就以会话/agent 为键管理状态。共享一份实例是回归其设计不是改写。以standardpreset 为例packages/preset/agent-presets/presets/standard/agent.cordis.ymlplan-mode、compaction-basic、tool-result-pruner等都放在带isolaterealm 的cordis:group行内而tokenMeter刻意留在宿主平面——它按 Session 键控每个 fold且投影单元是浏览器为每个会话读取的若放进 realm这些单元会随挂载的 preset 来来去去。4.1jobs-local完全离开 preset 平面jobs-local同样具备按 agent 分键的性质并已彻底离开preset 平面realm 之外的生产方tool-bash、tool-terminal、非 continuable 的tool-subagent以ctx.get解析该注册表而 entry-local realm 对它们不可见因此它组合在宿主平面只有面向模型的tool-jobs行仍留在各 preset 中见 standard/agent.cordis.yml 中 background jobs 一节的注释。4.2 preset yml 不变每 preset 一个 Entry、一个 entry-local realm决策不要求任何 preset 文件改动每 preset 挂一次 每 preset 一个 Entry其 entry 本地 realmisolate: name: true让两个 preset 的同名服务互不相干正如它从前隔开两个会话。在 standard/agent.cordis.yml 里planMode、compaction、delegation等组都携带isolate声明- id: planning name: cordis:group group: true isolate: planMode: true config: - id: plan-mode name: deepseek-ai/dsh-plan-mode4.3 共享 realm label 不是选项一个被否掉的优化是让多个 preset 共享同一个 realm label。源码明确说明了为什么不行provide()对同一 realm 符号下的第二次注册直接抛错——label 池化的是 REALM 而非实例。在按会话挂载的世界里共享 label会让第二次挂载崩溃。这正是 standard/agent.cordis.yml 头部注释所强调的labels join REALMS, and are not what this file needs。五、承重细节四个必须理解的实现约束5.1 常驻挂载挂在服务未追踪的selfCtx上经 traceable 代理调用的方法看到的this.ctx被重绑到调用方并携带 shadow从它派生的子树里每个 fiber 的 reflect 解析都从 shadow 的 fiber 起步entry 会在自己inject声明的服务上失败cannot get property tools without inject尽管它自己的 store 里明明有。因此常驻挂载必须挂在未追踪的原始上下文上——roster 构造时保存this.selfCtx ctxpackages/preset/agent-presets/src/index.ts。jobs-local的selfCtx先例如今有了第二个消费者。5.2 挂载一旦成功即持续供职直到组装文件 stamp 变化运行中的会话加入的组装必须在其文件被修改或删除后继续存活。实现上每个代际记录文件 stampmtimeMs size见 packages/preset/agent-presets/src/index.ts会话发现当前代际已陈旧时开启下一个代际。文件编辑——在创作改为仅复制copy-only之后文件是唯一的组装编辑器——无需任何创作调用丢弃指针即可到达后续会话。已加入的会话保持其代际被替代的代际只由整树卸载回收。这是刻意为之成本上限取决于编辑频率而非会话数并已记入包文档的 Known Limitationspackages/preset/agent-presets/README.md。一个已知的 TODO 是被替代的代际目前无法回收缺少 JoinedAgent 计数dsh-skill-filesystem的 watcher 会随之存活到进程结束。5.3peek()保持不看链限制与守卫restrictions guards定位的是单个 scope自己的贡献只有注册视图沿链继承。链上的限制求交——链上任一 scope 都可以为嵌套其内的一切遮蔽某个全局注册名称。也就是说继承是视图层面的安全相关的限制不会被父链传染。5.4 重新认父只能经由挂载首绑返回的ScopeParentBindingbindScopeParent返回的绑定句柄是 dsh-scope 中唯一的重链能力rebind见 packages/core/scope/src/index.ts。roster 私藏该句柄bindings: WeakMapScopeKey, ScopeParentBinding因此空白会话 recompose 是唯一的重链路径其他调用方无法挪动已组合的 agent。重链的合法性以旧父之下产出的东西一概不被保留为前提该前提由持有方保证——因为这条父链关系看不见会话日志。六、考虑过的替代方案设计文档明确记录了三个被否掉的方案及其代价原文见 2026-08-08 逐预设常驻挂载 note替代方案为何被否冷读时 resume抹掉 detached 投影token 计数被清宿主面 presenter 表 投影块完整性标志只修两个读取方留下这一类问题每会话模板挂载为了服务纯函数而复制每一份实例另有一条留档结论面向网关的goals域无论如何留在宿主平面——Remote 方法的接收者来自生成的 descriptor、在宿主上解析这正是shell-env宿主平面判据从消费侧读出的样子相关分析见 2026-08-10 宿主平面所有权 note。七、延伸阅读Scope 子系统文档——scope key、载体与分层注册的完整契约deepseek-ai/dsh-scope 包 README——父链与事件过滤的实现细节deepseek-ai/dsh-agent-presets 包 README——名单配置、创作与已知限制2026-08-03 会话 agent 由 preset 组装 note——按会话挂载时代的设计权衡与实测数字standardpreset 组装文件——isolaterealm 与宿主/agent 平面划分的活教材挂载实现mount.ts——挂载审计inactiveRows、leakedServices与write()覆写【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →