Commit Graph

1976 Commits

Author SHA1 Message Date
Alem Tuzlak 972dd64476 refactor(bot): split the Intelligence managed adapter into @copilotkit/bot-intelligence
Move the Intelligence-delivered managed-bot surface out of @copilotkit/bot into
its own package so the adapter, transports, contracts, and lifecycle ship
independently of bot core.

- New @copilotkit/bot-intelligence: intelligenceAdapter + DeliverySource/EgressSink
  (+ in-memory impls) + placeholder contracts + startManagedBots/validation/
  activation metadata. Production code imports only types from @copilotkit/bot
  and @copilotkit/bot-ui.
- @copilotkit/bot keeps the generic PlatformCodec seam (moved to src/codec.ts) and
  all core createBot changes (addAdapter, deferred store, id fields,
  __managed/skipIngressDedup, exclusive guard). It now also exports the
  FakeAdapter/FakeAgent test utilities for downstream adapter-package tests.
- Registered the new release scope: release.config.json, scripts/release/lib/
  config.ts, and the canary/publish/stable release workflows.

Tests preserved: bot 150 + bot-intelligence 19 (= the prior 169); bot-slack 261.
Builds typecheck across bot/bot-intelligence/bot-slack/runtime; publint/attw/
oxlint/oxfmt clean.
2026-06-29 14:30:28 +02:00
Alem Tuzlak 49767661ba feat(bot-slack): expose slackCodec via ./codec subpath for Bolt-free import 2026-06-29 14:03:32 +02:00
Alem Tuzlak 4d1ffc2199 Merge remote-tracking branch 'origin/main' into alem/oss-360-sdk-foundations
# Conflicts:
#	packages/bot/src/create-bot.ts
2026-06-29 14:01:14 +02:00
Markus Ecker bb117b1ef7 Merge remote-tracking branch 'origin/main' into mme/memory-core
# Conflicts:
#	packages/core/src/index.ts
2026-06-29 13:37:52 +02:00
Alem Tuzlak c55aa134be docs(runtime): clarify managed bots are validated at activation, not construction 2026-06-29 12:05:34 +02:00
Alem Tuzlak 6f5d1406eb feat(bot,bot-slack): PlatformCodec seam + Slack egress codec (OSS-363)
A shared, pure, per-platform codec so platform rendering semantics live in one
place instead of being duplicated between the local adapter and the
Intelligence/Connector-Outbox side.

- PlatformCodec interface in @copilotkit/bot (renderEgress: IR -> native; pure,
  no transport, no credentials)
- slackCodec in @copilotkit/bot-slack composing the existing pure
  renderSlackMessage, importable by the Connector Outbox without Bolt or creds

Ingress normalization is marked TODO(OSS-363): extracting the pure Slack event
-> neutral mapping from the Bolt listener (so the local adapter and Intelligence
webhook ingress share it) is the remaining, higher-risk half of that ticket.
2026-06-29 11:59:15 +02:00
Alem Tuzlak 9046b241e6 feat(runtime): typed managed-bots option on the Intelligence runtime (OSS-360)
Expose new CopilotRuntime({ intelligence, bots }) -- the Mode B entry point
for managed bots:

- bots is accepted only on the Intelligence runtime variant (bots?: undefined
  on the SSE variant), so TypeScript rejects bots without intelligence
- CopilotIntelligenceRuntime stores the declared bots; the facade exposes them
  via the existing isIntelligenceRuntime getter pattern
