Hook 参考

会话业务与路由在外部管理。useChatRuntime 管一个会话;useChatSessions 复用多个已打开会话。

useChatSessions

参数:adapter 必填且引用稳定;activeSessionId 可选并持续受控;onError、eventAttributes、stallThresholdMs 与单会话 hook 相同。

返回项契约
runtime当前选中会话的 ChatkitRuntime,初始化前、未选择或已释放时为空
actions.open(id)Promise;打开或复用并等待历史初始化,不改变外部选择;已释放则拒绝。历史/连接错误经 onError 报告,不保证已获取完整历史
actions.release(id)boolean;释放指定本地 runtime 和接收资源;不存在返回 false,不删除后端会话,不请求远端取消
store.getSnapshot(){ activeSessionId, openedSessions: readonly { id, status }[] };status 含 idle / running / completed / error / unknown,不包含目录
store.subscribe(listener)订阅资源与运行状态变化,返回退订函数
events汇总全部已打开会话的事件,各自保留 sessionId
errorshook 上没给 onError 时,全部已打开会话的错误从这里出,<Chatkit> / <ChatkitProvider> 订阅后交给自己的 onError
capabilities当前 adapter 的执行能力

切换保留旧 runtime,后台继续执行;直到显式 release、adapter 替换或 hook 卸载才释放。已释放的当前 ID 不会因普通重渲染自动重新打开,可显式 open 或切换 ID。应用负责选择下一个会话以及控制缓存数量;SDK 不内置 LRU 或空闲超时。

新建:应用调用后端 create,更新目录并导航到新 ID。首发前先完成创建;如果先发再导航,用 await chat.actions.open(id) 获取新 runtime,再调用其 actions.send,避免误发到旧会话。

删除:应用调用后端 delete,成功后更新目录、chat.actions.release(id),再决定下一条路由。若需要远端停止,应由后端删除语义或显式取消操作保证。

fork:应用调用后端 fork({ sessionId, messageId }),后端复制上下文并返回新 ID;应用更新目录并导航。SDK 通过 history 读取新会话。复制前端消息不等于后端 fork。单个 session 内的消息树分支切换不在本契约范围内。

useChatRuntime

function useChatRuntime(options: UseChatRuntimeOptions): ChatkitRuntime | undefined;

参数与 useChatSessions 相同,区别是 sessionId 必填,换了就重建运行时。 首次挂载、sessionId 为空,以及切换 sessionId 或适配器时可能返回 undefined,渲染前需要判断。

返回值 ChatkitRuntime:

字段说明
store对话的最新状态:getSnapshot() 返回 { sessionId, messages, sending, history }
actionssend、abort、loadMoreHistory,以及具备对应能力时的 steer、recover、regenerate、edit
updateContent更新已有消息、片段或工具的展示内容,详见本页末尾
events事件来源,<Chatkit> 订阅后转发给 onEvent
errorshook 上没给 onError 时的错误来源,<Chatkit> 订阅后交给自己的 onError
capabilities适配器具备哪些能力

useComposer

function useComposer(): ChatkitComposerApi;
方法返回说明
setText(text)boolean把输入框内容换成一段文字;也可以传 previous => next
insertText(text)boolean在光标处插入文字
getText()string输入框里的纯文字
setContent(content)boolean把输入框内容换成一组富文本节点
insertContent(content)boolean在光标处插入富文本节点
getContent()节点数组输入框里的富文本节点
insertReference({ kind, id, label })boolean在光标处插入一个引用标签
addAttachments(items, options?)Promise<ComposerAddAttachmentsResult>本地文件走上传;稳定资源直接加入;结果逐项说明是否受理
focus()boolean让输入框获得焦点
submit()boolean发送输入框里的内容,等同于点发送按钮

输入框未挂载时,同步写操作返回 false,读取返回空内容;addAttachments() 将每一项放进 rejected,原因为 unavailable。它的 accepted 只表示附件已加入草稿并给出正文位置 ID,本地文件的上传仍是异步流程。submit() 返回 true 只表示已调用输入框的提交动作,不代表消息已被受理或发送成功。

function QuickPrompt() {
  const composer = useComposer();
  return (
    <button
      onClick={() => {
        composer.setText('帮我总结这份文档');
        composer.focus();
      }}
    >
      总结
    </button>
  );
}

useCurrentSession

function useCurrentSession(): ChatkitCurrentSession;
字段类型说明
sessionChatkitSessionView | undefined当前会话;还没有会话时为空

会话的字段见上面的 ChatkitSessionView。

useCurrentRun

function useCurrentRun(): ChatkitRunInfo | undefined;

当前对话最近的一轮;还没有任何一轮时为空。内容没变时返回同一个引用。

