The launcher floats over a customer's page, and its border only earns its
place against a dark one -- so reviewing this branch needs a dark host page,
and the lab had no way to produce one.
Copied from `examples/v2/react/demo` rather than invented: the host owns a
theme state, and `CopilotChat` gets `className="dark"`, which is what makes
the package swap its own variable set. My first attempt stripped every
background instead, which is why the chat bubble, the send button, the
toolbar's on/off states and the error banner all vanished into one flat
grey -- the chat paints its own surfaces and has to be told, not undressed.
The colours are the demo's, by another route: it writes the oklch literals
that CopilotKit's variables use, and those are Tailwind's neutral steps --
`neutral-950` is `oklch(0.145 0 0)`, `neutral-50` is `oklch(0.985 0 0)`,
`neutral-800` is `oklch(0.269 0 0)`. Measured identical on the running lab.
`@custom-variant dark (&:is(.dark *))` is needed because Tailwind v4 points
`dark:` at `prefers-color-scheme` by default, so the toggle would have been
ignored in favour of the OS. Same declaration the package uses for its own
sheet.
The toggle sits top left, where the react demo puts it. Top right is where
the launcher floats.
Two type errors the example could not see. It has no check-types target,
and the import is type-only, so esbuild erases it and the build passes.
- `CopilotKitCoreFriendsAccess` came from `@copilotkit/core`, which the
example does not depend on. `react-core/v2` re-exports it.
- `onError` also accepts React's DOM error handler, so the parameter is a
union and reading `.error` / `.context` off it is not allowed. Narrow on
the CopilotKit shape first; a synthetic DOM event has nothing to report.
Example type errors go from 9 to 3. The three left are older: two react
-router codegen paths and one model name.
Add chat phrases and lab buttons that fail a frontend tool or emit RUN_ERROR.
Clear the Break threads cookie on load so a refresh does not keep a fake
thread-list failure.
GHSA-72qq-p3r5-f7wq (CVSS 9.3). web_core <= 0.10.1 passed an agent-supplied
`openUrl` argument straight to `window.open()` with no scheme allowlist, so a
Button whose `functionCall` named a `javascript:` URI executed arbitrary script
in the host origin when a user clicked it. The Basic Catalog is the default, so
no non-default configuration was required to be exposed.
We pinned 0.9.0 exactly, as a runtime dependency of two published packages
(@copilotkit/a2ui-renderer, @copilotkit/vue) and transitively of
@copilotkit/react-core and @copilotkit/angular, so downstream users could not
upgrade out of it on their own. 0.10.4 keeps the ./v0_9 and
./v0_9/basic_catalog entrypoints we import; the only symbol dropped from v0_9
is FrameworkSignal, which we never referenced.
Add regression tests over both renderers that reach the sink independently
(React and Lit). They assert that javascript: and data: URIs never reach
window.open, that https URLs still open with noopener,noreferrer, and that a
blocked scheme leaves the surface mounted rather than escaping into the click
handler. Verified they fail against 0.9.0 and pass against 0.10.4.
The reference page's Parameters section covered only `agentId` and `updates`, so
both props this branch adds were undocumented.
Adds an entry for each, and notes on `agentId` that passing `runtimeAgentId`
makes it required and turns it into a name the hook registers an agent under
rather than one it retrieves.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Writing a per-hook threadId onto an agent resolved by agentId alone mutates a
shared singleton, so two useAgent calls that share an agentId clobber each
other's thread (review feedback from @mme). Require runtimeAgentId when threadId
is provided: the hook then registers a private proxied agent (agentId ->
runtimeAgentId via CopilotKitCore.registerProxiedAgent) and scopes the threadId
to that instance instead of a shared one. Register/unregister run as one
balanced, StrictMode-safe effect, exposing the proxy via state so the hook
swaps from the provisional stand-in deterministically. Passing threadId without
runtimeAgentId now throws. Updates the React Native demo to the new API.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds /a2ui-catalog page and a runtime endpoint with NO a2ui config, so
A2UI switches on purely from the provider's a2ui.catalog (the #5774
path). Also fixes DemoButtonAgent, which never actually rendered: it
emitted the wrong activity content key (operations -> a2ui_operations)
and a non-canonical operation/component format. Rewritten to the A2UI
v0.9 wire format (createSurface/updateComponents, flat components, root
id "root") so the surface paints and the Confirm round-trip works.
Repairs TypeScript check-types across the monorepo and adds a CI gate so
regressions are caught going forward:
- core: bundler module resolution and strict-mode fixes
- sdk-js: bundler module resolution; keep codegen, formatter, packaging working
- react-core: fixes across components, hooks, and tests
- react-native: restore catch binding referenced by TypeError cause
- runtime: repair check-types and bound AI SDK schema inference
- web-inspector: nodenext import extensions, export Anchor
- remaining packages and node example: assorted check-types repairs
- deps: add missing type-only devDependencies
- license context driven from /info licenseStatus
- ci: run check-types in the static quality workflow
Squashed from 12 commits for a single, easily-revertable change.
The aisdk + tanstack agents expose a needsApproval bookFlight tool; /interrupts renders interrupts in-chat via useInterrupt(renderInChat) with a reusable InterruptCard and single/multiple suggestion pills. Requires OPENAI_API_KEY.
- Implemented audio transcription capabilities with error handling.
- Refactored CopilotChat component to utilize a directive for handling attachments.
- Improved CopilotChatReasoningMessage to manage streaming state and elapsed time more efficiently.
- Added new scroll view component for better message display and auto-scrolling behavior.
- Updated styles for A2UI surface components to enhance layout and scrolling.
- Enhanced tests for OpenGenerativeUIRenderer to ensure proper height measurement.
Render a per-turn persistent intelligence indicator that stays stable
across multi-step turns and settles into a "finished" tag. Splits the
component into IntelligenceIndicator (logic) + IntelligenceIndicatorView
(presentation), wires it into CopilotChatView / CopilotChatMessageView,
adds the slot styles to globals.css, and a Storybook story plus
timer-free logic tests.
## What does this PR do?
Adds a `position?: \"left\" | \"right\"` prop to the v2 `CopilotSidebar`
(and the underlying `CopilotSidebarView`), letting consumers anchor the
sidebar to either side of the viewport. Defaults to `\"right\"` so
existing usage is unchanged.
```tsx
<CopilotSidebar position=\"left\" />
```
### What changes when `position` flips
- **Anchor:** `cpk:right-0` ↔ `cpk:left-0`
- **Border side:** `cpk:border-l` ↔ `cpk:border-r`
- **Off-screen translate (closed state):** `cpk:translate-x-full` ↔
`cpk:-translate-x-full`
- **Body push margin:** `document.body.style.marginInlineEnd` ↔
`marginInlineStart` (with the matching `transition` CSS property name)
- **Aside element:** picks up a `data-position` attribute for
styling/test hooks
`position` is in the `useLayoutEffect` deps, so toggling it at runtime
cleans up the prior side's body margin before applying the new one.
### Tests
New `CopilotSidebarView.position.test.tsx` (7 cases) —
default/right/left class assertions, off-screen translate direction, and
verification that the wrapper forwards through to the view. All 32
sidebar-area tests pass; full react-core suite (1167 tests) green with
no regressions.
### Storybook
Added `RightPosition` and `LeftPosition` stories under
`UI/CopilotSidebarView` for visual diffing.
## Related PRs and Issues
- N/A
## Checklist
- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [ ] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] \"Allow edits by maintainers\" is checked
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The toggle button is hardcoded right-anchored (cpk:bottom-6 cpk:right-6).
When the sidebar sits on the left, the button should mirror to the left
so it lives behind/under the chat panel — otherwise it floats on the
opposite side from the sidebar it controls.
CopilotSidebarView now passes a position-aware className override into
the toggle slot (left-6 + right-auto, merged via tailwind-merge so the
default right-6 is dropped). Behavior on the right is unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lets consumers anchor the v2 CopilotSidebar to either side of the
viewport instead of the hardcoded right side. The prop flips the fixed
anchor, the border side, the off-screen translate direction, and the
body push margin (marginInlineStart vs marginInlineEnd) so the layout
mirrors correctly. Defaults to "right" for backward compatibility.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>