- @copilotkit/bot is imported type-only (it is pure-ESM; a value import would
  break this package's CJS output). Name validation + transport wiring happen
  in startManagedBots (called by the managed-listener bootstrap), not here.

Adds a type-only @copilotkit/bot workspace dependency.
2026-06-29 11:50:41 +02:00
Alem Tuzlak 35390eafa2 feat(bot): managed runtime API — bot name, validation, activation, lifecycle
The SDK slice of OSS-360, fully unit-tested with in-memory transports:

- createBot({ name }): project-unique id exposed as bot.name (optional for
  local bots; required + validated for managed)
- managed/runtime.ts:
  - assertValidBotNames: required, identifier-style, unique-per-runtime; fails loud
  - buildActivationMetadata: declared bot names + runtime env/versions (pure)
  - startManagedBots: validate -> attach intelligenceAdapter per bot (wired to its
    resolved transport) -> start; returns metadata + stop handle
- intelligenceAdapter now accepts a `store` it exposes as `stateStore`, so the
  Intelligence-backed backend flows through createBot's resolveBackend

Transports are injected by the caller (closed Gateway/Outbox in production,
in-memory in tests); this module owns no Slack creds, ingress, or outbox.
2026-06-29 11:07:53 +02:00
Alem Tuzlak fda5b8ed11 feat(bot): route all managed ingress kinds through the bridge adapter
Widen the placeholder ManagedIngressEnvelope to a discriminated union and route
every kind to the matching bot-core sink call, so managed bots reuse normal
routing for messages, commands, interactions, thread-starts, and reactions
(OSS-361) — not just plain turns.

- contracts: ManagedIngressBase + union over turn|command|interaction|
  thread_started|reaction
- IntelligenceAdapter.dispatchTo: switch on kind -> onTurn / onCommand /
  onInteraction / onThreadStarted / onReaction
- tests cover each kind dispatching to its handler and emitting egress
2026-06-29 11:00:26 +02:00
Ben Taylor ca28191042 feat(drawer): CopilotDrawer host theming, mobile launcher, action icons + thread-management/tooltip fixes (#5707)
## CopilotDrawer — SDK polish + thread-management fixes

Polish and fixes on top of the shipped `<copilotkit-drawer>`
([#5701](https://github.com/CopilotKit/CopilotKit/pull/5701)), surfaced
by real de-fork pilots run against a locally-built SDK + the hosted
Intelligence runtime: **langgraph-js** (rich canvas / inline
`CopilotChat` / dark theme) and **mastra** (the proverbs CoAgents demo /
`CopilotSidebar` / light theme / controlled→uncontrolled provider).
Spans **`@copilotkit/web-components`** and **`@copilotkit/react-core`**
— no example/de-fork changes here (those wait on a release that
publishes web-components + a `react-core` bump that includes
`CopilotDrawer`). Captured as Phase-5 acceptance requirements in the
[design doc](https://app.notion.com/p/3883aa3818528190b5d1f9b6ba26dca0).

### `react-core` — thread management
- **Thread switching works under `<CopilotKit>`.**
`CopilotChatConfigurationProvider` treated any `threadId` prop as
controlled, so the auto-minted, non-explicit threadId that
`<CopilotKit>`'s v1 bridge seeds blocked the drawer's imperative
`setActiveThreadId` / `startNewThread` — thread switching and "+ New"
were dead in every app wrapped in `<CopilotKit>`. A non-explicit
(`hasExplicitThreadId={false}`) threadId is now overridable; a genuine
caller-supplied threadId stays controlled.
- **"+ New" resets the chat.** `CopilotChat` clears messages when
switching to a fresh non-explicit thread so the welcome screen shows
instead of the prior thread's messages — including when a still-loading
`/connect` is superseded by the switch (the aborted connect's stale
snapshot is dropped instead of repopulating the view).
- **No upsell flash/stick.** `CopilotDrawer` treats a pending (`null`)
license status as loading, not unlicensed, so the upgrade upsell no
longer flashes (or sticks) before the runtime reports the license.
- **In-header drawer launcher is mobile-only.**
`CopilotModalHeader.DrawerLauncher` toggles `drawerOpen`, which only
drives the off-canvas *mobile* drawer; on desktop the drawer is a
persistent in-flow panel that ignores `open`, so the launcher was a dead
no-op there. It now renders only at ≤767px. On desktop the chat's own
open/close (the toggle FAB + the header close, both lucide `X`) is the
consistent pair.

### `web-components` — theming, launcher, icons, tooltips
- **Host-theme inheritance (incl. dark mode).** Each token now resolves
`--cpk-drawer-* override → host theme var
(`--background`/`--card`/`--foreground`/`--border`/…) → built-in light
default`. The drawer follows the host app's light/dark theme by
inheritance, instead of baking light-only values (it showed a light
drawer on a dark app). Custom properties aren't reset by the `:host {
all: initial }` guard, so the standalone fallback still holds.
- **Row actions are icon buttons with instant, on-brand tooltips.**
Archive / Unarchive / Delete render inline lucide-style SVGs
(`currentColor`). Native `title` is replaced by an instant CSS tooltip
(matches the React components' Radix `delayDuration: 0`; `title`'s
show-delay is browser-fixed at ~1.5s), styled to match the standard
CopilotKit tooltip — a primary-colored bubble with an arrow, not a
surface/bordered box — and positioned to the side so the list's
scroll-overflow never clips it. The tooltip is suppressed while the
delete-confirm dialog is open (the clicked trash button keeps
`:focus-visible` otherwise, leaving its "Delete" tooltip floating over
the dialog).
- **Clipped thread names get a tooltip.** A truncated name exposes its
full text via the same instant primary-bubble tooltip as the row actions
(not the native `title`), shown only when actually clipped. The name
text moved to an inner span (so the outer can host the un-clipped
bubble) and the hovered row is z-lifted (each row is its own stacking
context from the entry-animation transform, which otherwise painted the
bubble under later rows).
- **Archived rows are muted**, no longer struck through.
- **Refetch preserves the list.** A refetch (e.g. Active↔All toggle)
keeps the known threads visible; the full loading state only renders on
the initial empty fetch.
- **Empty `footer` region hides** (it rendered as a stray bordered box
at the bottom). Driven by a `slotchange` listener, mirroring the
`memories` region.
- **Self-owned mobile launcher.** When the drawer is a closed off-canvas
mobile modal it renders its own floating "open threads" launcher, so
it's always openable without the host wiring a header button. The icon
is swappable via a `launcher-icon` **slot**, position is themeable via
`--cpk-drawer-launcher-top` / `--cpk-drawer-launcher-left` (so a host
can center it on its own header controls), and it exposes
`part="launcher"`. The richer in-header
`CopilotModalHeader.DrawerLauncher` remains an optional integration.

### Tests
- **react-core**: thread-control + non-explicit-override cases on
`CopilotChatConfigurationProvider`, the "+ New" message reset on
`CopilotChat`, license-pending gating on `CopilotDrawer`, and the
mobile-only / desktop-hidden launcher on `CopilotModalHeader`. New
regression tests verified red-green; chat + provider suites green, `tsc
--noEmit` clean, build green. (The superseded-connect *race* guard is
covered by live verification + its synchronous sibling test — an
async-timing unit test would be flaky, which the repo treats as a bug.)
- **web-components**: element tests for the icon tooltips +
confirm-dialog suppression, the clipped-name tooltip (`data-tooltip` +
placeholder), archived styling, refetch-preserves-list, footer
hide-when-empty, and mobile launcher render/open + desktop-absent.
Drawer suite green, `tsc --noEmit` clean, build + `es-check` green under
`CI=true`. (Truncation detection + tooltip stacking are layout/CSS —
verified live, not in jsdom.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-28 08:44:06 -05:00
Jeel Gor 9632ca901c Merge branch 'main' into fix/5601-windows-cross-platform-scripts 2026-06-27 15:48:22 +05:30
Benjamin Taylor 9223fc476a fix(web-components): stamp name-clipped on the row so the tooltip z-lift fires
_syncNameClipping toggled name-clipped on .row-name, but the stacking fix in
styles.ts targets .row.name-clipped:hover — a different element — so the z-index
lift never matched and clipped-name tooltips still painted under later rows
(each row is its own transform stacking context). Stamp the flag on the owning
.row too; the tooltip bubble stays scoped to .row-name:hover so a row-action
hover never surfaces it. Adds a red-green contract test asserting the class
lands on both the row-name and the row.

Addresses MikeRyanDev review on #5707.
2026-06-26 17:11:25 -05:00
Benjamin Taylor 31f31eeebd fix(web-components): tooltip for clipped CopilotDrawer thread names
A long thread name is clipped with an ellipsis; expose the full text via the
same instant primary-bubble tooltip as the row actions (not the native `title`),
shown only when the name is actually truncated. The name text moved to an inner
span so the outer `.row-name` can host the un-clipped bubble, and the hovered
row is z-lifted so the bubble isn't painted under later rows (each row is its
own stacking context from the entry-animation transform).
2026-06-26 16:54:55 -05:00
Benjamin Taylor a4d129d8fa fix(react-core): render the CopilotModalHeader drawer launcher only on mobile
The in-header thread-drawer launcher toggles `drawerOpen`, which only drives the
off-canvas MOBILE drawer; on desktop the drawer is a persistent in-flow panel
that ignores `open`, so the launcher was a dead no-op there (it appeared to do
nothing on click). Gate it on a reactive mobile viewport check so it renders
only at ≤767px. On desktop the chat's own open/close — the toggle FAB + the
header close (both lucide X) — is the consistent pair; nothing masquerades as a
chat control.
2026-06-26 16:54:55 -05:00
Benjamin Taylor 4fbb5d1f65 fix(web-components): match CopilotDrawer row-action tooltips to the standard CPK tooltip
Row-action tooltips used a surface background + border, which read as a button.
Restyle to the standard CopilotKit tooltip: primary bubble, primary-foreground
text, an arrow, no border. Also suppress the tooltip while the delete-confirm
dialog is open — the clicked trash button keeps :focus-visible, which otherwise
left its "Delete" tooltip floating over the dialog.
2026-06-26 16:54:55 -05:00
Benjamin Taylor af854aa5ff fix(react-core): make CopilotDrawer thread switching work under <CopilotKit>
CopilotChatConfigurationProvider treated any `threadId` prop as controlled, so
the auto-minted non-explicit threadId that <CopilotKit>'s v1 bridge seeds
blocked the drawer's imperative setActiveThreadId/startNewThread — thread
switching and "+ New" were dead in every app wrapped in <CopilotKit>. A
non-explicit (`hasExplicitThreadId={false}`) threadId is now overridable; a
genuine caller-supplied threadId stays controlled.

Also, surfaced during the langgraph-js de-fork validation:
- CopilotChat clears messages when switching to a fresh non-explicit thread
  ("+ New") so the welcome screen shows instead of the prior thread — including
  when a still-loading /connect is superseded by the switch.
- CopilotDrawer treats a pending (null) license status as loading, not
  unlicensed, so the upgrade upsell no longer flashes or sticks before the
  runtime reports the license.
2026-06-26 16:54:55 -05:00
Benjamin Taylor 2664df54a9 feat(web-components): CopilotDrawer host-theme inheritance, action icons, self-owned mobile launcher, and UX fixes
Polish on top of the shipped <copilotkit-drawer> (#5701), surfaced by the first
real de-fork pilot (langgraph-js):

- Theming follows the host app's light/dark theme: each token resolves
  override -> host theme var (--background/--card/...) -> built-in light default,
  instead of baking light-only values (drawer was light on a dark app).
- Row actions are icon buttons (inline lucide-style SVG, currentColor) with
  instant tooltips. Native title is replaced by a CSS tooltip (matches the
  react components' delayDuration:0; title's show-delay is browser-fixed) and is
  positioned to the side so the list's scroll-overflow never clips it.
- Archived rows are muted, no longer struck through.
- A refetch (e.g. Active<->All filter toggle) keeps the known list visible;
  the full loading state shows only on the initial empty fetch.
- The reserved footer region hides when nothing is slotted into it (it rendered
  as an empty box at the bottom); mirrors the memories region.
- Mobile gets a self-owned floating launcher so the drawer is always openable
  with no host header wiring. Its icon is swappable via a launcher-icon slot and
  its position via --cpk-drawer-launcher-top/left (host can center it on its own
  header controls); exposes part="launcher".

Adds element tests for icons+tooltips, archived styling, refetch-preserves-list,
footer hide-when-empty, and the mobile launcher (render + open + desktop-absent).
2026-06-26 16:54:55 -05:00
Alem Tuzlak e0307facc8 refactor(bot): drop bot-store-redis/postgres adapters (never published)
The StateStore interface and the in-memory MemoryStore default remain;
durable backends can be reintroduced as a follow-up. Both adapter packages
were merged in #5613 but never published to npm, so removal is a clean
delete with no consumer impact.

- Delete packages/bot-store-redis and packages/bot-store-postgres.
- Revert the bot release scope and drift guard to bot + bot-ui.
- Strip the Redis dep, demo:restart script, restart demo, docker-compose,
  and REDIS_URL env from examples/slack.
- Rewrite the bot persistence/transcripts docs around "MemoryStore default
  + implement the StateStore interface yourself for durability".
2026-06-26 14:40:10 -07:00
tylerslaton c16dc1a363 chore: release bot v0.1.0 2026-06-26 21:15:26 +00:00
Benjamin Taylor d10e9c5cfc test(bot): guard telemetry platform allow-list against new adapters
Adds a monorepo-invariant test that scans sibling bot-* adapter packages for their declared `platform` literal and fails if any is missing from normalizePlatform's allow-list. It immediately caught the new bot-teams adapter (platform "teams") that landed on main — now added to the allow-list.
2026-06-26 15:45:06 -05:00
Benjamin Taylor 4d67b2bef7 fix(bot): normalize telemetry platform and emit agent_run after finalization
Address PR review: bound the free-form adapter platform label to slack|discord|telegram|whatsapp|custom (no tenant/project leakage, capped cardinality); emit oss.bot.agent_run only after the transcript-append + renderer.finish() steps succeed, with a finalize stage on oss.bot.agent_run_failed for late failures.
2026-06-26 15:39:31 -05:00
github-actions[bot] e064403cac style: auto-fix formatting 2026-06-26 15:12:00 -05:00
Benjamin Taylor a822da8708 feat(bot): emit oss.bot.* lifecycle telemetry from createBot and Thread
createBot emits configured + started/start_failed; Thread emits agent_run/agent_run_failed around runAgentLoop. Zero new env vars. Includes mocked-wiring unit tests and a real-BotTelemetry e2e test.
2026-06-26 15:12:00 -05:00
Benjamin Taylor 363e6d92a1 refactor(bot): runAgentLoop reports iterations and interrupted 2026-06-26 15:12:00 -05:00
Benjamin Taylor e6b84c030b feat(bot): add anonymous oss.bot.* telemetry helper and event catalog
BotTelemetry posts 5 oss.bot.* events at 100% via @copilotkit/shared's lambdaClient. Anonymous (no telemetry_id/license/key), opt-out via COPILOTKIT_TELEMETRY_DISABLED/DO_NOT_TRACK, suppressed under test. 3-tier anonymous_id (durable store -> project cache file -> per-process UUID). errorClass() maps errors to a bounded category, never a raw message.
2026-06-26 15:12:00 -05:00
Martha Schumann f4e8a8c000 feat(web-inspector): add thread debugger provider 2026-06-26 11:35:05 -07:00
Alem Tuzlak 9f1a814859 feat(bot): add intelligenceAdapter managed bridge + transports (OSS-361)
@internal, undocumented bridge that runs the bot SDK from Intelligence-
delivered events. Pure plumbing over injected DeliverySource (inbound) and
EgressSink (outbound) transports; production wires Realtime Gateway +
Connector Outbox, tests/headless wire the in-memory implementations.

- src/managed/: placeholder contracts (TODO(OSS-377)), transport interfaces,
  in-memory transports, IntelligenceAdapter + intelligenceAdapter() factory
- ingress: managed turn -> onTurn; ack on success, nack on throw (at-least-once)
- egress: deterministic operationId = `${turnId}:${seq}` (reset per turn, so a
  redelivered turn reproduces the same ids for Connector Outbox dedupe); minted
  MessageRef carries routing for update/delete; buffering run-renderer emits a
  post op for agent text
- create-bot: skipIngressDedup capability (managed skips ingress dedup and relies
  on egress idempotency; local adapters unchanged) + assertExclusive guard
  (intelligenceAdapter must be the only adapter on a bot in V1)
2026-06-26 19:09:55 +02:00
Alem Tuzlak 1d5a3ad670 feat(bot): defer store resolution + addAdapter + ingress id fields
Foundations for Intelligence-delivered managed bots (OSS-360 SDK slice),
all backwards-compatible:

- createBot `adapters` is now optional + new `bot.addAdapter()` (throws if
  called after start), so the runtime can attach a delivery adapter late
- backend/transcripts/registry resolution and component registration are
  deferred from construction to start(); new resolveBackend precedence
  (explicit store.adapter -> adapter-provided stateStore -> MemoryStore),
  warning when more than one adapter provides a store
- bot.transcripts throws if accessed before start()
- optional stateStore on PlatformAdapter; optional turnId/deliveryId on
  IncomingTurn/InteractionEvent/IncomingCommand; eventId/turnId/deliveryId
  on IncomingMessage, propagated from the turn for customer-side idempotency
2026-06-26 18:47:10 +02:00
Ran Shem Tov 47e255f670 feat(react-core): add client-side onAction interceptor to v2 A2UI renderer
Add an optional onAction interceptor to createA2UIMessageRenderer so apps
can handle A2UI actions client-side (e.g. navigate) instead of forwarding
every action to the agent.

- onAction(action, forward) runs before forwarding. Return null to handle
  client-side and stop forwarding, return a modified action to forward it,
  or return undefined to forward unchanged.
- Threaded from createA2UIMessageRenderer options through ReactSurfaceHost.
- Extracted runA2UIAction helper for deterministic unit testing.
- Default behavior is unchanged when onAction is not supplied.
2026-06-26 15:57:28 +02:00
Alem Tuzlak f97d0c5213 feat(bot): give <Message onReaction> a thread + messageRef (onClick parity)
The reaction handler now receives the conversation `thread` and an
update-capable `messageRef` for the reacted message — the same surface an
`onClick` gets via `ctx.thread`/`ctx.message.ref`. A reaction can now post new
UI (`thread.post`), swap the message in place (`thread.update(messageRef, …)`),
run the agent, or block on a human choice (`thread.awaitChoice`, HITL).

- bot-ui: `MessageReaction` gains `thread` and `messageRef`.
- platform-adapter: `IncomingReaction` gains an optional adapter-provided
  `messageRef` (engine falls back to `{ id: messageId }`).
- create-bot: threads `thread` + `messageRef` into both the global
  `ReactionEvent` and the per-message handler.
- Slack/Discord/Telegram reaction decoders emit a platform-specific,
  update-capable `messageRef` (channel+ts / channelId+id / chatId+messageId).
2026-06-26 14:40:39 +02:00
Alem Tuzlak d6b01d379a feat(bot): typed Renderable, durable <Message onReaction>, and richer JSX props
Type the bot UI surface and broaden the cross-platform component vocabulary,
adding only capabilities that more than one adapter can express.

- bot-ui: type the `Thread` interface's `ui` params (`post`/`update`/
  `awaitChoice`/`postEphemeral`) as `Renderable` instead of `unknown`, so JSX
  is checked at the call site and the `{ raw }` escape hatch is explicit.
- `<Message onReaction>`: per-message reaction callback `(emoji, { added, user,
  rawEmoji, messageId })`. Stripped from the IR before it reaches the adapter,
  routed from reaction ingress by message id. Durable on the same terms as a
  component `onClick` — a `{ component, props }` snapshot is persisted and the
  component is re-rendered to re-derive the handler after a restart; inline
  handlers route in-process only.
- `Button.url` link buttons — Slack, Discord, Teams, Telegram.
- `Field.label` — typed (Discord and Telegram already consumed it untyped);
  newly rendered on Slack.
- `Select.multi` multi-select — Slack (`multi_static_select` in an input block
  + `selected_options` decode), Discord (min/max values + `component` bounds
  decode), Teams (`isMultiSelect`); Telegram/WhatsApp degrade to single-select.

Slack-only capabilities (Button.confirm, Image.title, Input label/initialValue/
required, Select.initialValue) were intentionally left out.
2026-06-26 13:11:20 +02:00
Lukas Moschitz 7ef6fa7f61 feat(react-core): useMemories hook on the core memory store 2026-06-26 11:30:36 +02:00
tylerslaton 34aecf1c97 chore: release bot-teams v0.1.0 2026-06-25 22:48:57 +00:00
Tyler Slaton 02bf7f934b build(core): raise build heap ceiling to 8GB via cross-env (#5328)
## What

Bake a heap ceiling into the `@copilotkit/core` build script:

```diff
-"build": "tsdown",
+"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 tsdown",
```

(`cross-env` is already used elsewhere in the repo; added here as a core
devDependency.)

## Why

The core build (tsdown + dts generation) has a ~3.45GB working set and
OOMs under `nx run-many`, where it competes with sibling builds and GC
falls behind.

This mostly bites **local development**. Agents (and humans) routinely
have to prefix commits with `NODE_OPTIONS=--max-old-space-size=8192`
just to get the build through pre-commit hooks. CI already sets this
flag at the workflow level, so baking it into the build script means
every invocation path gets the same headroom without anyone remembering
to add it: local lefthook hooks, `nx run-many`, a direct `pnpm build`,
CI, and Windows (hence `cross-env`).

Scoped to core only, since it's the single package that OOMs.
2026-06-25 15:26:52 -07:00
Markus Ecker 99b221d9e5 fix(core): memory socket never joined its channel (no realtime deltas)
The memory store's socket effect created the `user_meta:memories:<code>`
channel and observed its events, but never subscribed the join-outcome
stream — and `ɵphoenixChannel$` only calls `channel.join()` when that stream
is subscribed. So the socket connected but no `phx_join` was ever sent: the
gateway saw the connection, the channel was never joined, and saved memories
never pushed to the client (REST snapshot worked; live deltas silently never
arrived). The thread store joins because its merged `joinOutcome$` subscribes
the stream.

Merge `ɵjoinPhoenixChannel$(channel$)` into the socket effect's output so the
join actually fires; swallow a failed/timed-out join so a transient rejection
doesn't tear down the metadata stream (Phoenix re-attempts on reconnect). Add
a `joinCount` spy to MockChannel and assert the realtime test actually joins —
this regression passed before because the mock delivered events without a join.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 23:38:33 +02:00
Austin Merrick ca920066ac build(core): raise build heap ceiling to 8GB via cross-env
The @copilotkit/core build (tsdown with dts generation) has a working set
of about 3.45GB. Node's default old-space ceiling is roughly 4GB and CI pins
NODE_OPTIONS to 4096, leaving almost no headroom. Under nx run-many the build
competes for CPU with sibling builds, GC falls behind, and the process tips
over the heap limit. nx flags it as a flaky task and pre-commit/CI builds fail
intermittently with a V8 heap OOM.

Bake the ceiling into the core build script with cross-env so every invocation
path gets consistent headroom: local lefthook hooks, nx run-many, CI, and
direct pnpm build, on every platform including Windows. 8192 matches the value
already used by the e2e workflow and gives roughly 2x headroom over the working
set.

Scoped to core only; it is the single package that OOMs.
2026-06-25 14:01:39 -07:00
Austin Merrick 7a309fc210 feat(bot-teams): Microsoft Teams PlatformAdapter with Adaptive Cards, streamed replies, and HITL
Adds the @copilotkit/bot-teams package: a PlatformAdapter that bridges
the CopilotKit runtime to Microsoft Teams. Renders agent output as
Adaptive Cards (including native <Chart> components via bot-ui), streams
replies with a typing-indicator heartbeat, supports human-in-the-loop
confirmations, and handles inbound files via the Graph API with channel
file support.
2026-06-25 12:56:04 -07:00
github-actions[bot] 21306d11e4 style: auto-fix formatting 2026-06-25 19:43:20 +00:00
Nathan 🔶 Tarbert 46beb253d9 fix: avoid getAgent probe warning in CopilotListeners for absent default agent (#5533) 2026-06-25 15:42:35 -04:00
Markus Ecker cd0739800e fix(runtime): identify memory-subscribe user via header, not body
ɵsubscribeToMemories mirrored ɵsubscribeToThreads and sent userId in the
body, but the platform's memory routes resolve the app user from the
x-cpki-user-id header (like listMemories/createMemory), not the body — so
POST /api/memories/subscribe returned 401 AUTH_UNAUTHENTICATED. Send the
user via the header instead; the body is now empty.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:33:00 +02:00
Markus Ecker 4f50068244 fix(runtime): add missing /memories/subscribe route + handler
The memory store client POSTs /memories/subscribe to mint realtime join
credentials, but the runtime router had no such route — the path fell
through to /memories/:id (memories/mutate), so a POST returned 405 Method
Not Allowed. Threads had the full chain (route → handleSubscribeToThreads →
platform); memory was missing the runtime proxy between the client and the
platform's POST /api/memories/subscribe.

Add `memories/subscribe` to the route union, match it before /memories/:id
(and exclude "subscribe" from the :id rule, mirroring threads), add
handleSubscribeToMemories returning { joinToken, joinCode } (memory delivers
the join code here, unlike threads where it rides the thread-list response),
and ɵsubscribeToMemories on the platform client.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:17:37 +02:00
Markus Ecker 4211bd58d8 chore: format memory SDK files with oxfmt 2026-06-25 19:49:34 +02:00
Benjamin Taylor 225a3fc646 fix(web-components): contain mobile-modal focus including the backdrop
The mobile drawer is a modal dialog, but the Tab trap was bound to .root only,
while the backdrop button renders as a sibling OUTSIDE .root — so Tab from the
backdrop (or any out-of-root node) could escape the modal. Move the trap to the
host keydown listener (keydown is composed, so it catches the backdrop too) and
include the backdrop in the focusable cycle; keep initial focus on the first
real control. Adds a regression test for backdrop/outside-root Tab containment.
2026-06-25 11:28:32 -05:00
Benjamin Taylor d07888c611 fix(web-components): make the UMD lit-inlining CI-safe
The UMD bundle inlines lit for a self-contained CDN <script>; inlining lit also
pulls in its runtime deps (@lit/reactive-element, lit-html, lit-element,
@lit-labs/ssr-dom-shim). tsdown flags that transitive bundling as 'unintended'
and promotes the warning to a fatal error under CI, breaking
@copilotkit/web-components:build (and every dependent). Declare all lit packages
in noExternal and set inlineOnly: false to mark the bundling intentional.
2026-06-25 11:28:32 -05:00
Markus Ecker ca8e2fa064 refactor(core): drop thread-store user_meta sharing; memory owns its socket 2026-06-25 18:02:43 +02:00
Markus Ecker 250028469d feat(core): memory store opens its own user_meta:memories socket 2026-06-25 17:58:57 +02:00
Markus Ecker 3e04352d94 feat(core): memory store fetches its own subscribe credentials 2026-06-25 17:54:04 +02:00
Markus Ecker ce24806c1c feat(core): add wsUrl + credentials events to the memory store context 2026-06-25 17:47:48 +02:00
github-actions[bot] ba85b2f0a6 style: auto-fix formatting 2026-06-25 15:45:46 +00:00
Benjamin Taylor 36d0bb636f feat(angular): add injectThreads for the threads SDK
Angular signal wrapper over the core thread store: reactive runtime context
(re-dispatches when wsUrl/threadEndpoints arrive), enabled-gated single-slot
registration, bound result methods, and synthesized error/loading parity with
react-core.
2026-06-25 10:42:47 -05:00