12420 Commits

Author SHA1 Message Date
Austin Merrick f54e99697b fix(build): replace Unix-only commands in package.json scripts with Node.js equivalents (#5602)
## What does this PR do?

This PR fixes build failures on Windows by replacing Unix-only shell
commands (`rm -rf`, `cp`, `mkdir -p`) in `package.json` scripts with
cross-platform Node.js `fs` built-in commands.

This follows the project's existing codebase pattern for cross-platform
operations, as seen in `packages/react-ui/package.json` (line 45).

### 🛠️ Changes:
- **`packages/runtime`**: Replaced `rm -rf` in `generate-graphql-schema`
with `fs.rmSync`.
- **`packages/vue`**: Replaced `cp` in `build:types` and `rm -rf` in
`clean` with `fs.cpSync` and `fs.rmSync`.
- **`packages/angular`**: Replaced `mkdir -p` and `cp` in `build:css`
with `fs.mkdirSync` and `fs.cpSync`.
- **`examples/v1/next-openai`, `next-pages-router`, `state-machine`**:
Replaced `rm -rf` clean commands with a single Node.js loop that deletes
`.turbo`, `node_modules`, `dist`, and `.next`.

All modified packages now build successfully on Windows.

## Related PRs and Issues

- Closes #5601

## 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 (lets us help iterate on
your PR directly — faster turnaround for everyone)
2026-07-01 09:56:00 -07:00
Tyler Slaton 7527ee64d0 fix(release): fold web-components into monorepo scope 2026-07-01 09:54:51 -07:00
Austin Merrick 66de791b40 fix(vue): inherit chat configuration agent id in useAgent (#5695)
## Summary

- Make Vue `useAgent` resolve agent IDs from explicit prop, then
surrounding chat configuration, then `DEFAULT_AGENT_ID`.
- Add regression coverage for bare `useAgent()` inside a non-default
configured chat and for explicit prop precedence.
- Update the Vue parity matrix note for the `useAgent` precedence
behavior.

Fixes #5656

## Verification

- `pnpm nx run @copilotkit/vue:test --
src/v2/hooks/__tests__/use-agent.test.ts` (failed before the fix with
`Received: "default"`, passes after)
- `pnpm --dir packages/vue exec eslint src/v2/hooks/use-agent.ts
src/v2/hooks/__tests__/use-agent.test.ts`
- `pnpm nx run @copilotkit/vue:check-types`
- `pnpm nx run @copilotkit/vue:test` (94 files / 1007 tests)
- `lefthook pre-commit test-and-check-packages` (ran `@copilotkit/vue`
test, build, publint, and attw)
- `git diff --check upstream/main...HEAD`

## Notes

- `pnpm nx run @copilotkit/vue:lint` still fails on pre-existing
unrelated Vue lint errors across untouched files; the changed files pass
eslint directly.
2026-07-01 09:54:41 -07:00
Benjamin Taylor 0399facf05 test(vue): unit-test isMobileViewport guard, reverse mobile mutual-exclusion, de-brittle clear-on-fresh
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:52:29 -05:00
Benjamin Taylor a3d919a995 fix(vue): resolve net-new lint (no-dupe-keys handlers, slot attr) + guard matchMedia in isMobileViewport
CopilotThreadsDrawer.vue declared local handlers `onNewThread`/`onLicensed`
with the same names as the `onNewThread`/`onLicensed` input-callback props,
tripping vue/no-dupe-keys. Renamed the handlers to `handleNewThread`/
`handleLicensed` (props left untouched) and updated their template bindings
(`@new-thread`, `@licensed`) and the one internal call site in `onDelete`
that re-implemented the new-thread flow inline.

Rewrote the per-row `:slot="`row:${t.id}`"` binding as
`v-bind="{ slot: `row:${t.id}` }"` to satisfy vue/no-deprecated-slot-attribute
without changing behavior — it still compiles to a real DOM `slot` attribute
used to project light-DOM children into the custom element's named shadow
slots (not a Vue component slot).

Added a `typeof window.matchMedia !== "function"` guard to
isMobileViewport(), matching CopilotModalHeader.vue and the React reference,
so environments where `window` exists but `matchMedia` doesn't (some test
runners, embedded webviews) don't throw when the provider opens the
drawer/modal.

