使用TinyRobot常见误区包括:未引入样式文件导致组件无样式;混淆v0.3.x与v0.4API;组件命名遗漏Tr前缀;useTheme在ThemeProvider外调用失效;中文输入法误触发送;ShadowDOM下Teleport挂载失败;SenderCompat模式类型混淆;存储策略不当导致数据超限;SSE流式响应解析错误。
用 TinyRobot 搞 AI 聊天界面,上手确实很快——三个组件加一个工具函数就能跑通 Demo。但真到实际开发,总会碰到一些“代码没报错,但就是不好使”的怪事。这些坑往往不是逻辑问题,而是用法没对——你以为某个 API 是那么用的,其实它需要另一种方式。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
这篇文章汇总了 9 个最常见的 TinyRobot 入门误区,每个都附带具体场景、错误示例和正确方案。如果你刚开始用 TinyRobot,先看完这篇再动手,能帮你省下至少两天的调试时间。
症状:代码写好了,页面渲染了,但气泡没有圆角、没有阴影、没有背景色,Sender 输入框就是一坨光秃秃的 div。看起来就像一堆裸 HTML 元素堆在一起。
原因:TinyRobot 的所有样式(包括布局、颜色、圆角、阴影、CSS 变量)都集中在一个 CSS 文件 @opentiny/tiny-robot/dist/style.css 中。如果你没有引入这个文件,组件只有结构,没有样式。
错误做法:
复制代码// main.ts
import { createApp } from 'vue'
import App from './App.vue'
// 没有引入样式文件!const app = createApp(App)
app.mount('#app')
正确做法:
复制代码// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import '@opentiny/tiny-robot/dist/style.css' // 必须引入!const app = createApp(App)
app.mount('#app')
关键要点:
症状:按照文档写了 responseProvider,但 TypeScript 提示找不到这个参数;或者用了 client 参数,但实际装的是 v0.4 版本。
原因:TinyRobot v0.4 是一次重大升级,useMessage 和 useConversation 的 API 有 Breaking Changes:
client 参数 → v0.4 改为 responseProviderclient → v0.4 改为 useMessageOptions错误做法(混用旧版 API):
复制代码// 这是 v0.3.x 的写法,在 v0.4 中已经不存在 client 参数了
const { messages, sendMessage } = useMessage({
client: myClient, // v0.4 没有 client 了!
})
正确做法(v0.4 API):
复制代码// v0.4 使用 responseProvider
const { messages, sendMessage } = useMessage({
responseProvider: async (requestBody, abortSignal) => {
// 处理请求...
},
})
如果你正在从 v0.3.x 迁移到 v0.4,TinyRobot 提供了 SenderCompat 组件帮助平滑过渡。具体迁移方法请参考官方迁移文档。
关键要点:
pnpm add @opentiny/tiny-robot@0.4.1 或 pnpm add @opentiny/tiny-robot@0.3.3@opentiny/tiny-robot-kit 引入症状:模板中写了 或 ,页面报错 "Component Bubble is not resolved";或者 script 中写了 import Bubble from '@opentiny/tiny-robot',TypeScript 报错找不到。
原因:TinyRobot 所有组件以 Tr 为前缀(Tr = TinyRobot 的缩写)。在 中引入时使用大驼峰命名(TrBubble),在 中使用小写连字符()。这是 Vue 3 的标准命名转换规则。
错误做法:
复制代码
正确做法:
复制代码
组件命名对照表:
| Script 引入名 | 模板使用名 |
|---|---|
| TrBubble | |
| TrSender | |
| TrContainer | |
| TrPrompts | |
| TrWelcome | |
| TrAttachments | |
| TrFeedback | |
| TrHistory | |
| ThemeProvider | |
关键要点:ThemeProvider 是特殊组件,模板中直接用 ,因为它不是 Tr 前缀。
症状:调用了 useTheme() 获取主题控制方法,但 setTheme() 和 toggleColorMode() 不生效,或者 useTheme() 直接返回 false。
原因:useTheme 是依赖注入式的组合式函数,它必须在 ThemeProvider 包裹的组件内部调用。如果在 ThemeProvider 外面的组件调用,就找不到注入的上下文,返回 false。
错误做法:
复制代码
正确做法:
复制代码
复制代码
关键要点:
useTheme() 必须在 ThemeProvider 包裹的子组件中调用症状:使用中文输入法时,打字过程中按 Enter 想选择候选词,结果消息被直接发送出去了。日文、韩文输入法也有同样的问题。
原因:这是 contentEditable 输入框的经典问题。TinyRobot v0.3+ 已经在底层处理了 IME compositionStart/compositionEnd 事件,但如果你自定义了提交逻辑或覆盖了快捷键行为,可能会绕过内置的 IME 保护。
错误做法:
复制代码
正确做法:
复制代码
Sender v0.4 的快捷键配置:
复制代码// v0.4 的 Sender 基于 Tiptap,内置了快捷键控制
// 默认:Enter 发送,Ctrl+Enter / Shift+Enter 插入换行
// IME 输入时 Enter 不会触发发送
关键要点:
@submit 事件,不要手动监听 keydown症状:在 Shadow DOM 环境中使用 TinyRobot,DropdownMenu、Tooltip 等弹出类组件的浮层无法显示,或者浮层挂载到了主文档 body 上而非 Shadow DOM 内部。
原因:TinyRobot 的弹出类组件内部使用了 Teleport 来挂载浮层。默认 Teleport to="body" 会将浮层挂载到主文档的 body 上,但如果你的应用运行在 Shadow DOM 中,浮层就脱离了 Shadow DOM 的样式隔离,导致样式丢失或位置错误。
解决方案:TinyRobot v0.2.11+ 已经支持 Shadow DOM 的 Teleport 兼容性。使用时需要:
Teleport to="body"appendTo 属性需要配置 复制代码
关键要点:
appendTo 属性,可以指定挂载目标症状:从 v0.3.x 迁移到 v0.4 时,使用 SenderCompat 组件,但模板编辑功能的行为不一致——有时候模板内容是字符串,有时候是结构化数据。
原因:SenderCompat 是 v0.4 提供的兼容组件,帮助 v0.3.x 用户平滑过渡。它有两种输入模式:template(模板模式,结构化编辑)和 block(块模式,纯文本)。两者的数据处理方式不同:
错误做法:
复制代码
正确做法:
复制代码
关键要点:
mode 属性决定内容数据格式症状:聊天记录越来越多,突然发现页面刷新后历史消息丢失了一部分,或者 localStorage 报错 "Quota exceeded"。
原因:useConversation 默认使用 LocalStorage 存储策略,而 LocalStorage 的容量限制通常是 5-10MB。对于长对话、多会话的场景,5MB 很容易撑爆。
错误做法:
复制代码// 默认 LocalStorage,大量数据会爆
const { conversations, activeConversation } = useConversation({
useMessageOptions: { responseProvider }
})
正确做法:
根据你的数据量选择合适的存储策略:
复制代码// 大量数据使用 IndexedDB
import { indexedDBStorageStrategyFactory } from '@opentiny/tiny-robot-kit'const { conversations, activeConversation } = useConversation({
useMessageOptions: { responseProvider },
storage: indexedDBStorageStrategyFactory({
dbName: 'my-chat-db',
}),
})
复制代码// 小量数据用 LocalStorage(默认行为)
import { localStorageStrategyFactory } from '@opentiny/tiny-robot-kit'const { conversations, activeConversation } = useConversation({
useMessageOptions: { responseProvider },
storage: localStorageStrategyFactory({
key: 'my-chat-data',
}),
})
复制代码// 需要服务器持久化:自定义存储策略
const customStorage: ConversationStorageStrategy = {
async loadConversations() {
const res = await fetch('/api/conversations')
return res.json()
},
async loadMessages(id: string) {
const res = await fetch(`/api/conversations/${id}/messages`)
return res.json()
},
async sa veConversation(conv: ConversationInfo) {
await fetch('/api/conversations', {
method: 'POST',
body: JSON.stringify(conv)
})
},
async sa veMessages(id: string, messages: ChatMessage[]) {
await fetch(`/api/conversations/${id}/messages`, {
method: 'PUT',
body: JSON.stringify(messages)
})
},
async deleteConversation(id: string) {
await fetch(`/api/conversations/${id}`, { method: 'DELETE' })
},
}
存储策略对比:
| 策略 | 容量 | 性能 | 适用场景 |
|---|---|---|---|
| LocalStorage | 5-10MB | 快 | 少量数据、简单场景 |
| IndexedDB | 无限(磁盘空间) | 中 | 大量数据、长对话历史 |
| 自定义 | 取决后端 | 取决网络 | 服务器持久化、多端同步 |
关键要点:
症状:接入真实 SSE API 后,AI 回复不完整、内容丢失、或者浏览器控制台报 JSON 解析错误。
原因:SSE(Server-Sent Events)的数据格式是 data: {...}nn 的文本流,不能直接用 response.json() 解析。需要用 TinyRobot 提供的 sseStreamToGenerator 工具函数将 fetch 的 Response 转为 AsyncGenerator。
错误做法:
复制代码// 直接用 fetch + json() 处理 SSE 流
async function responseProvider(requestBody: any, abortSignal: AbortSignal) {
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ ...requestBody, stream: true }),
signal: abortSignal,
})
return response.json() // SSE 流不能用 json() 解析!
}
正确做法:
复制代码// 使用 sseStreamToGenerator 处理 SSE 流
import { sseStreamToGenerator } from '@opentiny/tiny-robot-kit'async function responseProvider(requestBody: any, abortSignal: AbortSignal) {
const response = await fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_API_KEY}`,
},
body: JSON.stringify({ ...requestBody, stream: true }),
signal: abortSignal,
}) // sseStreamToGenerator 将 Response 转为 AsyncGenerator
return sseStreamToGenerator(response)
}
非流式 API 不需要 sseStreamToGenerator:
复制代码// 非流式 API:直接返回完整 JSON
async function nonStreamingResponseProvider(requestBody: any, abortSignal: AbortSignal) {
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ ...requestBody, stream: false }),
signal: abortSignal,
})
return response.json() // 非流式可以用 json()
}
SSE 数据格式与 ChatCompletion 的映射:
TinyRobot 的 useMessage 期望 SSE 流的每个 chunk 是 OpenAI 兼容的 ChatCompletion 格式:
复制代码{
"choices": [{
"delta": { "content": "你好" },
"finish_reason": null
}]
}
如果你的后端返回的格式不同(比如自定义的 SSE 格式),需要在 sseStreamToGenerator 之前做格式转换,或者使用 onCompletionChunk 钩子自定义处理逻辑。
关键要点:
sseStreamToGeneratorresponse.json()onCompletionChunk 自定义处理| 坑位 | 症状 | 核心原因 | 一句话解决方案 |
|---|---|---|---|
| 1 | 组件无样式 | 没引入 style.css | import '@opentiny/tiny-robot/dist/style.css' |
| 2 | v0.3/v0.4 API 混用 | 版本 API 不兼容 | 确认版本,用 v0.4 的 responseProvider |
| 3 | 组件名找不到 | Tr 前缀缺失 | 组件用 TrXxx / |
| 4 | useTheme 返回 false | 在 ThemeProvider 外调用 | 在 ThemeProvider 子组件中调用 |
| 5 | IME 输入误发送 | 绕过 Sender 内置 IME 保护 | 用 @submit 事件而非 keydown |
| 6 | Shadow DOM 浮层丢失 | Teleport 挂载位置错误 | 版本 >= 0.2.11,配置 appendTo |
| 7 | SenderCompat 数据格式错 | template/block 混淆 | 根据 mode 选择数据处理方式 |
| 8 | 存储容量爆满 | 默认 LocalStorage 太小 | 大数据用 IndexedDB 或自定义存储 |
| 9 | SSE 流解析错误 | 没用 sseStreamToGenerator | 流式用 sseStreamToGenerator |
记住这 9 个坑位,TinyRobot 入门阶段 99% 的“莫名其妙不工作”问题都能快速定位。如果你遇到了不在列表中的问题,欢迎到 GitHub Issues 反馈,社区会帮你解决。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述