Repository navigation
fix(vercel-ai): preserve normalized final tool inputs - #88
Merged
Merged
Conversation
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.
Problem
Streamfold 0.1.14 drops complete AI SDK
fullStreamtool calls when the model emits no argument deltas. When deltas are present, it completes before the SDK applies schema defaults or transforms. UI message streams also lose normalized input after streamed deltas.Reproduction: use
streamTextwith a tool schemaz.object({ city: z.string(), units: z.string().default("celsius") })and model input{"city":"Paris"}. Consume eitherresult.fullStreamorresult.toUIMessageStream()withreadStructured(source, { integration: vercelAI }). The completed value should containunits: "celsius"exactly once. The SDK conformance suite reproduces both transport variants on AI SDK 7.0.152 using its real stream conversion and aMockLanguageModelV4transport.Root cause
The adapter ignored
tool-callevents, finalizedfullStreamcalls on the earliertool-input-end, and used authoritative final JSON only when no parser was active.Change
Accept final inputs from both
tool-callandtool-input-available. Within SDK step boundaries, wait for the normalizedtool-call; finalize any remaining calls atfinish-stepor EOF. Streams without SDK step boundaries retain immediatetool-input-endcompletion.Extend the existing pool
finish(id, finalText?)path to validate replacements with the same byte/depth limits and snapshot mode. Matching text reuses the parser. Replacement text, value, partial value, byte count, and patches agree. Duplicate suppression and the manual completion history remain intact. No provider SDK runtime dependency is added.Verification
fullStreamconformance cases failed before this follow-up: one returned no completion, the other omitted the default. Both pass after the fix, including schema transforms. The original UI normalization regression also failed before the initial fix and passes now.pnpm release:check: 185 JavaScript tests and 11 Rust tests passed, plus types, syntax, Rust formatting, clippy, and package dry-run.CHROME_EXECUTABLE=... pnpm test:browser: Chromium passed.This is a correctness fix. Final-input serialization and comparison add work; no CPU speedup is claimed.
Public surface
Adds optional
finalTextto the existing poolfinishmethod and explicitly types Verceltool-callevents. Updates README, API reference, changelog, SDK-typed example, and public type fixture. No new exports or runtime dependencies.