Repository navigation
deps(ai): migrate the Vercel AI SDK from 5 to 6 - #184
Merged
Merged
Conversation
Version set (all in devDependencies, bundled by rollup into out/main):
ai 5.0.265 -> 6.0.297
@ai-sdk/provider 2.0.5 -> 3.0.18
@ai-sdk/openai 2.0.129 -> 3.0.121
@ai-sdk/anthropic 2.0.105 -> 3.0.125
@ai-sdk/google 2.0.99 -> 3.0.129
@ai-sdk/openai-compatible 1.0.56 -> 2.0.80
Ran the official v6 codemod (npx @ai-sdk/codemod@3.0.8 v6), then fixed what it
could not:
- Provider spec V2 -> V3 in the tests: MockLanguageModelV2 ->
MockLanguageModelV3, LanguageModelV2* -> LanguageModelV3*.
- The scripted provider fixtures were still building V2 stream parts, so a V3
mock received a string `finishReason` and flat usage. The suite caught it -
10 tests failed - and the fixtures now use the V3 shape:
`finishReason: { unified, raw }` and nested `inputTokens`/`outputTokens`
totals. This is the one place a type-only migration was not enough.
- Embedding entry points renamed: textEmbedding -> embedding,
textEmbeddingModel -> embeddingModel.
- The local `convertToCoreMessages` helper in ModelClient was only a plain
mapper; the codemod renamed it after the SDK function it is not. It is now
`toModelMessages`, and the stale `CoreMessage` comment is corrected.
One behavior change had to be actively prevented, not just reviewed:
AI SDK 6 flips OpenAI's `strictJsonSchema` default from false to true.
`QuizService`, `AnkiCardService` and `MindMapService` build schemas with
`.optional()` fields, and OpenAI's strict mode requires every property to be
listed in `required`. Verified at the request-body level:
responses default -> text.format.strict = true
responses strictJsonSchema:false -> text.format.strict = false
and verified that the zod schema conversion leaves optional fields out of
`required`. So without a fix, openai-responses would start rejecting the
generated quiz/Anki/mind-map schemas. The `ProtocolAdapter` interface and
`ModelClient` now carry `structuredOutputProviderOptions()`, the
openai-responses adapter answers it, and the three services pass it to
`streamObject`.
Only openai-responses needs it: openai-completions goes through
`@ai-sdk/openai-compatible`, which sends `json_object` unless
`structuredOutputs` is enabled, so its `strictJsonSchema` never applies.
Verified on Linux x64 (WSL2):
- `npm run typecheck` - clean
- `npm test` - 470/470 pass (469 + the strictness regression test)
- `npm run build:unpack && npm run smoke:packaged` - 29 checks pass
Not changed, deliberately: the app still calls the deprecated `streamObject`
(v6 deprecates it in favour of `streamText` + `Output.object`); it works and
rewriting three services does not belong in a version bump. Likewise the
`'openai-compatible'` providerOptions key is deprecated in favour of
`'openaiCompatible'` and still works, including for #179's reasoning effort;
it now logs a warning.
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
Upgrade the AI SDK from 5 to 6, keeping the runtime behaviour identical.
ai@ai-sdk/provider@ai-sdk/openai@ai-sdk/anthropic@ai-sdk/google@ai-sdk/openai-compatibleThis is the second step of the two-stage 5 → 6 → 7 plan: it lands the provider-spec V2 → V3 migration on its own, so the semantics change in 7 does not hide inside a double jump.
How
Ran the official codemod
npx @ai-sdk/codemod@3.0.8 v6, then fixed the three things it cannot know:The test fixtures, not just the types. The codemod renamed
MockLanguageModelV2→MockLanguageModelV3but left the scripted provider chunks as V2 stream parts, so a V3 mock received a stringfinishReasonand flat usage numbers. The suite caught this — 10 tests failed — and the fixtures now build the V3 shape:This is the part of the migration a type-only change would have shipped silently: the
as never[]cast on those fixtures is why it typechecked while being wrong.Embedding entry points —
textEmbedding→embedding,textEmbeddingModel→embeddingModel.A misleading codemod rename. The local
convertToCoreMessagesinModelClientis a plain mapper, not the SDK function the codemod named it after. Renamed totoModelMessageswith the staleCoreMessagecomment corrected.The one real behaviour change, and how it is prevented
AI SDK 6 flips OpenAI's
strictJsonSchemadefault fromfalsetotrue.QuizService,AnkiCardServiceandMindMapServicebuild schemas with.optional()fields, and OpenAI strict mode requires every property to be listed inrequired.I verified both halves of this at the request-body level rather than assuming:
So without a fix, openai-responses would start rejecting the generated quiz / Anki / mind-map schemas.
ProtocolAdapterandModelClientnow carrystructuredOutputProviderOptions(), the openai-responses adapter answers it, and the three services pass it tostreamObject.Only openai-responses needs it.
openai-completionsgoes through@ai-sdk/openai-compatible, which sendsresponse_format: { type: 'json_object' }unlessstructuredOutputsis enabled, so itsstrictJsonSchemanever applies — I checked the provider source, not the guide.Verification (Linux x64, WSL2)
npm run typechecknpm testnpm run build:unpack && npm run smoke:packagedThe packaged smoke matters here because the AI SDK is a
devDependencythat rollup bundles intoout/main, so a bad upgrade can break the bundle, not just the types.Deliberately not changed
streamObjectis deprecated in 6 (in favour ofstreamText+Output.object) but still works. Rewriting three services does not belong in a version bump; it is the natural content of the 6 → 7 PR.'openai-compatible'providerOptions key is deprecated in favour of'openaiCompatible'. It still works, including [Feat] Reasoning models hit the output ceiling: make truncation recoverable #179's reasoning-effort path, but now logs a warning. Flagged rather than renamed so this PR stays behaviour-identical.Rollback
Revert the branch. No schema, storage format, or persisted data changes; the provider-spec V2 → V3 change is internal to the SDK.
Stacking
The 6 → 7 PR will stack on this branch (base
deps/ai-sdk-6), because the v7 codemod can only run on v6 code.