mcpField
A
ai-sdk-ui

ai-sdk-ui

github.com/jezweb開発1.1k517 回インストール3 週間前に更新
リポジトリ

ai-sdk-ui について

ai-sdk-ui は、Vercel AI SDK を使う React 開発者向けの UI スキルです。ストリーミングチャット、ツール承認、構造化出力、移行時のトラブル対応を扱います。

主な機能

  1. 01React のチャット・補完フック
  2. 02ストリーミングと構造化出力
  3. 03ツール呼び出しと承認フロー
  4. 04ファイル添付とメッセージ保存
  5. 05移行ガイドとエラー対処

活用シーン

  1. 01React や Next.js の AI チャット UI 構築
  2. 02ストリーミング応答やツール呼び出しの表示
  3. 03ツール実行前のユーザー承認
  4. 04useChat 連携の問題解決

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jezweb/claude-skills --skill ai-sdk-ui

インストール後、Claude Code で/ai-sdk-uiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
.claude-plugin/
plugin.json
references/
links-to-official-docs.md
nextjs-integration.md
streaming-patterns.md
top-ui-errors.md
use-chat-migration.md
rules/
ai-sdk-ui.md
scripts/
check-versions.sh
templates/
custom-message-renderer.tsx
message-persistence.tsx
nextjs-api-route.ts
nextjs-chat-app-router.tsx
nextjs-chat-pages-router.tsx
package.json
use-chat-attachments.tsx
use-chat-basic.tsx
use-chat-tools.tsx
use-completion-basic.tsx
use-object-streaming.tsx

詳細

AI SDK UI - フロントエンド React フック

Vercel AI SDK v6 を使用した、AI 搭載ユーザーインターフェース向けのフロントエンド React フックです。

バージョン:AI SDK v6.0.42(安定版) フレームワーク:React 18+/19、Next.js 14+/15+ 最終更新日:2026-01-20


AI SDK v6 安定版(2026年1月)

**ステータス:**安定版リリース **最新バージョン:**[email protected]、@ai-sdk/[email protected]、@ai-sdk/[email protected] **移行:**v5 から v6 への破壊的変更は最小限です

v6 の新しい UI 機能

1. メッセージパーツ構造(破壊的変更) v6 では、メッセージの内容は .content ではなく .parts 配列から取得します。

// ❌ v5 (OLD)
{messages.map(m => (
  <div key={m.id}>{m.content}</div>
))}

// ✅ v6 (NEW)
{messages.map(m => (
  <div key={m.id}>
    {m.parts.map((part, i) => {
      if (part.type === 'text') return <span key={i}>{part.text}</span>;
      if (part.type === 'tool-invocation') return <ToolCall key={i} tool={part} />;
      if (part.type === 'file') return <FilePreview key={i} file={part} />;
      return null;
    })}
  </div>
))}

パーツの種類:

  • text - .text プロパティを持つテキストコンテンツ
  • tool-invocation - .toolName、.args、.result を持つツール呼び出し
  • file - .mimeType、.data を持つファイル添付
  • reasoning - モデルの推論(利用可能な場合)
  • source - ソースの引用

3. エージェントとの連携 InferAgentUIMessage<typeof agent> を使った型安全なエージェントとのメッセージング:

import { useChat } from '@ai-sdk/react';
import type { InferAgentUIMessage } from 'ai';
import { myAgent } from './agent';

export default function AgentChat() {
  const { messages, sendMessage } = useChat<InferAgentUIMessage<typeof myAgent>>({
    api: '/api/chat',
  });
  // messages are now type-checked against agent schema
}

4. ツール承認ワークフロー(Human-in-the-Loop) ツールを実行する前にユーザーの確認を求めます。

import { useChat } from '@ai-sdk/react';
import { useState } from 'react';

