## Summary
- Remove `@langchain/community` from `@copilotkit/sdk-js`
peerDependencies — it's declared as `^0.3.58` but never imported
anywhere in the package
- This was the only constraint blocking `@langchain/core@1.x` resolution
for consumers using the LangGraph JS starter
## Context
`@copilotkit/sdk-js` has zero imports from `@langchain/community`. The
`^0.3.58` peer dep forced npm to resolve `@langchain/community@0.3.x`,
which transitively pulled in `@getzep/zep-cloud` → `langchain@0.3.x`,
conflicting with `sdk-js`'s own `langchain@>=1.0.0` peer requirement.
Removing the unused peer dep eliminates this resolution conflict
entirely.
## Test plan
- [ ] `npm install` in a fresh project using `@copilotkit/sdk-js`
resolves without peer dep warnings for `@langchain/community`
- [ ] Existing LangGraph JS starter installs cleanly
- [ ] No runtime behavior change (nothing imported from the removed dep)
@copilotkit/sdk-js declares @langchain/community as a peer dependency
but never imports from it. The ^0.3.58 constraint was the only thing
blocking @langchain/core@1.x resolution for consumers. Remove it
entirely since it serves no purpose.
## Summary
- Fixes#2986
- `reqOrRequest instanceof Request` fails when `@hono/node-server`
polyfills the Request class with a different prototype
- Replaced with a duck-type check (`isRequestLike`) that verifies `url`,
`method`, and `headers` properties exist
- The `!res` guard ensures IncomingMessage objects (which always come
with a ServerResponse) are still routed correctly
## Test plan
- [x] Added `request-duck-type.test.ts` covering native Request,
polyfilled Request, null/undefined, and missing properties
- [x] All 1225 existing runtime tests pass
- [x] Build passes
## Summary
- `sendMessage` returns `Promise<void>` but `usePushToTalk` accessed
`.id` on the result, causing a `TypeError` crash during push-to-talk
transcription
- Added guard to check if `sendFunction` returns a message before
accessing `.id`
- Updated `SendFunction` type to accept `Promise<Message | void>`
Fixes#3011
## Test plan
- [x] Added unit tests verifying void return handling
- [x] Added unit tests verifying message-with-id return handling
- [x] All react-ui tests pass
## Summary
- `.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
Fixes#2325
## Test plan
- [x] All react-ui tests pass
- [ ] Visual verification: render CopilotKit chat in a constrained
container (e.g. 300px sidebar) and confirm no horizontal scrollbar
appears
## 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
- `Button` component wrapped with `React.forwardRef` to fix ref warning
from Radix UI's `DropdownMenuTrigger asChild` pattern
Closes#2947
## Test plan
- [x] All affected packages build successfully
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## 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
## Summary
- Skips keydown handling during IME composition (e.g. CJK input) by
checking `isComposing`/`keyCode 229`
- Guards textarea measurement from resetting value mid-composition,
which would break the composition session
Closes#3318
## Summary
- Always calls `onChange("")` after send in controlled mode so the
parent component is notified to clear its state
- Previously `onChange` was only called inside the `!isControlled`
branch, leaving controlled parents unaware the input was submitted
Closes#3593
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
- `buildFrontendTools` only checked `tool.available !== false` but the
`available` field can also be the string `"disabled"`, which is truthy
- Added `tool.available !== "disabled"` to the filter so disabled tools
are properly excluded
- Added test verifying tools with `available: "disabled"` are filtered
out
## Test plan
- [x] New test: tool with `available: "disabled"` is excluded from
`buildFrontendTools`
- [x] All existing available-filtering tests still pass
- [x] Full core test suite passes (338 tests)
## Summary
- onThumbsUp/onThumbsDown/onReadAloud/onRegenerate callbacks on
CopilotChatAssistantMessage were receiving the browser SyntheticEvent
instead of the AssistantMessage object
- Wrapped the onClick handlers to pass the message explicitly:
`onClick={() => onThumbsUp(message)}`
- Same fix applied to onReadAloud and onRegenerate for consistency
## Test plan
- [x] Red-green verified: test confirms callback arg has `id`, `role`,
`content` and NOT `nativeEvent`/`target`
- [x] Full react-core test suite passes (1071 tests)
- [x] Build passes
Closes#3457
## Summary
- useRenderCustomMessages threw "Agent not found" when the agent was
undefined during the connecting state
- Changed the throw to return null, allowing the component to render
gracefully while the agent is being resolved
## Test plan
- [x] Red-green verified: test calls hook with nonexistent agent,
asserts returns null not throws
- [x] Full react-core test suite passes (1071 tests)
- [x] Build passes
Closes#3497
## Summary
- CopilotListeners called useAgent() unconditionally, which throws when
no agents are registered and no runtimeUrl is configured
- Split into CopilotListeners (outer, handles error subscription) and
CopilotListenersAgentSubscription (inner, uses useAgent)
- Inner component only renders when agents exist or a runtime is
configured
## Test plan
- [x] Red-green verified: render CopilotListeners with no agents, assert
no throw
- [x] Full react-core test suite passes (1071 tests)
- [x] Build passes
Closes#3249
## 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)
## Summary
- LangChain adapter now always uses `randomId()` for message stream IDs
instead of relying on `lc_kwargs.id` (which GoogleGenerativeAI sets to
`"0"` for all messages)
Closes#2929
## Test plan
- [x] `@copilotkit/runtime` tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- Default `max_tokens` was hardcoded to 1024, causing truncated
responses for most use cases
- Increased default from 1024 to 4096 while still respecting
user-provided `maxTokens`
Fixes#2354
## Test plan
- [x] Added test verifying default max_tokens is 4096 when not specified
- [x] Added test verifying user-provided maxTokens is passed through
- [x] All existing anthropic adapter tests pass
## Summary
- Providers like `@ai-sdk/openai-compatible` emit sequential IDs
(`txt-0`, `reasoning-0`, `msg-0`) that are treated as unique but collide
across requests
- The existing check only caught the literal `"0"` — expanded to match
the `^(txt|reasoning|msg)-0$` pattern
- Both `text-start` and `reasoning-start` event handlers now use
`randomUUID()` for these non-unique IDs
## Test plan
- [x] Added `provider-id-collision.test.ts` with 4 tests covering txt-0,
reasoning-0, msg-0, and legitimate ID preservation
- [x] All 1226 runtime tests pass (including existing
config-tools-execution tests)
Fixes#3410, #3623
## Summary
- `onAfterRequest` middleware callback was called with `{}` instead of
actual hook parameters
- Now forwards `threadId`, `runId`, `inputMessages`, `outputMessages`,
and `url` from the v2 runtime's `hookParams`
- The `onBeforeRequest` handler at line 566 already did this correctly;
this fix makes `onAfterRequest` consistent
## Test plan
- [x] Added `on-after-request.test.ts` verifying the callback receives
threadId and runId (not empty object)
- [x] All 1226 runtime tests pass
Fixes#2124
## Summary
Fixes#2450
Token trimming in the Anthropic adapter could remove assistant messages
containing `tool_use` blocks while keeping the corresponding user
messages with `tool_result` blocks. Anthropic's API rejects orphaned
`tool_result` messages. This adds a post-processing step that removes
orphaned `tool_result` blocks after trimming.
## Test plan
- [ ] Verify token trimming preserves tool_use/tool_result pairing
- [ ] Verify orphaned tool_result blocks are removed
- [ ] Verify messages with mixed content (tool_result + text) retain
non-orphaned content
## Summary
Fixes#2405
Both OpenAI and Anthropic adapters used a hardcoded token limit for
message trimming. This adds an optional `maxInputTokens` constructor
parameter to both adapter classes, allowing consumers to override the
default context window limit.
## Test plan
- [ ] Verify default behavior unchanged when `maxInputTokens` not
provided
- [ ] Verify custom `maxInputTokens` is passed through to
`limitMessagesToTokenCount`
## Summary
Fixes#2504
When Anthropic returns a `tool_use` block for a tool not registered in
the current action set, the adapter would crash trying to process it.
This adds a check against known action names and skips unknown tool_use
blocks gracefully.
## Test plan
- [ ] Verify known tools are still processed normally
- [ ] Verify unknown tool_use blocks are skipped without crashing
## Summary
- langchain-mcp-adapters sends tool call result content as an array of
`{type:"text", text:string}` objects
- Extracts and joins text parts so downstream consumers always receive a
plain string
Closes#2922
Closes#3141
`applyCredentialsToAgents`/`applyCredentialsToAgent` were defined but
never called from `initialize()`, `setAgents__unsafe_dev_only()`, or
`addAgent__unsafe_dev_only()`. Only remote agents received credentials
via constructor. Local agents now receive credentials alongside headers.
Split from #3838.
Closes#3741
Add `toolCallId` prop to all three status branches (InProgress,
Executing, Complete) of the ToolCallRenderer, and update the
`ReactToolCallRenderer` type to include it in the discriminated union.
Split from #3838.
Closes#1936
`extractParametersFromSchema` now preserves enum values as structured
data on string parameters, recursively extracts nested object
attributes, and converts object arrays to `object[]` type with
attributes. This ensures complex MCP tool schemas survive the
`Parameter[]` -> Zod conversion without losing nested structure.
Split from #3838.
The docs table and prose claimed `debug: true` sets `verbose: true`,
but the implementation intentionally defaults verbose to false (PII
safety). Fixed the table and explanatory text to match.
Also removed packages/vscode-extension/README.md which was committed
on this branch by mistake — it describes an unrelated VS Code extension
and has nothing to do with debug mode.
Two new test cases covering the core behavioral fix:
- User collapses during streaming → panel stays collapsed after stream ends
- User collapses then re-expands during streaming → panel stays open after stream ends
Without act(), React 18 defers the state update through its scheduler,
which can race with waitFor polling on slow CI runners (Node 20.x/22.x).
Wrapping in act() forces synchronous flush.
The auto-collapse useEffect unconditionally called setIsOpen(false) when
streaming ended, overriding any manual expand/collapse the user had
performed. Add a userToggledRef that tracks explicit clicks so the
effect only auto-collapses when the user hasn't interacted.
The CopyButton in react-core was showing the "copied" checkmark based on
an independent clipboard availability check rather than the actual copy
result. This meant a failed copy (e.g. permission denied) would still
show the success indicator. Now the onClick handler returns the boolean
from copyToClipboard, and handleClick uses that to drive the UI state.
Also removes unsafe type casts of onClick to Promise<void>.
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.
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.
Extract getErrorSuppression as a pure testable function from the
routeError closure. Replace the mock-only test that only proved mock
wiring with 12 real assertions covering all visibility x isDev
combinations against the actual logic.
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 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 shared visitedRefs Set was mutated in place, so when two sibling
properties referenced the same $def (e.g. billing and shipping both
referencing Address), the second resolution was incorrectly flagged as
circular. Clone the set before recursing so each branch has its own
ancestry path. Added regression test that fails without this fix.
Recursive JSON schemas that reference themselves via $ref would cause
infinite recursion and stack overflow. This adds a visited set that
tracks which $ref paths have been seen during resolution. When a cycle
is detected, it breaks with z.any() and logs a console.warn so users
get feedback. Also adds console.warn for the generic z.any() fallback
on unsupported schema types.
Adds tests for circular refs, non-circular $ref resolution, anyOf with
$ref variants, integer type, null type, and unsupported type warning.