## Summary
Fixes#2194
`CopilotModal` and `CopilotModalProps` were not exported from
`@copilotkit/react-ui`, making them inaccessible to consumers. Adds both
exports to the chat barrel file.
## Test plan
- [ ] Verify `CopilotModal` and `CopilotModalProps` are importable from
`@copilotkit/react-ui`
## Summary
- The loading spinner only appeared when the last message had role
"user"
- During tool execution the last message can have role "tool", hiding
the indicator
- Now also show it when the trailing message is a tool result
Closes#3055
Closes#1921
The Markdown component accepted `components` but not `urlTransform`,
preventing users from customizing URL sanitization. Added `urlTransform`
as an optional prop with passthrough to `MemoizedReactMarkdown`.
Split from #3838.
## Summary
- `checkForUpdates()` in dev console is now gated on `showDevConsole`,
preventing unnecessary network requests when the console is disabled
Closes#2751
## Test plan
- [x] `@copilotkit/react-core` tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The truthiness check swallowed null, which is a valid value in
react-markdown that explicitly disables the default URL sanitizer.
Changed to an explicit undefined check.
## Summary
- Removes the `key` prop from `CodeBlock` in `Markdown.tsx` entirely
- The original `Math.random()` key caused React to remount the component
on every render, producing visible flickering
- A content-based key (language + content prefix) still changes every
streaming token, causing the same problem
- Without an explicit key, React uses positional identity — stable
across re-renders while content streams in
Closes#2669
## Test plan
- [x] `@copilotkit/react-ui` tests pass
- [x] `@copilotkit/react-ui` build succeeds
- [ ] Manual: verify code blocks no longer flicker during streaming in
chat UI
## Summary
Fixes#2234
React's hydration fails when block-level elements (like `<div>`) are
nested inside `<p>` tags in the Markdown component. Replaces the `<p>`
wrapper with `<div>` (adding `copilotKitParagraph` class for styling) to
prevent SSR hydration mismatches.
## Test plan
- [ ] Verify Markdown rendering in SSR context has no hydration errors
- [ ] Verify paragraph styling is preserved via `copilotKitParagraph`
class
Address review feedback: extract the repeated clipboard availability check +
writeText + error handling pattern into a shared copyToClipboard() utility in
@copilotkit/shared. All 9 call sites across angular, react-core, and react-ui
now use the shared utility instead of duplicating the same code block.
Same bug pattern as console.css and input.css: bare `.dark,` was a
standalone selector leaking all --copilot-kit-* CSS custom properties
onto any element with a .dark class. Also removed broken `:root`
pseudo-element from `body[style*="color-scheme: dark"] :root` — :root
cannot be a descendant of body, so this selector never matched.
Fix: drop standalone `.dark,` (redundant with `html.dark` and
`body.dark`) and remove the non-functional `:root` descendant.
The blockquote.copilotKitMarkdownElement p selector targeted literal <p>
elements inside blockquotes, but paragraphs now render as <div> after
the hydration fix. Updated to target .copilotKitParagraph class instead.
Also removes unused import and adds a regression test for this selector.
Add null checks for navigator.clipboard across all copy-to-clipboard
calls to prevent TypeError in non-localhost environments where the
Clipboard API is unavailable. The copied indicator now only appears
after a confirmed successful write, preventing false positive UX
feedback when the clipboard API is missing or the write fails.
The original Math.random() key caused React to remount the CodeBlock on
every render. The PR's content-based key (language + content prefix) still
changed every streaming token, causing the same flickering. Removing the
key entirely lets React use positional identity, which is stable across
re-renders while content streams in.
Closes#2669
The p tag was changed to div to fix hydration errors, but CSS selectors
still targeted p.copilotKitMarkdownElement. Updated to use the
.copilotKitParagraph class selector so paragraph styling (line-height,
font-size, margin) applies correctly to the new div element.
The Markdown component accepted components but not urlTransform,
preventing users from customizing URL sanitization. Added urlTransform
as an optional prop with passthrough to MemoizedReactMarkdown.
The loading spinner only appeared when the last message had role "user".
During tool execution the last message can have role "tool", hiding the
indicator. Now also show it when the trailing message is a tool result.
checkForUpdates() fired unconditionally on mount, making a network
request even when the dev console was disabled. Now the useEffect
short-circuits when showDevConsole is false.
The .copilotKitMessagesFooter used width:97% which caused horizontal
overflow in constrained containers. Changed to width:100% with
box-sizing:border-box so padding is included in the width calculation.
sendMessage returns Promise<void> but usePushToTalk accessed .id on
the result, causing a TypeError crash. Guard the .id access with an
existence check and update the SendFunction type to accept void.
818e4e767 added min-height: 100vh / height: 100% to
.copilotKitSidebarContentWrapper and its children in an attempt to
support full-height children inside the sidebar. This caused empty
space equal to the full viewport height to appear below the app
content whenever CopilotSidebar was mounted, even when collapsed.
The wrapper only needs to push the page content left (via margin-right)
when the sidebar expands — it does not need to control its own height.
Remove the height rules; child layout is the responsibility of the
app, not the sidebar wrapper.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The drag-and-drop wrapper div added in fc1cfa09d (attachments feature)
broke the flex layout of the chat window. The div had no class when
not dragging, so no CSS rule applied flex-grow — messages and input
collapsed to their natural height instead of filling the window.
Add copilotKitChatBody class to the wrapper and give it flex: 1 1 0%
so it claims the remaining window height, restoring the input-pinned-
to-bottom behaviour present in 1.51.1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reverts the copy-dts.mjs approach from #3612 in favor of typesVersions
which is the standard Node/TS mechanism for resolving subpath types
under legacy moduleResolution: "node".
- New docs/(root)/migration-guides/ section with migrate-to-v2, migrate-attachments,
migrate-to-1.10.X, migrate-to-1.8.2
- Troubleshooting now only contains error-debugging, observability-connectors, common-issues
- Update all @deprecated JSDoc URLs from /troubleshooting/ to /migration-guides/
- Update doc cross-links (multimodal-attachments page, snippet import)
- Move snippet to snippets/shared/migration-guides/
- Set minimum version to v1.56.0 (was vX.Y.Z placeholder)
- Restore console.error as safety net in processFiles catch blocks (errors no longer
silently vanish when onUploadFailed callback is not provided)
- Add try/catch to useBlobUrl atob() — gracefully handles malformed base64 instead of
crashing the component tree
- Fix DocumentLightboxContent: use blobUrl instead of undefined src variable
- Add .catch() to View Transition API transition.finished promise
- Codemod: preserve actual imageUploadsEnabled value (false, dynamic expressions)
instead of hardcoding true — adds 3 new test cases (18 total)
- Replace all placeholder @deprecated versions (v1.x.0) with @since 1.56.0
- Add missing @since to ImageRenderer, ImageRendererProps, AIMessage.image tags
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
- Fix stale closure in paste handler by using processFilesRef pattern
- Wrap processFiles calls in try/catch across paste, file upload, and drop handlers
- Add early return for empty/falsy accept string in matchesAcceptFilter
- Block send while attachments are still uploading
- Add id field to Attachment interface, replace _id hack with randomUUID()
- Add 10s timeout to generateVideoThumbnail to prevent infinite hanging
- Show placeholder div for uploading attachments instead of rendering incomplete source
- Include filename context in upload error messages