---
url: /chat/chat-threads.md
---
# ChatThreads 会话列表

多会话工作台：左侧会话列表 + 右侧会话区。配合 `useChatSessions` 使用——它给每个会话挂一个独立的 `useChatEngine` 实例，**切走只是不渲染，回答继续流**，切回来内容还在。

> 本页组件在独立包 `@wil-works/evoke-chat` 里，安装与注册见 [Chatbot 对话窗口](/chat/chatbot)顶部说明。

家族既有原则不变：不发请求、不落存储。`transport` 由你注入，持久化由你经 `snapshot()` 取走、经 `initialThreads` 灌回。

## 基础用法

`useChatSessions` 交出的对象直接传给 `EbAiConsole` 的 `sessions`：列表、引擎、发送全接管，未传 `sessions` 时 Console 仍是原来的单栏形态。

## 只列表、自己排布

不想要 Console 那套编排时，`EbChatThreads` 可以单独用；`#item` 插槽整条接管，`itemProps` 用于回落默认渲染（与 `ChatList#message` 同款约定）：

## 持久化

引擎不碰存储，但给足了取与回灌的入口：

```js
// 取走：thread 元数据 + 各自的消息数组
const saved = JSON.stringify(sessions.snapshot())

// 回灌
const sessions = useChatSessions({
  initialThreads: JSON.parse(saved),
  transport,          // (content, attachments, context, { threadId }) => ...
  onChange: (thread, reason) => { /* create / rename / pin / archive / remove / select / update */ },
  onReject: ({ threadId, reason }) => { /* 目前只有 concurrency */ },
})
```

## 并发与重排

* **切走不中断**：每个会话各持一个引擎，切走只是不渲染。代价是可能同时有多个会话在流式，所以有 `maxConcurrentStreaming`（`0` 为不限）；用满时 `send()` 返回 `false` 并走 `onReject({ reason: 'concurrency' })`。
* **列表不会因点击重排**：`updatedAt` 只在真的产生新消息时推进。选中、改名、置顶都不动它——否则用户刚点的条目会在指针底下跳走。

## API

## 未做

* **列表虚拟滚动**：分组标题与虚拟列表本身冲突（要拍平成带 sticky 表头），与其交一个半成品不如先不做；消息列表侧同理。
* 会话分享、多模型并行对比、跨设备同步。
