ai-sdk-ui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AI SDK UI - Frontend React Hooks

AI SDK UI - 前端React钩子

Frontend React hooks for AI-powered user interfaces with Vercel AI SDK v6.
Version: AI SDK v6.0.42 (Stable) Framework: React 18+/19, Next.js 14+/15+ Last Updated: 2026-01-20

用于基于Vercel AI SDK v6构建AI驱动用户界面的前端React钩子。
版本: AI SDK v6.0.42(稳定版) 框架: React 18+/19, Next.js 14+/15+ 最后更新: 2026-01-20

AI SDK v6 Stable (January 2026)

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

Status: Stable Release Latest: ai@6.0.42, @ai-sdk/react@3.0.44, @ai-sdk/openai@3.0.7 Migration: Minimal breaking changes from v5 → v6
状态: 稳定发布 最新版本: ai@6.0.42, @ai-sdk/react@3.0.44, @ai-sdk/openai@3.0.7 迁移: 从v5到v6的破坏性变更极少

New UI Features in v6

v6中的新UI功能

1. Message Parts Structure (Breaking Change) In v6, message content is now accessed via
.parts
array instead of
.content
:
tsx
// ❌ 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>
))}
Part Types:
  • text
    - Text content with
    .text
    property
  • tool-invocation
    - Tool calls with
    .toolName
    ,
    .args
    ,
    .result
  • file
    - File attachments with
    .mimeType
    ,
    .data
  • reasoning
    - Model reasoning (when available)
  • source
    - Source citations
3. Agent Integration Type-safe messaging with agents using
InferAgentUIMessage<typeof agent>
:
tsx
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. Tool Approval Workflows (Human-in-the-Loop) Request user confirmation before executing tools:
tsx
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. Auto-Submit Capability Automatically continue conversation after handling approvals:
tsx
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. Structured Output in Chat Generate structured data alongside tool calling (previously only available in
useObject
):
tsx
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
  });
}

1. 消息部件结构(破坏性变更) 在v6中,消息内容现在通过
.parts
数组访问,而非
.content
:
tsx
// ❌ 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. Agent集成 使用
InferAgentUIMessage<typeof agent>
实现与Agent的类型安全消息传递:
tsx
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. 工具审批工作流(人工介入) 在执行工具前请求用户确认:
tsx
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. 自动提交功能 处理审批后自动继续对话:
tsx
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
中可用):
tsx
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 Hook - v4 → v5 Breaking Changes

useChat钩子 - v4 → v5破坏性变更

CRITICAL: useChat no longer manages input state in v5!
v4 (OLD - DON'T USE):
tsx
const { messages, input, handleInputChange, handleSubmit, append } = useChat();

<form onSubmit={handleSubmit}>
  <input value={input} onChange={handleInputChange} />
</form>
v5 (NEW - CORRECT):
tsx
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>
Summary of v5 Changes:
  1. Input management removed:
    input
    ,
    handleInputChange
    ,
    handleSubmit
    no longer exist
  2. append()
    sendMessage()
    : New method for sending messages
  3. onResponse
    removed
    : Use
    onFinish
    instead
  4. initialMessages
    → controlled mode
    : Use
    messages
    prop for full control
  5. maxSteps
    removed
    : Handle on server-side only
See
references/use-chat-migration.md
for complete migration guide.

重要提示: v5中useChat不再管理输入状态!
v4 (OLD - DON'T USE):
tsx
const { messages, input, handleInputChange, handleSubmit, append } = useChat();

<form onSubmit={handleSubmit}>
  <input value={input} onChange={handleInputChange} />
</form>
v5 (NEW - CORRECT):
tsx
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 Hook (Deprecated)

useAssistant钩子(已废弃)

⚠️ Deprecation Notice:
useAssistant
is deprecated as of AI SDK v5. OpenAI Assistants API v2 will sunset on August 26, 2026. For new projects, use
useChat
with custom backend logic instead. See the openai-assistants skill for migration guidance.
Interact with OpenAI-compatible assistant APIs with automatic UI state management.
Import:
tsx
import { useAssistant } from '@ai-sdk/react';
Basic Usage:
tsx
'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>
  );
}
Use Cases:
  • Building OpenAI Assistant-powered UIs
  • Managing assistant threads and runs
  • Streaming assistant responses with UI state management
  • File search and code interpreter integrations
