DSH / PLUGIN / PLATFORM

dsh-api-remotes

v0.1.0-rc.5deepseek-ai / deepseek-harness47f943859b

DSH 已内置插件运行时与平台内置源码Web UI
运行时构成
HOSTCLIENTUITOOLDATAFLOW

概览

dsh-api-remotes

为本应用选定的 Host Remote 能力提供双侧 BFF。Host 入口负责 Agent/Session 身份策略;Client 入口以运行时值形式导入生成的 /remote 产物,通过 ctx.remote.$mount() 挂载每项贡献,并重新导出对应的声明合并。Client 业务包依赖该外观,而不依赖 Gateway 实现或单独的 Remote 运行时入口。
BUILT-IN / ATOMIC
已随 DSH 提供,无需单独安装

这是 Harness 已内置的原子模块,不是可独立激活的 Profile 层。

能力

它贡献了什么

HostCordis loadableZero-config
Client / UIWeb UI0 contributions
Model tools0None declared
Profile stateenabledweb

README / ZH

插件文档

@deepseek-ai/dsh-api-remotes

English | 中文

为本应用选定的 Host Remote 能力提供双侧 BFF。Host 入口负责 Agent/Session 身份策略;Client 入口以运行时值形式导入生成的 /remote 产物,通过 ctx.remote.$mount() 挂载每项贡献,并重新导出对应的声明合并。Client 业务包依赖该外观,而不依赖 Gateway 实现或单独的 Remote 运行时入口。

createApiRemoteAgentResolver() 会复用 live Agent、恢复普通冷会话、对并发恢复去重、保留 subagent ownership fence,并为 Typert agentsession lookup 配置同一个 resolver。标准 Web API Proxy 提供 Agent 默认值和 scope 设置,再将返回的 resolver 用于旧方法,使已迁移与未迁移方法共用同一份策略实现。

当前 Client 组合挂载 Goal Remote 贡献和只读 Host 插件清单贡献(pluginInventory/list)。该组合卸载时,Cordis effect 的所有权机制会撤回所有贡献;@deepseek-ai/dsh-api-gateway/client 负责描述符校验、可追踪 namespace Service、直接与作用域方法、调用与取消。Client 入口通过 Cordis 消费共享的 TypertClientRemote 接口,不导入具体 Gateway;它只以 type-only 形式重新导出 Gateway Client face 的声明合并,因此消费端经由本外观取到转发事件词汇时,运行时不会多出一条通往 Gateway 实现的边。

本包不包含传输逻辑或 Host 服务发现逻辑。Web 或未来的 TUI 只要提供同一份不依赖 React 的 ctx.remote 约定,均可复用其 Client face。

转发的 Host 事件

src/remote-events.ts 持有 API_REMOTE_FORWARDED_EVENTS——本应用原样转发给消费端的 Host cordis 事件名单(无投影、无脱敏、无改名),它同时就是 ctx.remote.$on 的合法键集;只含类型的 src/types.ts 派生其选择面。多转发一个事件只需在该数组里加一行:类型投影、消费端键面与 Host 转发循环全部由它派生。

监听器签名不在此处重写。名单内每条事件的 cordis Events 声明都住在其 owner 包 client-safe 的 ./types 出口(dsh-agent-presetsdsh-commandsdsh-credentialsdsh-llmdsh-settings),本包两个 face 都把那些声明纳入编译面,因此「原样转发」是构造性成立的,不需要另立证明。Host face 还额外把名单断言给 TypertForwardableEvent:未声明的事件名、绑定 AgentScope 的事件、以及形状不是单向的事件都会在此被拒绝。

构建边界

仓库中的普通包只属于一个 TypeScript face:Host 包登记在根 tsconfig.host.json,Client 包登记在根 tsconfig.client.jsonapi-remotes 是唯一刻意拆分的特例,因为它的 Host 入口要参与 Host Typert 图,而 src/client/index.ts 必须等 Host tsdown 生成业务包的 /remote 声明后才能编译。

本包根 tsconfig.json 只是引用 tsconfig.host.jsontsconfig.client.json 的 solution。Host aggregate 和 Host 直接消费方引用前者,Client aggregate 和 Client 直接消费方引用后者;禁止把包根 solution 放进任一 aggregate 的依赖图。两个 project 拥有互不重叠的源码和 .tsbuildinfo,但共享 lib/types 输出目录——只有一处刻意的例外:src/remote-events.tssrc/types.ts 同时列进两个 face 的 files,因为转发事件名单是「消费端能收到什么」的唯一控制点,Host 转发循环与 Client 的 ctx.remote.$on 键面必须读同一份声明,而不是两份可能彼此漂移的声明。

这条例外不止是一行 files。根 tsconfig.base.json@deepseek-ai/dsh-api-remotes/types 映射到 src/types.ts——源平面,与其余所有 workspace 子路径一致,也与生成的 /remote 产物相反(后者没有 paths 条目,靠 exports 命中构建产物)。于是两个 face 都把同一份名单与类型投影收进各自的 program,并向 lib/types 发射逐字相同的 remote-eventstypes 输出;.tsbuildinfo 仍各自独立。没有任何门禁强制两个 face 的源文件互不重叠——scripts/project-reference-faces.ts 只校验「引用一个 split project 必须指到对应 face」——因此本段记录这次双列为何是有意的。

包内 clientBundle(..., { hostPhase: true }) 让 Host tsdown 打包 Host 入口,让后续 Client tsdown 只打包 browser 入口。普通 Client 插件仍使用单一 Client project,并在 Client tsdown 阶段一起生成 Node loader 入口和 browser bundle;不得因一个包同时存在 src/index.tssrc/client/index.ts 就复制本包的拆分。

模型体验

无,因为该 BFF 只选择 Remote 应用方法和身份策略,不注册任何模型接口。

KV Cache 影响

无直接影响;其触发的任何模型可见行为均由已挂载的 Host 能力负责。

已知限制与暂缓事项

  • 能力集合由构建时显式导入的值固定确定;Client 不会在运行时发现 Host 中已启用的服务或 Remote 定义。
  • 若要增加能力,必须显式导入相应的 /remote 值并在此组合中挂载。
  • 在剩余 BFF 配置迁移到 api-remotes 之前,标准 Web Host 仍从旧 API Proxy 提供恢复默认值与 Agent scope 设置。

LIMITATIONS

已知限制

- 能力集合由构建时显式导入的值固定确定;Client 不会在运行时发现 Host 中已启用的服务或 Remote 定义。 - 若要增加能力,必须显式导入相应的 `/remote` 值并在此组合中挂载。 - 在剩余 BFF 配置迁移到 `api-remotes` 之前,标准 Web Host 仍从旧 API Proxy 提供恢复默认值与 Agent scope 设置。