## Problem
The published declaration files for `@copilotkit/react-core`,
`@copilotkit/react-ui`, and `@copilotkit/react-textarea` contain imports
that TypeScript cannot resolve, so **`attw` (Are The Types Wrong)
reports `InternalResolutionError` across every resolution mode**
(`node10` / `node16` / `bundler`). In `@copilotkit/react-core` this was
being **masked in CI** by `--ignore-rules internal-resolution-error` on
the package's `attw` script — so the existing `check:packages` gate
looked green while consumers under `moduleResolution:
bundler`/`node16`/`nodenext` got broken types (the symptom reported in
#3324: `has no exported member 'useAgent'`, etc.).
Two distinct artifacts leaked into the emitted `.d.ts` / `.d.cts` /
`.d.mts` (neither affects the JS bundles):
1. **Side-effect CSS imports** — `import "./index.css"` is intentionally
kept in the JS so styles auto-load for bundler consumers, but
`rolldown-plugin-dts` also left it in the declarations, where TypeScript
can't resolve a `.css` as a typed module.
2. **Extensionless relative `./context` import** —
`@copilotkit/react-core/v2/headless` re-exports the externalized context
module; the JS bundle correctly externalizes it to
`@copilotkit/react-core/v2/context`, but the declaration kept the
relative `./context`, which is invalid in ESM declarations.
> Note: this is **not** the missing-`exports.types`-condition theory
from #3324. tsdown deliberately relies on co-located `.d.mts`/`.d.cts`
siblings; `@copilotkit/core` already resolves cleanly. The real defects
are the two leaked imports above.
## Fix
A small tsdown `build:done` hook post-processes the emitted declarations
**on disk** (after every format is written, so it catches both `.d.mts`
and `.d.cts`):
- strips side-effect CSS imports from declarations (JS keeps them);
- rewrites the relative `./context` import to the
`@copilotkit/react-core/v2/context` package path (matching how the JS
bundle externalizes it).
Also:
- **Removed the `--ignore-rules internal-resolution-error` band-aid**
from `react-core`'s `attw` script so the existing CI gate validates for
real.
- **Dropped the dead `codeSplitting` option** from the UMD configs —
tsdown never reads it (it's a rolldown-only key), and it was failing
`tsc` in the configs that type-check themselves. UMD output is unchanged
(single file).
## Verification
- All three packages build; **no CSS or relative-`./context` imports
remain in any declaration**, while the JS bundles still contain them
(styles auto-load preserved).
- `attw` + `publint` pass for all packages **with no suppression**
(`react-core`'s `/v2`, `/v2/headless`, `/v2/context` are green for
node16-cjs/esm/bundler).
- Unit tests pass.
- A standalone consumer project (real tarball install, `skipLibCheck:
false`) type-checks the public APIs — including `useAgent` /
`useFrontendTool` / `useConfigureSuggestions` — cleanly under **both
`bundler` and `nodenext`**, and the headless↔context class is nominally
identical.
## Out of scope (follow-ups)
- `@copilotkit/react-native`: its `--ignore-rules
internal-resolution-error` currently suppresses nothing (no IRE) and it
has a separate `NoResolution` flag.
- `@copilotkit/vue`: a large, genuine set of `.vue`/relative-import
declaration errors unrelated to this change.
Relates to #3324.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Redesigns the shared `<copilotkit-threads-drawer>` element
(`@copilotkit/web-components`) to the new Figma UX, keeping the React,
Vue, and Angular wrappers in lockstep. Pure-VIEW change — no
`@copilotkit/core`, runtime, or `useThreads` changes.
**Ticket:** [ENT-1051](https://linear.app/copilotkit/issue/ENT-1051) ·
**Figma:** [Thread
Drawer](https://www.figma.com/design/feSsBJw1qCfLp0JNnOurrJ/CopilotKit-Intelligence?node-id=723-78)
· **Spec:**
[Notion](https://app.notion.com/p/3953aa381852819ab464dae3894e7f18)
## What changed
- **Header** → right-aligned icon row. On desktop it holds the
**collapse** toggle (sidebar glyph); on mobile the **close** toggle. No
title text, no "+ New" pill. Optional `slot="header"` preserved (empty
by default; the toggle right-aligns after it).
- **New Conversation** row (plus-square + label) below the header —
keeps `part="new-thread-button"` + the `new-thread` event.
- **Recent Conversations** heading + **funnel** filter icon → Active/All
popover. Preserves `_filter` + `filter-change` and
`part="filter-active"`/`filter-all"`.
- **Per-row kebab menu** (⋮) holding Archive/Unarchive + Delete —
preserves those events + parts. An open kebab now shields the rest of
the list from hover so it reads as a single surface (see Review fixes).
- **Delete confirm** is a native `<dialog>` opened with `showModal()`
(browser top layer), centered over the drawer's visible box — it can't
paint under other UI or drop below the fold. jsdom falls back to the
`open` attribute.
- **Archived rows** render italic/muted inline in the "All" view.
- **Desktop collapse** → `collapsed` / `collapsible` props (default
**expanded**) + a `collapse-change` event / `CollapseChangeDetail`.
Collapsing sets `--cpk-drawer-reserved-width: 0` on the document root so
the host grid reclaims the column with no hydration flicker.
- **Unified floating cluster** (Figma "closed" mockup) =
`[sidebar-toggle] [+ New Conversation]`, shown in both the mobile-closed
and desktop-collapsed states. Mobile stays an off-canvas modal (backdrop
/ Escape / focus-trap).
## Compatibility
- All existing `::part()` names and events are preserved; only
**additive** parts are introduced: `collapse-toggle`, `close-toggle`,
`section-heading`, `filter-toggle`, `row-menu`, `row-menu-popover`,
`launcher-cluster`, `launcher`, `launcher-new-thread`, plus
`confirm-dialog`/`confirm-cancel`/`confirm-delete`/`backdrop`. One
additive event: `collapse-change`.
- Additive wrapper props: `recentLabel` (all frameworks);
`collapsible`/`collapsed` + `onCollapseChange` (React) / equivalents in
Vue & Angular.
- **Usage note (now in the docs):** the drawer and `<CopilotChat>` must
share a chat-configuration provider so the drawer drives the chat —
`CopilotChatConfigurationProvider` (React/Vue) /
`provideCopilotChatConfiguration()` (Angular). The v2
`CopilotKitProvider` does not provide that context on its own.
- Verified: **no example `::part()` theme changes required** — every
example themes the drawer via inherited `--cpk-drawer-*` custom
properties.
## Descoped / changed during development (re: earlier review)
- **Client-side search was removed at the designer's request.** There is
**no** search UI, `search` event, `search-toggle`/`search-input` part,
or `onSearch` wrapper prop in the shipped element. Any remaining
"search" mention in older comments is stale.
- **Desktop collapse was briefly backed out, then re-restored** per the
designer (commit `8bfd245305`). The shipped element **has** collapse
(`collapsed` is a live public property — it was not removed).
## Review fixes (commit `0b4f6ca392`)
Addressing @MikeRyanDev and @marthakelly:
- **`core/threads.ts`** — a full-list refetch (filter-change / retry)
now clears `fetchMoreError` on both `listRequested` and `listSucceeded`,
so the inline "couldn't load more — retry" banner no longer survives
onto a fresh list.
- **Escape while confirming delete** — the host keydown handler now
consumes Escape while a confirmation is open; previously the bubbled
keydown fell through and closed the whole mobile drawer along with the
confirmation.
- **Open kebab menu shields the list** — `.list.menu-open
.row:not(.menu-open)` gets `pointer-events: none`, so other rows no
longer reveal their kebab / paint a host `::part(row):hover` background
around or behind the open popover. Click-away dismissal is preserved via
the existing document pointerdown handler. (Verified live in the
langgraph-js example.)
- **Docs token** — dropped the removed `--cpk-drawer-rail-width` from
the web-components README.
## Testing
All suites run via `nx`, green through each package's lefthook
pre-commit gate:
- `@copilotkit/web-components` — **92** drawer element tests + `:build`
green. Covers header collapse/close toggles, New Conversation, funnel
filter switch, `recentLabel`, kebab open + archive/delete routing,
confirm-dialog gating + native cancel + **backdrop-click dismiss**,
**Escape-while-confirming (no drawer close)**, **open-menu row shield**,
collapse/cluster/column-reclaim, archived-italic, preserved
parts/events, `header` slot + `label` aria-labels.
- `@copilotkit/core` — **553** tests incl. the new `clears a lingering
fetchMoreError when a full list refetch succeeds`.
- `@copilotkit/react-core` — CopilotThreadsDrawer suite + full package
**1419** green.
- `@copilotkit/vue` — **32** incl. SSR + the `collapsible`
boolean-prop-default regression test.
- `@copilotkit/angular` — CopilotThreadsDrawer spec **35** (incl.
**scoped-chat-input focus**: prefers the ancestor `copilot-chat-view`
over the document-global fallback); full package **178**.
## Follow-on
- Docs (screenshot + reference/guide) on the release-gated docs PR
**#5780**.
- Release (`web-components` + `react-core` + `vue` + `angular`,
lockstep) + CLI scaffolding bump.
- Example grid/theme updates ride the release in **#5828**.
- **[ENT-1080](https://linear.app/copilotkit/issue/ENT-1080)** — dedup
the per-wrapper `findChatInput` / open-state fallback (marthakelly #6,
deliberately deferred as a cross-package refactor).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Design iteration (Ben's designer):
- RESTORE desktop collapse. Re-add collapsed/collapsible + collapse-change
(element + all three wrappers, lockstep), the desktop header collapse toggle,
and the CollapseChangeDetail type/re-export. Default is EXPANDED.
- UNIFY the closed affordance into one floating cluster (Figma 'closed' mockup):
a sidebar-glyph toggle + a New Conversation (+) icon button, shown in BOTH the
mobile-closed state (adds New Conversation to the old single launcher) and the
desktop-collapsed state. Parts: launcher-cluster, launcher, launcher-new-thread.
- COLUMN RECLAIM (no empty reserved gap): on desktop-collapse the element sets
--cpk-drawer-reserved-width: 0px on the document root (reaches the grid past
the wrapper host via :root inheritance); hosts read it in grid-template-columns.
Default expanded never sets it, so no hydration flicker.
- DELETE MODAL centered over the DRAWER PANEL, not the viewport: keeps the
top-layer showModal() robustness (never clipped) but drives --confirm-cx/cy
from the visible .root rect and caps width to the drawer band.
- Vue fix: default collapsible to true in the wrapper. Vue coerces an omitted
Boolean prop to false, which was silently forcing collapsible=false (collapse
toggle vanished) — React/Angular pass undefined and keep the element default.
Validated live in the Nuxt (Vue) and Angular demos against managed Intelligence:
collapse/expand, cluster + New Conversation, column reclaim, drawer-centered
top-layer modal, mobile cluster. Tests: web-components 89, react-core 1419,
vue 32, angular 34 — all green.
Parity with the vue fix: the react-core drawer wrapper references the Lit
`<copilotkit-threads-drawer>` element from @copilotkit/web-components, which was
not externalized in the main ESM/CJS build entry — so tsdown inlined the whole
element + a second copy of lit-html into the react-core dist.
This bloats the library and breaks Vite-based React consumers with a duplicate
lit-html binding ("Identifier 'h' has already been declared"); webpack/Next
consumers dedupe it so it went unnoticed. Externalizing it (as @copilotkit/core,
@copilotkit/shared, @copilotkit/web-inspector, @copilotkit/a2ui-renderer already
are) resolves the import to the single real package at runtime. The self-contained
UMD builds intentionally keep it inlined.
react-core test suite: 1416/1416 pass.
The thread panel is a persistent always-visible sidebar on desktop; the Figma
"closed" mockup is the MOBILE state, already covered by off-canvas behavior.
- web-components: remove the `collapsed`/`collapsible` properties,
`_toggleCollapsed`, the header collapse-toggle button, and the
collapsed-cluster render branch; render() always paints the full panel body.
Gate the now control-less header on a `_hasHeader` slotchange flag so no empty
bar renders. Drop the unused `iconSidebar`, the `CollapseChangeDetail` type +
`collapse-change` event-map entry, the index re-export, and the
`.root.collapsed`/`.collapsed-cluster` styles.
- react: drop the `collapsible` prop + property assignment, the
`onCollapseChange` prop + `collapse-change` listener/handler, and the local
`CollapseChangeDetail` type.
- vue: drop the `collapsible` prop + element binding, the `collapse-change`
emit + `@collapse-change` handler, and the local `CollapseChangeDetail` type.
- angular: drop the `collapsible` input + property push, the `collapseChange`
@Output + event wiring (and now-unused EventEmitter/Output imports), and the
local `CollapseChangeDetail` type.
- tests: remove all collapse tests across the four packages; add an element
header-gating test. Mobile off-canvas (open-driven) behavior is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Also fixes the collapsible-default test assertion (element defaults collapsible=true,
mirroring licensed; the prior undefined assertion only passed vs a stale dist).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirror the existing recentLabel (passthrough) and onSearch (element-event)
props with two additive props targeting the element's forthcoming
`collapsible` property and `collapse-change` event.
- react: add `collapsible?: boolean` (pushed as an element PROPERTY, like the
default-true boolean `licensed`) and `onCollapseChange?: (collapsed) => void`
(wired via the handler-ref addEventListener block, like onSearch).
- vue: add `collapsible?: boolean` (imperative property push in the
watchEffect, like `licensed`) and re-emit the element's `collapse-change`
event as `collapse-change(collapsed)` (matching the `search` emit convention).
- angular: add a `collapsible` signal input (property push in the effect, like
`licensed`) and `@Output() collapseChange = new EventEmitter<boolean>()`
wired from the element's `collapse-change` event (like `search`).
CollapseChangeDetail is declared locally in each wrapper with a TODO to switch
to the package export once the parallel element PR that adds the collapse
feature lands and is published (the built element types in this worktree
predate it).
Testing: added mirrored tests per framework (property-set + event-passthrough);
full nx test suites green (react-core 1420, vue 1070, angular 178); check-types
and build green for all three packages.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bucket A — mobile open-flash:
- Default the drawer element's `open` property to `false`. On a mobile viewport
the previous `open = true` default made the first render satisfy
_isMobileModalOpen(), painting the modal + body scroll-lock + focus steal for
one frame before any wrapper effect could close it. Desktop is unaffected
(only .root.mobile.open / _isMobileModalOpen() consume `open`).
- Element tests: added an `open` option to setup(); updated the 6 mobile/desktop
tests that relied on the old open=true default to opt in explicitly; added a
regression test asserting a fresh mobile element defaults open=false and paints
no backdrop / applies no scroll-lock until opened.
Bucket B — dead CSS + inert `confirming` machinery:
- styles.ts: removed the `.row-action[data-tooltip]` hover/focus tooltip rules
and the `.root.confirming .row-action[data-tooltip]…` suppression rules — no
rendered .row-action carries data-tooltip anymore (row actions moved into the
kebab menu as labeled .row-menu-items). Kept the .row-action base rules (still
used by the confirm-dialog Cancel button + fetch-more retry).
- element: removed the now-inert `confirming` root class (it gated only the
dead CSS above) and its stale comment; deleted the test asserting the no-op
tooltip suppression. Refreshed two comments that referenced the removed
row-action tooltip lineage.
Bucket B — comment/test hygiene:
- react-core CopilotThreadsDrawer.tsx: reworded the imprecise event-rebind
comment to describe the actual [mounted] deps.
- angular spec: added a beforeEach resetting the module-level threadsState
signals + clearing mock fns to remove order-coupling (parity with react/vue).
- vue use-threads.test.ts: aligned MockThreadStore.unarchiveThread + its
assertion to the real core contract (PATCH /threads/{id} { archived:false },
not POST /threads/{id}/unarchive).
Verified: web-components (89), vue (1068), angular (176), react-core suites all
green; web-components + react-core builds green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D2 — wire fetchMoreError end-to-end:
- core: add a dedicated `fetchMoreError` channel to the thread store, tracked
separately from the initial-list `error`. `nextPageFailed` now writes
`fetchMoreError` (was `error`), so a paginated-load failure preserves the
loaded list and drives the element's inline "couldn't load more — retry"
panel instead of a full-panel error. Cleared on fetch-more request (retry),
on success, and reset on context change / stop. New symbols:
* `ThreadState.fetchMoreError`
* `ThreadSelectors.fetchMoreError` + `ɵselectFetchMoreError`
Call sites of `ɵselectFetchMoreError`:
* packages/core/src/threads.ts (export)
* packages/react-core/src/v2/hooks/use-threads.tsx (selector read)
* packages/vue/src/v2/hooks/use-threads.ts (bindThreadStoreSelector)
* packages/angular/src/lib/threads.ts (bridge to signal)
* packages/vue/src/v2/hooks/__tests__/use-threads.test.ts (core mock)
Call sites of `ThreadSelectors.fetchMoreError` (mock objects updated):
* packages/core/src/__tests__/core-thread-store-auto-unregister.test.ts
* packages/core/src/__tests__/thread-store-registry.test.ts
- react/vue/angular: expose `fetchMoreError` on the hook/composable/store and
push it onto `el.fetchMoreError`, making the dead `retry{scope:"fetch-more"}`
handler reachable. Initial-list error behavior unchanged.
D1 — Angular wrapper open-state coordination: drive `el.open` from the config's
`drawerOpen` (default CLOSED) so the element no longer springs open full-screen
and scroll-locks on mobile load; handle `(open-change)` -> `config.setDrawerOpen`
with a provider-less local-state fallback; call `config.registerDrawer()` with
cleanup on destroy. The config's drawer members were fully functional (only
marked "RESERVED/unwired") — wiring them makes them consumed, so their comments
were updated accordingly (no reservation conflict).
D3 — Angular focus-return: add a `findChatInput` scoped to the Angular chat
selectors (`copilot-chat-view` container, `textarea[copilotChatTextarea]`) and
focus it on thread select, mirroring React/Vue.
A6 — react wrapper comment rot: "nine outbound events" -> "eleven" (2 spots).
DEFAULT_AGENT_ID parity (react): import `DEFAULT_AGENT_ID` from
`@copilotkit/shared` instead of hardcoding `"default"` (equal value).
Angular test isolation: three list-path tests now set `licenseStatusSignal`
explicitly instead of relying on inherited module-level state.
Tests: core 552, react-core 1417, vue 1068, angular 176 — all pass;
check-types passes for all four packages.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Also re-exports SearchDetail from @copilotkit/web-components/threads-drawer
so the React wrapper's type import resolves.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two related bugs in the React <CopilotThreadsDrawer> surface.
Bug 1 (web-components): the delete-confirm dialog's backdrop is
`position:absolute; inset:0; z-index:10`, but `.root` was not a positioning
context, so on desktop it resolved against the viewport and its low z-index
lost to the chat composer (`position:relative; z-index:20`), painting the
dialog UNDER the input. Anchor `.root` with `position:relative` to confine the
modal to the drawer column. Framework-agnostic (Angular wraps the same element).
Bug 2 (react-core): the provider's immediate runtime-info catch-up read grabbed
`a2uiEnabled` but omitted `licenseStatus`. The core starts its `/info` fetch
during construction, so on a cold first load (incognito/hard refresh) the
`Connected` event can fire before the passive subscribe effect runs; the event
is missed and license status stays null forever, pinning the drawer to
"Loading threads…". Read all three values immediately, mirroring the subscriber.
Angular/Vue already read licenseStatus in their catch-up, so they are unaffected.
Adds a deterministic regression test for the provider race (red before, green after).
ENT-1046
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve the single conflict in packages/web-inspector/src/index.ts by keeping
both additions: this branch's CpkMemoryList memory-tab element and main's
ɵCpkThreadDetails back-compat alias (independent top-level declarations).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a `licenseUrl` property to the shared element (default
https://docs.copilotkit.ai/intelligence). The locked view's Upgrade CTA now
dispatches a cancelable `licensed` event carrying the url and, unless the
host calls preventDefault(), opens it in a new tab; a blank url suppresses
navigation. React and Angular wrappers expose an optional `licenseUrl` prop.
License-gate the Angular drawer like React: surface `licenseStatus` as a
signal on the CopilotKit service and gate the wrapper on
status valid|expiring && checkFeature("threads"), skipping the thread fetch
while unlicensed and showing the loading state (not the locked view) until
the status resolves. Reverses the earlier always-licensed Angular call.
Closes ENT-1027.
Final naming decision. Renames the public component + element across the
board: React/Angular CopilotDrawer -> CopilotThreadsDrawer, the Lit element
copilotkit-drawer -> copilotkit-threads-drawer (tag, CopilotKitThreadsDrawer
class, COPILOTKIT_THREADS_DRAWER_TAG, defineCopilotKitThreadsDrawer), the
@copilotkit/web-components/drawer subpath -> /threads-drawer (+ src dir),
the CopilotThreadsDrawerRow directive / copilotThreadsDrawerRow input, and
all prose/test references. Generic types (DrawerThread, DrawerFilter),
--cpk-drawer-* tokens, and ::part names are unchanged. Behavior unchanged.
Per review, settle the locked-view affordance on a neutral 'license'
name. Renames the event (unlicensed -> licensed), React prop
(onUnlicensed -> onLicensed), slot/part/class (licensed, licensed-cta),
LicensedDetail type, data-testid, render method, and identifier-referencing
comments/test names. The existing 'licensed' boolean gate is unchanged;
prose describing the not-licensed state still reads 'unlicensed'/'locked
view'. Behavior unchanged; Angular unaffected.
Per review, drop the 'upsell' monetization jargon. Renames the event
(upsell -> unlicensed), the React prop (onUpsell -> onUnlicensed), the
slot/part/class (upsell -> unlicensed, upsell-cta -> unlicensed-cta),
the UnlicensedDetail type, the data-testid, and all comments/test names.
Behavior unchanged. Angular is unaffected (always-licensed, no gate).
Wires up the previously-dormant pagination plumbing (ENT-1016):
- Element: render a 'Load more' button at the list bottom when hasMore
(and not fetching / not errored), emitting a new load-more event
(LoadMoreDetail). Distinct from retry{scope:'fetch-more'} (error
recovery); both advance pagination.
- React CopilotDrawer: add a limit prop (forwarded to useThreads) and
route load-more to fetchMoreThreads.
- Angular CopilotDrawer: add a limit input (forwarded to injectThreads)
and route load-more to fetchMoreThreads.
Tests: element load-more render + emit + precedence; React limit
forwarding + load-more routing; Angular load-more routing.
Mirrors the Angular wrapper + the copilotkit-drawer element's label
property: sets the drawer region aria-label and default header text,
defaulting to the element's built-in "Threads" when omitted.
CopilotChat message wrappers used viewport-keyed `cpk:sm:px-0`, collapsing
horizontal padding to 0 at any viewport >=640px. The message column is
`max-w-3xl` (768px) centered; the design assumes the chat fills the viewport,
so at >=640px the column has side gutters and inner padding can drop to 0.
But when the chat lives in a sub-viewport-width pane (e.g. the threads drawer
rail beside the chat, ~580px on an 820px iPad-portrait viewport), `sm:px-0`
still fires on viewport width while the 768px column overflows the narrow
pane and sits flush against both edges. The input wrapper looked fine because
it is visually inset by its own pill, so only message text appeared broken.
Make the padding container-relative instead of viewport-relative:
- add `cpk:@container` (container-type: inline-size) to the chat root, and
- switch the message/input/suggestion wrappers from `cpk:sm:px-0` to the
container variant `cpk:@3xl:px-0`.
Padding now tracks the chat's own width and drops to 0 only once the container
is at least as wide as the column's own max-width, so the column has real
gutters; in any narrower pane the `px-4` inner padding is retained. React,
Angular, and Vue kept in lockstep.
Note on the breakpoint: Tailwind v4 container-query breakpoints differ from
viewport breakpoints (`@sm` = 24rem/384px, not 640px). A mechanical
`sm:` -> `@sm:` swap would still collapse the ~580px repro pane. `@3xl`
(48rem/768px) is used because it exactly matches the column's `max-w-3xl`,
which is the width at which side gutters first appear.
Verified: full-width desktop chat unchanged (container >=768px -> px-0);
580px pane retains 16px padding; render-prop layouts without a container
ancestor degrade safely to `px-4`; sidebar/popup `data-*` padding overrides
are unaffected.
ENT-1020
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Memory, NewMemory, MemoryChanges, MemoryKind, and MemoryScope are the
memory types surfaced by the useMemories / injectMemories hook result
shapes, so export them unprefixed as supported public API instead of
behind the ɵ "internal" marker. Internal memory plumbing (MemoryStore,
the selectMemories* selectors, state/context/event types,
createMemoryStore) keeps the ɵ prefix.
Updates the react-core and angular hook signatures, the web-inspector
Memories tab, and the affected tests to the unprefixed names.
- Revert the v2 useRenderToolCall fallback: when no per-tool or wildcard renderer is
registered, return null instead of auto-painting DefaultToolCallRenderer. Showing the
card is opt-in via useDefaultRenderTool().
- The auto-card default shipped silently in v1.57.2 (commit ba60df5d33, buried in a
showcase per-tool-testids commit, no CHANGELOG entry) and leaked internal tool names +
raw args/result JSON (e.g. generate_a2ui) into every v2 app's chat in production.
- Remove the now-dead defaultToolCallRenderAdapter + __testOnly_ export + unused imports.
- Rewrite the resolver test to assert the 3-state opt-in contract: useDefaultRenderTool()
-> card, useDefaultRenderTool({render}) -> custom, no hook -> nothing.