---
description: Vercel AI SDK conventions
globs: ["app/**/*.{ts,tsx}","src/**/*.{ts,tsx}","lib/**/*.ts"]
alwaysApply: false
---

# Vercel AI SDK (v5)

- Server calls use `ai` core functions: `streamText` for chat, `generateText` for one-shot, `generateObject`/`streamObject` with a zod schema for structured data.
- Models come from provider packages (`@ai-sdk/openai`, `@ai-sdk/anthropic`, ...) or the project's gateway config. Keep model ids in one config module.
- Route handlers return `result.toUIMessageStreamResponse()` for `useChat`. Convert incoming UI messages with `convertToModelMessages(messages)`.
- Client: `useChat` from `@ai-sdk/react` with a transport; render `message.parts` (text, tool calls, reasoning) rather than a single `content` string. Manage the input with your own `useState`.
- Tools: `tool({ description, inputSchema: z.object(...), execute })`. Bound multi-step loops with `stopWhen: stepCountIs(n)`.
- Tools that change data or cost money need user confirmation (no `execute` on the server; handle approval in the UI).
- Set `maxOutputTokens`, handle `onError`, and pass `abortSignal` so cancelled requests stop billing.
- Log usage from `onFinish` (`usage`, model) for cost tracking.
- Keys only on the server (`OPENAI_API_KEY` etc.); never call providers from client components.

## Don't
- Don't use v4 names (`maxTokens`, `parameters` in tools, `toDataStreamResponse`, `message.content`) in new code.

## Done when
Typecheck passes and tests use `MockLanguageModelV2` from `ai/test` instead of real API calls.
