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>
The suggest path called configureAgentForRequest, which conditionally
attaches A2UI/MCPApps/OpenGenerativeUI middleware. MCPApps setup can
incur a listTools network round-trip per suggestion under
available:"always" — contradicting the handler's side-effect-free
contract. Since suggest runs force toolChoice: copilotkitSuggest, those
middleware-injected tools are dead weight. Replace the call with only
the header forwarding it needs (extractForwardableHeaders).
Also wire request.signal to agent.abortRun() so an aborted client
request cancels the server-side provider run instead of letting it run
to completion (best-effort; the listener never throws).
Tests: assert no middleware is attached (agent.use never called),
forwarded headers land on agent.headers, and aborting the signal calls
agent.abortRun(). Runtime mock is now typed (no as any); runner spies
kept to prove the direct-run path is preserved.
Follow-up to #5793 (this commit landed on that branch minutes after it
merged).
The chart components' descriptions steered the model to answer
chart-shaped questions BY rendering ("do NOT answer in plain text"),
which it obeyed too literally: "which policy is closest to its limit?"
produced the right chart and no answer. Every chart description now
carries the same rule — the chart replaces restating the raw numbers,
not the answer itself; follow the render with one or two grounded
sentences. The pending-approvals card gets a matching "point at what
needs attention" line.
Verified live: the budget-usage pill now yields the chart plus "The
Marketing policy is closest to its limit…".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The chart components' descriptions steered the model to answer chart-shaped
questions BY rendering ("do NOT answer in plain text"), which it obeyed too
literally: "which policy is closest to its limit?" produced the right chart
and no answer. Every chart description now carries the same rule — the chart
replaces restating the raw numbers, not the answer itself; follow the render
with one or two grounded sentences. Pending-approvals card gets the matching
"point at what needs attention" line.
Verified live: the budget-usage pill now yields the chart plus "The Marketing
policy is closest to its limit…".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## What
Makes the banking showcase pass the click-around test — every moment
reachable by clicking, zero typing — and turns the two dead dashboard
tabs into real views. Tracks
[FOR-190](https://linear.app/copilotkit/issue/FOR-190); claims
[FOR-178](https://linear.app/copilotkit/issue/FOR-178).
### Three new "wow moments" (all additive, under `src/components/wow/`)
1. **Proactive copilot** — on every fresh load the copilot has already
noticed the overnight policy breaches and offers to walk through them,
before the user types or clicks anything. Tap-to-accept opens the panel
and sends the request on the user's behalf (same `addMessage` +
`runAgent` path a suggestion-pill click takes). Dismissal is per page
load — the opening beat replays on every reload, never re-nags within
one.
2. **Talk to what you see** — the four brand charts (previously
summonable only inside chat) now render as the dashboard's **Analytics
tab** (was "coming soon"), each carrying contextual conversation-starter
pills ("Explain this spike", "Who's closest to their limit?"). Answers
are grounded via the existing `useAgentContext` readables and drill down
with the existing gen-UI components.
3. **Real work product** — "Prep the Q2 spend report for the board"
files a durable artifact (agent-written summary + highlights, live
embedded charts) in the **Reports tab** (was "coming soon") through a
new `createReport` frontend tool, `/api/v1/reports` route, and store
collection.
### Fully click-drivable chat
- **The complete use-case catalog (12 pills) is always available**
(`available: "always"`), not just on the welcome screen: the 4
self-learning arc beats plus charts, breakdowns, cash flow, approvals
explainer, report prep, PIN change, and team invite. Bubbles persist
after every exchange — no typing ever required. Panel widened 440→560px
so pills flow two-per-row.
- **In-chat pending approvals are actually usable**: the dashboard's
~550px approval table rendered its Actions column past the chat card's
edge — visible but unclickable. New `PendingApprovalsChat` stacks each
charge as a chat-width card with labeled Approve/Deny/File-exception
actions, with exact behavioral parity (over-limit gating,
`PolicyExceptionInline` form, identical teach-mode recording payloads
and step narration) — an officer can demonstrate the unlock entirely
inside the chat.
### Correctness / quality fixes (found by Playwright click-through
sweeps)
- **`navigateToPageAndPerform` killed the conversation**:
`window.location.href` did a full reload, tearing down the chat panel
mid-run. Now `router.push`; card operations also land on `/` (where the
card tools are registered) instead of `/cards`, which mirrors the
dashboard and has none.
- **`StatisticsChart` is a real chart now** (dashboard rail +
spending-trend gen-UI): y-axis dollar gridlines, aligned x-axis labels,
and hover showing the exact month + amount with a guide line. Still
hand-rolled SVG, no charting dependency.
- **`next build` was failing on `main`** (`chat-inbox.tsx` CSS custom
property typing) — production build now compiles, unblocking deploy
(FOR-176).
## Scope boundary
Deliberately additive: no changes to the teach-mode arc, memory
substrate, runtime prompt, or A2UI surface (all separately owned and in
flight, see #5763). Shared-seam edits are minimal registrations plus the
surgical fixes above.
## Validation
Driven end-to-end with Playwright against a live agent (`gpt-5.4-mini`),
screenshots captured for every beat:
- All three wow moments, click-through to grounded agent payoff
- Full **teach → demonstrate (live step feed) → save → recall** arc in
OSS mode: the agent applied the learned procedure to a different
over-limit charge unaided
- In-chat approval flow end-to-end: file exception → row flips to
Cleared → approve → queue drains
- Pills persist after exchanges; chart tooltip renders on hover
- `tsc`, oxlint, oxfmt, and `next build` all clean
Known issue observed during validation, **not addressed here**:
HITL/message cards occasionally render twice (one stale, one live) — the
mid-stream `message.id` remount bug that #5340 / #5354 fix in
react-core; this demo inherits the fix when one lands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Dismissal was persisted in sessionStorage, so after one engagement the
demo's opening beat — the copilot noticing breached charges before the
user types or clicks anything — never appeared again for the whole tab
session. Demo-wrong: every fresh load must open with it. Dismissal is now
per-page-load component state; within a load it still never re-nags (the
wrapper stays mounted across client-side navigation).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Click-around feedback fixes on the banking demo:
- In-chat pending approvals are now actually usable: the dashboard's 4-column
approval table is ~550px wide, so inside the chat card its Actions column
rendered past the card edge — visible but unclickable. New
PendingApprovalsChat stacks each charge as a chat-width card with labeled
Approve/Deny/File-exception actions, with exact behavioral parity
(over-limit gating, PolicyExceptionInline form, identical teach-mode
recordUserAction payloads and logStep narration).
- Suggestion bubbles never disappear: the full use-case catalog (12 pills —
the 4 self-learning arc beats plus charts, breakdowns, cash flow, approvals
explainer, report prep, PIN change, team invite) is registered with
available:"always", so the demo stays fully click-drivable after every
exchange. Panel widened 440→560px so pills flow two-per-row instead of
stacking.
- StatisticsChart (dashboard rail + spending-trend gen-UI) is a real chart
now: y-axis dollar gridlines, x-axis labels aligned to the plot area, and
pointer hover showing the exact month + amount with a guide line and
highlighted point. Still hand-rolled SVG, no charting dependency.
Validated with Playwright: approvals filed and approved entirely inside the
chat (Cleared state transition + queue drains), pills persist after
exchanges, tooltip renders on hover.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make the banking demo pass the click-around test: every moment reachable by
clicking, zero typing, and the dead Analytics/Reports tabs replaced with real
views (FOR-190; claims FOR-178).
Additive modules under src/components/wow/:
- ProactiveNotice: on load, the copilot surfaces overnight policy breaches
unprompted and offers to walk through them (tap-to-accept -> existing
pending-approvals gen-UI). Session-scoped dismissal.
- ChartCard + AnalyticsView: the four brand charts (previously chat-only)
rendered as the dashboard's Analytics tab, each carrying contextual
conversation-starter pills grounded via the existing useAgentContext data.
- createReport tool + ReportsView: "prep the Q2 spend report" files a durable
artifact (summary + highlights + live charts) in the Reports tab through a
new /api/v1/reports REST route and store collection.
- useAskCopilot: shared open-panel + addMessage + runAgent helper (same path
a suggestion-pill click takes).
Correctness fixes found by a full Playwright click-through sweep:
- navigateToPageAndPerform: full-page reload tore down the chat panel mid-run
(conversation and in-flight operation lost); now client-side router.push.
Card operations also targeted /cards, which mirrors the dashboard and has no
card tools — they now land on / where the tools are registered.
- chat-inbox: CSS custom property cast so `next build` compiles again
(production build was failing on main, blocking deploy).
Validated end-to-end with Playwright against a live agent, including the full
teach -> demonstrate -> save -> recall arc in OSS mode.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## Summary
Adds a public **Vue `CopilotThreadsDrawer`** — a thin wrapper over the
shared `<copilotkit-threads-drawer>` Lit element — bringing the
Threads-v2 drawer to Vue at parity with the shipped React and Angular
verticals. This is the Vue fast-follow tracked in the [CopilotDrawer —
Vue wrapper](https://app.notion.com/p/3883aa38185281fc8a2cfb69cd1dd88e)
spec.
**SDK-only PR** (`packages/vue`). Like the Angular vertical, the example
de-fork / demo route is a **separate follow-up** — the Vue examples
can't consume the drawer until `@copilotkit/web-components` + a
`react-core` release ship *and* the examples support managed
Intelligence.
Recon during planning corrected the spec's original "cheapest/thinnest
wrapper" premise: Vue is thin on element interop (native
`isCustomElement` + `v-bind`/`v-on`) but — exactly like Angular — needed
an active-thread foundation built. So this ports the full vertical, not
just a binding layer.
## What changed (SDK layers)
- **`useThreads` augmentation** (`hooks/use-threads.ts`): `enabled`
gate, `listError` (genuine list errors, excludes dev/config errors),
`isMutating`, `unarchiveThread` / `refetchThreads` / `startNewThread`;
plus **`registerThreadStore` core-registry integration** and
**`threadEndpoints` list/mutation gating** (React parity).
- **Active-thread + drawer-awareness on
`CopilotChatConfigurationProvider`**: `setActiveThreadId` /
`startNewThread` with the non-explicit-seed override (so
thread-switching + "+ New" work under `<CopilotKit>`), and `drawerOpen`
/ `setDrawerOpen` / `drawerRegistered` / `registerDrawer` with
bidirectional mobile (`<768px`) mutual-exclusion.
- **Clear-on-fresh in `CopilotChat`**: clears the conversation on a
genuine new-thread switch, guarded against initial mount and agent-store
swaps.
- **Mobile launcher in `CopilotModalHeader`**: renders only when a
drawer is registered AND the viewport is mobile.
- **The `CopilotThreadsDrawer.vue` wrapper** + barrel export.
- **SSR safety:** the wrapper imports the `<copilotkit-threads-drawer>`
Lit element **lazily** (`await import(...)` inside `onMounted`,
client-only) rather than at module scope. The element evaluates `class …
extends HTMLElement` at import time, which crashes Nuxt/Vite SSR
(`HTMLElement is not defined`) — a static import would break SSR for
**every** `@copilotkit/vue` consumer, not just drawer users. (Found via
live Nuxt testing; see Testing.)
Load-bearing behaviors carried from the React/Angular rounds: license
gate never flashes the locked view (`licensed || pending`, `loading ||
pending`) and issues no `/threads` fetch while unlicensed; provider-less
`localDrawerOpen` fallback; id-keyed per-row slot reconciliation.
## How it was built & reviewed
Executed via the `micro-task-execution` three-tier model (curator →
decomposition-reviewer → 8 waves, each opus-reviewed) → integration
review → **`cr-loop`: 4 seven-agent review rounds + 7 fix batches,
converged to zero mandatory findings + a Procedure 3 promotion-audit
with zero promotions.** The loop caught and fixed real defects the
per-wave reviews missed: a `useThreads` stuck-loading bug on
`enabled:false`, a wrong chat-input focus `data-testid` (silent a11y
failure), a `CopilotChatToggleButton` fallback regression from the
provider change, net-new lint (`no-dupe-keys`, deprecated `:slot`), and
— surfaced by the promotion audit as load-bearing on the shipped
surfaces — the `registerThreadStore` (inspector visibility) and
`threadEndpoints` gating parity gaps.
## Testing
**Automated (all green in the worktree):**
- `nx run @copilotkit/vue:test` — **99 files / 1061 tests passed**. New
coverage: full `useThreads` augmented surface incl. store registration +
endpoint gating + mutation guards + `enabled` re-arm; the wrapper's
entire 10-event routing table; license pending-vs-resolved gating;
delete-active-thread reset; clear-on-fresh (with a mutation-check
proving it's non-vacuous); bidirectional mobile mutual-exclusion;
`isMobileViewport` guards; the mobile launcher; the
`setModalOpen`-undefined contract that `CopilotChatToggleButton` depends
on.
- `nx run @copilotkit/vue:build` — succeeds (this is the real type gate:
`vue-tsc --declaration`); the compiled `dist` exports
`CopilotThreadsDrawer`.
- `nx run @copilotkit/vue:check-types` — passes.
- `pnpm install --frozen-lockfile` — passes (lockfile in sync).
- Lint: all new/changed source files are clean. (The package-wide `nx
lint` has 173 pre-existing errors, red on `main` and unrelated to this
change.)
Red-green discipline was applied to every behavioral fix (test written
to fail against the bug, then confirmed green after the fix).
**Live-verified via a throwaway hacked example** (uncommitted; the
examples can't ship managed Intelligence yet, so the committed
demo/de-fork is a follow-up): wired the Vue Nuxt demo's runtime to a
managed-Intelligence runtime (`CopilotKitIntelligence` + `licenseToken`,
creds from a CLI scaffold) and loaded `/threads`. Observed: `/info`
reports `mode:"intelligence"`, `licenseStatus:"valid"`,
`threadEndpoints:{list,inspect,mutations,realtimeMetadata: true}`; the
drawer renders the **real thread list from the platform** (licensed —
not the locked or endpoints-unavailable gates), with the Active/All
filter, "New thread", per-row Archive/Delete, and the mobile launcher;
`CopilotChat` renders beside it; no console errors.
This live run is what surfaced the SSR bug above: before the lazy-import
fix, `/threads` (and `/`) 500'd with `HTMLElement is not defined`; after
it, `/threads` → 200 and the error is gone. (Note: the added node-env
regression test `CopilotThreadsDrawer.ssr.test.ts` is a forward-looking
smoke guard — current Lit ships a Node-guarded build so vitest-node
can't reproduce Nuxt's Vite-SSR resolution; the fix's proof is the live
Nuxt run.)
## Release gate
Like the React/Angular de-forks, the wrapper depends on
`@copilotkit/web-components` being published and a
`react-core`/`web-components` release containing the drawer.
`packages/vue` publishes alongside.
## Follow-up work (separate PRs, none blocking)
Tracked in **ENT-1037** (related to ENT-1035): the cross-framework
767/768 mobile-breakpoint reconciliation, `useThreads.startNewThread`
config-error dismissal parity, an identity-guarded
`unregisterThreadStore`, and CopilotChat send/connect error-UX parity.
The Vue examples are intentionally left as-is (no Vue de-fork).
Review feedback (@marthakelly) has been addressed in-branch — see the
review reply.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## What this does
Replaces the hand-rolled `threads-drawer/` fork in **every
threads-enabled integration example** with the SDK
`<CopilotThreadsDrawer>` (shipped in `@copilotkit/react-core` 1.62.1):
- `page.tsx` → SDK `<CopilotThreadsDrawer>` inside an **uncontrolled**
`CopilotChatConfigurationProvider` (the drawer drives the active thread;
"+ New" resets). The locked-view Upgrade CTA opens the Intelligence docs
**by default** (ENT-1027), so no `onUpsell` wiring is needed.
- reserved-column `page.module.css` (no layout shift when the
client-only drawer mounts)
- no-flash theme script where the example uses a `useEffect`
`ThemeProvider`
- canvas examples: `ExampleLayout` half/half + `w-full` fix
- deleted the per-example `threads-drawer/` fork
**16 examples:** adk, agno, a2a-middleware, agentcore (Vite/AWS —
build-validated only), crewai-crews, crewai-flows, langgraph-fastapi,
langgraph-js, langgraph-python, llamaindex, mastra, mcp-apps,
ms-agent-framework-dotnet, ms-agent-framework-python, pydantic-ai,
strands-python.
All browser-validated against a live Intelligence project during the
de-fork (drawer mounts, threads list/switch, reserved column, theme, ~0
console errors) except agentcore, which is `pnpm build` exit-0 (its
Bedrock/Cognito harness can't run locally).
## Release status — ready
The drawer landed on `main` and shipped in **1.62.1** —
`@copilotkit/react-core` plus the previously-missing
`@copilotkit/web-components` (now published and pinned in lockstep at
1.62.1). Every example is bumped from `workspace:*` / `1.61.0` →
**1.62.1**.
**Retest:** a standalone `npm install` + `next build` of pydantic-ai
(copied outside the monorepo, so it consumes the published packages)
resolves `CopilotThreadsDrawer` from `@copilotkit/react-core` + the
`@copilotkit/web-components/threads-drawer` subpath and compiles clean.
## Notes
- [x] Examples bumped to the published `1.62.1` (react-core + runtime).
`@copilotkit/web-components` is pulled transitively — no direct dep
needed.
- `.env` stays local only (gitignored; validation creds are not in this
PR).
- Branch is examples-only — no `pnpm-workspace.yaml` link entries or
`pnpm-lock.yaml` churn.
- agentcore: 3 previously-undeclared `@radix-ui/*` deps were added to
its `package.json` so it builds under pnpm.
## Related
- SDK `CopilotThreadsDrawer` (renamed from the interim `CopilotDrawer`)
— shipped in 1.62.1.
- Follow-ups surfaced during this work: ENT-1004 (CI smoke-matrix ↔ CLI
threads-set drift), ENT-1005 (CopilotThreadsDrawer theming hooks).
Address PR review: delete the 4 stray package.json.bak files left by the
version-bump tooling, and restore examples/teams/appPackage/{color,outline}.png
to main (the de-fork commit had rewritten them into raw LFS-pointer text —
incidental fallout unrelated to this PR's scope).
A stray comment edit left langgraph-js's example-layout/index.tsx one line
off from the langgraph-python north-star, tripping the verbatim parity check.
Match it exactly.
The drawer shipped in 1.62.1 (react-core + the previously-missing
web-components package). Move the de-forked examples off the workspace:*
placeholder (and 1.61.0 runtime) onto the published 1.62.1, so they consume
the real SDK CopilotThreadsDrawer. Verified: a standalone install + next build
of pydantic-ai resolves CopilotThreadsDrawer from the published packages.
Rename import + usage from CopilotDrawer to CopilotThreadsDrawer across the
de-forked examples, and drop the now-redundant onUpsell handler: ENT-1027
makes the element open the Intelligence docs URL by default via licenseUrl.
Comments updated; --cpk-drawer-* tokens unchanged. Holds until the drawer
packages are published.
Replace the hand-rolled threads-drawer fork in every threads-enabled
integration example with the SDK <CopilotDrawer> (uncontrolled
CopilotChatConfigurationProvider + reserved-column layout + theme no-flash
where applicable). 16 examples; all browser/build-validated locally.
DRAFT — depends on #5707 and the subsequent npm release; not mergeable until
the SDK publishes @copilotkit/web-components and react-core bumps. Pre-merge
TODOs in the PR description.
## Summary
- add Intelligence thread run-activity metadata normalization and
subscription support
- reconnect explicit native Intelligence chats on remote run activity
without keeping /connect or /run streams long-lived
- harden replay cursor handling, passive /connect completion, and
passive replay tool execution
## Verification
- `pnpm --dir packages/core exec vitest run
src/__tests__/threads.test.ts src/__tests__/intelligence-agent.test.ts
src/__tests__/core-run-agent-resume.test.ts
src/__tests__/core-connect-thread-switch.test.ts
src/__tests__/core-connect-passive-replay.test.ts
src/__tests__/core-follow-up.test.ts`
- `pnpm --dir packages/react-core exec vitest run
src/v2/components/chat/__tests__/CopilotChat.runActivityReconnect.test.tsx
src/v2/components/chat/__tests__/CopilotChat.absentThreadConnect.test.tsx
src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx
src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.tsx`
- `pnpm --dir packages/core run check-types`
- `pnpm --dir packages/react-core run check-types`
- `pnpm --filter @copilotkit/core run build`
- `pnpm --filter @copilotkit/react-core run build`
- pre-commit package checks passed for affected package set
## Manual testing needed before ready
- two browser tabs/devices on the same explicit Intelligence thread: tab
A sends a later run, tab B live-syncs through wake-triggered /connect
replay
- old/new compatibility smoke tests: old client with new gateway, new
client with old gateway
Draft until manual testing is complete.
- Type elRef as CopilotKitThreadsDrawerElement (drop the `& Record<string, unknown>`
escape hatch) so every el.<prop> write is checked against the real element type.
- Replace the 12-entry watch([...]) dependency array with watchEffect, which
auto-tracks its reads and removes the maintenance hazard of keeping the array
in sync.
- Extract MOBILE_MAX_WIDTH_QUERY in is-mobile-viewport.ts and reuse it in
CopilotModalHeader's matchMedia listener to remove the within-Vue duplication
of the breakpoint literal.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CopilotThreadsDrawer.vue previously imported
`@copilotkit/web-components/threads-drawer` statically at module scope.
That module defines a Lit custom element, and eagerly loading it on every
`@copilotkit/vue` import risked an `HTMLElement is not defined`-style crash
under SSR (Node has no DOM) for any consumer that imports the package on
the server, e.g. Nuxt.
Fix: import the element module lazily, inside `onMounted`, so it is only
ever evaluated client-side. `elementTag`/`mounted` are set once the dynamic
import resolves, and the template gates rendering on `mounted`.
Consequence: the wrapper now mounts the custom element asynchronously.
Updated `CopilotThreadsDrawer.test.ts` so `mountDrawer()` awaits
`flushPromises()` (resolving the dynamic import) plus a trailing
`nextTick()` (flushing the render and the `flush: "post"` property-push
watcher) before returning, and centralized this settle in the shared
helper instead of repeating ad hoc `nextTick()` calls per test.
Added `CopilotThreadsDrawer.ssr.test.ts`, a `@vitest-environment node`
regression test asserting the package entry (which re-exports
CopilotThreadsDrawer) imports without throwing when there is no
`HTMLElement` global, guarding against reintroducing an eager DOM-dependent
import into the barrel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Vue examples cannot consume the drawer until @copilotkit/web-components +
a react-core release ship AND the examples support managed Intelligence — same
constraint as the Angular vertical, which kept its demo route as a separate
follow-up PR. This PR is SDK-only (packages/vue).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ports two React-parity gaps (audit-flagged as user-facing) into the Vue
`useThreads` composable, mirroring react-core `use-threads.tsx`.
Fix A — register the thread store with core's single-slot registry:
- Adds a `watch([resolvedEnabled, resolvedAgentId])` that calls
`copilotkit.value.registerThreadStore(agentId, store)` and, via the
watch's `onCleanup`, `unregisterThreadStore(agentId)` on
disable/agentId-change/unmount. Gated on `resolvedEnabled` so a disabled
(unlicensed) store never evicts a co-mounted live store for the same agent.
Fix B — gate list + mutations on `copilotkit.threadEndpoints`:
- Derives `threadListEndpointSupported`/`threadMutationsSupported` via
`!== false` (legacy runtimes advertise `undefined` => supported).
- Context-dispatch watcher skips dispatching (setContext(null)) when the
list endpoint is unsupported, so no `/threads` fetch fires.
- Folds `threadEndpointsError` ("Thread endpoints are not available on this
CopilotKit runtime") into `error` (NOT `listError`, which stays
storeError-only) and factors `!threadEndpointsUnavailable` into
`preConnectLoading` so the UI doesn't spin against an endpoint-less runtime.
- `guardMutation` wraps rename/archive/unarchive/delete to reject with
"Thread mutations are not available on this CopilotKit runtime" when
`threadEndpoints.mutations === false`, before touching the network.
Call sites:
- The shipped `CopilotThreadsDrawer` consumes `error` for its user-facing
error banner (now surfaces the endpoints-unavailable message instead of
spinning) and `listError` for genuine list-load failures (unchanged
contract: storeError only, no config/runtime-setup leakage). Its `enabled`
prop (unlicensed gate) already suppressed fetches; it now also correctly
suppresses core-registry registration so a co-mounted live chat store for
the same agent is not evicted. Mutation buttons (rename/archive/delete)
reject locally on runtimes that don't serve mutations.
Item 3 (startNewThread configErrorDismissed) intentionally left out of scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>