CopilotModalHeader.vue:40 `_className` unused-var lint error predates this
branch (introduced in 28d07ccaa, already on main) and is left as out of
scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:47:15 -05:00
Tyler Slaton 9ed48a9dc3 fix(web-components): keep generated tokens formatted 2026-07-01 09:44:46 -07:00
Tyler Slaton 3e8e409f1f chore(release): add web-components release scope 2026-07-01 09:43:04 -07:00
Benjamin Taylor b1e1d108ef fix(vue): correct chat-input focus testid + scope lookup, add provider-less drawerOpen fallback
focusChatInput() queried `[data-testid="copilot-chat-textarea"]`, a testid
that exists nowhere in the Vue package (copied from React) — the `?.` made
the miss silent, so focus never returned to the composer after selecting a
thread. Corrected to `copilot-chat-input-textarea` (CopilotChatInput.vue)
and added React-parity scoping: `findChatInput` walks up from the drawer's
element via `closest('[data-testid="copilot-chat-view"]')` to scope the
input lookup to the enclosing chat, falling back to a document-global query
when no such ancestor exists. Sole call site: `onThreadSelected`.

Added a `localDrawerOpen` ref fallback for when there is no surrounding
`CopilotChatConfigurationProvider` (`config.value === null`): previously
`el.open` was pinned to `false` forever and `onOpenChange` was a no-op in
that case, since both routed through `config.value?.`. A `drawerOpen`
computed / `setDrawerOpen` function now pick the provider's state when
present and the local ref otherwise; both the property-push watcher and
`onOpenChange` route through them. Mirrors React's bare-drawer-starts-closed
fallback.

Documented (no behavior change) that the `row` scoped slot, unlike React's
`renderRow`, has no per-row escape hatch back to the element default — once
provided it projects for every thread.

