🤖 chore: upgrade AI SDK to v7 - #3707
Conversation
- Bump ai 6.0.175 → 7.0.19 and @ai-sdk/* providers to v7-compatible majors - Normalize AI SDK 7 nested usage (inputTokenDetails/outputTokenDetails) into mux's persisted flat shape at all ingestion boundaries; re-inject Anthropic cache-write tokens into providerMetadata for stable pricing/display - streamText result semantics: usage now spans all steps (old totalUsage); final-step values read from finalStep - allowSystemInMessages for cached system-message prepending (streamManager, advisor) - Migrate devtools middleware + spec gates from LanguageModelV3 to V4 - Pin xai chat-completions API (v7 defaults to Responses API) - Explicitly disable OpenAI reasoningSummary for unsupported models (v7 defaults to detailed) - Preserve MCP redirect-following for user-configured servers (v7 defaults to error) - ToolExecutionOptions is now generic with required context; media tool-result parts removed
- Migrate deprecated stream.totalUsage readers to stream.usage (memory consolidation/harvest, status generator) - Pin streamText<ToolSet> generics so Tool's any-context doesn't infect the inferred result type (no-unsafe-return) - Add behavioral tests for normalizeUsage/withCacheWriteMetadata - Fix tests hit by v7 behavior changes: RFC 8414 canonical issuer for MCP OAuth metadata, provider class-name suffix matching, v7 usage promise name
|
@codex review |
CI's flake-hash-check computed the new offlineCache outputHash after the bun.lock changes from the AI SDK v7 dependency bumps.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c4828eee89
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The 2.9.x line peers with ai@^6; 3.0.0 targets ai@^7 and emits v4-spec models consistent with the other upgraded providers. Addresses Codex review feedback on PR #3707.
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
AI SDK 7's convertToModelMessages requires FileUIPart.url to parse as a real URL (new URL(part.url)) and inlines data: URLs itself. The v6-era rewrite to raw base64 now throws 'Invalid URL', breaking every image/PDF attachment send. Rebuild the canonical data:<mediaType>;base64,<payload> form instead — still normalizing URL-encoded (non-base64) data URIs, which the SDK's splitDataUrl would otherwise corrupt. Also update flake.nix offline-cache hash for the OpenRouter bump's bun.lock change (hash from CI's flake-hash-check diff). Verified: tests/ipc/streaming/sendMessage.images.test.ts 5/5 pass locally (with bridge OPENAI_BASE_URL unset; the 403s under the bridge URL are a local env mismatch, not a product issue).
Summary
Upgrades the AI SDK from v6 (
ai@6.0.175) to v7 (ai@7.0.19), bumping all@ai-sdk/*providers to their v7-compatible majors, and adapts mux's usage accounting, streaming, middleware, and provider configuration to the v7 breaking changes — while keeping mux's persisted data shapes (chat.jsonl, session-usage.json, analytics ETL) fully backward compatible with no data migration.Background
AI SDK 7 shipped 2026-06-25 with several breaking changes that affect mux directly:
usage.inputTokenDetails.{noCache,cacheRead,cacheWrite}Tokensandusage.outputTokenDetails.reasoningTokens; Anthropic cache-write tokens moved offproviderMetadata.anthropic.cacheCreationInputTokensonto usage.result.usagenow accumulates across ALL steps (oldtotalUsage, now deprecated); final-step values moved toresult.finalStep.{ role: "system" }insidemessagesthrows unlessallowSystemInMessages: true— mux prepends a cached system message for Anthropic prompt caching.specificationVersion: "v4"models;LanguageModelV3Middlewaregates no longer match.reasoningSummarydefaults to"detailed"whenever reasoning effort is set, and MCP HTTP/SSE transports reject redirects by default.ToolExecutionOptions<CONTEXT>is now generic with a requiredcontextfield; tool-resultmediaparts were removed fromToolResultOutput.Notably, ESM-only
ai@7is NOT a blocker for mux's CommonJS main-process build:require(esm)works on Node 22 / Electron 40, verified against the compileddist/output.Implementation
src/common/utils/tokens/usageHelpers.ts): newnormalizeUsage()andwithCacheWriteMetadata()convert live v7 usage into mux's persisted flat V2 shape and re-inject Anthropic cache-write tokens intoproviderMetadata.anthropic.cacheCreationInputTokens. Applied at every ingestion point: StreamManager (finish-stepevents,getStreamMetadata,getAggregatedProviderMetadata),SessionUsageService.recordHeadlessUsage(choke point for all headless callers), advisor tool, and/btwside questions. Downstream consumers (pricing, IPC, ETL, historical rows) are untouched;createDisplayUsageadditionally self-heals nested shapes defensively.getStreamMetadatareadsusage(all-steps) +finalStep.usage/finalStep.providerMetadata(context window display); deprecatedtotalUsagereaders migrated (memory consolidation/harvest, status generator).allowSystemInMessages: trueon the two streamText calls that receive prepended cached system messages (StreamManager, advisor transcript).LanguageModelV3*→LanguageModelV4*(structurally identical spec); v3 spec gates inaiService/providerModelFactorynow check"v4".provider.chat();reasoningSummary: nullsent explicitly for models that reject the parameter; MCP transports passredirect: "follow"(user-configured, trusted URLs).ToolExecutionOptions<unknown>+context: undefinedacross ~35 test files and 3 production call sites; media tool-result fixtures cast (production rewrite pathextractToolMedia*already strips them before providers see them).Validation
/btwside question, and a follow-up turn.session-usage.jsonexactly; second turn showed 96.9k cache reads, proving prompt caching still hits across turns underallowSystemInMessages.reasoningTokens), DevToolsrawRequestcapture through the V4 middleware, and headless (title/status generator) spend recording all verified against sandbox session files.require()smoke test ofdist/node/services/streamManager.js+ friends against the ESM-only ai@7 graph.Risks
Pains
Tooltype defaults its context generic toany, which infectsstreamText's inferred result type and tripsno-unsafe-return; fixed by explicitly pinningstreamText<ToolSet>.@ai-sdk/mcpv2 strictly validates OAuth metadata issuers (RFC 8414 canonical form), which surfaced as opaquestartDesktopFlowfailures in tests until the underlying error was extracted._(e.g._OpenAIChatLanguageModel), breakingconstructor.nameequality assertions in tests.Generated with
mux• Model:anthropic:claude-fable-5• Thinking:xhigh• Cost:$79.25