See official docs for complete API reference: https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-assistant

⚠️ 废弃通知: 自AI SDK v5起,
useAssistant
已被废弃。OpenAI Assistants API v2将于2026年8月26日停止服务。对于新项目,请使用
useChat
搭配自定义后端逻辑。迁移指南请查看openai-assistants技能。
与兼容OpenAI的Assistant API交互,自动管理UI状态。
导入:
tsx
import { useAssistant } from '@ai-sdk/react';
基础用法:
tsx
'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
  • 管理Assistant线程与运行
  • 流式传输Assistant响应并管理UI状态
  • 文件搜索与代码解释器集成
完整API参考请查看官方文档: https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-assistant

Top UI Errors & Solutions

常见UI错误与解决方案

See
references/top-ui-errors.md
for complete documentation. Quick reference:
完整文档请查看
references/top-ui-errors.md
。快速参考:

1. useChat Failed to Parse Stream

1. useChat Failed to Parse Stream

Error:
SyntaxError: Unexpected token in JSON at position X
Cause: API route not returning proper stream format.
Solution:
typescript
// ✅ CORRECT
return result.toDataStreamResponse();

// ❌ WRONG
return new Response(result.textStream);
错误:
SyntaxError: Unexpected token in JSON at position X
原因: API路由未返回正确的流格式。
解决方案:
typescript
// ✅ CORRECT
return result.toDataStreamResponse();

// ❌ WRONG
return new Response(result.textStream);

2. useChat No Response

2. useChat无响应

Cause: API route not streaming correctly.
Solution:
typescript
// 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); // ✅
}
原因: API路由未正确流式传输。
解决方案:
typescript
// App Router - 使用toDataStreamResponse()
export async function POST(req: Request) {
  const result = streamText({ /* ... */ });
  return result.toDataStreamResponse(); // ✅
}

// Pages Router - 使用pipeDataStreamToResponse()
export default async function handler(req, res) {
  const result = streamText({ /* ... */ });
  return result.pipeDataStreamToResponse(res); // ✅
}

3. Streaming Not Working When Deployed

3. 部署后流式传输不工作

Cause: Deployment platform buffering responses.
Solution: Vercel auto-detects streaming. Other platforms may need configuration.
原因: 部署平台缓冲响应。
解决方案: Vercel会自动检测流式传输。其他平台可能需要配置。

4. Stale Body Values with useChat

4. useChat中的陈旧Body值

Cause:
body
option captured at first render only.
Solution:
typescript
// ❌ 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
});
原因:
body
选项仅在首次渲染时被捕获。
解决方案:
typescript
// ❌ WRONG - body仅被捕获一次
const { userId } = useUser();
const { messages } = useChat({
  body: { userId },  // Stale!
});

// ✅ CORRECT - 使用受控模式
const { userId } = useUser();
const { messages, sendMessage } = useChat();

sendMessage({
  content: input,
  data: { userId },  // 每次发送时都是最新值
});

5. React Maximum Update Depth

5. React最大更新深度超限

Cause: Infinite loop in useEffect.
Solution:
typescript
// ❌ WRONG
useEffect(() => {
  saveMessages(messages);
}, [messages, saveMessages]); // saveMessages triggers re-render!

// ✅ CORRECT
useEffect(() => {
  saveMessages(messages);
}, [messages]); // Only depend on messages
See
references/top-ui-errors.md
for 13 more common errors (18 total documented).

原因: useEffect中出现无限循环。
解决方案:
typescript
// ❌ WRONG
useEffect(() => {
  saveMessages(messages);
}, [messages, saveMessages]); // saveMessages触发重渲染!

