Skip to content

fix(vercel-ai): preserve normalized final tool inputs - #88

Merged
Kinfe123 merged 4 commits into
mainfrom
fix/vercel-final-input
Oct 29, 2026
Merged

Kinfe123 merged 4 commits into
mainfrom
fix/vercel-final-input

Conversation

@Kinfe123

@Kinfe123 Kinfe123 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Streamfold 0.1.14 drops complete AI SDK fullStream tool 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 streamText with a tool schema z.object({ city: z.string(), units: z.string().default("celsius") }) and model input {"city":"Paris"}. Consume either result.fullStream or result.toUIMessageStream() with readStructured(source, { integration: vercelAI }). The completed value should contain units: "celsius" exactly once. The SDK conformance suite reproduces both transport variants on AI SDK 7.0.152 using its real stream conversion and a MockLanguageModelV4 transport.

Root cause

The adapter ignored tool-call events, finalized fullStream calls on the earlier tool-input-end, and used authoritative final JSON only when no parser was active.

Change

Accept final inputs from both tool-call and tool-input-available. Within SDK step boundaries, wait for the normalized tool-call; finalize any remaining calls at finish-step or EOF. Streams without SDK step boundaries retain immediate tool-input-end completion.

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

  • Both new fullStream conformance 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.
  • Focused SDK, lifecycle, and managed-reader suites: 40 passed. Covers final-only calls, interleaved calls, step fallback, duplicate completion, limits, immutable values, cancellation, and existing end-only behavior.
  • Pool regression tests protect replacement patches, removed fields, byte counts, unchanged snapshot identity, partial-input replacement, limits, invalid JSON, and cleanup.
  • 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 finalText to the existing pool finish method and explicitly types Vercel tool-call events. Updates README, API reference, changelog, SDK-typed example, and public type fixture. No new exports or runtime dependencies.

@Kinfe123
Kinfe123 merged commit e4a2653 into main Oct 29, 2026
6 checks passed
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.

1 participant