tanstack-ai-vue-skilld について
TanStack AI を使ったストリーミングチャットや生成機能を構築する Vue 3 向けコンポーザブルライブラリです。ヘッドレスクライアントをリアクティブな状態として扱えます。
主な機能
- 01リアクティブなストリーミングチャット状態
- 02型付きクライアントツールの実行
- 03画像・音声・スピーチ・動画の生成
- 04構造化出力と文字起こし用コンポーザブル
- 05BYOK と WebMCP ツール用コンポーザブル
活用シーン
- 01Vue でストリーミングチャット画面を構築
- 02Vue アプリに画像や音声の生成を追加
- 03WebMCP に実行可能なクライアントツールを登録
インストール
コマンドをコピーしてターミナルで実行します。
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) - ピア依存関係:
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 またはエフェクトスコープ内で実行する必要があります。
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は呼び出しごとに 1 つのChatClientを生成します。connection(またはその他のトランスポートの識別情報)を変更するには、再マウントするかkeyプロパティを変更する必要があります。body、forwardedProps、context、queueは監視され、変更が即時に同期されます(出典:src/types.ts:77-79、src/use-chat.ts:212-230)。- コールバックオプション(
onChunk、onFinish、onErrorなど)は、呼び出し時にオプションオブジェクトを通じて参照されるため、リアクティブなオプションや変更されたオプションは、クライアントを再生成せずに反映されます(出典:src/use-chat.ts:85-91)。 bodyよりforwardedPropsを優先してください。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) を実装して、ここから再エクスポートされる @tanstack/ai-client の clientTools() でラップします。これにより、as const を使わなくても part.name、part.input、part.output が適切な型に絞り込まれます。クライアントツールは自動的に実行されるため、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 ではなく、承認 ID(part.approval.id)です(出典:src/types.ts:193-199)。 - 再読み込み時に何も復元されない:永続化には安定した
threadIdが必要です。指定しない場合、クライアントはマウント後に ID を生成し、チャットは一時的なままとなります(出典:src/use-chat.ts:101-103)。
参考資料
- useChat API:オプション、戻り値の完全な形式、構造化出力、中断、キュー、ライブモード、再開。
- 生成コンポーザブル:
useGenerationと 6 つの特化型フック、onResultによる変換、永続化、useAudioRecorder。 - チャット UI:
/uiサブパス、ファクトリー設定、レンダリングレスコンポーネント、非推奨コンポーネントからの移行。 - BYOK と WebMCP:
/byokサブパス、useByok、useWebMCPTools。