# DeepSeek Harness 源码核查与接入决策 ## 1. 核查范围、版本与证据 本项目先读取官方仓库,再选择插件接入点。源码核查日期为 **2026-10-18**;仓库地址仍为 [deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness),默认开发分支为 `master`。本报告所有源码链接固定到提交 **`687f282e8625c6b8d11ff58211a90524be2e4317`**,避免上游移动后改变论据。 该快照中 Harness 相关包的版本为 **`0.2.1-rc.2`**,Cordis 为 **`4.0.5`**,当前逻辑 Session 格式为 **V4**。项目仍处于开发者预览阶段;不能把可用的公开接口称为已经承诺长期兼容的稳定 API。因此本插件的 `engines.dsh` 和共享实例相关 peer dependency 都锁定已核查版本。源码快照与 npm 版本是两种证据:本报告不假定相同版本号意味着 npm 构建与任意后续 `master` 提交逐字相同,实际兼容性由发布包上的构建、注册和运行测试进一步核验。 Host 注册测试实际安装并使用 `@deepseek-ai/cordis@4.0.5`、`@deepseek-ai/dsh-tools@0.2.1-rc.2`、`@deepseek-ai/dsh-system-prompt@0.2.1-rc.2`、`@deepseek-ai/dsh-scope@0.2.1-rc.2` 和 `@deepseek-ai/dsh-util-values@0.2.1-rc.2`,配置与文档校验使用 `zod@4.4.3`。测试不是把相似接口写成一个本地 mock 后自行证明兼容;具体依赖树由 `package-lock.json` 固定。 依据:[官方 README](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/README.md)、[工具包 manifest](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/package.json)、[Cordis manifest](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/vendor/cordis/package.json)、[Session 类型与版本](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/session/src/types.ts)。 本次工作不修改官方源码、Agent Loop 或 Session 格式。源码的 `AGENTS.md`、架构文档、工具编写文档及其对应实现都已读取;接口结论优先以实现和实际测试为准。 ## 2. 插件安装和加载机制 Harness 使用 Cordis 插件树。一个 Host 插件可以是导出 `name`、`inject`、`Config`、`apply(ctx, config)` 的 ESM 模块。`inject` 表示服务依赖,Cordis 在依赖可用之后激活插件。`Config` 必须实现同步 Standard Schema;Cordis 实际调用 `Config['~standard'].validate(config)`,不是把一个普通 JSON 对象当成运行时校验器。本插件使用 Zod 4 的 Standard Schema 实现。 插件内的 `ctx.tools.register()` 和 `ctx.systemPrompt.section()` 已经使用 Cordis effect 管理注册;卸载所属 fiber 会撤销贡献,无需另写一个全局注册表或操作主程序代码。 一个能够独立安装、启用和移除的发行包还要声明 **bundle**,而不只是提供一个 JS 文件: ```json { "dsh": { "bundle": { "patch": "./cordis.patch.yml" } } } ``` 对应 patch 插入本插件的 Host 行。用户通过 `dsh plugin --profile web add <包或本地目录>` 安装,profile 的 bundle 列表决定插件配置层的组合顺序。`dsh --profile web --dump-config` 可以在启动前查看最终配置。移除使用 `dsh plugin --profile web remove dsh-plugin-intelligent-ui`;已有 Plugin Manager 界面也管理 bundle 的启用状态。是否立即热更新取决于该 profile 是否启用 HMR,不能将安装成功等同于当前进程已经激活成功。 配置层顺序为 profile 的 bundles、profile patch、home patch、命令行 `--patch`。用户配置和权限策略仍可覆盖插件默认行为。 依据:[插件发布教程](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/docs/user/develop/basic/publish.md)、[Cordis 配置校验实现](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/vendor/cordis/src/fiber.ts)、[Plugin Manager](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/boot/plugin-manager/README.md)。 ## 3. 可扩展接口清单 | 能力 | 已核实接口 / 所属源码 | 本插件的使用方式与边界 | |---|---|---| | Host 工具 | `defineTool()`、`ctx.tools.register()`,`packages/core/tools/src/index.ts` 与 `schema.ts` | 注册 `intelligent_ui`,由 Harness 正常呈现为模型工具。 | | 规划指引 | `ctx.systemPrompt.section()`,`packages/core/system-prompt/src/index.ts` | 可关闭的规划说明和完整 DSL 参考;不截获每一次用户请求,不用关键词规则强制 UI。 | | 多 Agent 作用域 | `createScope()`、`bindScopeParent()`、`ScopedLayers`,`packages/core/scope/src` | 全局注册由子作用域继承;保留 allow/deny 过滤和局部覆盖。 | | Client 包发现 | `dsh.client` 与 `exports['./client']`,`packages/client/modules/src/index.ts` | Host Loader 发现包之后纳入浏览器模块图。 | | 原生工具视图 | `ctx.slots.inject()`、`ctx.slots.register()`,`packages/client/ui-slots` | 等待所属 slot 存在,再按工具名注册渲染组件。 | | 工具进度与回执 | keyed slot `tool.call.toolview`,`packages/client/ui-tool/src/client/contract/slots.ts` | key 为 `intelligent_ui`,保留原有调用记录,显示生成进度、错误和成功回执。 | | 持续可见的聊天 UI | `ctx.uiConversation.events.register(ConversationNodeDefinition)`,`packages/client/ui-conversation/src/client/contract/conversation.ts` | 从成功结果 metadata 派生独立节点;无需改变 Session 事件格式。 | | 聊天节点渲染与分组 | keyed slot `conversation.chat.node`;`ChatNode.groupTree`,`packages/client/ui-chat/src/client/contract` | key 为 `intelligent-ui`,`groupTree: 'turn'` 使完整界面位于过程折叠区之外。 | | 历史 UI 数据 | `output.presentationMeta()` → `tool/result.data.meta` | 在工具结果事件中保存经过验证的完整 DSL。 | | PTC 子工具结果 | `tool/ptc-dispatch-start`、`tool/ptc-dispatch` | 元数据同样随子调用结果落盘;Client 复用工具结果节点。 | | 工具权限 | `tools/pre-execute`、monotonic guards、`tools/execute`、`tools/post-execute` | UI生成、stream和P1目标均走正常流水线;bridge传递实际parent/rootCallId。 | | 用户确认 | `ctx.approval.request()` 和 `approval/request` | P1写入动作在真实打开的Agent turn中申请审批;缺少服务或上下文不默认允许。 | | Session 流 | `session/event`,Session Controller `page` / `follow` | 完整结果和P2每步checkpoint复用传输、分页和恢复。 | | 后续 Agent 输入 | Host `SessionController.prompt`、Client `SessionFace.prompt` | P1通过正式scoped Host Remote保留动作,再用Host prompt进入正常Agent turn。 | | 正式Host Remote | `TypertRemoteService`、`@Remote`、实际invocation principal与resources | `intelligentUi/reserve/get/cancel/list/catalog`声明并检查Session资源,不信任Client自报主体。 | | Remote贡献加载 | Host typert-loader;Client `remote.$mount` | 提供`./typert`和`./remote`export;Host自动发现,Client显式mount后再inject自己的namespace。 | | 持久化扩展 | `defineDomain`、`domainTable`、`ctx.storageDomain.open` | 保存动作账本和stream状态;每次写入显式校验、快照和冻结。 | 上述接口真实存在,但它们分属 Host、Client、模型和持久化边界,不能互换。尤其不能把 Host `presentResult()` 当作 Web React 组件注册 API。 ## 4. Host 工具协议:新版 canonical output 是必要条件 当前 `ToolDefinition` 的必需输出声明为 `output.schema` 和 `output.render`;`output.presentationMeta` 可选。`execute(args, exec)` 只返回符合输出 Schema 的 **canonical JSON value**。以前常见的“工具直接返回 `{content, meta}`”写法不符合本次核查版本。 本插件输出: ```json { "protocol": "dsh.intelligent-ui", "version": "1.0", "document": { "version": "1.0", "id": "...", "mode": "interactive_ui", "title": "...", "state": {}, "derived": {}, "root": {} } } ``` 上面的 `document` 缩略示意不构成有效组件;完整有效样例见项目 `examples/`。实际实现先运行完整 `parseDocument()`,并按配置检查 UTF-8 字节数,然后构造 envelope。`output.render` 返回简短回执;`output.presentationMeta` 生成同一 envelope,并再次验证可能经策略替换的文档。 **canonical `value` 不会自动保存到 Session。** `ToolExecutionSuccess.value` 的源码注释和类型明确把它限定为执行期间的数据。历史 UI 必须通过 `presentationMeta` 进入 durable `tool/result.meta`。这是选择现有工具结果作为接入点的关键原因。 `ctx.tools.register()` 借用可信的工具定义;`schemas()` 只向模型传递允许的工具字段。execute、输出投影函数和 Host 回调不会作为工具 Schema 暴露给模型。本插件也不读取 `exec.agent` 的隐藏上下文、环境变量、凭据或文件。 依据:[工具运行时与输出类型](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/index.ts)、[defineTool 实现](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/schema.ts)、[Agent Loop 持久化 call/result](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/agent-loop/src/tool-calls.ts)。 ### 4.1 为什么工具参数没有直接使用递归 `$ref` Harness 内建的工具 Schema DSL 是受限子集,允许 `type`、`oneOf`、`properties`、`required`、布尔值 `additionalProperties`、`items`、标量 `enum` / `const` 和少量注释字段。它不支持 `$ref`、`$defs`、`minimum`、`maxLength` 等完整 JSON Schema 关键字;未知关键字会被拒绝,而不是自动得到验证。 因此插件在工具入口使用 `document: { type: 'json', required: true }`。模型依然提交结构化对象,不必嵌套序列化字符串。递归组件、表达式、值范围、引用完整性和资源限制由共享 `parseDocument()` 严格验证。工具的隐式参数根在 Harness 中是开放对象,本插件执行体额外拒绝 `document` 以外的参数。 发行包同时提供独立的完整 JSON Schema,供编辑器、第三方生产者和测试使用。JSON Schema 验证与跨节点语义检查是两个层次;单独运行前者不能替代 `parseDocument()` 对重复 ID、状态引用、依赖环等关系的检查。 直接注册原始 `ToolDefinition.parameters` 可以绕过 `defineTool` 的输入 DSL 编译,但不能据此承诺所有下游模型和 PTC SDK 都支持任意递归 Schema。本项目避免依赖这个不必要的兼容性假设。 依据:[实际支持的关键字和拒绝规则](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/json-schema.ts)。 ### 4.2 规划不是固定模板,也不是选择正确性的保证 全局 `systemPrompt.section()` 与工具描述向 Agent 提供三类呈现方式及完整 DSL。Agent 自行选择:简单事实通常直接文字回答;结构比较可以使用表格、卡片或图表;需要探索参数时可生成输入、滑块、局部计算和结果。 此实现没有按关键词选择某张完整页面,没有额外的模型请求,也没有修改 Agent Loop。它提供的是模型规划指引和经过验证的执行能力,不保证任意模型对任意提示都选择最优界面。确定性的 mock 验证覆盖接口链路;真实模型的呈现质量需要使用目标模型另外评估。 全局工具和提示章节会被 Agent / preset 作用域继承。`tools.allow` / `deny` 仍可隐藏本工具;插件的提示提供函数发现工具不可见时返回空文本。若部署使用完整替换的 system prompt,它可以抑制本插件章节;插件不会绕过这种部署选择。 依据:[作用域链](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/scope/src/index.ts)、[工具可见性与限制](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/index.ts)、[全局/作用域提示合并](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/system-prompt/src/index.ts)。 ## 5. Client 接入、消息生命周期与错误隔离 Web Client 使用 React 和自己的 slots / renderer 系统。一个包通过 `dsh.client.platform: 'web'`、依赖边 `dsh.client.inject`、以及构建好的 `./client` export 被纳入现有 Client Modules 图。插件脚本由 `/plugins` 载入;Client Modules 使用 lazy CJS 工厂协议,不能把未经该协议包装的任意 ESM 文件当成原生客户端产物。 本项目使用两个相互配合的官方扩展点。`tool.call.toolview` 的 `intelligent_ui` key 负责生成中状态、失败提示和完成回执。成功后的完整界面使用 `ctx.uiConversation.events.register()` 注册的 `ConversationNodeDefinition` 派生,再通过 `conversation.chat.node` 的 `intelligent-ui` key 渲染。普通工具、普通文本和原始调用记录继续使用原有机制。`ctx.slots.inject()` 的作用是等待 slot 声明;如果直接向尚未声明的 slot 注册,上游会在加载时报错。 仅把可交互界面放在工具视图里会受到工具过程自动折叠的影响:Agent 完成回复后,用户可能需要重新展开执行详情才看见计算器。上游公开的 `ChatNode.groupTree` 提供直接解决办法:`'turn'` 表示节点属于当前 Turn,但位于该 Turn 的过程 disclosure 外面。本插件设置这个位置,使完成的 UI 保持在对话正文中,无需篡改聊天组件或强制整个过程区永远展开。 完整结果本身就是一份自包含的 `start` 事件来源:节点以 tool call 身份关联结果,不要求原始 `tool/call` 也恰好在当前分页窗口里。定义不会返回 `exclusive: true`,因此原生工具 reducer 仍可处理同一个结果,保留调用与回执供检查。完整交互树只在独立聊天节点中创建一个状态所有者,成功的工具回执不会再创建第二份滑块和表单状态。注册、节点渲染、样式和 locale 都跟随 Cordis 生命周期撤销。 当前真实 `ToolCallViewProps` 是阶段联合:`preparing`、`start`、`result`。已完成阶段的 `block` 为 `ToolResultNode`,包含 `meta`、`isError`、内容和调用身份。模型生成参数尚未结束的 `preparing` 阶段不等于一份可执行/可交互的有效文档。P0 等待已完成、已验证的 metadata,再由 Client 重新运行文档验证并渲染。 Web Client 不使用 Host 的 `presentCall()` / `presentResult()` 选择 React 视图。其 conversation node reducer 从原始 Session `tool/call` 和 `tool/result` 组装节点,`meta` 被保留给 renderer。本插件的独立节点也只读这些结果事件,不追加一份重复的持久化 UI 日志,也不将 Host 实现导入浏览器。 渲染失败必须限制在对应工具卡片内。未知协议版本、损坏 metadata、失败的工具结果都需要可见的降级,不得使整条对话崩溃。模型只能选择白名单组件和属性;不能传入任意 `onClick`、HTML、CSS、URL、React props 或函数。 依据:[Client Modules 的发现与协议](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/docs/subsystems/client-modules.md)、[工具视图阶段与 slot 类型](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-tool/src/client/contract/slots.ts)、[ConversationNodeDefinition 合约](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-conversation/src/client/contract/conversation.ts)、[事件定义注册及撤销](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-conversation/src/client/conversation/event-registry.ts)、[同一事件的非排他投影](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-conversation/src/client/conversation/assembler.ts)、[Chat 分组位置语义](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-chat/src/client/contract/group-tree.ts)、[工具节点 reducer](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-chat/src/client/conversation-nodes/tool.ts)。 ## 6. Session、PTC 与持久化边界 Harness Session 是追加事件日志。Agent Loop 在模型工具请求之后记录 `tool/call`,运行工具流水线,再记录带 `surfaceOp` / `sourceEventSeqs` 关联的 `tool/result`。后者引用工具调用的事件序号;不需要本插件再发明一个聊天消息容器。 本插件的完整文档保存在结果 metadata 中。刷新和重新打开历史会话时,现有 Session Controller 的 `page` / `follow`、conversation event assembler 和 keyed chat renderer 可以重新获得文档。复用的不是临时内存内的一份页面对象,而是当前或恢复后 Session 的原始结果数据。结果自包含的节点定义也避免把 UI 可恢复性绑定到原始工具调用是否位于当前历史分页窗口。 **结构持久化和可变状态持久化必须分开说明。** metadata 保存生成完成时的文档及初始 state。用户后续改变的浏览器状态由 Client 层按其实际实现管理;它不是 Host Session 事件,不意味着其他设备会共享,也不能充当执行外部操作的审计记录。恢复文档只创建/恢复显示状态,不自动触发按钮、表单、Agent 或工具。 默认 base profile 的工具呈现模式为 native。PTC preset 将模型可直接调用的工具集合折叠为 `run_code`,但工具通过该 SDK 的子调用仍进入相同权限流水线。当前源码的 `ToolRuntime.createSuccessResult()` 会为子调用计算 `presentationMeta`;`ptc.ts` 将其复制到 `tool/ptc-dispatch.meta`,Client 的子结果 reducer 再保留它。上游 cookbook 有一处“nested Code dispatch 跳过 projector”的描述与当前实现不同;本项目依据实际实现与类型,不能依据该一句话丢弃 PTC metadata。没有执行过完整 PTC 场景时,也不能把源码可达性描述成该场景已经验证通过。 PTC 完成事件与 native 的 `tool/result` 不同,因此不能仅凭工具视图的复用声称独立聊天节点会自动出现。插件的 PTC 节点匹配必须显式识别 `tool/ptc-dispatch`、本工具名称、成功状态和 metadata 协议,并以 `subCallId` 作为子调用身份。相应官方 assembler 回放 fixture 与完整 PTC Agent 执行是两个不同验证层次,实际完成情况以测试报告为准。 外部插件自定义 Session 事件还涉及 V4 的已知事件目录、兼容性、迁移和 reader 行为。源码提供 `appendPluginRecord()`,但其说明将它界定为实验性、可忽略记录,并对本仓库生产调用位置有约束;它不是本项目 P0 所需的持久化捷径。复用已存在的 `tool/result.meta` 避免新增 Session 格式。 依据:[Session 类型](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/session/src/types.ts)、[Session 事件/实验记录实现](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/session/src/index.ts)、[PTC 事件类型](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/types.ts)、[PTC 子调用结果记录](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/ptc.ts)。 ## 7. 权限边界与0.2.0外部动作 DSL1.0继续只接受set/reset。0.2.0的DSL1.1添加声明动作字典,Button/Form可以invoke声明ID;工具目标由可信配置映射,模型不能直接提供toolName、主体或确认标志。未知action或`confirm: true`不会授予权限。 P1实际调用`ctx.tools.execute`并传递所属Agent、signal、parent token和rootCallId;不会从registry取定义后直接调用execute。可信capability限制目标,真实参数Schema与运行前后权限仍有效。 正常执行序列包含 pre-policy、不可逆放宽的 monotonic guards、around-dispatch、post-policy 和 final result notification。`tools/pre-execute` 可以返回 allow、deny、cancel 或 ask。ask 由真实 `approval` 服务完成;缺少服务、缺少所属 Agent、没有回答通道或用户拒绝都不允许执行。`approval/asked` 和 `approval/decided` 是现有日志事实。 **`ctx.tools.execute()`本身不负责追加普通tool/call与tool/result,ApprovalService还要求打开的Agent turn。** 因此空闲UI RPC不能直接获得完整审批与日志生命周期。0.2.0使用正式Remote保留动作,再调用SessionController.prompt,模型在真实turn中调用intelligent_ui_action;bridge校验保留身份并执行目标。Session保留bridge调用与审批,操作账本额外记录实际目标、参数摘要、状态与公开结果。 bridge通常增加一次模型请求,简单本地交互不增加请求。callback也作为明确的用户后续请求入队,accepted仅指入队成功。SessionController的requestId去重不能代替外部效果幂等,插件另外使用持久化账本并对重启后的不确定执行保留unknown,不自动重跑。 依据:[工具流水线与 serviceAsk](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/core/tools/src/index.ts)、[审批事件与结果类型](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/interaction/user-approval/src/types.ts)、[Client SessionFace](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/api/session-controller/src/client/contract/session.ts)、[请求入队去重](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/api/session-controller/src/commands.ts)。 ## 8. Streaming 与测试结论的界限 上游已有实时agent/assistant-stream与durable Session事件。P0仍等待完整合法文档;P2另外实现open/patch/complete/cancel,每次合法组件变更形成完整checkpoint,通过正常工具结果逐步展示。没有将不完整模型参数当作可执行节点。 P2协议包含sourceCallId、uiId、generation、seq、baseRevision、revision、type与完整snapshot;Host持久化状态并拒绝重复调用身份、错误基线和旧epoch。Client用同一conversation context ID聚合,官方assembler不会每次重新start,稳定React key保留状态。完整链路已使用实际Harness和指定真实模型测试;样本与边界见VALIDATION。 Host 单元测试使用实际 npm Cordis、SystemPrompt、ToolRuntime 与 scope primitive,不用伪造 `ctx` 来宣称插件兼容。它们验证注册/卸载、Schema 拒绝、metadata、取消、真实权限 waterfall 和作用域限制;完整 Web 测试另由启动脚本运行。 官方还提供无 API key 的 `startMockLlmServer()`,可脚本化输出 `tool_call_success` 和后续文本,供真实 DeepSeek adapter / Agent Loop / Web 页面验证。其返回的 `baseURL` **不包含 `/v1`**,传给 `DEEPSEEK_BASE_URL` 时要追加 `/v1`。测试使用明确的假 token,只访问本机回环地址。另一种官方方式是 `LlmAdapter` 测试插件或 `dsh-llm-replay`;Web 模型选择还需要该 adapter 广告模型目录。 本报告区分源码结论、确定性基础设施验收与真实模型验收。0.2.0已使用用户授权的deepseek-v4.1-flash执行完整Harness测试,但少量样本不代表全部自然语言任务的成功率。首次无效DSL与模型修复情况同样记录。 依据:[架构中的事件与流](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/docs/architecture.md)、[官方 mock server](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/test-support/llm-mock-server/src/index.ts)、[官方无 Key adapter fixture](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/test-support/loader-smoke/tests/fixtures/cli-mock-llm.ts)、[LLM replay 文档](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/test-support/llm-replay/README.md)。 ## 9. 独立安全审查与具体回归要求 实现完成后另行逐项阅读了文档预检、Zod Schema、受限表达式、状态更新和全部组件渲染路径。审查不是只检查是否存在 `eval` 字符串:输入的资源边界、控件共享同一状态时的约束、恢复时的状态保留也会影响安全与可靠性。下面三项问题在修复前通过运行代码复现,而不是假设性的风险。 | 修复前问题 | 可复现条件 | 必须保留的回归断言 | |---|---|---| | Host 接受、Client 拒绝的文档预算不一致 | 一份含 64 个 Text 叶节点的合法文档为 262,100 UTF-8 bytes;固定 envelope 将其增加到 262,161 bytes。Client 若对整个 envelope 套用 262,144 bytes 的文档预算,会拒绝 Host 已接受的 UI。 | envelope 只做固定外层的严格 own-property descriptor 检查;文档单独经过 `parseDocument()`。近上限合法文档必须渲染,未知外层字段和 getter 必须拒绝,getter 调用次数为零。 | | 多控件共享状态时的值域不一致 | 数值 state 的范围为 0–100,Slider 的范围收窄到 0–20,另一个 NumberInput 或按钮可写入 50,产生滑块显示与实际计算值不一致;`step: 1` 也曾接受 10.5。Select 同样可能被另一输入或 action 写入未声明选项。 | 初始值、直接输入、本地 set、恢复值都遵守统一的有效控件约束;数值约束只定义在 state,控件 props 只能省略或精确重复。step 以 min / 0 为基点处理浮点误差;Select 约束所有写入源,多个 Select 共享字段时必须使用同一选项值集合。 | | 多字段编辑超过总预算后静默清空 | 23 个字符串字段均允许 4,096 字符。前 22 项填入 `界` 重复 4,096 次曾全部成功,状态达到 270,626 bytes;再编辑另一项时,旧实现的 `restoreState()` 因总预算失败返回默认值,悄悄清空此前输入。 | 候选状态超过总预算时原子拒绝该次写入并保留既有有效字段,或者采用明确的独立状态预算;不能接受一份状态后在下一次普通编辑时无提示地重置全部字段。 | 另外检查了未知本地事件的防御性拒绝、损坏 metadata 的降级、派生值除零后的恢复、默认表达式错误、嵌套深度、重复 ID、原型污染键、非 JSON 对象、getter / `toJSON`、Markdown 中的 HTML / 图片 / 链接,以及未知组件与外部 action。具体修复与执行结果以相应自动化测试和项目测试报告为准;这里列出可持续验证的条件,避免后续升级时失去这些边界。 这三项缺陷已修复并复核。审查者重新运行 `npx vitest run tests/host.test.ts tests/shared.test.ts`,得到 **70 / 70 通过**(Host 11 项、shared 59 项)。额外直接运行原先的边界输入,确认 262,100 bytes 的文档通过 Client envelope 解析;中文大字段的第 22 次超限写入抛出错误,第 23 个字段的小编辑仍保留先前全部 21 个有效大字段。数值域、step、Select 和恢复状态的回归包含在 shared 测试中。Client DOM 与官方 conversation assembler 的测试属于单独测试文件,执行数量以最终测试报告为准。 上述三项是P0发现并保留的回归。0.2.0安全结论为:**不执行模型生成的代码;外部工具动作只通过明确手势、可信Host能力和Harness权限/审批执行。** 这不是对整个Harness和所有依赖不存在动态模块加载或Function的断言。可信插件程序加载与不可信UI数据有不同边界。 ## 10. P1/P2补充核查与实际决策 ### 正式Remote而非无主体的命令捷径 命令注册并不保证处理函数自动得到网络调用主体。当前Gateway为正式Remote调用建立invocation Context;@Remote的resources可绑定Session,remoteAccess进一步检查principal。插件使用TypertRemoteService,并在每个方法再次从真实Context取主体。真实Gateway + Peer + strict TYPERT测试覆盖拒绝/允许,Client也通过实际Gateway验证响应decode,而非仅手写fetch对象。 第三方Remote不会被api-remotes的内置固定贡献列表自动加入。插件提供公开./remote贡献,在Client显式$mount,再在子inject中等待本namespace。Host通过./typert export由官方Loader注册,避免重复注册。官方generator含monorepo布局假设;插件使用官方纯createTypertRemoteInfo组装严格贡献,并用真正Loader/Gateway回归其兼容性。 依据:[Remote协议](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/typert/protocol/src/index.ts)、[Host registry](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/typert/registry/src/index.ts)、[Loader](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/typert/loader/src/index.ts)、[Remote access](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/api/remote-access/src/index.ts)。 ### storage-domain并不代替每次写入校验 正式domain API可用于独立持久化,但table.put/update并非每次都按Zod自动验证。插件在写入前显式做descriptor检查、严格解析、快照与冻结。内部账本/stream元数据与模型document分别限制预算,避免扩大DSL限制或把内部记录上限错误传给公共解析器。 依据:[Storage domain服务](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/storage/storage-domain/src/index.ts)、[Domain实现](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/storage/storage-domain/src/domain.ts)。 ### 调用身份、卸载与验证范围 ToolRuntime不会自行按callId去重;Agent Loop也可能保存同callId的多份结果。插件因此给stream保留全代调用身份,并对静态UI同来源却不同文档的歧义安全拒绝。callId是关联线索,不是单独的授权或幂等保证。 所有服务和Client贡献绑定Cordis生命周期。原生PluginManager的application字段说明Host配置是否applied,完整热启停仍须验证Client模块图和effect回收;不能只看到开关变化便声称两端已卸载。相关实际验收与限制见VALIDATION,而不从API名称推测完成。