export default function ChatWithApproval() {
  const { messages, sendMessage, addToolApprovalResponse } = useChat({
    api: '/api/chat',
  });

  const handleApprove = (toolCallId: string) => {
    addToolApprovalResponse({
      toolCallId,
      approved: true,  // or false to deny
    });
  };

  return (
    <div>
      {messages.map(message => (
        <div key={message.id}>
          {message.toolInvocations?.map(tool => (
            tool.state === 'awaiting-approval' && (
              <div key={tool.toolCallId}>
                <p>Approve tool call: {tool.toolName}?</p>
                <button onClick={() => handleApprove(tool.toolCallId)}>
                  Approve
                </button>
                <button onClick={() => addToolApprovalResponse({
                  toolCallId: tool.toolCallId,
                  approved: false
                })}>
                  Deny
                </button>
              </div>
            )
          ))}
        </div>
      ))}
    </div>
  );
}

5. 自動送信機能 承認を処理した後、会話を自動的に続行します。

import { useChat, lastAssistantMessageIsCompleteWithApprovalResponses } from '@ai-sdk/react';

export default function AutoSubmitChat() {
  const { messages, sendMessage } = useChat({
    api: '/api/chat',
    sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
    // Automatically resubmit after all approval responses provided
  });
}

6. チャットでの構造化出力 ツール呼び出しと同時に構造化データを生成します(以前は useObject でのみ利用可能でした)。

import { useChat } from '@ai-sdk/react';
import { z } from 'zod';

const schema = z.object({
  summary: z.string(),
  sentiment: z.enum(['positive', 'neutral', 'negative']),
});

export default function StructuredChat() {
  const { messages, sendMessage } = useChat({
    api: '/api/chat',
    // Server can now stream structured output with chat messages
  });
}

useChat フック - v4 から v5 への破壊的変更

重要:v5 では useChat が入力状態を管理しなくなりました!

v4(旧版 - 使用しないでください):

const { messages, input, handleInputChange, handleSubmit, append } = useChat();

<form onSubmit={handleSubmit}>
  <input value={input} onChange={handleInputChange} />
</form>

v5(新版 - 正しい使用方法):

const { messages, sendMessage } = useChat();
const [input, setInput] = useState('');

<form onSubmit={(e) => {
  e.preventDefault();
  sendMessage({ content: input });
  setInput('');
}}>
  <input value={input} onChange={(e) => setInput(e.target.value)} />
</form>

v5 の変更点の概要:

  1. 入力管理の削除:input、handleInputChange、handleSubmit はなくなりました
  2. append() から sendMessage() へ:メッセージを送信する新しいメソッドです
  3. onResponse の削除:代わりに onFinish を使用します
  4. initialMessages から制御モードへ:完全に制御するには messages プロパティを使用します
  5. maxSteps の削除:サーバー側でのみ処理してください

完全な移行ガイドについては、references/use-chat-migration.md を参照してください。


useAssistant フック(非推奨)

⚠️ 非推奨のお知らせ:useAssistant は AI SDK v5 で非推奨になりました。OpenAI Assistants API v2 は 2026 年 8 月 26 日に提供終了となります。新しいプロジェクトでは、代わりにカスタムのバックエンドロジックと useChat を使用してください。 移行方法については、openai-assistants スキルを参照してください。

UI の状態を自動管理しながら、OpenAI 互換のアシスタント API とやり取りします。

インポート:

import { useAssistant } from '@ai-sdk/react';

基本的な使い方:

'use client';
import { useAssistant } from '@ai-sdk/react';
import { useState, FormEvent } from 'react';

