mcpField
T
tanstack-ai-vue-skilld

tanstack-ai-vue-skilld

github.com/skilld-dev开发184109 次安装3 周前更新
代码仓库

关于 tanstack-ai-vue-skilld

面向 Vue 3 的 TanStack AI 组合式函数库,用于构建流式聊天和 AI 生成界面。它将无头客户端封装为响应式状态,供 Vue 应用使用。

主要功能

  1. 01响应式流式聊天状态
  2. 02类型化客户端工具执行
  3. 03图像、音频、语音和视频生成
  4. 04结构化输出与转录组合式函数
  5. 05BYOK 与 WebMCP 工具组合式函数

适用场景

  1. 01在 Vue 中构建流式聊天界面
  2. 02为 Vue 应用添加图像或音频生成
  3. 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.md
chat-ui.md
generation-composables.md
use-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)

核心规则

  1. 每个组合式函数都必须在组件 setup 或 effect scope 中运行。通过 onScopeDispose 自动清理;作用域拥有该连接(来源:src/use-chat.ts:259-269)。
  2. 所有响应式状态均为 DeepReadonly<ShallowRef<T>>。在脚本和模板中都使用 .value 读取。切勿重新赋值;请使用返回的方法(setMessages、clear、reset)(来源:src/use-chat.ts:425-457)。
  3. 传入 connection 适配器(例如 fetchServerSentEvents('/api/chat'),此适配器由本包重新导出)或 fetcher。未提供时,生成钩子会抛出 useGeneration requires either a connection or fetcher option(来源:src/use-generation.ts:272-274)。
  4. 每次调用 useChat 都会创建一个 ChatClient。更改 connection(或其他传输标识)需要重新挂载,或更改 key 属性;body、forwardedProps、context 和 queue 会被监听并实时同步(来源:src/types.ts:77-79、src/use-chat.ts:212-230)。
  5. 回调选项(onChunk、onFinish、onError 等)会在调用时通过 options 对象读取,因此响应式或已变更的选项无需重新创建客户端即可生效(来源:src/use-chat.ts:85-91)。
  6. 优先使用 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用于自定义类型的基础组合式函数
useGenerateImageImageGenerateInputImageGenerationResult
useGenerateAudioAudioGenerateInputAudioGenerationResult
useGenerateSpeechSpeechGenerateInputTTSResult
useTranscriptionTranscriptionGenerateInputTranscriptionResult
useSummarizeSummarizeGenerateInputSummarizationResult
useGenerateVideoVideoGenerateInputVideoGenerateResultjobId、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)。

指南:references/chat-ui.md

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。

评论

支持 Markdown