The routeError function returned early for ALL errors when
showDevConsole was false, suppressing user-visible errors
(TOAST and BANNER visibility) in production.
Now only DEV_ONLY and SILENT errors are suppressed in production.
TOAST and BANNER errors are always surfaced to the chat UI.
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.
The hardcoded 1024 default was too restrictive for most use cases,
causing truncated responses. Increase to 4096 as a more reasonable
default while still respecting user-provided maxTokens.
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>
Verify that:
- State is tracked when a run errors (getStateByRun returns error state)
- A new run after an error works correctly (runFinished flag resets,
second run tracked independently)
When the backend emits RunErrorEvent via the AG-UI protocol, several
components did not handle it:
- ProxiedCopilotRuntimeAgent: isRunning stayed true, causing
data-copilot-running to never transition to false (infinite spinner)
- StateManager: activeRun entries were never cleaned up, runFinished
flag never set (stale state on subsequent runs)
- Angular CopilotKitAgent: same isRunning bug as the proxy agent
- useAgentNodeName: node name stuck at last step instead of "end"
onRunErrorEvent is distinct from onRunFailed — the former handles
protocol-level RUN_ERROR events from the backend, the latter handles
local exceptions (network errors, deserialization failures).
## Summary
- **Root cause**: `CopilotChatMessageView` deduplicated messages with
`new Map(messages.map(m => [m.id, m]))`, which keeps only the *last*
occurrence of each ID. During streaming, when an agent fires multiple
tool calls in one turn, the same message ID appears multiple times:
first with text content, then with empty content + tool calls appended.
The last entry wins, wiping the text.
- **Fix**: Replace "keep last" with a **merge** strategy for assistant
messages — recover non-empty `content` from any earlier occurrence while
keeping the latest `toolCalls` (which accumulate). All other message
roles retain "keep last" behavior.
- **Test**: Added a regression test covering the three-occurrence
scenario (text → first tool call → second tool call) to confirm the
merged message renders both the original text and the final tool call
set.
## Test plan
- [x] New test `"preserves assistant text content when later duplicate
has empty content (multi-tool-call scenario)"` passes
- [x] Existing dedup tests (single duplicate, order preservation,
activity rendering) all pass unchanged
- [x] Full `@copilotkit/react-core` test suite: **950 passed, 0 failed**
(baseline was 949)
Closes#3470🤖 Generated with [Claude Code](https://claude.com/claude-code)
TanStackChatMessage.content uses any[] for multimodal so
messages are directly passable to any adapter without casts.
Add env.d.ts with vite/client types for CSS imports.
- 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
The ui/message handler added messages to the chat but never called
runAgent(), so the agent never processed MCP-sent messages.
- Use copilotkit.runAgent({ agent }) through RunHandler for frontend
tools, context, tool execution, and abort support
- Send JSON-RPC response immediately after addMessage, before agent run
- Agent run is fire-and-forget with error logging
- followUp parameter: true=always, false=skip, default=user messages only
Fixes#3216
- Fix JSDoc: "while keeping the latest toolCalls" was wrong for the ?? case;
now says "recovers toolCalls from earlier occurrences if the latest is
undefined" and notes that [] is treated as intentional
- Add @internal annotation to signal export is for testing only
- Remove redundant AssistantMessage casts inside the role-narrowed branch
- Add missing content assertion to "uses latest content" render test
- Add test: [] toolCalls from later chunk is kept (not fallen back from)
- Add test: undefined content on both sides is handled without error
- Add changeset for @copilotkit/react-core patch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>