// ✅ CORRECT
useEffect(() => {
  saveMessages(messages);
}, [messages]); // 仅依赖messages
完整的18种常见错误请查看
references/top-ui-errors.md

Streaming Best Practices

流式传输最佳实践

Performance

性能

Always use streaming for better UX:
tsx
// ✅ 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' });
始终使用流式传输以提升用户体验:
tsx
// ✅ GOOD - 流式传输(实时显示生成的内容)
const { messages } = useChat({ api: '/api/chat' });

// ❌ BAD - 非流式传输(用户需等待完整响应)
const response = await fetch('/api/chat', { method: 'POST' });

UX Patterns

UX模式

Show loading states:
tsx
{isLoading && <div>AI is typing...</div>}
Provide stop button:
tsx
{isLoading && <button onClick={stop}>Stop</button>}
Auto-scroll to latest message:
tsx
useEffect(() => {
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
Disable input while loading:
tsx
<input disabled={isLoading} />
See
references/streaming-patterns.md
for comprehensive best practices.

显示加载状态:
tsx
{isLoading && <div>AI正在输入...</div>}
提供停止按钮:
tsx
{isLoading && <button onClick={stop}>Stop</button>}
自动滚动到最新消息:
tsx
useEffect(() => {
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
加载时禁用输入:
tsx
<input disabled={isLoading} />
完整最佳实践请查看
references/streaming-patterns.md

React Strict Mode Considerations

React Strict Mode注意事项

React Strict Mode intentionally double-invokes effects to catch bugs. When using
useChat
or
useCompletion
in effects (auto-resume, initial messages), guard against double execution to prevent duplicate API calls and token waste.
Problem:
tsx
'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();
  }, []);
}
Solution:
tsx
// ✅ 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]);
Why It Happens: React Strict Mode double-invokes effects to surface side effects. The SDK doesn't guard against concurrent requests, so both invocations create separate streams that fight for state updates.
Impact: Duplicate messages, doubled token usage, race conditions causing TypeError: "Cannot read properties of undefined (reading 'state')".

React Strict Mode会故意双重调用effect以捕获bug。当在effect中使用
useChat
useCompletion
时(如自动恢复、初始消息),需防止双重执行以避免重复API调用和令牌浪费。
问题:
tsx
'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(() => {
    // ❌ 在严格模式下触发两次 → 两个并发流
    sendMessage({ content: 'Hello' });
    // or
    resumeStream();
  }, []);
}
解决方案:
tsx
// ✅ 使用ref跟踪执行
import { useRef } from 'react';

const hasSentRef = useRef(false);

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

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

// 针对resumeStream的特定解决方案:
const hasResumedRef = useRef(false);

useEffect(() => {
  if (!autoResume || hasResumedRef.current || status === 'streaming') return;
  hasResumedRef.current = true;
  resumeStream();
}, [autoResume, resumeStream, status]);
原因: React Strict Mode双重调用effect以暴露副作用。SDK不会防范并发请求,因此两次调用会创建独立的流,导致状态更新冲突。
影响: 重复消息、令牌使用翻倍、竞态条件导致TypeError: "Cannot read properties of undefined (reading 'state')"。

When to Use This Skill

何时使用本技能

Use ai-sdk-ui When:

适用场景:

  • Building React chat interfaces
  • Implementing AI completions in UI
  • Streaming AI responses to frontend
  • Building Next.js AI applications
  • Handling chat message state
  • Displaying tool calls in UI
  • Managing file attachments with AI
  • Migrating from v4 to v5 (UI hooks)
  • Encountering useChat/useCompletion errors
  • 构建React聊天界面
  • 在UI中实现AI补全
  • 向前端流式传输AI响应
  • 构建Next.js AI应用
  • 处理聊天消息状态
  • 在UI中显示工具调用
  • 管理与AI相关的文件附件
  • 从v4迁移到v5(UI钩子)
  • 遇到useChat/useCompletion错误

Don't Use When:

