Skip to content

feat(ai-sdk-middleware)!: support AI SDK v7 (provider spec V4)#43

Merged
MyPrototypeWhat merged 4 commits into
mainfrom
claude/inspiring-shannon-a41e21
Jun 25, 2026
Merged

feat(ai-sdk-middleware)!: support AI SDK v7 (provider spec V4)#43
MyPrototypeWhat merged 4 commits into
mainfrom
claude/inspiring-shannon-a41e21

Conversation

@MyPrototypeWhat

@MyPrototypeWhat MyPrototypeWhat commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary

Adds AI SDK v7 (provider spec V4) support to @context-chef/ai-sdk-middleware. Released as a major (2.0): AI SDK v7's wrapLanguageModel rejects a v3-spec middleware at the type level, so v7 support cannot coexist with v6 in one published artifact. v6 users stay on the existing 1.x line — no existing user is broken.

What changed

  • Middleware now implements the V4 spec (specificationVersion: 'v4'); all public types LanguageModelV3*LanguageModelV4*.
  • Prompt adapter handles V4's restructured FilePart.data (now the SharedV4FileData tagged union) via a small fileDataSignal() helper — at both the provider altitude (adapter.ts) and the app ModelMessage altitude (modelMessageAdapter.ts, where provider-utils@5 widened data too). Binary / URL / inline payloads still round-trip losslessly; runtime behavior unchanged.
  • Peers bumped to ai>=7 / @ai-sdk/provider>=4.
  • Removed deprecated APIs that were slated for this major: planCompaction / compactHistory / CompactionPlan (provider-prompt altitude → use the ModelMessage equivalents), and onBudgetExceeded (→ onBeforeCompress).
  • Test fixtures/assertions migrated to V4 shapes; budget-exceeded hook test retargeted to onBeforeCompress; stale V3 comments corrected.
  • README badge + install note + changeset (major) documenting the 2.x = v7 / 1.x = v6 split.

Scope

  • Only @context-chef/ai-sdk-middleware. @context-chef/core has no ai/@ai-sdk dependency (verified) and is untouched; @context-chef/tanstack-ai is out of scope.

Durable in-loop compaction on v7

No new API needed: AI SDK v7 fixed vercel/ai#9631 so prepareStep-returned messages now persist across steps. That makes compactModelMessages() inside a ToolLoopAgent prepareStep genuinely durable on v7 (it wasn't on v6). Documented in the changeset.

Verification

  • tsc --noEmit clean (incl. tests)
  • vitest: 119/119 pass in this package
  • biome check: clean
  • Full monorepo: typecheck 3/3, tests 714 + 119 + 66 pass, build 3/3 — core & tanstack-ai unaffected

Commits

  1. feat!: V3→V4 migration (AI SDK v7 support)
  2. fix: handle V4 tagged file data in the app-altitude ModelMessage adapter (review follow-up)
  3. refactor!: remove deprecated compaction APIs (planCompaction/compactHistory/CompactionPlan, onBudgetExceeded) — 2.0 is the major they were slated for

Migrate the middleware from AI SDK v6 (provider spec V3) to v7 (V4):
- specificationVersion 'v3' -> 'v4'; public types LanguageModelV3* -> V4*
- handle V4 FilePart.data tagged union (SharedV4FileData) in the prompt adapter
  via fileDataSignal(); binary/URL payloads still round-trip losslessly
- bump peers to ai>=7 / @ai-sdk/provider>=4; build/dev deps to ai@7 / provider@4
- migrate test fixtures and assertions to V4 shapes

AI SDK v7's wrapLanguageModel rejects v3-spec middleware, so this requires
AI SDK v7. Released as 2.0 (changeset); v6 users stay on the 1.x line.

Verified: tsc --noEmit clean, 126 tests pass, biome clean, full monorepo
typecheck/test/build green (core + tanstack-ai untouched).
…apter

