Integrates 3 gap demos (authored in parallel worktrees, ported onto the
upgraded branch):
- background-agents (OSS-426): run_deep_research tool flagged
background:{enabled:true} + Mastra backgroundTasks:{enabled:true} → the bridge
maps background-task-started → a live 'working' activity card. Completion is
out-of-band by design (not asserted). Dedicated route + fixture + e2e + qa.
- observational-memory (OSS-427): OM enabled on the agent Memory
(scope:thread, observation 600/300) + surfaced via getLocalAgents({
observationalMemory:true }). SIZABLE pills trip the token-size trigger.
NOTE: OM data-om-* chunks come from the OM processor + observer LLM, not the
mocked completion — so it does NOT replay deterministically under aimock; the
e2e asserts the deterministic subset (page + pills + completing turn) and
full OM-card verification needs a real-LLM run (documented in qa).
- browser-use (OSS-91): Mastra-only, real-LLM. browse_web tool drives a LOCAL
headless Playwright Chromium (NO Browserbase) — top HN / page read, rendered
as in-chat cards. Non-deterministic → no aimock D6 fixture; smoke e2e only.
Needs 'npx playwright install chromium' at runtime (documented in Dockerfile+qa).
Shared: 3 agents + registrations + backgroundTasks toggle, 2 tool exports,
manifest features+demos (now 42 demos, not_supported_features still []),
playwright dep, demoAgentNames excludes for the 4 dedicated-route cells.
next build clean (all routes); validate-parity 0-fail; validate-pins baseline (38).
validate-pins FAILed: mastra's @copilotkit/* now pin to 1.62.1 (needed for the
OSS-383 native-interrupt react-core resume fix) while the canonical pin is
1.61.2. Add a per-slug override for mastra (the sanctioned deviation mechanism
for a single integration during a runtime upgrade) rather than bumping the
global canonical (which would force all 20 integrations to 1.62.1). Pins fail
set returns to baseline (count=38, hash unchanged) → gate passes.
Drop the bespoke 'Mastra bridge' phrasing (used nowhere else in the mastra
docs — they say 'embed a Mastra agent in Copilot Runtime' / 'Mastra natively
supports AG-UI'). Show tracingOptions the canonical way, inside
new CopilotRuntime({ agents: MastraAgent.getLocalAgents({ mastra, ... }) }),
matching quickstart.mdx + shared-state/*.mdx, instead of a bare getLocalAgents.
The @copilotkit/react-core v2 resume-path bug that quarantined gen-ui-interrupt
+ interrupt-headless is fixed as of 1.62.1, so migrate both cells to the native
interrupt path and move them out of not_supported_features.
- Bump @copilotkit/* 1.61.2 -> 1.62.1 (react-core/runtime/shared/voice/
a2ui-renderer + web-inspector core override). next build clean (40 routes).
- Backend: new src/mastra/tools/interrupt.ts — a real Mastra suspend tool
(schedule_meeting) with suspend/resume schemas; returns suspend() directly so
the agentic loop pauses. Wired into interruptAgent (was tools:{}). Instance
storage (src/mastra/index.ts) already satisfies the resume snapshot prereq;
emitInterruptOutcome defaults true in the v1 bridge so the standard
RUN_FINISHED outcome fires (resumable on client >=1.61.2).
- gen-ui-interrupt: useHumanInTheLoop workaround -> native useInterrupt
(renderInChat), reading the Mastra suspend wrapper's suspendPayload.
- interrupt-headless: hand-rolled on_interrupt subscription -> native
useInterrupt({renderInChat:false}) placed in the app surface (the hook handles
both the standard outcome and legacy on_interrupt + the correct resume array).
- manifest: not_supported_features now []; gen-ui-interrupt + interrupt-headless
in features; interrupt_pattern: native (parity with langgraph-python).
- fixture: gen-ui-interrupt.json userMessage keys (introductory sales team call
/ one-on-one with Alice) didn't substring-match the D6 probe + e2e prompts
(never caught while skipped) -> aligned to 'intro call with the sales team' /
'1:1 with Alice'. interrupt-headless.json already correct.
Local D6 e2e not run (Docker daemon container-create wedged in this env);
build-verified + relying on CI/harness. Native suspend/resume path is
dojo-proven on CopilotKit >=1.61.2.
The v1 bridge (@ag-ui/mastra 1.1.0-alpha.0) emits reasoning start/content/end
and STATE_DELTA shared-state streaming, so the already-wired demos + e2e +
aimock fixtures go live. Moves out of not_supported_features into features:
- agentic-chat-reasoning, reasoning-default-render, tool-rendering-reasoning-chain (OSS-384)
- shared-state-streaming (OSS-423)
Adds the missing reasoning-default / reasoning-custom manifest demo entries.
not_supported_features now holds only gen-ui-interrupt + interrupt-headless,
matching the langgraph-python gold standard, which quarantines the same two
cells on an upstream @copilotkit/react-core v2 resume-path hook bug (published-
package fix, out of scope). The native interrupt + RUN_FINISHED outcome path
ships in the bridge; the showcase cell is blocked by the same upstream bug.
Adds an OSS-424 execution-tracing note (tracingOptions inbound / traceId on
RUN_FINISHED.result outbound) to the Mastra Copilot Runtime doc.
Bumps the showcase Mastra integration onto the v1 bridge alpha that ships
interrupt outcome, reasoning emit, STATE_DELTA shared-state streaming,
background-task + observational-memory activity events, tracing passthrough,
and the a2ui-toolkit dep. next build passes (40 routes); unit tests identical
to the beta.2 baseline (13 pre-existing failures, unrelated to the bump).
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>
InMemoryAgentRunner gains an opt-in { onConcurrentRun: "throw" | "supersede" }
(default "throw", so existing consumers are unchanged). In "supersede" mode a
new run for an already-running thread aborts the prior run (agent.abortRun(),
mirroring stop()) instead of throwing "Thread already running" — so a fast
follow-up turn, or one after a dropped/aborted run, cleanly replaces the
previous one.
Superseding overlaps two runs on the module-global per-thread store, so all
four finalization sites (both resets and both historicRuns.push) are guarded on
store.currentRunId === request.input.runId and stamp the run's own id. A
superseded run therefore drops its partial events rather than resetting or
mislabeling the new run's state/history.
Used by the Intelligence-hosted (managed) Slack listener. (OSS-417)