关于 tanstack-ai-vue-skilld
面向 Vue 3 的 TanStack AI 组合式函数库,用于构建流式聊天和 AI 生成界面。它将无头客户端封装为响应式状态,供 Vue 应用使用。
主要功能
- 01响应式流式聊天状态
- 02类型化客户端工具执行
- 03图像、音频、语音和视频生成
- 04结构化输出与转录组合式函数
- 05BYOK 与 WebMCP 工具组合式函数
适用场景
- 01在 Vue 中构建流式聊天界面
- 02为 Vue 应用添加图像或音频生成
- 03通过 WebMCP 注册可执行客户端工具
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ skilld-dev/ vue-ecosystem-skills --skill tanstack-ai-vue-skilld安装后在 Claude Code 中输入/tanstack-ai-vue-skilld确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/byok-and-webmcp.mdchat-ui.mdgeneration-composables.mduse-chat.md详细介绍
@tanstack/ai-vue
用于 TanStack AI 流式聊天、结构化输出和媒体生成的 Vue 3 组合式函数。将无界面的 @tanstack/ai-client 类(ChatClient、GenerationClient、VideoGenerationClient)封装为响应式状态。
- 文档所述版本:
0.24.3(来源:package.json:3) - Peer 依赖:
vue >=3.5.0、@tanstack/ai ^0.58.0;运行时依赖:@tanstack/ai-client ^0.33.2、@tanstack/markdown ^0.0.13(来源:package.json:55-62) - 入口点:
.(主入口)、./ui(无界面聊天 UI 工厂)、./byok(自带密钥)(来源:package.json:23-36) - 官方文档:https://tanstack.com/ai/latest/docs/api/ai-vue 和 https://tanstack.com/ai/latest/docs/getting-started/quick-start-vue
- 安装:
pnpm add @tanstack/ai @tanstack/ai-vue @tanstack/ai-openai(还需一个提供方适配器;服务端聊天功能来自@tanstack/ai)
核心规则
- 每个组合式函数都必须在组件 setup 或 effect scope 中运行。通过
onScopeDispose自动清理;作用域拥有该连接(来源:src/use-chat.ts:259-269)。 - 所有响应式状态均为
DeepReadonly<ShallowRef<T>>。在脚本和模板中都使用.value读取。切勿重新赋值;请使用返回的方法(setMessages、clear、reset)(来源:src/use-chat.ts:425-457)。 - 传入
connection适配器(例如fetchServerSentEvents('/api/chat'),此适配器由本包重新导出)或fetcher。未提供时,生成钩子会抛出useGeneration requires either a connection or fetcher option(来源:src/use-generation.ts:272-274)。 - 每次调用
useChat都会创建一个ChatClient。更改connection(或其他传输标识)需要重新挂载,或更改key属性;body、forwardedProps、context和queue会被监听并实时同步(来源:src/types.ts:77-79、src/use-chat.ts:212-230)。 - 回调选项(
onChunk、onFinish、onError等)会在调用时通过 options 对象读取,因此响应式或已变更的选项无需重新创建客户端即可生效(来源:src/use-chat.ts:85-91)。 - 优先使用
forwardedProps而不是body;body已弃用,但仍会合并到相同的传输载荷中(来源:src/use-chat.ts:207-209)。
快速入门:流式聊天
服务端(Express 或任何返回 Tanstack AI SSE 的后端):
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
app.post('/api/chat', async (req, res) => {
const stream = chat({ adapter: openaiText('gpt-4o'), messages: req.body.messages })
const response = toServerSentEventsResponse(stream)
// pipe response.body to res
})
客户端组件:
<script setup lang="ts">
import { ref } from 'vue'
import { useChat, fetchServerSentEvents } from '@tanstack/ai-vue'
const input = ref('')
const { messages, sendMessage, isLoading } = useChat({
connection: fetchServerSentEvents('/api/chat'),
})
function handleSubmit() {
if (input.value.trim() && !isLoading.value) {
sendMessage(input.value)
input.value = ''
}
}
</script>
<template>
<div v-for="message in messages.value" :key="message.id">
<div v-for="(part, idx) in message.parts" :key="idx">
<p v-if="part.type === 'text'">{{ part.content }}</p>
</div>
</div>
<form @submit.prevent="handleSubmit">
<input v-model="input" :disabled="isLoading.value" />
<button type="submit">Send</button>
</form>
</template>
来源:官方快速入门,https://tanstack.com/ai/latest/docs/getting-started/quick-start-vue
类型化工具
使用 @tanstack/ai 中的 toolDefinition() 定义工具,在组件中实现 .client(fn),并将其包装在 clientTools() 中(此函数由本包从 @tanstack/ai-client 重新导出),这样 part.name、part.input 和 part.output 无需 as const 即可收窄类型。客户端工具会自动执行;没有 onToolCall 选项。使用 createChatClientOptions 和 InferChatMessages(两者均重新导出)推导消息类型。来源:https://tanstack.com/ai/latest/docs/api/ai-vue
<script setup lang="ts">
import { useChat, fetchServerSentEvents, clientTools } from '@tanstack/ai-vue'
import { updateUIDef } from './tool-definitions'
const updateUI = updateUIDef.client((input) => {
notification.value = input.message
return { success: true }
})
const { messages, sendMessage } = useChat({
connection: fetchServerSentEvents('/api/chat'),
tools: clientTools(updateUI),
})
</script>
共享聊天钩子
createChatHook(options)(根入口)会在模块作用域绑定选项,并返回一个 useChat 组合式函数。每个实例只能覆盖 threadId、live、forwardedProps、body 和 initialMessages;tools、interrupts 和 outputSchema 则保留在工厂选项中。如果与导入的 useChat 冲突,请在调用处重命名(来源:src/create-chat-hook.ts:28-45)。
const { useChat: useAppChat } = createChatHook(chatOptions)
const chat = useAppChat({ threadId: 'support-1' })
生成组合式函数
所有组合式函数都遵循同一模式:传入 connection 或 fetcher,调用 generate(input),读取响应式状态。
| 组合式函数 | 输入类型 | 结果类型 | 其他功能 |
|---|---|---|---|
useGeneration | 自定义 TInput | 自定义 TResult | 用于自定义类型的基础组合式函数 |
useGenerateImage | ImageGenerateInput | ImageGenerationResult | |
useGenerateAudio | AudioGenerateInput | AudioGenerationResult | |
useGenerateSpeech | SpeechGenerateInput | TTSResult | |
useTranscription | TranscriptionGenerateInput | TranscriptionResult | |
useSummarize | SummarizeGenerateInput | SummarizationResult | |
useGenerateVideo | VideoGenerateInput | VideoGenerateResult | jobId、videoStatus、onJobCreated、onStatusUpdate |
通用返回值:generate、result、isLoading、error、status、stop、reset、runId。有关详情、转换和持久化,请参阅:references/generation-composables.md
stop() 只会中止本地流,不会停止提供方已在运行的任务;请使用 runId 调用自己的端点,以取消任务或轮询状态(来源:src/use-generation.ts:124-131)。
聊天 UI(@tanstack/ai-vue/ui)
使用 /ui 子路径中的 createChatHook 构建聊天界面(请勿使用已弃用的预构建组件 Chat、ChatInput、ChatMessage、ChatMessages、ToolApproval;这些组件自 0.3.0 起弃用,并计划在 1.0.0 移除)。该子路径还导出了无渲染的 UIChat、UIProvider、UIMessages、UIMessage、UIPart、UIInterrupts、UIQueue,以及 createChatUI / createChatHookContexts。此子路径以原始 .ts/.vue 源码形式发布,因此会根据你的 tsconfig 进行类型检查(来源:package.json:28-31、src/ui.ts:2-33、src/chat-ui/types.ts:5)。
BYOK 和 WebMCP
useByok(client)会将ByokClient转换为响应式ByokSnapshot;使用/byok子路径中的defineByok、ByokClient、passkeyStorage等构建客户端。密钥通过x-byok-*请求头传递,不会放入请求正文(来源:src/use-byok.ts:5-14、src/use-generation.ts:35-38)。useWebMCPTools([searchProducts])会为当前作用域向 WebMCP 注册可执行的客户端工具;释放时会注销这些工具(来源:src/use-web-mcp-tools.ts:27-55)。
指南:references/byok-and-webmcp.md
故障排除
- 模板中的状态未更新:这些状态是
ShallowRef。在模板中也要使用isLoading.value。 useChat未应用选项更改:每个实例的传输身份(connection、threadId持久化结构)都是固定的。请重新挂载组件,或更改组件的key(来源:src/types.ts:77-79)。- 审批响应被拒绝:
addToolApprovalResponse接收的是审批 ID(part.approval.id),而不是工具调用 ID(来源:src/types.ts:193-199)。 - 重新加载后未恢复任何内容:持久化需要稳定的
threadId;如果未提供,客户端会在挂载后生成一个 ID,聊天内容将仅存在于当前会话中(来源:src/use-chat.ts:101-103)。
参考资料
- useChat API:选项、完整返回结构、结构化输出、中断、队列、实时模式、恢复。
- 生成组合式函数:
useGeneration和六个专用钩子、onResult转换、持久化、useAudioRecorder。 - 聊天 UI:
/ui子路径、工厂配置、无渲染组件、从已弃用组件迁移。 - BYOK 和 WebMCP:
/byok子路径、useByok、useWebMCPTools。