Added tests: focus-return after thread-selected (red against the old
testid), delete-of-active-thread resets to a new thread (plus the
negative non-active case), and the provider-less drawerOpen fallback
reflecting open-change events.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:41:17 -05:00
Benjamin Taylor 54b33a7947 fix(vue): re-arm useThreads loading indicator on enable/reconnect + gate preConnectLoading on enabled
Call sites: `preConnectLoading` only feeds `isLoading` (returned to consumers,
e.g. CopilotThreadsDrawer's licensed-gate loading state); `hasDispatchedContext`
is read only by `preConnectLoading` and written only in the context watcher.

Without gating on `resolvedEnabled`, useThreads({ enabled: false }) left
isLoading stuck true forever (hasDispatchedContext never set). Without
resetting the flag on the disabled/no-runtimeUrl branch, toggling
enabled false->true (or runtimeUrl removed+re-added) failed to re-arm the
pre-connect loading synthesis, regressing the empty-list flash it exists
to suppress. Brings the Vue hook back in parity with the React reference's
reset behavior for these two branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:37:01 -05:00
Benjamin Taylor 3b6c7affb8 feat(vue-demo): threads route with CopilotThreadsDrawer + CopilotChat
Add examples/v2/vue/demo/pages/threads.vue demonstrating the drawer
alongside chat. The demo has no root CopilotKitProvider (app.vue only
renders <NuxtPage/>), so the page mounts its own provider chain,
matching the runtime-url + show-dev-console convention used by every
sibling demo page. CopilotChatConfigurationProvider is left
uncontrolled (no threadId) so the drawer drives the active thread.
No natural nav list exists in index.vue or elsewhere in the demo, so
no nav link was added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:21:50 -05:00
Benjamin Taylor 9a34ea397d chore(vue-demo): register copilotkit-threads-drawer as a custom element in Nuxt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:19:57 -05:00
Benjamin Taylor d15d95804e feat(vue): export CopilotThreadsDrawer from the package entry
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:19:08 -05:00
Benjamin Taylor bd1289fa44 test(vue): CopilotThreadsDrawer renders element, routes thread-selected, fires onLicensed
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:14:19 -05:00
Benjamin Taylor 4cacf5fbd0 feat(vue): CopilotThreadsDrawer wrapper over the shared threads-drawer element
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:12:34 -05:00
Benjamin Taylor 989ed28762 test(vue): mobile drawer launcher visibility + toggle in CopilotModalHeader
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:08:38 -05:00
Benjamin Taylor aaa9916556 feat(vue): mobile drawer launcher in CopilotModalHeader
Adds a mobile-only launcher button at the leading edge of
CopilotModalHeader that toggles the drawer. It renders only when a
CopilotThreadsDrawer has registered with the chat configuration AND
the viewport is mobile (<=767px, matched via matchMedia and mirrored
from the React CopilotModalHeader implementation). Also exports
IconPanelLeftOpen from the shared icons barrel for the button's icon.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:06:32 -05:00
Benjamin Taylor d0c77d6d72 test(vue): cover drawer registerDrawer + mobile drawer/modal mutual-exclusion
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:02:50 -05:00
Benjamin Taylor e36a7c953c feat(vue): drawer-awareness state + mobile mutual-exclusion in chat config provider
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:01:34 -05:00
Benjamin Taylor 0254da874e feat(vue): add drawer-awareness fields to CopilotChatConfigurationValue type
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:00:03 -05:00
Benjamin Taylor 1def05e500 test(vue): clear-on-fresh clears messages on new-thread switch, not on mount
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:57:50 -05:00
Mike Ryan 25040e4d7c chore: release monorepo v1.62.0 (#5788)
## Release monorepo v1.62.0

**Scope:** `monorepo` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.62.0`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `monorepo` packages to npm at version `1.62.0`
   - Creates git tag `monorepo/v1.62.0`
   - Creates a GitHub Release with the final release notes

### Before merging

- [ ] CI is green (tests, lint, types, build)
- [ ] Version bumps look correct
- [ ] Release notes are accurate (edit in Notion if a draft was created)

---

> **Do not merge until CI is fully green.** The full test suite runs
automatically on this PR.
v1.62.0
2026-07-01 08:56:39 -07:00
Benjamin Taylor 0fea7a8ccb feat(vue): clear chat messages on fresh non-explicit thread switch
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:53:58 -05:00
Benjamin Taylor 60c01eef1d test(vue): cover active-thread setActiveThreadId/startNewThread + authoritative guard
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:51:28 -05:00
Benjamin Taylor daf26f22c1 feat(vue): active-thread override + setActiveThreadId/startNewThread in chat config provider
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:50:18 -05:00
Benjamin Taylor 6ba86c4027 feat(vue): add active-thread setters to CopilotChatConfigurationValue type
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:48:37 -05:00
MikeRyanDev ca836ff920 chore: release monorepo v1.62.0 2026-07-01 15:45:54 +00:00
Benjamin Taylor 259276d795 chore(vue): depend on @copilotkit/web-components for the threads drawer element
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:44:32 -05:00
Benjamin Taylor 89837c50fb feat(vue): expose unarchive/refetch/startNewThread/listError/isMutating + enabled gate on useThreads
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:43:09 -05:00
Benjamin Taylor 2f85aa7bc1 feat(vue): add isMobileViewport helper for drawer mobile mutual-exclusion
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:40:07 -05:00
Ran Shemtov 01354148b1 fix(react-core): render nothing for unhandled tool calls instead of auto default card (#5769)
## What

Revert the v2 tool-call resolver so an **unhandled** tool call (no
per-tool or wildcard renderer registered) renders **nothing** again,
instead of auto-painting the built-in `DefaultToolCallRenderer` card.

Showing the card is opt-in, exactly as before:

| Call | Result |
|---|---|
| `useDefaultRenderTool()` | built-in default tool-call card |
| `useDefaultRenderTool({ render })` | the caller's custom UI |
| neither | nothing renders |

## Why

The auto-card default was introduced in commit `ba60df5d33`
(2026-05-07), buried as the **last bullet** of a commit titled
`feat(showcase/langgraph-python): add per-tool testids`. It shipped
silently in **v1.57.2** with **no CHANGELOG entry** and is still live
through 1.61.2.

Effect: in v2, **every** agent tool call that surfaces in chat without a
registered renderer paints a card exposing the tool name, raw arguments
JSON, and raw result JSON — in production, for all customers. This is
how internal A2UI plumbing tools (`generate_a2ui`, `render_a2ui`,
`log_a2ui_event`) leaked into deployed showcase demos, and it equally
leaks any customer's own un-rendered tools.

Pre-1.57.2 behavior was `return null` (invisible). This restores that
opt-in contract.

## Changes

- `use-render-tool-call.tsx`: resolver returns `null` when no
per-tool/wildcard renderer matches.
- Removed the now-dead `defaultToolCallRenderAdapter` + `__testOnly_`
export + unused imports.
- Rewrote `use-render-tool-call.test.tsx` to drive the real
`useDefaultRenderTool` → real `useRenderToolCall` through a notifying
mock core, asserting all 3 states (card / custom / nothing).

## Showcase impact

None required. The opt-in `tool-rendering-*-catchall` demos already call
`useDefaultRenderTool()`, so their cards (and e2e specs) are unchanged.
No a2ui/declarative spec asserts the card — those demos simply stop
leaking it in prod.

## Verification

- `nx test react-core`: 1368 pass (107 files), incl. the new 3-scenario
suite.
- `nx check-types react-core`: clean.
- `nx build react-core`: clean.
- oxfmt `--check`: clean.
2026-07-01 16:48:26 +02:00
Ran Shemtov d0f4f27458 Merge branch 'main' into claude/happy-dirac-f6ed5e 2026-07-01 16:48:12 +02:00
Ran Shemtov c26b89dc51 fix: inspector shows no AG-UI events for per-thread agent clones (#5784)
Fixes #5773, a regression of #3872. The inspector event timeline stays
empty during runs — no `RUN_STARTED`, `TEXT_MESSAGE_*`, `TOOL_CALL_*`,
etc. — while connection status, agents, context and tools still
populate.

The cause is the same one #3872 fixed and that has since been dropped:
`useAgent` runs a per-thread *clone* of the registry agent, and clones
are never added to the registry. The inspector only subscribes to AG-UI
events via `onAgentsChanged`, so it never sees the clone that actually
runs, and every `recordAgentEvent` sits on the wrong instance. The
`onAgentRunStarted` bridge #3872 added is no longer declared on
`CopilotKitCoreSubscriber`.

Re-landing it against the current run path: `RunHandler` fires
`onAgentRunStarted` with the real run instance at the start of
`runAgent` (top-level only, so recursive tool follow-ups don't
re-subscribe) and `connectAgent`, and the inspector subscribes to that
instance. `subscribeToAgent` already keys by `agentId` and replaces, so
the clone cleanly supersedes the registry subscription and there's no
leak. Per-thread cloning is untouched.

Added a core regression test driving a run on a clone that isn't in the
registry and asserting the event fires once with that instance, plus
that recursive follow-up runs don't re-notify. Core and web-inspector
both typecheck; core suite green.
2026-07-01 10:29:29 +02:00
Ran Shemtov 55e0a884b3 Merge branch 'main' into fix/inspector-subscribe-per-thread-clone-events 2026-07-01 10:10:12 +02:00
Ran Shemtov e1321406bc fix(vue): enable A2UI via catalog-on-provider path (#5777) 2026-07-01 08:33:53 +02:00
Ben Taylor cbb24952c5 feat(web-inspector): add unified thread debugger (#5768)
## Summary
- Adds the unified web-inspector thread debugger surface as a standalone
`cpk-thread-inspector` custom element backed by a
`ThreadDebuggerProvider` contract for thread metadata, messages, AG-UI
events, and state.
- Keeps the existing full Web Inspector shell compatible by making the
internal `cpk-thread-details` element extend the new shared inspector
implementation.
- Normalizes persisted AG-UI event history into a first-class Timeline
view with run/message/tool/state/raw rows, source-event links into the
Raw AG-UI Events tab, metadata pills, and raw-event preservation for
top-level fields.
- Improves timeline/state loading behavior for standalone and
runtime-backed usage: state stays lazy-loaded, provider/runtime/header
swaps refetch safely, stale async responses are ignored, and
message-backed or raw-only threads no longer show an empty first tab.
- Adds a standalone web-inspector dev harness with AG-UI events,
Messages only, and Raw event only scenarios for shared UI validation
outside an app shell.
- Updates package/dev configuration for the harness (`dev:standalone`,
Vite dev dependency/config allowlist) and bumps
`@copilotkit/web-inspector` to `1.61.3`.

## Tests and Checks
- Expanded `packages/web-inspector` tests for the provider contract,
normalized timelines, raw event rendering, lazy state loading, stale
request handling, header-driven refetches, runtime fallbacks, and
first-tab timeline population.
- PR checks currently passing include build, check-types, format,
oxlint, package-quality, unit on Node 20/22/24, Python unit tests, shell
script tests, Validate Showcase, bundle-size, config/binary checks, and
integration starter/showcase jobs.
- Manual validation path documented in
`packages/web-inspector/README.md`: `pnpm nx run
@copilotkit/web-inspector:dev:standalone`, then validate AG-UI events,
Messages only, Raw event only, source-event navigation, and State at
`http://127.0.0.1:5177/`.

## Companion PR
- Intelligence managed debugger integration:
https://github.com/CopilotKit/Intelligence/pull/461

<img width="928" height="724" alt="Screenshot 2026-06-29 at 2 50 47 PM"
src="https://github.com/user-attachments/assets/c7936f1c-0780-4c0c-b5d2-1890db611460"
/>
<img width="927" height="1325" alt="Screenshot 2026-06-29 at 2 49 50 PM"
src="https://github.com/user-attachments/assets/48134189-7def-4312-b4d1-4bad28a93a12"
/>
e733" />
<img width="927" height="408" alt="Screenshot 2026-06-29 at 2 49 58 PM"
src="https://github.com/user-attachments/assets/1773b1f7-10a1-4905-ab6e-418d13031a49"
/>
<img width="929" height="583" alt="Screenshot 2026-06-29 at 2 50 07 PM"
src="https://github.com/user-attachments/assets/8f38f91d-296b-41dd-8b50-8c60739b387d"
/>
2026-06-30 21:50:44 -05:00
serhiizghama f9bba02c20 fix(web-inspector): subscribe to the running clone via onAgentRunStarted
The inspector subscribed to AG-UI events only through onAgentsChanged, which
skips per-thread clones, leaving the event timeline empty during runs
(regression of #3872). Subscribe to the run instance reported by
onAgentRunStarted so its events are recorded.
2026-07-01 08:23:53 +07:00
serhiizghama 7f0ca7eabf fix(core): notify subscribers of the agent instance at run start
Add an onAgentRunStarted subscriber event fired from RunHandler.runAgent and
connectAgent with the instance that actually runs. Per-thread clones (from
useAgent) are not in the agent registry, so onAgentsChanged never fires for
them and subscribers that only track registry agents can't observe their run.
2026-07-01 08:23:53 +07:00
Martha Schumann 5df64923cc fix: stabilize inspector live event caches 2026-06-30 17:03:25 -07:00
Martha Kelly Schumann f0eb837dad Merge branch 'main' into codex/unified-thread-debugger 2026-06-30 15:53:41 -07:00
Mike Ryan 2d318c6937 feat: CopilotThreadsDrawer + active-thread configuration (#5746)
## What

The **Angular `<CopilotDrawer>` feature** for the CopilotKit SDK — a
ready, usable threads drawer for Angular apps, plus the active-thread
foundation it sits on. (This PR merges the originally-staged PR1+PR2 so
it ships a working feature, not just plumbing.)

**Foundation — active-thread coordination (no new store):**
1. **`CopilotChatConfiguration`** — an injectable, signal-based service
mirroring React's `CopilotChatConfigurationProvider`: owns
`agentId`/`threadId` resolution (controlled prop → override → minted
fallback) + the `hasExplicitThreadId` welcome flag; `setActiveThreadId`
/ `startNewThread` setters that no-op when host-controlled;
single-instance via `useExisting`.
2. **`connectActiveThread`** (internal connector) — reactively pins the
resolved thread onto `agent.threadId` and owns the connect lifecycle
(per-run `AbortController` on `HttpAgent`s, a single caught connect
chain, a staleness-guarded loading cursor, abort+`detachActiveRun()`
teardown), mirroring the standalone `connectToAgent` path. Clears
messages only on a genuine new-thread transition (never on
mount/agent-swap).
3. **`CopilotChat`** consumes the ambient config when present
(input-first precedence: `[agentId]`/`[threadId]` win), seeds the config
from a set `[threadId]`; standalone `[threadId]` usage unchanged when no
provider is present.

**The drawer — `<copilot-drawer>`:**
4. A standalone `OnPush` wrapper around the framework-agnostic
`copilotkit-drawer` Lit element (`@copilotkit/web-components`). Events
bind declaratively; element properties are set imperatively via
`viewChild`+`effect` (the `a2ui-activity-renderer` precedent). Routes
the element's events
(`thread-selected`/`new-thread`/`archive`/`unarchive`/`delete`/`filter-change`/`retry`)
to the config + `injectThreads` mutations (delete-of-active resets to a
fresh thread).
5. **`CopilotDrawerRow`** directive for per-row custom content
(`slot="row:{id}"`), `onThreadSelect`/`onNewThread` host escape-hatch
callbacks, and `<ng-content>` slot passthrough
(`launcher-icon`/`memories`).
6. **`listError`** added to `injectThreads` — a filtered error (genuine
list/mutation errors only, excluding developer/config errors like
"Runtime URL is not configured") so the drawer's error panel never shows
dev strings to end users. Mirrors react-core's `useThreads`.

**Always-licensed:** Angular SDK licensing is no longer a thing, so the
wrapper does not wire the element's `licensed`/`upsell` — no upsell
path. **Inline-chat-only:** no Layer-2 open-state coordination (the
element self-provides its mobile launcher).

## Why

Angular had no active-thread provider (only `injectThreads`) and no
drawer component. This lands both so Angular apps get thread switching +
a usable threads drawer at parity with the React vertical, reinterpreted
for Angular's inline-chat-only surface.

## Testing

`@copilotkit/angular`: tsc clean, `oxlint` 0 errors, `ng-packagr` build
green, **152 tests pass** (full package suite). New coverage: config
precedence/controlled-vs-uncontrolled + single-instance identity;
connector connect-on-switch / clear-only-on-real-transition / cursor
staleness / no-unhandled-rejection / abort+detach teardown (verified
against a real `HttpAgent`); drawer prop binding, all 7 event routings
(incl. delete-active reset), escape-hatch overrides, `renderRow`
projection, `<ng-content>` slot passthrough, and the `listError`
dev-error-exclusion.

Hardened through a full `cr-loop` (foundation: 5 rounds; wrapper: 2
rounds) — the wrapper CR caught + fixed a real bug (the error panel was
leaking dev/config errors; fixed via the filtered `listError`).

## Dependency / release gate

Depends on `@copilotkit/web-components` (the `copilotkit-drawer`
element) being published — the same release gate as the React drawer
work (#5707). `packages/angular` publishes alongside.

## Follow-ups (out of scope, tracked)

- A demo `routes/threads` in `examples/v2/angular/demo` (kept separate
to keep this a clean SDK-only change).
- Pre-existing OSS packaging: `zod` is in `devDependencies` but imported
by production source — should move to `dependencies`/`peerDependencies`.
- `packages/angular/src/lib/threads.spec.ts` uses `describe/it` vs the
flat-`test` convention of sibling specs (pre-existing).
- Minor polish backlog from CR (renderRow multi-row tests, a docblock
tidy) — non-blocking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-30 15:46:35 -07:00
Benjamin Taylor 74b8a1981f feat(drawer): default Upgrade CTA URL + Angular license gate
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.
2026-06-30 17:34:39 -05:00
Benjamin Taylor f53a70c691 refactor(drawer): rename to CopilotThreadsDrawer / copilotkit-threads-drawer
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.
2026-06-30 17:34:39 -05:00
Benjamin Taylor eb3c20e865 refactor(drawer): rename unlicensed -> licensed across the public surface
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.
2026-06-30 17:34:39 -05:00
Benjamin Taylor d7cb0fded1 refactor(drawer): rename upsell -> unlicensed across the public surface
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).
2026-06-30 17:34:39 -05:00
Benjamin Taylor cf4f00ecc1 feat(drawer): activate thread pagination (Load more + limit prop)
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.
2026-06-30 17:34:38 -05:00
Benjamin Taylor f1cc30cda0 feat(react): add configurable label prop to CopilotDrawer
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.
2026-06-30 17:34:38 -05:00
Benjamin Taylor 0183a30369 fix(web-components): scroll the drawer thread list when it overflows (:host height + .list min-height:0) 2026-06-30 17:34:38 -05:00
github-actions[bot] 3c8e330fcb style: auto-fix formatting 2026-06-30 17:34:38 -05:00
Benjamin Taylor 10a5315c10 feat(angular): forward a label input to the drawer element 2026-06-30 17:34:38 -05:00
Benjamin Taylor 787b9ad382 feat(web-components): make the drawer label/aria-label configurable (label property, defaults to Threads) 2026-06-30 17:34:37 -05:00