Fixes#1979
## Summary
- Add `isOpenAIV5()` detection helper that checks whether `beta.chat`
was removed (v5 promoted it to `chat.completions`)
- Add `getChatCompletionsForStreaming()` helper that routes to the
correct completions namespace per SDK version
- Migrate `OpenAIAdapter` to use the new helper instead of direct
`beta.chat.completions` access
- Migrate `OpenAIAssistantAdapter` `runs.retrieve()` and
`submitToolOutputsStream()` to use v5 named path params (e.g.
`retrieve(runId, { thread_id })` instead of positional
`retrieve(threadId, runId)`)
- Add `openai` to peerDependencies with `^4.85.1 || ^5.0.0` range
- Add 11 unit tests covering v4/v5 detection, streaming dispatch, and
named path param calling conventions
## Notes
The remaining `openai.beta.threads.*` calls (`threads.create`,
`messages.create`, `runs.stream`) do NOT need migration because:
1. `beta.threads` still exists in v5 (only `beta.chat` was removed)
2. These methods have single path params, so their signatures are
unchanged
## Test plan
- [x] All 11 v5 compat tests pass (`nx run @copilotkit/runtime:test`)
- [x] Runtime package builds successfully (`nx run
@copilotkit/runtime:build`)
- [x] Pre-commit hooks pass (lint, format, publint, attw)
The compatibility layer correctly handles v6 (same API surface as v5),
but the version range ^5.0.0 excluded v6.x. Changed to >=5.0.0 so
users on the latest openai SDK don't get peer dependency warnings.
Remove orphaned demo-wrapper.tsx (1 file) and error-boundary.tsx (17 files)
that still imported from the deleted @copilotkit/showcase-shared.
Regenerate registry.json, demo-content.json, and starter-content.json.
Lockfile was stale after rebase — hashbrown deps not in pnpm-lock.yaml.
Also applies oxfmt formatting and syncs next.config.ts webpack alias
with the simplified form from main.
The openai specifier in package.json was updated to ^4.85.1 || ^5.0.0
but the lockfile was not regenerated, causing all CI jobs to fail with
frozen-lockfile mismatch errors.
- Fix convertInputToTanStackAI silently dropping multimodal
content (images, audio, video, documents) by converting
AG-UI content parts to TanStack AI ContentPart format
- Switch react-router example from Hono server to a React
Router resource route using createCopilotRuntimeHandler
- Both agents now use BuiltInAgent factory pattern
- Remove hono/react-router-hono-server deps from example
- Kill useJsonStable in CopilotChatConfigurationProvider — useShallowStableRef
is now the single stabilization primitive for both messageView props and labels
- Harden useShallowStableRef with isPlainObject guard so arrays, Dates, and
class instances are never shallow-compared (reference-only for non-plain objects)
- Remove redundant stableParentLabels — parentConfig?.labels is already stabilized
by the parent provider's own useShallowStableRef
- Uninstall ts-deepmerge from react-core dependencies (no longer imported anywhere)
- Add unit tests for useShallowStableRef in slots.test.ts (5 tests)
- Add changeset (patch) describing the FOR-75 performance fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Attachment queue & previews:
- Image lightbox with View Transition API morph animation
- Video lightbox with native controls and play button overlay
- Document lightbox (PDF via blob URL, text inline, info card fallback)
- Drop zone overlay with upload icon
- Filename preservation via InputContent metadata
- Proper video thumbnail sizing and play/pause indicator
- Fix attachment queue positioning (max-w-3xl constraint)
- Padding between X button and content for audio/document cards
- Document filenames wrap instead of truncating
Attachments config:
- onUploadFailed callback for validation/upload errors (file-too-large, invalid-type, upload-failed)
- onUpload accepts sync or async returns
- AttachmentUploadResult discriminated union with explicit interfaces
- Metadata field on Attachment and onUpload return type
AG-UI version bump:
- Bump @ag-ui/client, @ag-ui/core, @ag-ui/encoder, @ag-ui/proto to 0.0.51
- Remove process.env Vite workaround (fixed upstream in 0.0.51)
Deprecation lifecycle:
- @deprecated JSDoc on all legacy image upload APIs
- ImageRenderer, ImageRendererProps, ImageUpload type, imageUploadsEnabled prop,
inputFileAccept prop, ImageRenderer prop, AIMessage.image, ImageData
- Codemod at codemods/migrate-attachments.ts (15 tests)
- Migration guide updated with codemod instructions and new type shapes
Docs:
- New guide: docs/(root)/multimodal-attachments.mdx
- Updated migration guide with onUpload return type, metadata, codemod section
- Cross-links from prebuilt-components and migration guide
- Label change: "Add photos or files" → "Add attachments"
Tests:
- CopilotChat.attachments.test.tsx — 5 tests for onUploadFailed
- migrate-attachments codemod — 15 tests
- Add @tanstack/react-virtual to react-core deps; activate useVirtualizer
in CopilotChatMessageView when message count exceeds 50 (VIRTUALIZE_THRESHOLD).
Only visible items are mounted; total scrollable height is maintained via
an absolutely-positioned container div.
- Add scroll-element-context.ts to pass the scroll container ref from
CopilotChatView down to CopilotChatMessageView without circular imports.
- Expose window.__perfScrollEl (scroll container) and window.__perfMsgCount
(committed message count) for programmatic perf measurement.
- Update /perf demo page with two-phase timing: phase 1 measures event emit
time, phase 2 waits for all messages committed + scroll position stable
(animation settled). PerfPanel now shows emit / render+anim / total.
Benchmark results (MacBook, dev build):
Load 50 [anim]: emit 305ms render+anim 1433ms total 1739ms
Load 100 [anim]: emit 752ms render+anim 1578ms total 2331ms
Load 500 [anim]: emit 14.2s render+anim 1783ms total 16.0s
Load 50 [noAnim]: emit 299ms render+anim 182ms total 481ms
Load 100 [noAnim]: emit 771ms render+anim 161ms total 931ms
Load 500 [noAnim]: emit 13.9s render+anim 199ms total 14.1s
Key findings:
- React render cost is now O(1) in message count (161-199ms flat).
Virtualization fully decouples DOM work from history size.
- Animation (StickToBottom spring scroll-to-bottom) adds ~1.4-1.8s
regardless of message count; this is a fixed cost on every history load.
- The remaining bottleneck for large histories is event emit time (~5.6ms
per TEXT_MESSAGE_CHUNK through AbstractAgent). This is upstream of React
and tracked separately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@copilotkit/shared was doing `export * from "@copilotkit/license-verifier"`,
which pulled the entire license-verifier bundle (including Node's `crypto`)
into any client-side consumer. This caused "Module not found: Can't resolve
'crypto'" errors for users bundling @copilotkit/react-core for the browser.
Now shared only re-exports types (erased at compile time) and a client-safe
`createLicenseContextValue` inlined without crypto. Runtime imports
`createLicenseChecker` and `getLicenseWarningHeader` directly from
`@copilotkit/license-verifier`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous publish workflow released 1.55.0-next.8 to npm but the
post-release commit failed to push to main (blocked by branch
protection). This applies the version bumps and pre.json updates that
the workflow would have committed, unblocking future releases.
https://claude.ai/code/session_01N8sLK9h9p6FdRjyHqzKzVV
Add a new example app at examples/v2/react-router demonstrating CopilotKit
with React Router v7 (SSR/framework mode) and TanStack AI as the default agent.
- React Router v7 SSR with Hono server via react-router-hono-server
- CopilotKit runtime mounted as a Hono route on the same server
- TanStackAIAgent: thin AbstractAgent wrapper that accepts a chat() factory
callback, giving users full type safety over TanStack AI's adapter/model config
- Proper AG-UI event normalization bridging TanStack AI's event format to
what CopilotKit's @ag-ui/client pipeline expects
- Full-page CopilotChat UI with Tailwind CSS v4
Flatten all packages from packages/v1/* and packages/v2/* into packages/* —
every package now lives directly under the @copilotkit/ scope with no v1/v2
subdirectories.
- Move all v1 packages (react-core, react-ui, runtime, shared, etc.) from
packages/v1/* to packages/*
- Absorb v2 react code into packages/react-core/src/v2/ (exported via /v2 subpath)
- Absorb v2 agent code into packages/runtime/src/agent/ (exported via /v2 subpath)
- Move v2 packages (core, angular, demo-agents, etc.) to packages/*
- Replace all @copilotkitnext/* imports with @copilotkit/* equivalents
- Keep @copilotkitnext/angular as the sole exception (angular remains on next)
- Update CI workflows, renovate config, release scripts for flat structure
- No public API surface changes — all exports fields are preserved
Co-authored-by: Alem Tuzlak <t.zlak@hotmail.com>
Signed-off-by: Tyler Slaton <tyler@copilotkit.ai>
feat(runtime-v2): wire createLicenseChecker into CopilotRuntime
feat(runtime-v2): wire license checks into route handlers
feat(runtime-v1): pass licenseToken through to v2 runtime
@ag-ui/client 0.0.47 had a bug where connectAgent() hung forever
for agents that don't implement connect(), causing detachActiveRun()
and runAgent() to deadlock. Fixed in 0.0.48.