Draft
Conversation
Fixes an issue where `sendMessages()` returned an empty `ReadableStream` to `useChat`. The stream returned here is used to power important features of useChat, such as: - status changes (submitted -> streaming -> ready) - turn lifecycle hooks (e.g. `onToolCall`, `onData`, `onFinish`) - evaluating whether `sendAutomaticallyWhen` should send With an empty stream, none of these features worked. This transport aims to, as much as possible, be a drop-in replacement for the default transport so we need to make these features work. This commit returns the real stream from `turn.stream` to `useChat`, which allows these features to work as expected. As a result of this change, both `useChat` and `useMessageSync` now accumulate messages in parallel but both produce identical messages from the same underlying Ably events. When the AI SDK doesn't set messageId on the start chunk (currently this is logically equivalent to not being in 'persistence mode') useChat and the transport will assign different IDs. This commit adds `messageId` to `EncoderOptions` so that the server transport can pass its generated ID to the vercel encoder which uses it as a fallback, which ensures that both sides converge on the same ID.
useChat's internal write() compares message IDs against the last message in state.messages. If useMessageSync replaces the array mid-stream (e.g. when an observer turn arrives), the ID check can fail and push a duplicate message. ChatTransport now tracks whether an own-turn stream is active via a `streaming` flag and `onStreamingChange` callback. The stream is wrapped in a passthrough TransformStream that resolves a done promise on close or error, clearing the flag automatically. useMessageSync accepts an optional ChatTransport and suppresses setMessages while streaming. When the gate opens, an immediate sync fires to pick up any observer messages that arrived during the stream. Tests verify: streaming flag lifecycle (including error and pre-stream failure), useMessageSync gating and ungating with observer messages, and concurrent sendMessage behavior documenting the AbstractChat activeResponse limitation.
Enable monthly dependency update PRs for the root package, both demo apps, and GitHub Actions versions. Updates are grouped by type (minor/patch, major, security) to reduce PR noise.
Replace the monolithic serial test.yml with dev.yml containing parallel jobs: check (typecheck, format, lint, error-codes), unit tests, integration tests and build. Parallel jobs give faster wall-clock feedback, clearer failure attribution (each check is a separate PR status), and allow selective re-runs. Unit and integration tests run across Node 20, 22, and 24. Concurrency groups cancel in-progress runs when new commits are pushed.
Commit demo app lockfiles generated from a clean state (no node_modules) so npm ci works cross-platform. Note: npm has a known issue [1] where lockfiles can lose cross-platform optional deps under certain conditions. If demo CI breaks with "Missing: @next/swc-..." errors, delete node_modules and package-lock.json then regenerate from scratch. Provide a dummy ABLY_API_KEY env var for the build step. Next.js evaluates all route modules during `next build`, including the module-level Ably client initialization that requires an API key — even though the routes are never called at build time. An alternative (lazy-initializing the Ably client on first request) was considered but rejected to keep demo app code simple and representative of real usage patterns. [1] npm/cli#4828
Add @vitest/coverage-v8 with coverage config (disabled by default, enabled via --coverage flag in CI). On the base Node version, the test job collects coverage and posts a summary to PRs via vitest-coverage-report-action.
Deploy core UMD bundle to prod-cdn.ably.com on every GitHub release using the shared ably/cdn-deploy-action. Uses AWS OIDC federation for authentication. Versioned copies are uploaded (e.g. 0.0.2 -> 0, 0.0, 0.0.2) so consumers can pin to major/minor/patch.
Add typedoc with all 4 entry points configured. Generated docs are deployed to the SDK docs CDN on pushes to main and tag creation. "treatWarningsAsErrors" is set to false for now as the public API surface needs more JSDoc coverage.
The lifecycle tracker's clearScope was called on finish and abort but not on error. If error is the terminal event in a turn (no subsequent finish), the scope entry leaks. clearScope is idempotent so adding it defensively is harmless. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
43cac82 to
9eb72b5
Compare
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.
No description provided.