不适用场景:

  • Need backend AI functionality → Use ai-sdk-core instead
  • Building non-React frontends (Svelte, Vue) → Check official docs
  • Need Generative UI / RSC → See https://ai-sdk.dev/docs/ai-sdk-rsc
  • Building native apps → Different SDK required
  • 需要后端AI功能 → 改用ai-sdk-core
  • 构建非React前端(Svelte、Vue)→ 查看官方文档
  • 需要生成式UI / RSC → 查看https://ai-sdk.dev/docs/ai-sdk-rsc
  • 构建原生应用 → 需要使用其他SDK

Related Skills:

相关技能:

  • ai-sdk-core - Backend text generation, structured output, tools, agents
  • Compose both for full-stack AI applications

  • ai-sdk-core - 后端文本生成、结构化输出、工具、Agent
  • 结合两者构建全栈AI应用

Package Versions

包版本

Stable (v6 - Recommended):
json
{
  "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"
  }
}
Legacy (v5):
json
{
  "dependencies": {
    "ai": "^5.0.99",
    "@ai-sdk/react": "^1.0.0",
    "@ai-sdk/openai": "^2.0.68"
  }
}
Version Notes:
  • AI SDK v6.0.6 (stable, Jan 2026) - recommended for new projects
  • AI SDK v5.x (legacy) - still supported but not receiving new features
  • React 18.3+ / React 19 supported
  • Next.js 14+/15+ recommended
  • Zod 3.24.2+ for schema validation

稳定版(v6 - 推荐):
json
{
  "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):
json
{
  "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+用于 schema 验证

Links to Official Documentation

官方文档链接

Templates

模板

This skill includes the following templates in
templates/
:
  1. use-chat-basic.tsx - Basic chat with manual input (v5 pattern)
  2. use-chat-tools.tsx - Chat with tool calling UI rendering
  3. use-chat-attachments.tsx - File attachments support
  4. use-completion-basic.tsx - Basic text completion
  5. use-object-streaming.tsx - Streaming structured data
  6. nextjs-chat-app-router.tsx - Next.js App Router complete example
  7. nextjs-chat-pages-router.tsx - Next.js Pages Router complete example
  8. nextjs-api-route.ts - API route for both App and Pages Router
  9. message-persistence.tsx - Save/load chat history
  10. custom-message-renderer.tsx - Custom message components with markdown
  11. package.json - Dependencies template
本技能在
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和Pages Router的API路由
  9. message-persistence.tsx - 保存/加载聊天历史
  10. custom-message-renderer.tsx - 带Markdown的自定义消息组件
  11. package.json - 依赖模板

Reference Documents

参考文档

See
references/
for:
  • use-chat-migration.md - Complete v4→v5 migration guide
  • streaming-patterns.md - UI streaming best practices
  • top-ui-errors.md - 18 common UI errors with solutions
  • nextjs-integration.md - Next.js setup patterns
  • links-to-official-docs.md - Organized links to official docs

Production Tested: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev) Last verified: 2026-01-20 | Skill version: 3.1.0 | Changes: Updated to AI SDK v6.0.42 (+19 patches). Added React Strict Mode section. Expanded Issue #7 (stale body) with 3 workarounds. Added 6 new issues: TypeError with resume+onFinish (#13), concurrent sendMessage state corruption (#14), tool approval callback edge case (#15), ZodError on early stop (#16), convertToModelMessages tool approval bug (#17), undefined id infinite loop (#18). Error count: 12→18.
references/
目录包含:
  • use-chat-migration.md - 完整v4→v5迁移指南
  • streaming-patterns.md - UI流式传输最佳实践
  • top-ui-errors.md - 18种常见UI错误及解决方案
  • 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(陈旧body),添加3种解决方案。新增6个问题:TypeError with resume+onFinish (#13)、并发sendMessage状态损坏 (#14)、工具审批回调边缘情况 (#15)、提前停止时的ZodError (#16)、convertToModelMessages工具审批bug (#17)、undefined id无限循环 (#18)。错误总数从12个增加到18个。