deps: migrate AI SDK v5 to v7 - #441
Merged
Merged
Conversation
Bumps ai 5.0.108 -> 7.0.93, @ai-sdk/react 2.0.115 -> 4.0.96 and @ai-sdk/google 2.0.47 -> 4.0.64 (the @ai-sdk/* line runs three majors behind the core, verified against the published dist-tags). Applied the official @ai-sdk/codemod v6 and v7 bundles and reviewed every line. The codemods needed correcting in two places: they rewrote reasoningTokens/cachedInputTokens on our own Drizzle columns and DB rows in lib/services/llm-logs-service.ts and the admin RAG components, and they renamed useChat's onFinish to onEnd even though ChatInit still uses onFinish (onEnd is the server-side stream option). Both were reverted. Chat route changes: - convertToModelMessages is async in v6+ - system -> instructions - toUIMessageStreamResponse -> toUIMessageStream + createUIMessageStreamResponse - stream onFinish -> onEnd, whose finishReason is now optional - result.totalUsage -> result.usage, result.request -> result.finalStep.request - usage token details moved to inputTokenDetails/outputTokenDetails - createGoogleGenerativeAI -> createGoogle - dropped a @ts-expect-error the provider no longer needs - opt into include: { requestBody: true }; v7 omits request bodies by default Fixes a silent regression the compiler cannot catch: request.body is now a parsed object rather than a JSON string, so the route's typeof === 'string' guard nulled generationConfig and systemPrompt in every LLM log. Extracted into extractRequestMetadata with tests asserting the new object shape. Also raises engines.node to >=22 (required by v7) and types the org layout params as a Promise, which was already failing next build on this branch. Verified end to end against a local stub of the Google streaming API: tokens stream, the file_search tool call is emitted, grounding metadata renders as sources, and the conversation persists and reloads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Resolves bun.lock by regeneration; package.json auto-merged cleanly and keeps the AI SDK v7 pins alongside husky 9, exceljs and Node 22 from #436. Fixes a semantic conflict git could not see. #438 added __tests__/api/chat/route.test.ts with mocks written against the v5 AI SDK surface, while this branch migrated the route to v7: - @ai-sdk/google: createGoogleGenerativeAI -> createGoogle - ai: result.toUIMessageStreamResponse() -> createUIMessageStreamResponse({ stream: toUIMessageStream(...) }) Both mocks now match the surface the route actually calls. The merge was textually clean and the suite failed at collection, which is the only reason this was caught. Gate verified: typecheck, lint, 744 tests across 55 files, format:check, knip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GyBfVKhYQGLZhkcWiHaruY
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's Changed
Migrates the Vercel AI SDK from v5 to v7, two majors, using the official codemods for both hops plus a manual review of every changed line.
The v5-to-v6 hop moved
useChatto a message-parts model, where a message is an array of typed parts and a UI that does not render every part type silently drops tool-call output. That was the change most likely to break this app quietly rather than loudly, so it got the most attention.This supersedes #384, #385 and #387, which each bumped one package to the v6 line without the code migration, which is why all three failed CI. All three are now closed.
Type of Change
Testing
typecheck,lint,format:check,buildpass. 580 tests (575 + 5 new, onextractRequestMetadata, where the shape actually changed).__tests__/lib/ai/utils.test.tsand__tests__/lib/services/rag-service.test.tspass unmodified in substance, and it is worth being precise about why: neither asserts an AI SDK message shape. They exercise@google/genaigrounding metadata and File Search store operations, and@google/genaiis a separate SDK that was deliberately not bumped. There was no old shape to update.What was driven end to end, and what was not
There is no
GOOGLE_AI_API_KEYin the build sandbox. Rather than stop at a typecheck, a local HTTPS stub speaking the real Google streaming wire protocol was placed behindgenerativelanguage.googleapis.com, so the unmodified route, provider and UI ran for real against Chromium and real Postgres:file_searchtool call was emitted and persistedmessageMetadataand rendered as "Used 2 sources" with both documents linkedpromptTokens,completionTokens,reasoningTokensandcachedInputTokensthrough the newinputTokenDetails/outputTokenDetailspathsgenerationConfigand the system prompt persisted, confirminginstructions:still producessystemInstructionon the wireNot exercised against real Google infrastructure: actual Gemini generation, real File Search retrieval, real grounding, and the quota / rate-limit / auth error paths. The stub reproduces the protocol, not Google's behavior. All verification scaffolding (hosts entry, iptables rule, CA bundle, stub process) was torn down and re-verified as reverted.
One pre-existing bug fixed, out of scope but blocking
bun run buildwas already broken onmain:app/(logged-in)/org/[slug]/layout.tsxtypedparams: { slug: string }whileawaiting it, a Next 16 async-params error. Proved pre-existing by building HEAD in a clean worktree. One line, fixed here rather than buried, because the build gate cannot pass without it.Lockfile scope
The lockfile diff touches only the three AI SDK packages and their transitive dependencies.
eslint,vitest,stripe,bullmq,better-auth,nextandreactare untouched, each having its own migration PR coming.🤖 Generated with Claude Code
https://claude.ai/code/session_01GyBfVKhYQGLZhkcWiHaruY