5.1 KiB
@deepseek-ai/dsh-client-ui-conversation
English | 中文
ui-conversation 拥有与 target 无关的 Conversation 组装和共享浏览器 shell。它消费 Session Controller event feed,通过 ctx.uiConversation 暴露不依赖 React 的 registry 与逐 Session binding,并通过 ctx.uiSession 提供 useConversation、useInput 和 inputActions 标准 props。Chat 等具体 target 位于独立 package,由各自 package 注册 Definition、snapshot builder、View 和 renderer。
Conversation 组装
UiConversation.events 是 event Definition 的唯一 registry,UiConversation.views 是 target snapshot builder 的唯一 registry。两者都拒绝重复 key、保持注册顺序、返回幂等 disposer,并在 contribution roster 变化时重建现有 binding。UiConversation.binding(bindingOrSessionId) 为当前 Session Controller binding 返回 identity 稳定的 Conversation binding,不会另开 event source。
adapter 将每个 SessionEventEntry 转换成 { event, view? } 形式的 ConversationEventInput:原始 Session event 保持不变,仅在 envelope-level tool view 存在时携带 view。连续 revision 的 append 和 prepend 使用增量组装;replace window 或 revision 断档从完整已加载窗口重建。assembler 拥有 Context 匹配、Turn/Step location、target node 物化、target activity 和稳定 target source。ConversationSnapshot 只包含与 target 无关的 View 与 active-target 事实;Session lifecycle 状态仍属于 SessionSnapshot。
target package 通过 declaration merge 扩展 snapshot 与 Location data map,再调用 ctx.uiConversation.events.register(...) 和 ctx.uiConversation.views.register(...)。target 通过 ctx.uiConversation.binding(binding).target(targetId) 读取其 Session-owned source。注册属于 Cordis effect,返回的 disposer 从同一个 registry 移除 contribution。
Shell 与标准 props
本包注册 optional-Session conversation shell、strict Session header/body、View list、composer chain 与 bar、输入区域、Hero 区域、queue dock、草稿持久化和 phase 计算。ctx.uiSession.provide() 从同一个 Session binding 物化 Conversation 与 input source,并将 inputActions 作为稳定标准 prop 提供。
View 选择规则固定:有效且已注册的持久化选择优先,其次是已注册的 chat,否则不渲染 View;绝不选择第一个已注册 View。Shell phase 只组合 Session lifecycle 与 active-target set,不读取任何 target-specific snapshot。
常驻 composer 在无 Session 与有 Session 之间保持挂载。无 Session 时,同一个 textarea 保持 inert,Workspace picker 连接 blank Session;草稿文本镜像到逐 Session Conversation store。Queue 操作通过 scoped ctx.conversation service 寻址准确的 queue occurrence。繁忙时 Enter 行为保存在 Host-backed ui-conversation settings namespace。
临时 composer entry
conversation.composer 是通用 chain,其完整 owner currency 为:
/** Owner values used to elect a composer takeover. */
interface ComposerChainProps {
/** Current Session identity used by temporary business-owned entries. */
sessionId: SessionId | undefined
/** Current Session lifecycle state, absent without a selected Session. */
session: SessionSnapshot | undefined
/** Effective business-owned interaction awaiting the user in this Session. */
pendingInteraction: SessionPendingInteraction | undefined
}
业务 package 可仅在一个 Remote waterfall request pending 期间安装 entry:
import type { ComposerChainProps } from '@deepseek-ai/dsh-client-ui-conversation/client'
import type { ChainSelect, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
import type { SessionId } from '@deepseek-ai/dsh-session/types'
interface Request {
readonly sessionId: SessionId
}
type RequestComposerProps =
PropsRuntime<'conversation.composer'> & { matched: Request }
const select: ChainSelect<ComposerChainProps, Request> = owner =>
owner.sessionId === request.sessionId ? request : null
const dispose = ctx.slots.register(
{ name: 'conversation.composer', select },
RequestComposer,
)
try {
return await request.result
} finally {
dispose()
}
selector 必须是 owner currency 的纯函数。非 null 返回值作为 matched 传给组件;PropsRuntime<'conversation.composer'> 提供标准 Session 与 global props。Chain 顺序仍按 priority 升序,再按注册顺序;首个返回非 null 的 selector 获选。Shell 会在 takeover 下保持默认 composer 挂载。Request 状态、listener、response encoding 和任何 request-specific child slot 都属于业务 package,不进入 SessionSnapshot,也不由 core package 声明。
模型体验
无,因为本包渲染浏览器状态,并通过 Session Controller API 发送用户确认提交的输入,而不构造模型请求。
KV Cache 影响
无;Conversation 组装和浏览器输入状态不会改变提供方侧的 prompt cache。
已知限制与暂缓事项
- 只有已注册 target 可以渲染——除已注册的
chat偏好外,shell 刻意不提供隐式 fallback target。