export default function AssistantChat() {
  const { messages, sendMessage, isLoading, error } = useAssistant({
    api: '/api/assistant',
  });
  const [input, setInput] = useState('');

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    sendMessage({ content: input });
    setInput('');
  };

  return (
    <div>
      {messages.map(m => (
        <div key={m.id}>
          <strong>{m.role}:</strong> {m.content}
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          disabled={isLoading}
        />
      </form>
      {error && <div>{error.message}</div>}
    </div>
  );
}

ユースケース:

  • OpenAI Assistant を活用した UI の構築
  • アシスタントのスレッドと実行の管理
  • UI の状態を管理しながらアシスタントの応答をストリーミング
  • ファイル検索やコードインタープリターとの連携

完全な API リファレンスについては、公式ドキュメントを参照してください:https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-assistant


UI でよくあるエラーと解決方法

詳細については、references/top-ui-errors.md を参照してください。簡易リファレンス:

1. useChat でストリームの解析に失敗する

エラー:SyntaxError: Unexpected token in JSON at position X

原因:API ルートが適切なストリーム形式を返していません。

解決方法:

// ✅ CORRECT
return result.toDataStreamResponse();

// ❌ WRONG
return new Response(result.textStream);
2. useChat が応答しない

原因:API ルートが正しくストリーミングしていません。

解決方法:

// App Router - use toDataStreamResponse()
export async function POST(req: Request) {
  const result = streamText({ /* ... */ });
  return result.toDataStreamResponse(); // ✅
}

// Pages Router - use pipeDataStreamToResponse()
export default async function handler(req, res) {
  const result = streamText({ /* ... */ });
  return result.pipeDataStreamToResponse(res); // ✅
}
3. デプロイ後にストリーミングが機能しない

原因:デプロイプラットフォームが応答をバッファリングしています。

解決方法:Vercel はストリーミングを自動検出します。他のプラットフォームでは設定が必要な場合があります。

4. useChat で body の値が古いままになる

原因:body オプションが初回のレンダー時にのみ取得されています。

解決方法:

// ❌ WRONG - body captured once
const { userId } = useUser();
const { messages } = useChat({
  body: { userId },  // Stale!
});

// ✅ CORRECT - use controlled mode
const { userId } = useUser();
const { messages, sendMessage } = useChat();

sendMessage({
  content: input,
  data: { userId },  // Fresh on each send
});
5. React の最大更新深度エラー

原因:useEffect で無限ループが発生しています。

解決方法:

// ❌ WRONG
useEffect(() => {
  saveMessages(messages);
}, [messages, saveMessages]); // saveMessages triggers re-render!

// ✅ CORRECT
useEffect(() => {
  saveMessages(messages);
}, [messages]); // Only depend on messages

よくあるエラーをさらに 13 件(合計 18 件)掲載しています。詳細については、references/top-ui-errors.md を参照してください。


ストリーミングのベストプラクティス

パフォーマンス

より良い UX のため、常にストリーミングを使用してください:

// ✅ GOOD - Streaming (shows tokens as they arrive)
const { messages } = useChat({ api: '/api/chat' });

// ❌ BAD - Non-streaming (user waits for full response)
const response = await fetch('/api/chat', { method: 'POST' });
UX パターン

読み込み状態を表示する:

{isLoading && <div>AI is typing...</div>}

停止ボタンを用意する:

{isLoading && <button onClick={stop}>Stop</button>}

最新のメッセージまで自動スクロールする:

useEffect(() => {
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);

読み込み中は入力を無効にする:

<input disabled={isLoading} />

包括的なベストプラクティスについては、references/streaming-patterns.md を参照してください。


React Strict Mode に関する考慮事項

React Strict Mode では、バグを検出するため、意図的にエフェクトを二重に呼び出します。エフェクト内で useChat または useCompletion を使用する場合(自動再開、初期メッセージなど)は、重複した API 呼び出しやトークンの浪費を防ぐため、二重実行をガードしてください。

問題:

'use client';
import { useChat } from '@ai-sdk/react';
import { useEffect } from 'react';

export default function Chat() {
  const { messages, sendMessage, resumeStream } = useChat({
    api: '/api/chat',
    resume: true,
  });

  useEffect(() => {
    // ❌ Triggers twice in strict mode → two concurrent streams
    sendMessage({ content: 'Hello' });
    // or
    resumeStream();
  }, []);
}

解決策:

// ✅ Use ref to track execution
import { useRef } from 'react';

const hasSentRef = useRef(false);

useEffect(() => {
  if (hasSentRef.current) return;
  hasSentRef.current = true;

  sendMessage({ content: 'Hello' });
}, []);

// For resumeStream specifically:
const hasResumedRef = useRef(false);

useEffect(() => {
  if (!autoResume || hasResumedRef.current || status === 'streaming') return;
  hasResumedRef.current = true;
  resumeStream();
}, [autoResume, resumeStream, status]);

発生する理由: React Strict Mode は、副作用を明らかにするため、エフェクトを二重に呼び出します。SDK は同時リクエストをガードしないため、どちらの呼び出しも個別のストリームを作成し、状態更新を取り合います。

影響: メッセージの重複、トークン使用量の倍増、TypeError: "Cannot read properties of undefined (reading 'state')" を引き起こす競合状態。

出典: GitHub Issue #7891、Issue #6166


このスキルを使用する場合

ai-sdk-ui を使用する場合:
  • React のチャットインターフェースを構築する
  • UI に AI 補完機能を実装する
  • AI の応答をフロントエンドにストリーミングする
  • Next.js の AI アプリケーションを構築する
  • チャットメッセージの状態を処理する
  • UI にツール呼び出しを表示する
  • AI でファイル添付を管理する
  • v4 から v5 に移行する(UI フック)
  • useChat/useCompletion のエラーが発生している
使用しない場合:
  • バックエンドの AI 機能が必要 → ai-sdk-core を使用してください
  • React 以外のフロントエンド(Svelte、Vue)を構築する → 公式ドキュメントを確認してください
  • Generative UI / RSC が必要 → https://ai-sdk.dev/docs/ai-sdk-rsc を参照してください
  • ネイティブアプリを構築する → 別の SDK が必要です
関連スキル:
  • ai-sdk-core - バックエンドのテキスト生成、構造化出力、ツール、エージェント
  • フルスタックの AI アプリケーションには、両方を組み合わせてください

パッケージのバージョン

安定版(v6 - 推奨):

{
  "dependencies": {
    "ai": "^6.0.8",
    "@ai-sdk/react": "^3.0.6",
    "@ai-sdk/openai": "^3.0.2",
    "react": "^18.3.0",
    "zod": "^3.24.2"
  }
}

レガシー版(v5):

{
  "dependencies": {
    "ai": "^5.0.99",
    "@ai-sdk/react": "^1.0.0",
    "@ai-sdk/openai": "^2.0.68"
  }
}

バージョンに関する注意事項:

  • AI SDK v6.0.6(安定版、2026年1月) - 新規プロジェクトに推奨
  • AI SDK v5.x(レガシー) - 引き続きサポートされていますが、新機能は追加されません
  • React 18.3 以降 / React 19 をサポート
  • Next.js 14 以降 / 15 以降を推奨
  • スキーマ検証には Zod 3.24.2 以降

公式ドキュメントへのリンク

コア UI フック:

高度なトピック(リンクのみ):

Next.js との連携:

移行とトラブルシューティング:

Vercel へのデプロイ:


テンプレート

このスキルには、templates/ に以下のテンプレートが含まれています。

  1. use-chat-basic.tsx - 手動入力による基本的なチャット(v5 のパターン)
  2. use-chat-tools.tsx - ツール呼び出し UI のレンダリングに対応したチャット
  3. use-chat-attachments.tsx - ファイル添付のサポート
  4. use-completion-basic.tsx - 基本的なテキスト補完
  5. use-object-streaming.tsx - 構造化データのストリーミング
  6. nextjs-chat-app-router.tsx - Next.js App Router の完全な例
  7. nextjs-chat-pages-router.tsx - Next.js Pages Router の完全な例
  8. nextjs-api-route.ts - App Router と Pages Router の両方に対応する API ルート
  9. message-persistence.tsx - チャット履歴の保存と読み込み
  10. custom-message-renderer.tsx - Markdown に対応したカスタムメッセージコンポーネント
  11. package.json - 依存関係のテンプレート

参考ドキュメント

references/ を参照してください。

  • use-chat-migration.md - v4 から v5 への完全な移行ガイド
  • streaming-patterns.md - UI ストリーミングのベストプラクティス
  • top-ui-errors.md - よくある UI エラー 18 件と解決策
  • nextjs-integration.md - Next.js のセットアップパターン
  • links-to-official-docs.md - 公式ドキュメントへのリンク集

本番環境でのテスト済み:WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev) 最終確認日:2026-01-20 | スキルのバージョン:3.1.0 | 変更点:AI SDK v6.0.42 に更新(+19 件のパッチ)。React Strict Mode のセクションを追加。Issue #7(stale body)に回避策を 3 件追加。新たな問題を 6 件追加:resume+onFinish での TypeError(#13)、concurrent sendMessage による state の破損(#14)、tool approval callback のエッジケース(#15)、早期停止時の ZodError(#16)、convertToModelMessages の tool approval バグ(#17)、undefined id による無限ループ(#18)。エラー数:12→18。

コメント