Files
deepseek-harness/packages/client/resources/README.zh.md
T

5.2 KiB
Raw Blame History

description, kind
description kind
客户端资源模型:按协议注册的提供方把 URL 地址变成活数据,任何 slot 组件都通过 useResource 标准 hook 读取。 package-reference

@deepseek-ai/dsh-client-resources

English | 中文

概述

当组件只知道活数据的 URL 地址,而数据由另一个客户端包拥有时,请使用客户端资源;例如 tab 记录、链接或提及。资源地址使用 dsh-resource://<type>/…;需要作用域的协议把作用域编进路径。组件通过公开的 useResource hook 接收当前值与后续更新。不支持的协议与非资源 scheme(例如 sidebar://guide)不指向任何资源。

目录


使用本包

挂载无需任何配置:插件提供 ctx.resources,并通过 ctx.slots.provideRoot 贡献 resource 根 keyed hook,因此每个 slot 组件不论作用域都能收到它。

读取资源

每个 slot 组件都在 props 上收到 useResourceuseResource<P>(address) 以类型参数命名协议,返回 { status, value, failure }:地址协议没有提供方(或地址不是 dsh-resource:// URL)时为 none,提供方尚未产出值时为 loadinglive 携带最新一个 ok 帧的值,failed 表示最新一帧报告了失败,失败放在最后一个值旁。通过 hook 订阅就是钉住资源的方式;另一个持有者让资源保持存活时,新挂载的组件立刻读到最新值。

提供协议

协议所属的客户端包在 ResourceProtocolMap 声明其值类型,并以自有 effect 注册一个提供方。open 产出 RemoteResult 帧:先是当前内容,之后每次变化一帧,失败以 ok: false 帧而非抛错表达;必须在 signal 中止时停止:

declare module '@deepseek-ai/dsh-client-ui-slots' {
  interface ResourceProtocolMap { note: NoteView }
}

export const inject = ['resources']

export function apply(ctx) {
  ctx.effect(() => ctx.resources.register<'note'>({
    protocol: 'note',
    async *open(address, { signal }) {
      yield await readNote(address, signal)
      for await (const change of followNote(address, signal)) yield change
    },
  }), 'my-notes: note resource provider')
}

一个协议恰有一个提供方;第二次注册会抛错。提供方注册时若其协议的地址已被持有,则立即开流;提供方 dispose 时结束这些流并让它们回到 none

钉住资源

ctx.resources.pin(address, signal) 在不订阅的情况下让资源保持打开,直到 signal 中止。右侧 Sidebar 在 tab 记录的存续期内钉住每个已打开 tab 的地址,因此切换 tab 卸载正文不会关闭其流,切回时读到最新值。ctx.resources.source(address) 是 hook 背后的裸 observable,供 React 之外的调用方使用。

理解实现

生命周期

每个地址一条记录,持有一个快照 store、一个持有者计数(hook 订阅者加 pin)与运行中流的 AbortController。第一个持有者打开提供方的流;之后的持有者共享它;最后一个持有者释放时中止流并把快照重置为空闲(有提供方为 loading,没有为 none)。记录在页面存续期内保留,使 source() 在 React 渲染到订阅的窗口与 StrictMode 重挂载之间保持引用稳定。

失败

失败是帧而非抛错:提供方产出 { ok: false, error },资源变为 failed 并把该错误放在最后一个值旁;下一个 ok 帧将其清除。自行结束的流保持其最后状态。在中止流的那次释放之后到达的帧都被丢弃,并归还迭代器。提供方流内的抛错是编程错误,不会被捕获。

模型体验

无,因为本包在浏览器插件之间搬运值,不注册任何面向模型的内容。

KV Cache 影响

无;资源流不会组装模型请求。

已知限制与暂缓事项

  • 记录在页面存续期内保留——地址的记录在最后一个持有者离开后仍留在注册表中,只丢弃其状态。内存随读取过的不同地址数增长,而非随读取次数增长。
  • 中止合规由提供方负责——注册表会丢弃已释放的流仍产出的帧,但忽略 signal 的提供方会一直工作到它的下一帧。

开发备注

维护者工作上下文——点击展开

无。

运行时不变式: 不发布伴生入口。提供方归属与持有者计数只有注册表这一个拥有者,没有可供比对的独立运行时来源;注册的 dispose 与打开/关闭生命周期由行为测试断言。