课程总纲 / 阶段 3 · 插件开发
L17

UI 扩展:会话节点与设置卡片

在 Web 界面里加上你自己的界面元素。

预计阅读 25 分钟难度 ★★★★☆概念课为主

一、dsh UI 的分层思想UI Layers

两层,扩展点完全不同——先想清楚要"任何界面都有"还是"内置 Web 界面里的卡片"再动手:

是什么扩展点
通用 UI 层任何界面(终端、自建前端)都能做的渲染监听 session/event 渲染 + agent.followup() 回传输入(L05 见过骨架)
Web Client 层内置 Web 界面里的业务组件注册 ConversationNodeDefinition + 键控渲染器 / 设置卡片

二、通用 UI 层:事件流进、消息出Render from the Log

import type { Context } from '@deepseek-ai/cordis'
import { createUserMessage } from '@deepseek-ai/dsh-llm'
import { SessionId } from '@deepseek-ai/dsh-session'

export const name = 'my-ui'
export const inject = ['agents']

export function apply(ctx: Context) {
  // 出:渲染账本事件(模型流式文本 = assistant/chunk 事件流)
  ctx.on('session/event', (_session, event) => {
    if (event.type === 'assistant/chunk' && event.data.chunk.type === 'text-delta') {
      render(event.data.chunk.text)      // 你的渲染函数(终端/UI/任何东西)
    }
  })
  // 进:用户输入 → followup 送回收件箱
  onUserInput(text => ctx.agents.get(SessionId('client-session'))?.followup(
    createUserMessage({ content: [{ type: 'text', text }], source: { kind: 'user' } })
  ))
}

UI 只是账本的又一个读者(L07 的"一本账处处用"):数据来自事件流,输入走标准收件箱。协议驱动(ACP 等)用同一套机制——UI 和自动化客户端在架构上是同类。

三、Web Client 层:会话节点Conversation Nodes

ConversationNodeDefinition 让你在聊天流里插入自己的业务块(图表、审批单、工单卡片、数据预览),配键控渲染器决定样式。

四、Web Client 层:设置卡片Settings Cards

设置卡片给插件配设置面板——用户在 Settings 页点点点就能改配置,不用打开 YAML。它渲染/编辑的就是 L14 的 Config(schema 驱动表单),配置体验和校验天然一致。

五、写 UI 插件的三条纪律Discipline

  1. 从事件渲染,别另存状态。数据源是 session/event(唯一事实源);自己另存"当前显示什么",迟早和账本打架。
  2. 展示函数保持纯净。回放也要跑它们——禁 I/O、禁时钟、禁读会话状态(L13 硬规则,UI 层同样适用)。
  3. 输入走 followup / steer。用户操作变消息进收件箱交给智能体循环——别旁路直接改状态。
ConversationNode
聊天流里的自定义业务块定义。
键控渲染器
按节点类型键匹配的渲染函数。
followup / steer
向智能体回传消息的正规入口。
✏️ 动手练习
  1. docs/cookbook/adding-a-conversation-node.md,抄下注册一个节点需要的三样东西。
  2. docs/cookbook/adding-a-settings-card.md,确认设置卡片和 Config schema 的关系。
  3. 思考题:终端 UI 和 Web UI 都监听 assistant/chunk,为什么不会重复渲染对方的内容?(各是各的监听器,各自渲染各自的界面。)
📝 自测(点击展开答案)
1. 通用 UI 层和 Web Client 层的扩展点分别是什么?
通用层:session/event 渲染 + followup 输入(任何界面可用)。Web Client 层:ConversationNodeDefinition + 键控渲染器、设置卡片(仅内置 Web 界面)。
2. 为什么说"UI 只是账本的又一个读者"?
数据源全是 session/event 事件流,输入走 followup 进收件箱;UI、回放、遥测、协议客户端都是同一本账的不同读者。
3. 设置卡片和 Config 是什么关系?
设置卡片是 Config 的 schema 驱动表单界面:改的是同一份配置,yaml 手写和表单填写走同一套校验。
权威出处:adding-a-conversation-node.md · adding-a-settings-card.md · extension-cookbook(UI 插件节)