Files
deepseek-harness/.agents/notes/implemented/architecture/2026-07-23-toolview-dissolution.zh.md

4.6 KiB
Raw Blame History

Agent Note: toolview 溶解——工具行即 per-view keyed slot

Status: implemented

English | 中文

范围独立工具环ToolViewRegistry/ctx.toolviews/outlet为何退役、被什么取代。本决策产出的落地态叙述归 Web 客户端架构注;一切现在所运行其上的注册模型归 slot 体系标准 所有。后续的 Client Tool 展示所有权 决策仅取代本篇的 per-view 放置方式Tool 名称分发仍使用 keyed slot而非平行注册表。

Problem

视图环溶解进 slot 体系之后client 侧恰好还剩一套平行注册模型:工具环——一个具名注册表(ctx.toolviews),带自己的 register 文法、自己的 resolve 语义scoped 压 global 的谓词分发)、自己的 subscribe/version 对、自己的 inject 缓存、自己带私有错误边界的渲染出口。其中每一件都是 slot 机器已经拥有之物的第二份实现,而每一项未来能力(行草稿的 store 席位、i18n 注入、跨 bundle 身份都将不得不建两遍或漂移。这条环唯一像样的存在理由是tool 名是运行时开放集,而 SlotMap 是封闭声明表——以任意字符串为键的注册表看似结构上必需。

Decision

工具环作为独立基础设施已消失:工具行是各视图为自己声明的 keyed 子槽client 全域只剩一种注册模型。上述理由是空的——keyed slot 的 key 空间本就运行时开放SlotMap 声明槽、从不声明 keyask-user composer 的 key: 'question' 即先例),开放的 tool 名集合天然适配 entryKey 分发。

本决策最初把 'conversation.chat.toolview' 放在 chat 条目下,由 chat 渲染点逐行分发。后续的 Tool 展示所有权 将该放置方式移入整体 Tool 席位,并让 ui-tool 拥有一个 keyed 'tool.call.toolview' 子 slot。后续决策改变的是展示所有者而非本决策的核心约束Tool 注册继续使用普通 keyed-slot 机制,激活、替换、缓存、错误隔离、版本与 fallback 行为仍归框架所有。

接受的语义变化

四项行为增量是刻意接受而非疏漏。跨视图出场最初采用逐视图注册;后续 Note 记录了为何 root/subcall 编排后来证明由一个 Tool 级展示所有者统一负责是合理的。同 key 重复注册从注册表的 later-wins 静默覆盖变为 loud throw——纪律修正而非损失。会话维分发若行需要归组件内部标配 kit 已带 useSessions),不走注册表谓词——今天没有已落地的会话变体样例。第三方在 registry 级覆盖形态scoped 注册压过 global不复存在真出现的未来需求走 key 命名空间约定或组件内小 resolver永不复活平行注册表。

Alternatives considered

保留独立注册表(原形态)。 拒绝:其多维分发的每一维都有更正确的家——展示所有权归显式声明的子 slot会话维归已持有标配 kit 的组件内部。剩下的只是一份没有任何独有能力的 slot 机器副本。

renderToolView 提进标配 kit、注册表迁入 runtime 包。 拒绝Tool 展示是 Client UI 词汇;上提进 runtime 会把展示概念泄漏进数据对象层,且依然留着两套注册模型。

以订阅 refCount 推导槽声明(首个注册方订阅时隐式声明槽)。拒绝:隐式耦合加去抖复杂度;记为将来真出现多视图 UI 时的备选。

slots.register 之上的薄 registerToolView 门面。 缓建而非拒绝溶解后该门面只剩编译期语法糖slot 名字面量收窄、tool→key 词汇翻译、props 预组合运行时为零。按「enforce at the operation boundary」门面不是强制点保持不建有用的类型组合以导出的 Tool view props 别名兑现。若重复注册仪式今后足以证明其价值,可在不扰动直接注册的前提下补充门面。

Consequences

client 只有一种注册模型;审计谁渲染 Tool 调用就是读 slot register 调用,与其他所有 slot 同一套审计。注册方免费获得框架的错误隔离、inject 缓存与 store 席位——没有能力要建两遍。代价即上文接受的语义变化,主要是重复 key 会 loud failure且第三方无 registry 级覆盖。独立注册方在 ctx.slots.inject 中点名有类型约束的 slot因此依赖关系既显式又能跟随声明替换无需服务顺序约定。