Fixes#399
When the CopilotTextarea hovering popup (CMD+K / CTRL+K) is open and the
user presses `Escape`, the popup loses focus entirely, instead of safely
closing and returning focus to the underlying textarea.
This PR:
1. Adds an `Escape` key handler to the `HoveringInsertionPromptBoxCore`
component so the textarea can intercept the key.
2. Adds a document-level `Escape` listener to `HoveringToolbar` to
cleanly close the popup and use `ReactEditor.focus()` to restore focus
to the Slate editor.
## Testing
1. Run `textarea` example.
2. Type in the input, press `CMD+K` (or `CTRL+K`).
3. Press `Escape`.
4. The popup closes and focus is successfully returned to the editor
input without needing an extra mouse click.
The v1 CopilotRuntime always set afterRequestMiddleware on the v2 runtime,
causing parseSSEResponse to attempt reading the cloned SSE stream body even
when no user hooks existed. This results in "Failed to read SSE response
body in afterRequestMiddleware" warnings. Only register the handler when
the user actually provided afterRequestMiddleware or middleware.onAfterRequest.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The shouldCreateModalState guard introduced in #3101 made setModalOpen
and isModalOpen conditionally undefined when isModalDefaultOpen wasn't
explicitly passed. This broke programmatic modal control for anyone
using useCopilotChatConfiguration outside of CopilotPopup/CopilotSidebar.
Reverts to the simpler ?? fallback pattern: each provider always has
modal state, preferring parent state when available, falling back to
its own internal state otherwise. Initial state still respects the
local isModalDefaultOpen prop (fix from 76e381f78).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The V1 CopilotKit provider hardcoded useSingleEndpoint={true}, preventing
users from opting into REST transport mode. Now passes through the user's
prop value, defaulting to true for backward compatibility.