feat(vercel-ai-sdk): rewrite for AI SDK v6 with full event coverage#1626
feat(vercel-ai-sdk): rewrite for AI SDK v6 with full event coverage#1626MyPrototypeWhat wants to merge 8 commits into
Conversation
Upgrades the Vercel AI SDK integration from v4 to v6 and re-enables it in the Dojo. This rewrite goes well beyond a pure version bump: - Streams tool input deltas: maps `tool-input-delta` → incremental `TOOL_CALL_ARGS` events so clients can pre-fill UI before the model finishes speaking (the AG-UI killer feature for tool calls). - Full text/reasoning lifecycle: emits `TEXT_MESSAGE_START/CONTENT/END` using AI SDK's part ids directly. Same for `REASONING_*`. Forwards Anthropic encrypted reasoning signatures via `REASONING_ENCRYPTED_VALUE`. - Defensive synthesis for non-streaming providers: if a model emits a final `tool-call` without prior `tool-input-start`, the handler synthesizes the START/ARGS/END trio from the parsed input. - Multi-step (`stopWhen: stepCountIs(N)`): each step gets a fresh `currentStepAssistantId` used for `parentMessageId` on tool calls. Lazy push avoids trailing empty assistant messages. - Cleanup-phase synthesis: any tool call that finishes the run without a result gets a synthesized `TOOL_CALL_RESULT` so clients don't dangle. - Proper error/abort semantics: stream-internal `error` parts emit `RUN_ERROR` but the stream continues; thrown errors emit `RUN_ERROR` then complete; `abort` parts close gracefully via `abortSignal` propagation through Observable teardown. - Replaces the 80-line hand-rolled JSON-Schema → Zod converter with the built-in `jsonSchema()` helper from `ai`. Supports any JSON Schema including `oneOf`/`anyOf`/`enum`/`pattern`. - Splits the previous single-file implementation into `tool-converter.ts`, `message-converter.ts`, `stream-handler.ts`, and `vercel-ai-sdk.ts` for readability and unit-testability. - 70 tests across 8 files using `MockLanguageModelV3` from `ai/test`, covering text, reasoning, tool streaming, tool dedup, invalid tool-calls, multi-step, abort, error part, defensive close, and cleanup synthesis. Resolves ag-ui-protocol#933.
- README Quick Start / With Tools: pass messages via `initialMessages` in constructor (RunAgentParameters does not accept `messages`). - README step counter examples: first step is `step-1` (StreamHandler increments before emitting), not `step-0`. - StreamHandler: log a console.warn for unrecognized AI SDK stream part types instead of silently skipping, surfacing future v6 part additions. - VercelAISDKAgent: catch unforeseen StreamHandler errors and surface them via subscriber.error() instead of leaking as unhandled rejections.
… & abort Previously, both the `error` and `abort` stream-part handlers fell through to the cleanup phase and emitted MESSAGES_SNAPSHOT + RUN_FINISHED after the run had already failed. AG-UI consumers treat RUN_FINISHED and RUN_ERROR as mutually exclusive terminal events, so a consumer that tore down state on RUN_ERROR was confused by the trailing RUN_FINISHED. - `error` part: emit RUN_ERROR (code: stream_error_part) and complete(). - `abort` part: emit RUN_ERROR (code: aborted) and complete() instead of silently degrading into RUN_FINISHED. Mirrors the thrown-error path. - Drop the now-unused `cancelled` flag — the for-await loop exits via `subscriber.closed` once `complete()` runs. - Rewrite the abort test with a deferred promise instead of racing a 200 ms / 50 ms setTimeout pair, removing CI flake potential. The unsubscribe-driven abort path (the only real-world abort source in this code) is unaffected: by the time the AI SDK emits the `abort` part, the subscriber is already closed and the `emit()` guard swallows the synthesized RUN_ERROR — which is exactly what the existing `vercel-ai-sdk.test.ts` "propagates abort on unsubscribe" test asserts. All 70 tests pass; tsc --noEmit clean.
… in unsubscribe test - stream-handler.ts: `onToolCall` no longer appends to `assistantMessage.toolCalls` when an entry with the same id is already present. The downstream START/ARGS/END events were already deduped via `seenToolCalls`, but the toolCalls array push was unconditional, so a misbehaving provider that emitted the same `tool-call` twice would produce a malformed assistant message in MESSAGES_SNAPSHOT. - vercel-ai-sdk.test.ts: rewrite "propagates abort on unsubscribe" with a deferred promise instead of a `setTimeout(200)` race + `setTimeout(1000)` fallback. Suite duration drops from ~1.36s to ~490ms; this single test goes from 1014ms to 21ms. Removes the last wall-clock-based timing assertion in the package. 70 tests still pass; tsc --noEmit clean.
|
@MyPrototypeWhat is attempting to deploy a commit to the CopilotKit Team on Vercel. A member of the Team first needs to authorize it. |
|
Hi @NathanTarbert — picking this back up since #933 has been in Roadmap for a while. The Dojo wiring is included ( Happy to address feedback and to maintain the integration going forward, per the CONTRIBUTING.md note on community integrations. Also flagged the existing #1167 author as a courtesy. |
|
Hi @contextablemark @tylerslaton — sorry to ping cold. This v6 rewrite (#933) has been open for ~2 weeks without a reviewer assigned. Could one of you take a look or route it to the right person? Two things:
Thanks! |
Summary
Rewrites the Vercel AI SDK integration for AI SDK v6 with full AG-UI event coverage. Resolves #933.
This is an independent implementation, not based on #1167 (which has been waiting on review for a while). See #1167 for context.
What this PR adds vs the v4 version on main
tool-input-delta→ incrementalTOOL_CALL_ARGSevents so clients can pre-fill UI as args arriveREASONING_ENCRYPTED_VALUEstopWhen: stepCountIs(N)) with per-step assistant-message rotation; tool calls link back viaparentMessageIdtool-call→ fabricatedSTART/ARGS/END) and missing tool results (cleanup-phase synthesis)RUN_ERRORis terminal for stream-internalerror/abortparts (no misleadingRUN_FINISHEDafter a failed run)jsonSchema()helper (full JSON Schema support —oneOf/anyOf/enum/pattern— for free)tool-converter.ts/message-converter.ts/stream-handler.ts/vercel-ai-sdk.tsMockLanguageModelV3fromai/testcovering text, reasoning, tool streaming, tool dedup, invalid tool-calls, multi-step, abort, error part, defensive close, and cleanup synthesisTest plan
pnpm testinintegrations/vercel-ai-sdk/typescript— 70 tests pass (~490ms)pnpm typecheck— cleanagentic_chatscenario re-enabled and wired (apps/dojo/src/agents.ts,menu.ts,scripts/generate-content-json.ts)Coordination
Notified @iamrajhans on #1167.