Review follow-up: the bump to @ai-sdk/provider-utils@5 widened app-level
FilePart.data to also accept V4 tagged shapes ({ type: 'data', data }, …),
not just the bare shorthand. modelMessageAdapter read it via
`typeof part.data === 'string'`, so a tagged inline-string payload recorded
an empty attachment presence signal — an asymmetry with the provider-prompt
adapter the two are documented to keep in sync.

Add a local fileDataSignal() (parallel to adapter.ts) covering both the bare
shorthand and the tagged { type: 'data', data: string } form; add a fixture
asserting the tagged signal + verbatim round-trip. Image parts unchanged.
@MyPrototypeWhat

Copy link
Copy Markdown
Owner Author

Review pass (fresh-eyes code review)

Ran an independent review of the diff. No critical/important issues — the V3→V4 migration is correct (usage inputTokens.total unchanged, stringifyToolOutput/extractText content-variant handling intact, no stray V3 refs, peers/changeset coherent).

One sub-threshold finding was acted on (commit 047c69f): the bump to @ai-sdk/provider-utils@5 widened app-level FilePart.data to also accept V4 tagged shapes, so modelMessageAdapter reading it via typeof === 'string' had the same gap the provider adapter fixed — breaking the two adapters' documented "keep in sync" invariant. Added a parallel fileDataSignal() (bare shorthand + { type: 'data', data }) and a tagged-shape fixture. Not an observable bug today (presence-signal only; payload round-trips via pass-through), but restores symmetry.

Verification: tsc clean · 127 tests green · biome clean · full monorepo typecheck/test/build green (core + tanstack-ai untouched).

These were marked '@deprecated … removed in the next major'; 2.0 is that major.

Removed:
- planCompaction / compactHistory / CompactionPlan (provider-prompt altitude) —
  use the ModelMessage-altitude equivalents (planCompactionModelMessages /
  compactModelMessages / CompactionPlanModelMessages)
- onBudgetExceeded on ContextChefOptions — use onBeforeCompress

Drop the now-unused fromAISDK/toAISDK + provider type imports in compaction.ts and
the onBeforeCompress ?? onBudgetExceeded fallback in createJanitor. Delete
tests/compaction.test.ts (covered only the removed fns; the turn-split algorithm
is tested in core and at the ModelMessage boundary). Retarget the budget-exceeded
hook test to onBeforeCompress (preserves coverage). Folded into the 2.0 changeset.

Verified: tsc clean, 119 tests, biome clean, full monorepo green.
@MyPrototypeWhat

Copy link
Copy Markdown
Owner Author

Landed the deprecated-API cleanup as commit fcf1dda: removed planCompaction/compactHistory/CompactionPlan (provider-prompt altitude) and onBudgetExceeded, all of which were marked removed in the next major — 2.0 is that major. Kept the ModelMessage-altitude equivalents and onBeforeCompress; the budget-exceeded hook test was retargeted to onBeforeCompress so coverage is preserved. Folded into the 2.0 changeset. Full monorepo green (714 + 119 + 66).

Review of the cleanup surfaced shipped docs still pointing at APIs this 2.0
removed or at the old v6 spec:
- README: dropped the compactHistory / planCompaction sections (removed APIs;
  the ModelMessage equivalents are already documented above)
- middleware skill (SKILL.md + references/api-reference.md): LanguageModelV3 ->
  V4, onBudgetExceeded -> onBeforeCompress, 'ai (v6+)/(v3+)' -> (v7+)/(v4+)
- core README: the 'ai-sdk users: prefer ...' pointer now references
  compactModelMessages / planCompactionModelMessages (core's own
  planCompaction/compactHistory docs are unchanged — core still ships them)

Docs-only; no src/test changes. Repo-wide grep confirms no remaining references
to the removed middleware APIs.
@MyPrototypeWhat MyPrototypeWhat merged commit af670be into main Jun 25, 2026
0 of 2 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

prepareStep messages-overriding is not preserved between steps

1 participant