Commit Graph

14241 Commits

Author SHA1 Message Date
renovate[bot] ffb463f20d chore(deps): update zizmorcore/zizmor-action action to v0.6.1 2026-07-24 09:31:43 +00:00
Alem Tuzlak fa8bc80cfd fix(showcase/built-in-agent): use gpt-5.4 — staging returns empty on gpt-5.5 (#6149)
## Problem
After #6106 merged, **staging showed every built-in-agent cell capped at
D3** with the backend red:
```
Failure: empty assistant response   (level: chat)
Backend: https://showcase-built-in-agent-staging.up.railway.app
```
The D4 chat probe hits the main agent (`agentic_chat` / generic
`createBuiltInAgent`), which used **`gpt-5.5`** → the real OpenAI call
returns empty → the whole D-ladder gates → all cells stuck at D3.

## Root cause
- `gpt-5.5` is **unique to built-in-agent** (introduced in #6106). Every
other integration — including the **LGP reference that works on
staging** — uses **`gpt-5.4`** (38× across the repo).
- Staging's OpenAI account doesn't serve `gpt-5.5`, so every real call
came back empty.
- **aimock ignores the model id**, so this was invisible in local D6
(which is why it passed locally but broke on staging).
- The other factories also still had leftover `gpt-4o` / `gpt-4o-mini`
(a2ui, byoc, mcp-apps, ogui, subagents).

## Fix
Switch **all** `built-in-agent` `openaiText()` calls to **`gpt-5.4`**
(matches LGP, served on staging). `reasoning-factory` keeps `gpt-5.2`
(reasoning-capable; those demos are NSF-quarantined). 10 factory files,
model-string-only changes.

> Note: this deviates from the general "always gpt-5.5" preference
because this is an **LGP-parity** integration and staging only serves
`gpt-5.4` — parity + a working staging both require it.

## Verify
Once merged + redeployed, staging D4 chat should return real text and
the cells should climb past D3. (Can't be verified in local D6 since
aimock ignores the model.)
2026-07-24 11:30:42 +02:00
Alem Tuzlak eedea568a2 fix(showcase/built-in-agent): use gpt-5.4 (staging returns empty on gpt-5.5)
Staging D4 chat probe returned 'empty assistant response' for every cell,
capping all cells at D3. Root cause: the factories used gpt-5.5 (agentic-chat +
generic createBuiltInAgent) and leftover gpt-4o/gpt-4o-mini (a2ui, byoc, mcp-apps,
ogui, subagents). gpt-5.5 is unique to built-in-agent; every other integration —
including the LGP reference that works on staging — uses gpt-5.4, which staging's
OpenAI account serves. aimock ignores the model id, so this was invisible locally.

Switch all built-in-agent openaiText() calls to gpt-5.4 (matches LGP, unblocks
staging). reasoning-factory keeps gpt-5.2 (reasoning-capable, its demos are
NSF-quarantined). Note: deviates from the general gpt-5.5 house rule because this
is an LGP-parity integration and staging only serves gpt-5.4.
2026-07-24 11:21:48 +02:00
Lukas Moschitz eaa49e55b3 feat(showcase): port langgraph-fastapi declarative-gen-ui to canonical sales-analyst demo
Task 2 of OSS-582. Replace fastapi's old generic 'chart-picker' declarative-gen-ui
with langgraph-python's canonical sales-analyst demo, so it matches the shared D6
probe (which asserts sales-dashboard / DataTable / StatusBadge / InfoRow per pill):
- backend src/agents/src/a2ui_dynamic.py: generic prompt -> LGP sales-analyst graph
  (persona + dataset grounding + composition rules + generate_a2ui tool)
- frontend definitions.ts/renderers.tsx/chat.tsx/suggestions.ts byte-identical to LGP,
  add sales-context.ts (fictional Vantage Threads dataset + composition rules)
- d6 fixtures gen-ui-declarative.json + render-a2ui.json: LGP's, re-keyed to
  context=langgraph-fastapi

Verified D6 green via control-plane (real 12s browser run, canonical testids asserted).
a2ui-recovery intentionally NOT aligned: its fixtures have no context routing, so each
integration must keep a unique pill prompt (sanctioned per-slug divergence).
2026-07-24 11:10:22 +02:00
shixi-li 50cf16caf5 fix(react-core): sync provisional credentials after commit 2026-07-24 10:50:56 +08:00
Benjamin Taylor 7947b3753c fix(examples): bound channels.ready() so a wedged adapter start can't hang startup
Adversarial-review finding: ready() awaits all channels' startup; an adapter whose
start() hangs would block readiness forever. Both examples now pass timeoutMs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:20:31 -05:00
Benjamin Taylor 476682330b fix(channels-core): a channel whose adapters ALL fail to start now errors, not false-online
Adversarial-review finding: ɵruntime.start() swallowed every adapter start failure
and resolved, so the runtime reported status "online" on a dead channel (revoked
token, port-in-use). Now: if a channel has adapters and NONE started, start() rejects
so ChannelManager surfaces "error" (a partial start, >=1 adapter live, still counts as
started). Adds a channel-manager failStart regression test + updates the telemetry test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:20:30 -05:00
github-actions[bot] 9be9ca9829 style: auto-fix formatting 2026-07-23 23:48:15 +00:00
Benjamin Taylor 1f0ad3de3e refactor(channels-core): drop dead ɵruntime.provider copy (review nit)
The activation path reads the top-level channel.provider; the ɵruntime.provider
copy was never consumed. Keeps the real top-level accessor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:44:55 -05:00
Tyler Slaton 831cfc0745 feat(showcase/built-in-agent): LGP parity — byte-identical frontends + named-agent backend (#6106)
## What & why

Brings the **built-in-agent** showcase integration to parity with the
**LangGraph-Python (LGP)** reference: byte-identical demo frontends + a
named-agent backend registry (BuiltInAgent + TanStack AI), so every demo
climbs the D0–D6 ladder against the LGP gold standard.

## Changes (4 commits)

1. **P0 pattern** — `agentic-chat` byte-identical + named agent
(`agentic_chat`); proven D6-green locally. Fixed `gpt-4o` → `gpt-5.5` in
the shared factory.
2. **Frontend migration (all demos)** — every LGP `src/app/demos/*`
copied verbatim (`diff -r` clean), plus shared `components/ui` (25
shadcn primitives) + `lib/utils`, byte-identical. Added the 5 demos BIA
lacked (`a2ui-recovery`, `declarative-hashbrown`,
`declarative-json-render`, `shared-state-read`,
`threadid-frontend-tool-roundtrip`); added the frontend deps the copied
UI needs (radix-ui, cmdk, embla-carousel-react, react-markdown,
remark-gfm, yaml, …).
3. **Named-agent backend** — `/api/copilotkit` registers 22 named agents
(generic all-tools, fixture-driven; reasoning trio via the reasoning
adapter). 8 dedicated routes re-keyed `default` → LGP agent id;
`mcp-apps` also serves `headless-complete`; `ogui` serves both
open-gen-ui ids; `byoc-*` routes renamed to `declarative-*`; new
`a2ui-recovery` + `beautiful-chat` routes reuse existing agents. Dropped
BIA-only extras (`byoc-*`, `hitl-in-chat-booking`).
4. **Reconcile** — `manifest.yaml` (37 features / 40 demos;
`generate-registry` + `validate-parity` pass) + `PARITY_NOTES.md`.

> **Note on "byte-identical":** frontends are verbatim LGP **modulo
BIA's `consistent-type-imports` ESLint rule** (type imports split into
`import type {}`) — required for a green lint/PR, semantically & DOM
identical.

## D6 status (local sweep)

- **~33/40 demos GREEN** on the first sweep — byte-identical frontends +
named agents + existing fixtures work broadly.
- **4 RED locally are an aimock-infra issue, not this integration:** the
deployed `ghcr.io/copilotkit/aimock:latest` has no
`context`/`--context-field` fixture scoping, so cross-slug `userMessage`
collisions let earlier-loaded (`ag2`/`d4`) fixtures shadow BIA's own.
BIA's fixtures are **correct** and converge under a context-aware aimock
(present on aimock `origin/main`). Affects
`tool-rendering-custom-catchall`, `headless-complete`, `gen-ui-agent`,
`frontend-tools`. **Action for infra: redeploy aimock from a
context-aware build.** Details in `PARITY_NOTES.md`.
- **2 downstream-host RED (kept as features, informational — mirrors
LGP):** `declarative-gen-ui` (A2UI renderer host) and `mcp-apps` (MCP
iframe host).
- Quarantined NSF unchanged: `gen-ui-interrupt`, `interrupt-headless`,
`shared-state-streaming`, reasoning-trio.

D6 is informational/weekly (not a merge gate); these are documented for
parity tracking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-23 16:43:46 -07:00
Tyler Slaton bee67425b0 chore(deps): widen @anthropic-ai/sdk optional peer range (#6133)
## What

Widens the optional `@anthropic-ai/sdk` peer dependency of
`@copilotkit/runtime` from `^0.57.0` to `>=0.57.0`.

## Why

An outside contributor reported that `@copilotkit/runtime` still
declares an optional peer of `@anthropic-ai/sdk@^0.57.0`, which
conflicts with current SDK versions (e.g. `0.109`) and forces consumers
to install with `--legacy-peer-deps`.

The `^0.57.0` caret pins the range within `0.57.x` (since it's a `0.x`
version), so any newer minor trips the peer-conflict warning even though
the SDK works fine at runtime.

## Safety

The anthropic adapter only relies on stable `@anthropic-ai/sdk` APIs —
client construction (`new Anthropic({})`), `messages.create`, and
ephemeral `cache_control` — which have been stable across `0.x`
releases. The reporter confirms `0.109` works at runtime today; this
only removes the false install-time peer conflict.

## Change

One line in `packages/runtime/package.json`:

```diff
-    "@anthropic-ai/sdk": "^0.57.0",
+    "@anthropic-ai/sdk": ">=0.57.0",
```
2026-07-23 16:41:14 -07:00
Benjamin Taylor 3be86e1d84 docs(examples): rework teams + slack channel examples to the Plan C model
Both run their Channel through an Intelligence runtime that owns lifecycle:
new CopilotRuntime({ intelligence, identifyUser, channels: [bot] }) + handler.channels.ready()/stop(),
no bot.start(). Direct adapters retained (multi-platform slack now runs under Intelligence). Env + example READMEs note the required Intelligence key (free tier).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:37:29 -05:00
Benjamin Taylor 1f6f6c4d34 docs(channels): rewrite all 7 READMEs to the Plan C model
Channels require an Intelligence connection (API key, free tier); run via
CopilotRuntime({ intelligence, channels }) + handler.channels.ready()/stop();
no channel.start(), no standalone/DIY path. Adapters keep their credentials.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:35:25 -05:00
Benjamin Taylor e6dba4519b feat(runtime)!: Intelligence runtime starts direct-adapter channels (Plan C)
The ChannelManager (only constructed for an Intelligence runtime) now STARTS
direct-adapter channels via channel.ɵruntime.start() instead of recording them
"unmanaged" and skipping — so every channel runs only because Intelligence is
configured; there is no standalone path. Removed the now-dead "unmanaged" status;
direct channels reuse the bounded/idempotent teardown via a synthetic handle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:26:24 -05:00
Benjamin Taylor 5f0d01a727 feat(channels-core)!: remove public Channel.start/stop/addAdapter — runtime-driven only (Plan C)
Channels run only through the Intelligence runtime now; there is no public
lifecycle to call. The internal channel.ɵruntime.{start,stop,addAdapter} seam is
retained and is what the runtime drives. Internal callers + guard strings migrated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:22:54 -05:00
Ben Taylor dfe88819d8 fix(core): add circuit breaker to prevent infinite follow-up loops (#5158)
## Summary

Fixes #4819.

`processAgentResult` recurses into `runAgent` whenever `needsFollowUp`
is true, with **no depth limit, no circuit breaker, no duplicate
detection**. Any scenario that keeps `needsFollowUp = true` loops
forever:

- The LLM repeatedly calling the same tool
- The backend returning a `RunError` after receiving tool results
(#2416)
- Input processors reprocessing tool messages (#3044)

This silently consumes API quota and can DOS the backend. The only
existing workaround — setting `followUp: false` on a tool — is too blunt
and breaks legitimate multi-step workflows.

## Change

- Add an absolute safety cap `MAX_FOLLOW_UP_DEPTH = 100`, reusing the
existing `_runDepth` counter (incremented in `runAgent`, decremented in
its `finally`).
- In `processAgentResult`, when the depth cap is reached: stop
recursing, emit a `logger.warn` (for debuggability), and return the
current result normally (already-inserted tool messages are preserved).
- The cap is deliberately high so legitimate multi-step workflows
(search → fill form → confirm → update → send email) are never affected;
it only trips on runaway recursion.

This protects against **all** infinite-loop scenarios in the issue, not
just specific triggers, without requiring users to set `followUp:
false`.

## Test

- Added `core-full.test.ts` TEST 9b: an agent that always returns a
fresh tool call (so `needsFollowUp` stays true). Asserts the run
terminates, `runAgent` is capped at ≤100 calls, and a warning is
emitted.
- `nx run @copilotkit/core:test` → 40 files / 431 tests pass.
- `nx run @copilotkit/core:build` → success.
2026-07-23 18:21:02 -05:00
Benjamin Taylor e75c7f3db7 refactor(channels-core): relocate Channel lifecycle onto internal ɵruntime seam
Move start/stop/addAdapter/provider bodies onto channel.ɵruntime.*; the public
methods become thin delegators (behavior identical). Lets a runner drive the
lifecycle without the public API. Pure relocation — tsc + 156 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 18:14:12 -05:00
github-actions[bot] 814aa40d4e style: auto-fix formatting 2026-07-23 22:33:28 +00:00
David McKay 87c6b114db test: fix mock spy arity so check-types (tsc) passes
The vi.fn mock factories were 0-arg but invoked with the provider options in
the vi.mock adapters, tripping tsc (TS2554). vitest transpiles without type-
checking, so it passed vitest locally but failed the check-types job.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 15:31:47 -07:00
David McKay 885e392e70 test: assert union via toBeInstanceOf(z.ZodUnion) instead of untyped _def.typeName
_def.typeName isn't on ZodTypeDef's public type (TS2339 in check-types);
instanceof is the type-safe equivalent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 15:29:14 -07:00
github-actions[bot] 5baf058e0f style: auto-fix formatting 2026-07-23 21:58:31 +00:00
David McKay 4a7e4c8bdc fix(runtime): preserve anyOf/oneOf unions when converting frontend tool schemas
A frontend/client tool (`useFrontendTool`) whose Zod `parameters` use
`z.discriminatedUnion(...)` — or any schema that serializes to a JSON-schema
`anyOf`/`oneOf` node — silently lost the union-typed field when calling OpenAI.
The tool call arrived with that field missing or empty.

Root cause: the runtime has two JSON-Schema -> Zod converters. The shared one
(`@copilotkit/shared`) already handles `anyOf`/`oneOf` as `z.union`, but the
local copy in `packages/runtime/src/agent/index.ts` — used by the classic
`BuiltInAgent` / AI SDK path via `convertToolsToVercelAITools` — never did.
A union node carries no top-level `type`, so it hit the empty-schema guard and
collapsed to `z.object({})`. The reconstructed tool schema therefore dropped
the union entirely (most visibly for a union nested inside array `items`), so
the model was never offered those fields and could not emit them.

Fix: handle `anyOf`/`oneOf` as `z.union` before the empty-schema guard,
mirroring the shared converter. A single-variant union unwraps to that variant.

Backward compatible: only previously-broken union nodes change behavior
(empty object -> real union). Empty `{}` schemas, typed nodes, and the
`isJsonSchema` gate are untouched.

Repro: a `useFrontendTool` with `parameters: z.object({ blocks: z.array(
z.discriminatedUnion("type", [...])) })` against OpenAI — before, `blocks`
items arrived empty; after, both variants survive into the model call.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:57:47 -07:00
David McKay 0a582df4dd fix(react-native): add /headless subpath so custom-UI consumers skip chat/attachment native deps
The `@copilotkit/react-native` barrel statically re-exports the prebuilt chat
UI (CopilotChat / CopilotModal / CopilotSidebar / CopilotPopup, which import
`@gorhom/bottom-sheet`) and `useAttachments` (which imports
`expo-document-picker` + `expo-file-system`). Those are optional peer deps, but
a static re-export still forces Metro to resolve them at bundle time. A headless
consumer that uses only `CopilotKitProvider` + `useAgent` + `useFrontendTool`
(a fully custom UI) had to install every chat/attachment native dep or stub them
in `metro.config.js`, or the release bundle fails with
`Unable to resolve module expo-document-picker`.

Add a lean `@copilotkit/react-native/headless` entry that re-exports only the
provider, the platform-agnostic hooks, the render-tool registry, and the
core/AG-UI types — none of the chat UI or `useAttachments` — so those native
deps never enter the bundle graph and the metro-stub workaround is retired.

Mirrors `@copilotkit/react-core/v2/headless` (#5883): a standalone entry file,
wired into the tsdown entry list, the package.json `exports` map, and
`sideEffects` (it side-effect-imports the polyfills). The default barrel now
does `export * from "./headless"` and layers the chat UI on top, so it stays
fully backward compatible. Adds a static import-graph regression test asserting
the headless graph never reaches the chat/attachment modules or their native
peer deps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:56:43 -07:00
David McKay 0915ea4d11 fix(react-core): honor threadId prop on useAgent
UseAgentProps had no `threadId`, yet the shipped V2 React Native demo
calls `useAgent({ agentId: "default", threadId })`. Because the prop
didn't exist, it was silently dropped: the demo's thread state (and its
"New Chat" reset) never reached the agent, which ran under its own
auto-minted UUID. threadId was only ever sourced from a surrounding
`CopilotChatConfigurationProvider`, which the headless RN demo has none.

Accept an optional `threadId` on UseAgentProps and honor it. Resolution
precedence: an explicit `threadId` prop wins; otherwise fall back to the
chat configuration's threadId (gated on hasExplicitThreadId, as before).
When the prop is omitted, behavior is unchanged — fully backward
compatible. This makes the RN demo's existing usage work and unblocks
headless callers that have no chat-configuration provider in the tree.

Extends the threadId-propagation contract test with coverage for the
prop path (no provider, prop-over-config precedence, prop re-sync).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:54:58 -07:00
github-actions[bot] 93173c672b style: auto-fix formatting 2026-07-23 21:36:53 +00:00
David McKay 5952ea8943 fix(runtime): honor *_BASE_URL env vars in resolveModel for OpenAI-compatible endpoints
resolveModel() built each provider with only an apiKey, so a string model
spec (e.g. "openai/gpt-4o-mini") could not target an OpenAI-compatible
endpoint — OPENAI_BASE_URL was silently ignored, and the only workaround was
to construct the LanguageModel yourself and pass the instance. Same gap for
Anthropic and Google.

Now resolveModel passes baseURL from the standard env var
(OPENAI_BASE_URL / ANTHROPIC_BASE_URL / GOOGLE_GENERATIVE_AI_BASE_URL). It is
undefined when unset, so the provider falls back to its default endpoint —
fully backward compatible.

Tests: adds resolve-model-baseurl.test.ts (4 cases). Existing resolveModel
tests unchanged (118 runtime tests pass locally).

Discovered while building an OpenAI-compatible agent on the V2 runtime +
@copilotkit/react-native.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:35:12 -07:00
Ben Taylor a2cdfa6814 fix(react-core): expose lean hooks from /v2/headless to cut bundle bloat (#4893) (#5883)
## What & why

`@copilotkit/react-core`'s `/v2` entry (and the root entry) re-exports
from a
single **monolithic shared chunk**, so importing *any* symbol — even one
hook —
pulls the built-in chat-message rendering stack (`streamdown` → shiki,
`mermaid`,
`cytoscape`, `katex`) into the consumer's bundle: **~3 MB gzip / ~15 MB
raw**,
with no way to tree-shake it. Consumers who build a fully custom chat UI
and only
use hooks pay the full cost. (Issue #4893.)

A separate lean build entry — `@copilotkit/react-core/v2/headless` —
already
ships those hooks in their own small chunk **without** that stack (it's
how
`@copilotkit/react-native` mounts CopilotKit). This PR makes it usable
for a
custom web UI.

Measured with esbuild (react/react-dom external):

| import | bundled JS |
|---|---|
| hooks from `@copilotkit/react-core/v2` | **~2.96 MB** gzip (≈
importing full `CopilotChat`) |
| same hooks from `@copilotkit/react-core/v2/headless` | **~0.03 MB**
gzip |

> Note on the report: `@copilotkit/a2ui-renderer` doesn't bundle the
rich-text
> stack (its deps are `@a2ui/web_core`, `lit`, `clsx`, `zod`). The
weight is
> entirely `streamdown` (shiki/mermaid/cytoscape) + `katex`, pulled by
the
> built-in `CopilotChat*` message components.

## Changes

- **`headless.ts`** — export `useCopilotKit` + `useRenderToolCall` (both
DOM-free
and rendering-stack-free); fix `UseAgentUpdate` (a runtime `enum`) being
  re-exported via `export type`, which stripped its runtime value under
`isolatedModules` (so `useAgent`'s `updates` option was unusable from
headless
— a bug `tsc` can't catch). `useDefaultRenderTool` /
`useRenderCustomMessages`
/ `useRenderActivityMessage` stay in `/v2` (web-only markup or
`a2ui-renderer`).
- **Remove a `tailwind-merge` leak** — extract the tailwind-free ref
helpers
(`shallowEqual` / `useShallowStableRef`) into
`lib/shallow-stable-ref.ts` so the
  headless graph no longer pulls `tailwind-merge` via
  `CopilotChatConfigurationProvider`.
- **Test** — a small vitest export-surface test guarding the hook
surface and the
  `UseAgentUpdate` runtime value.

## Verification

`react-core` typecheck + vitest (1427) and `react-native` typecheck
pass. Shipped
`dist/v2/headless.mjs` imports only `react`, `@ag-ui/client`,
`@copilotkit/core`,
`@copilotkit/shared`, `@copilotkit/react-core/v2/context`, `zod` — no
rendering
stack.

## Notes / follow-ups

- Headless hooks read a **different React context** than the prebuilt
`/v2`
`<CopilotKitProvider>`, so the two can't be mixed — mount a lean
provider over
`/v2/context` (as `@copilotkit/react-native` does). Making the `/v2`
provider
reuse the standalone `/v2/context` singleton would remove that sharp
edge and
  is the natural follow-up.
- Existing bundle-size CI (`compressed-size-action`) already tracks
`headless.mjs`,
  so no new size tooling is added here.

Addresses #4893.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-23 14:56:00 -05:00
Ben Taylor 3edf06339c fix(core): don't surface a user-initiated Stop as an agent error (#5966) (#5967)
Fixes #5966. Follow-up to #5812 / #5885.

## Problem

After #5885 stopped the post-terminal `TEXT_MESSAGE_END` crash, pressing
**Stop** no longer breaks the chat — but for an agent that emits a
terminal `RUN_ERROR` (code `abort`) as its cancellation signal (e.g.
pydantic-ai's `AGUIAdapter`), the client still surfaces that as an
**error banner** ("This operation was aborted"). A user-initiated stop
is expected cancellation, not a failure.

Traced path (no abort suppression at any hop):
`RUN_ERROR(code:"abort")` → `RunHandler.onRunErrorEvent`
(`run-handler.ts`) → `emitAgentError(AGENT_RUN_ERROR_EVENT)` → `onError`
→ CopilotChat/react-ui `triggerChatError` → banner. The only existing
abort suppression is for the *local* fetch-abort rejection
(`run-handler.ts:318`), a different path.

## Fix

Suppress the error emission in `onRunErrorEvent` when the run was
user-aborted — mirroring the local-abort suppression already on the
`runAgent`/`connectAgent` paths:

```ts
const runWasAborted = this._runAbortController?.signal.aborted === true;
if (runWasAborted || event?.code === "abort") {
  return;
}
```

Prefers the client's own `_runAbortController.signal.aborted` (robust —
the agent-supplied `code` isn't standardized across agents; the
`code:"abort"` in the repro comes from the agent, not CopilotKit) with
`code === "abort"` as a secondary signal. Normal `RUN_ERROR`s are
unaffected.

## Testing

- **TDD** (`core-error-handling.test.ts`): two new tests fail pre-fix
and pass after —
- agent emits `RUN_ERROR` code `"abort"` → no `AGENT_RUN_ERROR_EVENT`
surfaced.
- run user-aborted mid-stream (via `agent.abortRun()`, which RunHandler
intercepts to abort the controller) → a subsequent `RUN_ERROR` with a
*non-abort* code is still suppressed (exercises the `signal.aborted`
path).
- The pre-existing test — normal `RUN_ERROR` (code `"bad_request"`)
still emits `AGENT_RUN_ERROR_EVENT` — continues to pass (control against
over-suppression).
- Full `@copilotkit/core` suite green: **578/578**. `tsc` 0 errors;
`oxlint` 0.

Note: this is a UX/product call (a user Stop shouldn't render as an
error). Suppressing in core fixes it for both the default chat banner
and app-level `onError` handlers; the run lifecycle still reflects the
termination.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-23 14:00:01 -05:00
Ben Taylor aa5e944889 fix(python-sdk): fold App Context into system prompt (#5807)
## Summary
- folds CopilotKit App Context into `ModelRequest.system_message` during
LangGraph model calls
- stops injecting App Context as a separate `SystemMessage` from
`before_agent`, avoiding non-consecutive system messages after LangGraph
reducers run
- updates middleware regression tests for state context, runtime
context, forwarded-header filtering, and message-history no-op behavior

## Root cause
`before_agent` inserted a new App Context `SystemMessage` into
`state["messages"]`, but the LangGraph message reducer can append new
message IDs rather than preserving positional insertion. With an
existing system prompt and prior conversation turns, this can produce
multiple non-consecutive system messages, which `langchain-anthropic`
rejects.

Fixes #5610.

## Validation
- `uv run pytest -q`
2026-07-23 13:37:10 -05:00
Mike Ryan 4a65196eeb fix(adk): pin working GCP resource detector (#6135)
## What does this PR do?

Pins `opentelemetry-resourcedetector-gcp==1.12.0a0` in the ADK starter.

`google-adk` accepts prerelease resource-detector versions, but `uv`
skips transitive prereleases by default. The only stable candidate,
`1.13.0`, was yanked because it breaks imports. That left the ADK
starter with no valid dependency set.

The direct pin selects the last working release without allowing
prereleases for every dependency. The ADK starter image can build again.

## Related PRs and Issues

- Failing job:
https://github.com/CopilotKit/CopilotKit/actions/runs/30027772426/job/89285780349

## Validation

- RED: `docker build --progress=plain -f
examples/integrations/adk/Dockerfile examples/integrations/adk` failed
at `uv pip install --system -e .` because the requirements were
unsatisfiable.
- GREEN: the same command resolved 124 Python packages, installed the
pinned detector, built the Next.js app, and exported the image.
- `pnpm nx affected -t lint,check-types,test,build --base=origin/main
--head=HEAD` found no affected Nx tasks because this starter is built
outside the Nx project graph.
- `oxfmt --check examples/integrations/adk/agent/pyproject.toml` passed.

## Checklist

- [x] I have read the Contribution Guide.
- [x] No documentation change is needed; this restores the existing
starter build.
- [x] Allow edits by maintainers is enabled.
2026-07-23 11:16:22 -07:00
Mike Ryan c484312e7c fix(adk): pin working GCP resource detector 2026-07-23 10:58:45 -07:00
renovate[bot] 1fcbc5c748 chore(deps): update docker/login-action action to v4.5.0 (#6126)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [docker/login-action](https://redirect.github.com/docker/login-action)
| action | minor | `v4.4.0` → `v4.5.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/592) for more information.

---

### Release Notes

<details>
<summary>docker/login-action (docker/login-action)</summary>

###
[`v4.5.0`](https://redirect.github.com/docker/login-action/compare/v4.4.0...v4.5.0)

[Compare
Source](https://redirect.github.com/docker/login-action/compare/v4.4.0...v4.5.0)

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/Los_Angeles)

- Branch creation
  - "before 9am every weekday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/CopilotKit/CopilotKit).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzUuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI3NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2026-07-23 17:48:35 +00:00
Mark Fogle c336514519 chore(deps): widen @anthropic-ai/sdk optional peer range
The optional peer dependency on @anthropic-ai/sdk was pinned to
^0.57.0, which conflicts with current SDK versions (e.g. 0.109) and
forces consumers to install @copilotkit/runtime with --legacy-peer-deps.

The anthropic adapter only relies on stable @anthropic-ai/sdk APIs
(client construction, messages.create, ephemeral cache_control), so
loosen the range to >=0.57.0 to remove the false peer conflict.

pnpm auto-installs this optional peer, so its specifier is mirrored in
the lockfile; update that specifier line to match. The resolved version
(0.57.0) still satisfies the range, so resolution is otherwise unchanged
and `pnpm install --frozen-lockfile` passes.

Reported by an outside contributor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 17:42:12 +00:00
renovate[bot] da41f1c685 chore(deps): update docker/login-action action to v4.5.0 2026-07-23 17:31:46 +00:00
Ben Taylor f239f6a2cd fix(react-core): forward refs through DropdownMenuTrigger and TooltipTrigger (#5936)
## Summary

`CopilotChatInput`'s `AddMenuButton` renders its trigger as nested Radix
`asChild` slots:

```tsx
<TooltipTrigger asChild>
  <DropdownMenuTrigger asChild>{button}</DropdownMenuTrigger>
</TooltipTrigger>
```

Radix `asChild` slots forward a ref to their child.
`DropdownMenuTrigger` and `TooltipTrigger` were plain function
components, so under React 18.3 the forwarded ref triggers this warning
on every render (reported in #5744):

```
Warning: Function components cannot be given refs. Attempts to access this ref will fail.
Did you mean to use React.forwardRef()?
```

## Change

Wrap `DropdownMenuTrigger` and `TooltipTrigger` in `React.forwardRef`,
forwarding the ref to the underlying Radix primitive — mirroring
`forwardRef` usage already present in this package (e.g. `Button`,
`CopilotChatInput.TextArea`). No behavior change; the ref now reaches a
DOM node and the warning is gone.

## Scope

Limited to the two primitives in the reported warning path. The other
shadcn/ui primitives in `react-core` follow the same React-19
(no-`forwardRef`) style and would warn identically when used as
`asChild` children under React 18.3 — happy to extend this to the rest
if you'd prefer full React 18.3 coverage.

## Verification

- `nx build @copilotkit/react-core` succeeds (compiles source +
generates type declarations).
- Pre-commit `test-and-check-packages` passes.

Fixes #5744
2026-07-23 12:30:42 -05:00
Alem Tuzlak bffb119091 fix(showcase): allowlist ms-agent-dotnet headless-complete custom-bubbles multi-file region
Restoring frontend parity re-added the @region[custom-bubbles] markers in both
message-assistant.tsx and message-user.tsx (matching the langgraph reference and
every other integration). Add the ms-agent-dotnet::headless-complete::custom-bubbles
key to the multi-file-region allowlist so the demo-content bundler accepts it.
2026-07-23 19:12:21 +02:00
Mike Ryan bcac9877ee fix(showcase): stage Angular assets in deployment images (#6131)
## What changed

- Build the canonical Angular browser bundle once when an integration
image needs it.
- Download and materialize that bundle inside each integration Docker
context.
- Generate the per-integration same-origin runtime config before Depot
builds the image.
- Run the same artifact path in the pre-merge build check.
- Rebuild integration images when the Angular host or its workspace
dependencies change.

## Why

The deployment workflow copied `public/angular` as a symlink whose
target sat outside each integration Docker context. The resulting images
had no `/angular/index.html`, so deployed Angular deep links returned
404.

Staging deploys the GHCR images built here. Production promotion pins
the same tested image digest, so the fix applies to both environments.

## Validation

- RED: `pnpm nx test @copilotkit/showcase-scripts -- --run
__tests__/angular-integration-hosting.test.ts` — 2 new workflow
assertions failed before the fix.
- GREEN: the same focused command — 46 tests passed.
- `pnpm nx test @copilotkit/showcase-scripts` — 2,322 tests passed.
- `pnpm nx build @copilotkit/showcase-angular-host` — passed, including
browser artifact audit and bundle budget.
- Staged the built artifact for `langgraph-python`, `mastra`, and `ag2`;
each contained `index.html` and the correct runtime config.
- `actionlint` passed for both changed workflows after ignoring existing
custom-runner and unrelated shellcheck notices.
- `git diff --check` passed.

## Known check

`pnpm nx exec -p @copilotkit/showcase-scripts -- tsc --noEmit -p
tsconfig.json` still reports six existing errors in
`equivalence-gate.ts`, `generate-search-index.ts`, and
`verify-prod-resweep.ts`. This change does not touch those files.
2026-07-23 10:03:16 -07:00
Ben Taylor b038115174 fix(sdk-js): preserve AIMessage metadata in middleware (#6091)
## What does this PR do?

- Preserve non-tool `AIMessage` fields when frontend tool calls are
intercepted in `afterModel` and restored in `afterAgent`, including
`additional_kwargs`, `response_metadata`, `usage_metadata`,
`invalid_tool_calls`, `id`, and `name`.
- Use a shared rebuild helper with `tool_calls` as the source of truth.
For LangChain v1 content blocks, remove stale `tool_call` and
`tool_call_chunk` blocks before reconstructing the message.
- Add regression coverage for the `reasoning + backend/frontend tool
calls -> afterModel -> afterAgent` flow, including metadata preservation
and v1 content block synchronization.

## Related PRs and Issues

- Closes #6087
- Related to #4759 and #5308

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] Documentation is not required because this is an internal
middleware bug fix with no public API changes
- [x] "Allow edits by maintainers" is checked (lets us help iterate on
your PR directly — faster turnaround for everyone)
2026-07-23 12:01:03 -05:00
Alem Tuzlak d35935b35f fix(showcase): repoint ms-agent-dotnet manifest highlights to existing files
The stale-file cleanup removed chat-slots/custom-welcome-screen.tsx, the
top-level headless-complete/{message-list,use-rendered-messages}.tsx, and the
top-level gen-ui-interrupt/time-picker-card.tsx, but their manifest highlight
entries still pointed at them, failing the registry bundler (shell/shell-docs/
shell-dojo builds). Repoint to the real files (slot-wrappers, chat/chat,
hooks/use-tool-renderers, _components/time-picker-card).
2026-07-23 18:56:16 +02:00
Mike Ryan b7e5e954f9 chore: release angular v0.3.0 (#6132)
## Release angular v0.3.0

**Scope:** `angular` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `angular` packages to `0.3.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 `angular` packages to npm at version `0.3.0`
   - Creates git tag `angular/v0.3.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.
angular/v0.3.0
2026-07-23 09:56:02 -07:00
MikeRyanDev cb4ab7fd8e chore: release angular v0.3.0 2026-07-23 16:47:06 +00:00
Mike Ryan 98711fbefb fix(showcase): stage Angular artifacts in deployment images 2026-07-23 09:46:29 -07:00
Alem Tuzlak 1ab3fba04e feat(showcase): restore ms-agent-dotnet frontend parity with the langgraph reference
Restore the root shell (globals.css theme+brand, manifest-driven index, layout,
middleware x-pathname, tsconfig), the declarative-gen-ui demo subtree, doc-snippet
region markers, import-style, and subagents to match the langgraph-python reference;
remove stale orphaned files. Load-bearing .NET adaptations (parse-json 3-layer
unwrap, multimodal shim, tool-based hitl, agent-config properties) are preserved.
2026-07-23 18:43:25 +02:00
Alem Tuzlak b70b6913f7 feat(showcase): wire ms-agent-dotnet D6 routing, manifest, and threadid demo
Add the per-token createSharedStateStreamingAgent route shim, register the
threadid-frontend-tool-roundtrip agent (frontend_tools passthrough) and its demo,
drop shared-state-streaming from not_supported_features, and add the a2ui-recovery
feature + demo entry to the manifest.
2026-07-23 18:43:24 +02:00
Alem Tuzlak 55b4da3005 feat(showcase): add a2ui-recovery cell for ms-agent-dotnet
Implement the render/validate/retry recovery loop with a2ui_recovery_exhausted
hard-fail as a raw-SSE endpoint (RecoveryAgent.cs, mounted in Program.cs), add
the demo frontend + API route, the deterministic aimock fixture, and the unique
per-slug PROMPTS entry in the shared d5-a2ui-recovery probe.
2026-07-23 18:43:23 +02:00
Alem Tuzlak dac30ed9f1 feat(showcase): stream shared-state document per-token for ms-agent-dotnet
Replace the final-snapshot-only shared-state-streaming behavior with a
write_document tool whose document arg streams; per-token state.document
emission is bridged on the copilotkit route (see the routing commit).
2026-07-23 18:43:22 +02:00
Mike Ryan b94478ba42 chore: release monorepo v1.63.2 (#6128)
## Release monorepo v1.63.2

**Scope:** `monorepo` | **Bump:** `patch`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.63.2`
   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.63.2`
   - Creates git tag `monorepo/v1.63.2`
   - 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.63.2
2026-07-23 09:37:51 -07:00
Lukas Moschitz db296afd91 fix(showcase): stop harness services racing on shared image tag
harness-control-plane and harness-pool-worker both declared a build: block
AND the same image: showcase-harness:local. Under the parallel docker buildx
bake path (default in recent Docker Compose) both targets build and race to
tag the identical image, failing the whole 'bin/showcase up' with
'image "...showcase-harness:local": already exists'. It only surfaces on a
cold parallel bake build (Colima/Homebrew, fresh clone), which is why it is
intermittent across toolchains.

Give the image a single build owner: harness-pool-worker now reuses the
image built by harness-control-plane (worker vs control-plane role is chosen
at runtime via HARNESS_ROLE) instead of declaring its own build:.
2026-07-23 18:27:21 +02:00
MikeRyanDev 69861f13df chore: release monorepo v1.63.2 2026-07-23 16:15:51 +00:00
Mike Ryan b07482da56 feat(angular): add first-class Angular Showcase support (#6109)
## Summary

Adds first-class Angular Showcase support and the public
`@copilotkit/angular`
package.

- Freezes 41 supported Angular features and keeps runnable cells as
frontend
  support intersected with backend support.
- Builds one Angular artifact and stages it into all 20 existing
integration
  images at same-origin `/angular/{feature}` routes.
- Keeps React `/demos/{feature}` routes unchanged and adds no Angular
service,
  proxy, image, deployment environment, or production activation.
- Matches the React SDK's MCP Apps inline sandbox, permissions, and
  resource-domain CSP semantics.
- Removes the temporary broad Angular proof workflow after it produced
the
  merge evidence below.

## Evidence

- [Angular proof run
29966964494](https://github.com/CopilotKit/CopilotKit/actions/runs/29966964494):
  all 48 jobs passed.
- Final report: 1,296 exact cells, 660 frontend comparisons, 636 Angular
pairs,
  and 41 registry-supported Angular features.
- Pairwise policy: zero Angular regressions, zero React regressions,
zero
  unowned failures, zero identity mismatches, and zero missing results.
- Chromium, Firefox, and WebKit each passed 16 browser checks and ten
cold
readiness samples. Maximum readiness was 250 ms, 163 ms, and 166 ms
against
  the 2,000 ms limit.
- All 20 existing integration images passed Angular hosting checks.
- Angular 20, 21, and 22 packed consumers passed.
- PR #6095 remains linked as prior implementation evidence. This branch
ports
  proven work without merging or resetting the old branch.

## Commits

- [x] Checkpoint 1 — baseline and registry (`873cbb8b6`)
- [x] MCP Apps activity renderer (`b3de484be`, Manfred Steyer)
- [x] Checkpoint 2 — core and package (`fec70d086`)
- [x] Checkpoint 3 — shared build and proof pair (`637845bb7`)
- [x] Checkpoint 4 — all supported features and docs (`4d32d941e`)
- [x] Checkpoint 5 — hardening and final exposure (`7ccd34a05`)
- [x] Review fixes (`cd0b5b406`)
- [x] Angular docs (`06df1ea15`, `1c0c76956`)
- [x] Remove the broad proof workflow (`c4919f9f7`)
- [x] Match React MCP Apps sandbox semantics (`053b00e84`)

## Delivery

- Rebased on `main` at `9855a8107`.
- Preserves both Angular docs commits.
- Uses one canonical Angular artifact across every existing integration
image.
- Preserves React routes and frozen-base comparison.
- Keeps accepted baseline failures owned and linked to issues.
- Excludes CLI scaffolding and Hashbrown work.
2026-07-23 09:06:03 -07:00