{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ai-sdk-ui",
    "name": "Ai Sdk Ui",
    "source": "tencent",
    "type": "skill",
    "category": "通讯协作",
    "sourceUrl": "https://clawhub.ai/Veeramanikandanr48/ai-sdk-ui",
    "canonicalUrl": "https://clawhub.ai/Veeramanikandanr48/ai-sdk-ui",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ai-sdk-ui",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ai-sdk-ui",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      ".claude-plugin/plugin.json",
      "README.md",
      "SKILL.md",
      "references/links-to-official-docs.md",
      "references/nextjs-integration.md",
      "references/streaming-patterns.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "slug": "ai-sdk-ui",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-29T03:28:17.656Z",
      "expiresAt": "2026-05-06T03:28:17.656Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ai-sdk-ui",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ai-sdk-ui",
        "contentDisposition": "attachment; filename=\"ai-sdk-ui-0.1.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "ai-sdk-ui"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/ai-sdk-ui"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/ai-sdk-ui",
    "agentPageUrl": "https://openagent3.xyz/skills/ai-sdk-ui/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ai-sdk-ui/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ai-sdk-ui/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "AI SDK UI - Frontend React Hooks",
        "body": "Frontend React hooks for AI-powered user interfaces with Vercel AI SDK v6.\n\nVersion: AI SDK v6.0.42 (Stable)\nFramework: React 18+/19, Next.js 14+/15+\nLast Updated: 2026-01-20"
      },
      {
        "title": "AI SDK v6 Stable (January 2026)",
        "body": "Status: Stable Release\nLatest: ai@6.0.42, @ai-sdk/react@3.0.44, @ai-sdk/openai@3.0.7\nMigration: Minimal breaking changes from v5 → v6"
      },
      {
        "title": "New UI Features in v6",
        "body": "1. Message Parts Structure (Breaking Change)\nIn v6, message content is now accessed via .parts array instead of .content:\n\n// ❌ v5 (OLD)\n{messages.map(m => (\n  <div key={m.id}>{m.content}</div>\n))}\n\n// ✅ v6 (NEW)\n{messages.map(m => (\n  <div key={m.id}>\n    {m.parts.map((part, i) => {\n      if (part.type === 'text') return <span key={i}>{part.text}</span>;\n      if (part.type === 'tool-invocation') return <ToolCall key={i} tool={part} />;\n      if (part.type === 'file') return <FilePreview key={i} file={part} />;\n      return null;\n    })}\n  </div>\n))}\n\nPart Types:\n\ntext - Text content with .text property\ntool-invocation - Tool calls with .toolName, .args, .result\nfile - File attachments with .mimeType, .data\nreasoning - Model reasoning (when available)\nsource - Source citations\n\n3. Agent Integration\nType-safe messaging with agents using InferAgentUIMessage<typeof agent>:\n\nimport { useChat } from '@ai-sdk/react';\nimport type { InferAgentUIMessage } from 'ai';\nimport { myAgent } from './agent';\n\nexport default function AgentChat() {\n  const { messages, sendMessage } = useChat<InferAgentUIMessage<typeof myAgent>>({\n    api: '/api/chat',\n  });\n  // messages are now type-checked against agent schema\n}\n\n4. Tool Approval Workflows (Human-in-the-Loop)\nRequest user confirmation before executing tools:\n\nimport { useChat } from '@ai-sdk/react';\nimport { useState } from 'react';\n\nexport default function ChatWithApproval() {\n  const { messages, sendMessage, addToolApprovalResponse } = useChat({\n    api: '/api/chat',\n  });\n\n  const handleApprove = (toolCallId: string) => {\n    addToolApprovalResponse({\n      toolCallId,\n      approved: true,  // or false to deny\n    });\n  };\n\n  return (\n    <div>\n      {messages.map(message => (\n        <div key={message.id}>\n          {message.toolInvocations?.map(tool => (\n            tool.state === 'awaiting-approval' && (\n              <div key={tool.toolCallId}>\n                <p>Approve tool call: {tool.toolName}?</p>\n                <button onClick={() => handleApprove(tool.toolCallId)}>\n                  Approve\n                </button>\n                <button onClick={() => addToolApprovalResponse({\n                  toolCallId: tool.toolCallId,\n                  approved: false\n                })}>\n                  Deny\n                </button>\n              </div>\n            )\n          ))}\n        </div>\n      ))}\n    </div>\n  );\n}\n\n5. Auto-Submit Capability\nAutomatically continue conversation after handling approvals:\n\nimport { useChat, lastAssistantMessageIsCompleteWithApprovalResponses } from '@ai-sdk/react';\n\nexport default function AutoSubmitChat() {\n  const { messages, sendMessage } = useChat({\n    api: '/api/chat',\n    sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,\n    // Automatically resubmit after all approval responses provided\n  });\n}\n\n6. Structured Output in Chat\nGenerate structured data alongside tool calling (previously only available in useObject):\n\nimport { useChat } from '@ai-sdk/react';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  summary: z.string(),\n  sentiment: z.enum(['positive', 'neutral', 'negative']),\n});\n\nexport default function StructuredChat() {\n  const { messages, sendMessage } = useChat({\n    api: '/api/chat',\n    // Server can now stream structured output with chat messages\n  });\n}"
      },
      {
        "title": "useChat Hook - v4 → v5 Breaking Changes",
        "body": "CRITICAL: useChat no longer manages input state in v5!\n\nv4 (OLD - DON'T USE):\n\nconst { messages, input, handleInputChange, handleSubmit, append } = useChat();\n\n<form onSubmit={handleSubmit}>\n  <input value={input} onChange={handleInputChange} />\n</form>\n\nv5 (NEW - CORRECT):\n\nconst { messages, sendMessage } = useChat();\nconst [input, setInput] = useState('');\n\n<form onSubmit={(e) => {\n  e.preventDefault();\n  sendMessage({ content: input });\n  setInput('');\n}}>\n  <input value={input} onChange={(e) => setInput(e.target.value)} />\n</form>\n\nSummary of v5 Changes:\n\nInput management removed: input, handleInputChange, handleSubmit no longer exist\nappend() → sendMessage(): New method for sending messages\nonResponse removed: Use onFinish instead\ninitialMessages → controlled mode: Use messages prop for full control\nmaxSteps removed: Handle on server-side only\n\nSee references/use-chat-migration.md for complete migration guide."
      },
      {
        "title": "useAssistant Hook (Deprecated)",
        "body": "⚠️ Deprecation Notice: useAssistant is deprecated as of AI SDK v5. OpenAI Assistants API v2\nwill sunset on August 26, 2026. For new projects, use useChat with custom backend logic instead.\nSee the openai-assistants skill for migration guidance.\n\nInteract with OpenAI-compatible assistant APIs with automatic UI state management.\n\nImport:\n\nimport { useAssistant } from '@ai-sdk/react';\n\nBasic Usage:\n\n'use client';\nimport { useAssistant } from '@ai-sdk/react';\nimport { useState, FormEvent } from 'react';\n\nexport default function AssistantChat() {\n  const { messages, sendMessage, isLoading, error } = useAssistant({\n    api: '/api/assistant',\n  });\n  const [input, setInput] = useState('');\n\n  const handleSubmit = (e: FormEvent) => {\n    e.preventDefault();\n    sendMessage({ content: input });\n    setInput('');\n  };\n\n  return (\n    <div>\n      {messages.map(m => (\n        <div key={m.id}>\n          <strong>{m.role}:</strong> {m.content}\n        </div>\n      ))}\n      <form onSubmit={handleSubmit}>\n        <input\n          value={input}\n          onChange={(e) => setInput(e.target.value)}\n          disabled={isLoading}\n        />\n      </form>\n      {error && <div>{error.message}</div>}\n    </div>\n  );\n}\n\nUse Cases:\n\nBuilding OpenAI Assistant-powered UIs\nManaging assistant threads and runs\nStreaming assistant responses with UI state management\nFile search and code interpreter integrations\n\nSee official docs for complete API reference: https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-assistant"
      },
      {
        "title": "Top UI Errors & Solutions",
        "body": "See references/top-ui-errors.md for complete documentation. Quick reference:"
      },
      {
        "title": "1. useChat Failed to Parse Stream",
        "body": "Error: SyntaxError: Unexpected token in JSON at position X\n\nCause: API route not returning proper stream format.\n\nSolution:\n\n// ✅ CORRECT\nreturn result.toDataStreamResponse();\n\n// ❌ WRONG\nreturn new Response(result.textStream);"
      },
      {
        "title": "2. useChat No Response",
        "body": "Cause: API route not streaming correctly.\n\nSolution:\n\n// App Router - use toDataStreamResponse()\nexport async function POST(req: Request) {\n  const result = streamText({ /* ... */ });\n  return result.toDataStreamResponse(); // ✅\n}\n\n// Pages Router - use pipeDataStreamToResponse()\nexport default async function handler(req, res) {\n  const result = streamText({ /* ... */ });\n  return result.pipeDataStreamToResponse(res); // ✅\n}"
      },
      {
        "title": "3. Streaming Not Working When Deployed",
        "body": "Cause: Deployment platform buffering responses.\n\nSolution: Vercel auto-detects streaming. Other platforms may need configuration."
      },
      {
        "title": "4. Stale Body Values with useChat",
        "body": "Cause: body option captured at first render only.\n\nSolution:\n\n// ❌ WRONG - body captured once\nconst { userId } = useUser();\nconst { messages } = useChat({\n  body: { userId },  // Stale!\n});\n\n// ✅ CORRECT - use controlled mode\nconst { userId } = useUser();\nconst { messages, sendMessage } = useChat();\n\nsendMessage({\n  content: input,\n  data: { userId },  // Fresh on each send\n});"
      },
      {
        "title": "5. React Maximum Update Depth",
        "body": "Cause: Infinite loop in useEffect.\n\nSolution:\n\n// ❌ WRONG\nuseEffect(() => {\n  saveMessages(messages);\n}, [messages, saveMessages]); // saveMessages triggers re-render!\n\n// ✅ CORRECT\nuseEffect(() => {\n  saveMessages(messages);\n}, [messages]); // Only depend on messages\n\nSee references/top-ui-errors.md for 13 more common errors (18 total documented)."
      },
      {
        "title": "Performance",
        "body": "Always use streaming for better UX:\n\n// ✅ GOOD - Streaming (shows tokens as they arrive)\nconst { messages } = useChat({ api: '/api/chat' });\n\n// ❌ BAD - Non-streaming (user waits for full response)\nconst response = await fetch('/api/chat', { method: 'POST' });"
      },
      {
        "title": "UX Patterns",
        "body": "Show loading states:\n\n{isLoading && <div>AI is typing...</div>}\n\nProvide stop button:\n\n{isLoading && <button onClick={stop}>Stop</button>}\n\nAuto-scroll to latest message:\n\nuseEffect(() => {\n  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n}, [messages]);\n\nDisable input while loading:\n\n<input disabled={isLoading} />\n\nSee references/streaming-patterns.md for comprehensive best practices."
      },
      {
        "title": "React Strict Mode Considerations",
        "body": "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.\n\nProblem:\n\n'use client';\nimport { useChat } from '@ai-sdk/react';\nimport { useEffect } from 'react';\n\nexport default function Chat() {\n  const { messages, sendMessage, resumeStream } = useChat({\n    api: '/api/chat',\n    resume: true,\n  });\n\n  useEffect(() => {\n    // ❌ Triggers twice in strict mode → two concurrent streams\n    sendMessage({ content: 'Hello' });\n    // or\n    resumeStream();\n  }, []);\n}\n\nSolution:\n\n// ✅ Use ref to track execution\nimport { useRef } from 'react';\n\nconst hasSentRef = useRef(false);\n\nuseEffect(() => {\n  if (hasSentRef.current) return;\n  hasSentRef.current = true;\n\n  sendMessage({ content: 'Hello' });\n}, []);\n\n// For resumeStream specifically:\nconst hasResumedRef = useRef(false);\n\nuseEffect(() => {\n  if (!autoResume || hasResumedRef.current || status === 'streaming') return;\n  hasResumedRef.current = true;\n  resumeStream();\n}, [autoResume, resumeStream, status]);\n\nWhy 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.\n\nImpact: Duplicate messages, doubled token usage, race conditions causing TypeError: \"Cannot read properties of undefined (reading 'state')\".\n\nSource: GitHub Issue #7891, Issue #6166"
      },
      {
        "title": "Use ai-sdk-ui When:",
        "body": "Building React chat interfaces\nImplementing AI completions in UI\nStreaming AI responses to frontend\nBuilding Next.js AI applications\nHandling chat message state\nDisplaying tool calls in UI\nManaging file attachments with AI\nMigrating from v4 to v5 (UI hooks)\nEncountering useChat/useCompletion errors"
      },
      {
        "title": "Don't Use When:",
        "body": "Need backend AI functionality → Use ai-sdk-core instead\nBuilding non-React frontends (Svelte, Vue) → Check official docs\nNeed Generative UI / RSC → See https://ai-sdk.dev/docs/ai-sdk-rsc\nBuilding native apps → Different SDK required"
      },
      {
        "title": "Related Skills:",
        "body": "ai-sdk-core - Backend text generation, structured output, tools, agents\nCompose both for full-stack AI applications"
      },
      {
        "title": "Package Versions",
        "body": "Stable (v6 - Recommended):\n\n{\n  \"dependencies\": {\n    \"ai\": \"^6.0.8\",\n    \"@ai-sdk/react\": \"^3.0.6\",\n    \"@ai-sdk/openai\": \"^3.0.2\",\n    \"react\": \"^18.3.0\",\n    \"zod\": \"^3.24.2\"\n  }\n}\n\nLegacy (v5):\n\n{\n  \"dependencies\": {\n    \"ai\": \"^5.0.99\",\n    \"@ai-sdk/react\": \"^1.0.0\",\n    \"@ai-sdk/openai\": \"^2.0.68\"\n  }\n}\n\nVersion Notes:\n\nAI SDK v6.0.6 (stable, Jan 2026) - recommended for new projects\nAI SDK v5.x (legacy) - still supported but not receiving new features\nReact 18.3+ / React 19 supported\nNext.js 14+/15+ recommended\nZod 3.24.2+ for schema validation"
      },
      {
        "title": "Links to Official Documentation",
        "body": "Core UI Hooks:\n\nAI SDK UI Overview: https://ai-sdk.dev/docs/ai-sdk-ui/overview\nuseChat: https://ai-sdk.dev/docs/ai-sdk-ui/chatbot\nuseCompletion: https://ai-sdk.dev/docs/ai-sdk-ui/completion\nuseObject: https://ai-sdk.dev/docs/ai-sdk-ui/object-generation\n\nAdvanced Topics (Link Only):\n\nGenerative UI (RSC): https://ai-sdk.dev/docs/ai-sdk-rsc/overview\nStream Protocols: https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocols\nMessage Metadata: https://ai-sdk.dev/docs/ai-sdk-ui/message-metadata\n\nNext.js Integration:\n\nNext.js App Router: https://ai-sdk.dev/docs/getting-started/nextjs-app-router\nNext.js Pages Router: https://ai-sdk.dev/docs/getting-started/nextjs-pages-router\n\nMigration & Troubleshooting:\n\nv4→v5 Migration: https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0\nTroubleshooting: https://ai-sdk.dev/docs/troubleshooting\nCommon Issues: https://ai-sdk.dev/docs/troubleshooting/common-issues\n\nVercel Deployment:\n\nVercel Functions: https://vercel.com/docs/functions\nStreaming on Vercel: https://vercel.com/docs/functions/streaming"
      },
      {
        "title": "Templates",
        "body": "This skill includes the following templates in templates/:\n\nuse-chat-basic.tsx - Basic chat with manual input (v5 pattern)\nuse-chat-tools.tsx - Chat with tool calling UI rendering\nuse-chat-attachments.tsx - File attachments support\nuse-completion-basic.tsx - Basic text completion\nuse-object-streaming.tsx - Streaming structured data\nnextjs-chat-app-router.tsx - Next.js App Router complete example\nnextjs-chat-pages-router.tsx - Next.js Pages Router complete example\nnextjs-api-route.ts - API route for both App and Pages Router\nmessage-persistence.tsx - Save/load chat history\ncustom-message-renderer.tsx - Custom message components with markdown\npackage.json - Dependencies template"
      },
      {
        "title": "Reference Documents",
        "body": "See references/ for:\n\nuse-chat-migration.md - Complete v4→v5 migration guide\nstreaming-patterns.md - UI streaming best practices\ntop-ui-errors.md - 18 common UI errors with solutions\nnextjs-integration.md - Next.js setup patterns\nlinks-to-official-docs.md - Organized links to official docs\n\nProduction Tested: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev)\nLast 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."
      }
    ],
    "body": "AI SDK UI - Frontend React Hooks\n\nFrontend React hooks for AI-powered user interfaces with Vercel AI SDK v6.\n\nVersion: AI SDK v6.0.42 (Stable) Framework: React 18+/19, Next.js 14+/15+ Last Updated: 2026-01-20\n\nAI SDK v6 Stable (January 2026)\n\nStatus: 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\n\nNew UI Features in v6\n\n1. Message Parts Structure (Breaking Change) In v6, message content is now accessed via .parts array instead of .content:\n\n// ❌ v5 (OLD)\n{messages.map(m => (\n  <div key={m.id}>{m.content}</div>\n))}\n\n// ✅ v6 (NEW)\n{messages.map(m => (\n  <div key={m.id}>\n    {m.parts.map((part, i) => {\n      if (part.type === 'text') return <span key={i}>{part.text}</span>;\n      if (part.type === 'tool-invocation') return <ToolCall key={i} tool={part} />;\n      if (part.type === 'file') return <FilePreview key={i} file={part} />;\n      return null;\n    })}\n  </div>\n))}\n\n\nPart Types:\n\ntext - Text content with .text property\ntool-invocation - Tool calls with .toolName, .args, .result\nfile - File attachments with .mimeType, .data\nreasoning - Model reasoning (when available)\nsource - Source citations\n\n3. Agent Integration Type-safe messaging with agents using InferAgentUIMessage<typeof agent>:\n\nimport { useChat } from '@ai-sdk/react';\nimport type { InferAgentUIMessage } from 'ai';\nimport { myAgent } from './agent';\n\nexport default function AgentChat() {\n  const { messages, sendMessage } = useChat<InferAgentUIMessage<typeof myAgent>>({\n    api: '/api/chat',\n  });\n  // messages are now type-checked against agent schema\n}\n\n\n4. Tool Approval Workflows (Human-in-the-Loop) Request user confirmation before executing tools:\n\nimport { useChat } from '@ai-sdk/react';\nimport { useState } from 'react';\n\nexport default function ChatWithApproval() {\n  const { messages, sendMessage, addToolApprovalResponse } = useChat({\n    api: '/api/chat',\n  });\n\n  const handleApprove = (toolCallId: string) => {\n    addToolApprovalResponse({\n      toolCallId,\n      approved: true,  // or false to deny\n    });\n  };\n\n  return (\n    <div>\n      {messages.map(message => (\n        <div key={message.id}>\n          {message.toolInvocations?.map(tool => (\n            tool.state === 'awaiting-approval' && (\n              <div key={tool.toolCallId}>\n                <p>Approve tool call: {tool.toolName}?</p>\n                <button onClick={() => handleApprove(tool.toolCallId)}>\n                  Approve\n                </button>\n                <button onClick={() => addToolApprovalResponse({\n                  toolCallId: tool.toolCallId,\n                  approved: false\n                })}>\n                  Deny\n                </button>\n              </div>\n            )\n          ))}\n        </div>\n      ))}\n    </div>\n  );\n}\n\n\n5. Auto-Submit Capability Automatically continue conversation after handling approvals:\n\nimport { useChat, lastAssistantMessageIsCompleteWithApprovalResponses } from '@ai-sdk/react';\n\nexport default function AutoSubmitChat() {\n  const { messages, sendMessage } = useChat({\n    api: '/api/chat',\n    sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,\n    // Automatically resubmit after all approval responses provided\n  });\n}\n\n\n6. Structured Output in Chat Generate structured data alongside tool calling (previously only available in useObject):\n\nimport { useChat } from '@ai-sdk/react';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  summary: z.string(),\n  sentiment: z.enum(['positive', 'neutral', 'negative']),\n});\n\nexport default function StructuredChat() {\n  const { messages, sendMessage } = useChat({\n    api: '/api/chat',\n    // Server can now stream structured output with chat messages\n  });\n}\n\nuseChat Hook - v4 → v5 Breaking Changes\n\nCRITICAL: useChat no longer manages input state in v5!\n\nv4 (OLD - DON'T USE):\n\nconst { messages, input, handleInputChange, handleSubmit, append } = useChat();\n\n<form onSubmit={handleSubmit}>\n  <input value={input} onChange={handleInputChange} />\n</form>\n\n\nv5 (NEW - CORRECT):\n\nconst { messages, sendMessage } = useChat();\nconst [input, setInput] = useState('');\n\n<form onSubmit={(e) => {\n  e.preventDefault();\n  sendMessage({ content: input });\n  setInput('');\n}}>\n  <input value={input} onChange={(e) => setInput(e.target.value)} />\n</form>\n\n\nSummary of v5 Changes:\n\nInput management removed: input, handleInputChange, handleSubmit no longer exist\nappend() → sendMessage(): New method for sending messages\nonResponse removed: Use onFinish instead\ninitialMessages → controlled mode: Use messages prop for full control\nmaxSteps removed: Handle on server-side only\n\nSee references/use-chat-migration.md for complete migration guide.\n\nuseAssistant Hook (Deprecated)\n\n⚠️ 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.\n\nInteract with OpenAI-compatible assistant APIs with automatic UI state management.\n\nImport:\n\nimport { useAssistant } from '@ai-sdk/react';\n\n\nBasic Usage:\n\n'use client';\nimport { useAssistant } from '@ai-sdk/react';\nimport { useState, FormEvent } from 'react';\n\nexport default function AssistantChat() {\n  const { messages, sendMessage, isLoading, error } = useAssistant({\n    api: '/api/assistant',\n  });\n  const [input, setInput] = useState('');\n\n  const handleSubmit = (e: FormEvent) => {\n    e.preventDefault();\n    sendMessage({ content: input });\n    setInput('');\n  };\n\n  return (\n    <div>\n      {messages.map(m => (\n        <div key={m.id}>\n          <strong>{m.role}:</strong> {m.content}\n        </div>\n      ))}\n      <form onSubmit={handleSubmit}>\n        <input\n          value={input}\n          onChange={(e) => setInput(e.target.value)}\n          disabled={isLoading}\n        />\n      </form>\n      {error && <div>{error.message}</div>}\n    </div>\n  );\n}\n\n\nUse Cases:\n\nBuilding OpenAI Assistant-powered UIs\nManaging assistant threads and runs\nStreaming assistant responses with UI state management\nFile search and code interpreter integrations\n\nSee official docs for complete API reference: https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-assistant\n\nTop UI Errors & Solutions\n\nSee references/top-ui-errors.md for complete documentation. Quick reference:\n\n1. useChat Failed to Parse Stream\n\nError: SyntaxError: Unexpected token in JSON at position X\n\nCause: API route not returning proper stream format.\n\nSolution:\n\n// ✅ CORRECT\nreturn result.toDataStreamResponse();\n\n// ❌ WRONG\nreturn new Response(result.textStream);\n\n2. useChat No Response\n\nCause: API route not streaming correctly.\n\nSolution:\n\n// App Router - use toDataStreamResponse()\nexport async function POST(req: Request) {\n  const result = streamText({ /* ... */ });\n  return result.toDataStreamResponse(); // ✅\n}\n\n// Pages Router - use pipeDataStreamToResponse()\nexport default async function handler(req, res) {\n  const result = streamText({ /* ... */ });\n  return result.pipeDataStreamToResponse(res); // ✅\n}\n\n3. Streaming Not Working When Deployed\n\nCause: Deployment platform buffering responses.\n\nSolution: Vercel auto-detects streaming. Other platforms may need configuration.\n\n4. Stale Body Values with useChat\n\nCause: body option captured at first render only.\n\nSolution:\n\n// ❌ WRONG - body captured once\nconst { userId } = useUser();\nconst { messages } = useChat({\n  body: { userId },  // Stale!\n});\n\n// ✅ CORRECT - use controlled mode\nconst { userId } = useUser();\nconst { messages, sendMessage } = useChat();\n\nsendMessage({\n  content: input,\n  data: { userId },  // Fresh on each send\n});\n\n5. React Maximum Update Depth\n\nCause: Infinite loop in useEffect.\n\nSolution:\n\n// ❌ WRONG\nuseEffect(() => {\n  saveMessages(messages);\n}, [messages, saveMessages]); // saveMessages triggers re-render!\n\n// ✅ CORRECT\nuseEffect(() => {\n  saveMessages(messages);\n}, [messages]); // Only depend on messages\n\n\nSee references/top-ui-errors.md for 13 more common errors (18 total documented).\n\nStreaming Best Practices\nPerformance\n\nAlways use streaming for better UX:\n\n// ✅ GOOD - Streaming (shows tokens as they arrive)\nconst { messages } = useChat({ api: '/api/chat' });\n\n// ❌ BAD - Non-streaming (user waits for full response)\nconst response = await fetch('/api/chat', { method: 'POST' });\n\nUX Patterns\n\nShow loading states:\n\n{isLoading && <div>AI is typing...</div>}\n\n\nProvide stop button:\n\n{isLoading && <button onClick={stop}>Stop</button>}\n\n\nAuto-scroll to latest message:\n\nuseEffect(() => {\n  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n}, [messages]);\n\n\nDisable input while loading:\n\n<input disabled={isLoading} />\n\n\nSee references/streaming-patterns.md for comprehensive best practices.\n\nReact Strict Mode Considerations\n\nReact 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.\n\nProblem:\n\n'use client';\nimport { useChat } from '@ai-sdk/react';\nimport { useEffect } from 'react';\n\nexport default function Chat() {\n  const { messages, sendMessage, resumeStream } = useChat({\n    api: '/api/chat',\n    resume: true,\n  });\n\n  useEffect(() => {\n    // ❌ Triggers twice in strict mode → two concurrent streams\n    sendMessage({ content: 'Hello' });\n    // or\n    resumeStream();\n  }, []);\n}\n\n\nSolution:\n\n// ✅ Use ref to track execution\nimport { useRef } from 'react';\n\nconst hasSentRef = useRef(false);\n\nuseEffect(() => {\n  if (hasSentRef.current) return;\n  hasSentRef.current = true;\n\n  sendMessage({ content: 'Hello' });\n}, []);\n\n// For resumeStream specifically:\nconst hasResumedRef = useRef(false);\n\nuseEffect(() => {\n  if (!autoResume || hasResumedRef.current || status === 'streaming') return;\n  hasResumedRef.current = true;\n  resumeStream();\n}, [autoResume, resumeStream, status]);\n\n\nWhy 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.\n\nImpact: Duplicate messages, doubled token usage, race conditions causing TypeError: \"Cannot read properties of undefined (reading 'state')\".\n\nSource: GitHub Issue #7891, Issue #6166\n\nWhen to Use This Skill\nUse ai-sdk-ui When:\nBuilding React chat interfaces\nImplementing AI completions in UI\nStreaming AI responses to frontend\nBuilding Next.js AI applications\nHandling chat message state\nDisplaying tool calls in UI\nManaging file attachments with AI\nMigrating from v4 to v5 (UI hooks)\nEncountering useChat/useCompletion errors\nDon't Use When:\nNeed backend AI functionality → Use ai-sdk-core instead\nBuilding non-React frontends (Svelte, Vue) → Check official docs\nNeed Generative UI / RSC → See https://ai-sdk.dev/docs/ai-sdk-rsc\nBuilding native apps → Different SDK required\nRelated Skills:\nai-sdk-core - Backend text generation, structured output, tools, agents\nCompose both for full-stack AI applications\nPackage Versions\n\nStable (v6 - Recommended):\n\n{\n  \"dependencies\": {\n    \"ai\": \"^6.0.8\",\n    \"@ai-sdk/react\": \"^3.0.6\",\n    \"@ai-sdk/openai\": \"^3.0.2\",\n    \"react\": \"^18.3.0\",\n    \"zod\": \"^3.24.2\"\n  }\n}\n\n\nLegacy (v5):\n\n{\n  \"dependencies\": {\n    \"ai\": \"^5.0.99\",\n    \"@ai-sdk/react\": \"^1.0.0\",\n    \"@ai-sdk/openai\": \"^2.0.68\"\n  }\n}\n\n\nVersion Notes:\n\nAI SDK v6.0.6 (stable, Jan 2026) - recommended for new projects\nAI SDK v5.x (legacy) - still supported but not receiving new features\nReact 18.3+ / React 19 supported\nNext.js 14+/15+ recommended\nZod 3.24.2+ for schema validation\nLinks to Official Documentation\n\nCore UI Hooks:\n\nAI SDK UI Overview: https://ai-sdk.dev/docs/ai-sdk-ui/overview\nuseChat: https://ai-sdk.dev/docs/ai-sdk-ui/chatbot\nuseCompletion: https://ai-sdk.dev/docs/ai-sdk-ui/completion\nuseObject: https://ai-sdk.dev/docs/ai-sdk-ui/object-generation\n\nAdvanced Topics (Link Only):\n\nGenerative UI (RSC): https://ai-sdk.dev/docs/ai-sdk-rsc/overview\nStream Protocols: https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocols\nMessage Metadata: https://ai-sdk.dev/docs/ai-sdk-ui/message-metadata\n\nNext.js Integration:\n\nNext.js App Router: https://ai-sdk.dev/docs/getting-started/nextjs-app-router\nNext.js Pages Router: https://ai-sdk.dev/docs/getting-started/nextjs-pages-router\n\nMigration & Troubleshooting:\n\nv4→v5 Migration: https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0\nTroubleshooting: https://ai-sdk.dev/docs/troubleshooting\nCommon Issues: https://ai-sdk.dev/docs/troubleshooting/common-issues\n\nVercel Deployment:\n\nVercel Functions: https://vercel.com/docs/functions\nStreaming on Vercel: https://vercel.com/docs/functions/streaming\nTemplates\n\nThis skill includes the following templates in templates/:\n\nuse-chat-basic.tsx - Basic chat with manual input (v5 pattern)\nuse-chat-tools.tsx - Chat with tool calling UI rendering\nuse-chat-attachments.tsx - File attachments support\nuse-completion-basic.tsx - Basic text completion\nuse-object-streaming.tsx - Streaming structured data\nnextjs-chat-app-router.tsx - Next.js App Router complete example\nnextjs-chat-pages-router.tsx - Next.js Pages Router complete example\nnextjs-api-route.ts - API route for both App and Pages Router\nmessage-persistence.tsx - Save/load chat history\ncustom-message-renderer.tsx - Custom message components with markdown\npackage.json - Dependencies template\nReference Documents\n\nSee references/ for:\n\nuse-chat-migration.md - Complete v4→v5 migration guide\nstreaming-patterns.md - UI streaming best practices\ntop-ui-errors.md - 18 common UI errors with solutions\nnextjs-integration.md - Next.js setup patterns\nlinks-to-official-docs.md - Organized links to official docs\n\nProduction 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."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Veeramanikandanr48/ai-sdk-ui",
    "publisherUrl": "https://clawhub.ai/Veeramanikandanr48/ai-sdk-ui",
    "owner": "Veeramanikandanr48",
    "version": "0.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ai-sdk-ui",
    "downloadUrl": "https://openagent3.xyz/downloads/ai-sdk-ui",
    "agentUrl": "https://openagent3.xyz/skills/ai-sdk-ui/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ai-sdk-ui/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ai-sdk-ui/agent.md"
  }
}