字段说明
id这一轮的 id
statusqueued、starting、running、attaching、interrupting、completed、failed、interrupted
phase阶段:idle、sampling、tool、awaiting-external、finalizing
origin来源:local(本地发起)或 remote(远端轮次)
createdAt运行时受理的时刻;历史轮次以恢复的数据为准
startedAt交给适配器的时刻
executionStartedAt首次记录执行产出或活动的时刻,不等于正文绘制时刻
finishedAt结束的时刻
aborted用户是否点了停止
connection可选连接状态:connected / disconnected / recovering,不等同于执行结果
cancellation可选远端取消进度:remote 为 unknown / accepted / confirmed;remoteStatus? 为已知的远端终态
interruptReason可选中断原因
error可选失败原因 { code, message, retryable? }
workItems后端上报的工作项数量 { total, active, failed }
function BusyHint() {
  const run = useCurrentRun();
  return run?.phase === 'tool' ? <span>正在调用工具…</span> : null;
}

useChatkitActions

function useChatkitActions(): ChatkitActions;
方法返回说明
send(input)Promise<boolean>发送一条消息,不经过输入框。input 是一段文字,或完整的发送输入
recover?(runId)Promise<boolean>查询或续接已有轮次,不重新发送输入;需历史或续接能力
abort()Promise<boolean>请求后端停止;true 仅代表受理,等待终态确认
regenerate?(messageId?)Promise<boolean>重新生成;不给 messageId 时针对最后一条回答
edit?(messageId, input)Promise<boolean>编辑某条用户消息后重发
openPanel(id)boolean打开右侧面板;id 交给面板里的内容
closePanel()boolean关闭右侧面板
  • 带 ? 的方法只在后端支持时存在,调用前要判断。
  • 发送类操作的返回值表示是否被受理,不代表回答成功完成。恢复、停止的返回值也不代表远端任务已完成或已取消。面板操作在聊天区未挂载时返回 false。
  • send 同样经过 onSend。
function RetryButton() {
  const { regenerate } = useChatkitActions();
  return regenerate ? <button onClick={() => regenerate()}>换一个回答</button> : null;
}

SessionList

<SessionList sessions={items} activeSessionId={activeSessionId} onSelect={setActiveSessionId} style={{ width: 260 }} />

会话列表组件,和 <Chatkit> 分开摆放。属性:sessions、activeSessionId?、onSelect、onCreate?、onRename?、onRemove?、onLoadMore?、loading?、hasMore?、itemActions?、itemBadge?、header?、footer?、locale?、onError?、className?、style?,说明见会话列表。

ChatkitProvider

<ChatkitProvider sessions={sessions}>
  <PageHeader />
  <SessionList />
  <Chatkit />
</ChatkitProvider>

让公开 hooks 和内置功能组件在聊天区之外也能用。

属性说明
sessions / runtime选择一种接入方式;都不给时抛错
其余与 <Chatkit> 的 props 相同
children页面内容;里面的 <Chatkit /> 可以不写任何 props
  • 里面的 <Chatkit /> 从 Provider 取全部 props,自己写了的优先。
  • Provider 下的 hooks 与聊天区里的 hooks 操作的是同一个输入框、同一个面板。
  • 例子见调整内置功能。

说明

  • 适配器必须是稳定引用(模块级或 useMemo)。onError、eventAttributes 可以写内联函数,不会导致重建。
  • 两个建立运行时的 hook 在 React 18 / 19 的 StrictMode 下可以正常使用。修改 stallThresholdMs 会重建运行时;它不是无损的动态阈值开关。
  • 运行时跟着这两个 hook 所在的组件:组件卸载时释放。没给适配器 history 时,要保留对话就把 hook 写在不会卸载的上层组件里,或者隐藏而不是移除对话界面,见会话与历史从哪来。
  • 类型都从 @volcengine/chatkit 导出:UseChatSessionsOptions、UseChatRuntimeOptions、ChatSessions、ChatkitRuntime、ChatkitComposerApi、ComposerAddAttachmentsOptions、ComposerAddAttachmentsResult、ChatkitCurrentSession、ChatkitActions、SessionListProps、ChatkitRunInfo、ChatkitProviderProps。

消息上下文与语言

  • useMessageContext() 返回当前消息体的 ChatkitRenderMessage;用于消息体内的自定义组件。没有消息上下文时返回 null,应自行兜底。
  • useI18n() 返回 { locale, t, setLocale };应在 <Chatkit> 内部提供的语言上下文中使用,缺少上下文时会抛错。页面统一切换语言优先更新 settings.locale;仅包一层 ChatkitProvider 不会为其外部子组件创建语言上下文。

更新已有内容

useChatRuntime 返回的 runtime.updateContent(change) 接受一个 ContentChange 或只读数组,返回 Promise<ContentUpdateResult>。可更新工具标题、消息/片段 metadata 与业务 data;会话接入使用 sessions.runtime。异步调用必须保存原目标运行时,不能在返回时读新的当前会话。完整签名和错误码见 适配器扩展 API。