Commit Graph

1187 Commits

Author SHA1 Message Date
copilotkit-qa-bot[bot] 589d59f96a fix(react-native): make headless bundles Metro-safe 2026-08-28 13:04:29 -07:00
Ben Taylor d692f25852 feat(runtime): expose Learning Container selector (#6767)
## What does this PR do?

Adds `getLearningContainerId` to `CopilotKitIntelligence` so developers
can assign Intelligence Threads to Learning Containers without a
theta-prefixed Runtime option.

The selector receives:

- The resolved application `user`.
- The parsed AG-UI `input` for the run.
- The `agentId` and the `web` or `channel` surface.

Web runs pass the exact parsed `RunAgentInput`. Channel runs build the
same canonical input that the AgentRunner receives. Channels also carry
the resolved application user through the core and Intelligence adapter
boundaries.

The Runtime validates the selected stable ID and sends only that ID with
the existing Thread create or lock call. Intelligence stays responsible
for project scope, entitlements, Container lookup, and the one-time
Thread binding. Persisted AG-UI events remain the source for Learning
snapshots.

The old `ɵlearning` Runtime option remains as a deprecated fallback. The
Runtime rejects configurations that set both APIs.

## Why?

Learning Container assignment is an Intelligence SDK concern. Developers
also need the resolved user and complete run input to select a Container
from application data without reading raw transport details.

## Related PRs and Issues

- Refs
[ENT-1149](https://linear.app/copilotkit/issue/ENT-1149/enable-projects-to-learn-from-agent-runs-and-publish-reusable-skills)
- Related design: #6746

## Validation

- GitHub CI: 53 passed, 3 skipped
- `pnpm nx run-many -t test,check-types,build -p @copilotkit/runtime
@copilotkit/channels-core @copilotkit/channels-intelligence`
- `pnpm nx run-many -t publint,attw,check-dts -p @copilotkit/runtime
@copilotkit/channels-core @copilotkit/channels-intelligence`
- `pnpm lint` (0 errors; existing warnings remain)
- `npm run typecheck` and `npm run build` in `showcase/shell-docs`
- `npm test` in `showcase/shell-docs` has one pre-existing failure at
`inspector-docs.test.ts:141`: the tracked Threads callout contains
`Playground`.

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] Maintainer edits are available because this PR uses a branch in
the main repository
2026-08-28 13:02:10 -05:00
Ben Taylor 28c5208596 docs: document reading AG-UI context in a Pydantic AI agent (#6768)
## Problem

Pydantic AI's AG-UI adapter reads `messages`, `tools`, `state`,
`thread_id` and `resume` off `RunAgentInput`, and nothing else.
`context` — the field `useAgentContext` travels on — is never passed to
the agent.

Nothing errors when it is dropped. There is no warning and no console
message, so an agent that received none of the page's entries still
answers confidently about them. A developer who wires `useAgentContext`
against a Pydantic AI agent gets a well-formed answer about data the
agent never had.

Verified against `pydantic-ai-slim` 2.33.0 and current upstream `main`:
zero references to `run_input.context` across all nine modules in
`pydantic_ai/ui/ag_ui/`.

## Why there was no page

The omission is deliberate upstream, not a bug.
[pydantic/pydantic-ai#7105](https://github.com/pydantic/pydantic-ai/issues/7105)
was closed as completed by
[#7106](https://github.com/pydantic/pydantic-ai/pull/7106): `run_input`
is public, so `adapter.run_input.context` has always worked, and
auto-injecting client-submitted text into `instructions` would let a
prompt injection inherit operator authority. Upstream documented the
route instead of adding API.

What was missing was a CopilotKit page saying any of this.
`useAgentContext`'s reference page documents the frontend hook only, and
the four existing `agent-app-context` pages cover built-in-agent,
langgraph, mastra and microsoft-agent-framework.

## What's here

`pydantic-ai/agent-app-context.mdx`, the fifth such page, wired into the
integration's App Control nav after `shared-state`.

Two details the page pins down, both verified against a running agent
rather than adapted from a sibling page:

- **`value` is a string, not your object.** `useAgentContext` calls
`JSON.stringify` before the run leaves the browser, and AG-UI types
`Context.value` as a string on both ends. `json.loads` is required, and
a shape check like `isinstance(entry.value, list)` can never pass. A
failed check is indistinguishable from context never being sent, which
is what makes this one expensive.
- **`from_request`, not `dispatch_request`.** The one-line
`AGUIAdapter.dispatch_request(request, agent=agent)` used elsewhere in
these docs parses the request internally, leaving no `run_input` to
build `deps` from. The context route needs the two-step form.

The page also carries upstream's trust rule: entries reach the model as
tool output, never as `instructions`, and facts the *server* established
are what belong in instructions.

## Verification

The documented `agent.py`, served over real HTTP with AG-UI request
bodies shaped exactly as the runtime sends them:

| Case | Result |
|---|---|
| Asks about the shared entries | Answers from them, all three
colleagues |
| Asks about someone never sent | Declines, and names exactly the three
the page did send |
| `context` arrives empty | Reports an empty list rather than inventing
one |

Suite: **480 passed / 2 failed**. Both failures (`inspector-docs`,
`llm-text` mastra tool-rendering) reproduce identically on pristine
`origin/main` content — confirmed by reverting both files and
re-running.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-28 12:52:57 -05:00
Benjamin Taylor 9acc242f34 docs: document reading AG-UI context in a Pydantic AI agent
Pydantic AI's AG-UI adapter reads `messages`, `tools`, `state`, `thread_id`
and `resume` off `RunAgentInput`, and nothing else. `context` -- the field
`useAgentContext` travels on -- is never passed to the agent, and nothing
errors when it is dropped, so an agent that received none of the page's
entries still answers confidently about them.

That omission is deliberate upstream (pydantic/pydantic-ai#7105, closed by
#7106): entries are client-submitted, so the adapter leaves it to the
application to decide what to trust, and `run_input` is public for exactly
this purpose. What was missing on our side was a CopilotKit page saying so.

Add `pydantic-ai/agent-app-context.mdx`, the fifth such page, alongside
built-in-agent, langgraph, mastra and microsoft-agent-framework, and wire it
into the integration's App Control nav.

Two details the page pins down, both verified against a running agent rather
than adapted from a sibling page:

- `useAgentContext` JSON-stringifies `value` and AG-UI types
  `Context.value` as a string on both ends, so `json.loads` is required and
  a shape check like `isinstance(entry.value, list)` can never pass.
- The one-line `AGUIAdapter.dispatch_request(request, agent=agent)` used
  elsewhere in these docs parses the request internally, leaving no
  `run_input` to build `deps` from. The page uses the two-step
  `from_request` form instead.

The page also carries upstream's trust rule: entries reach the model as tool
output, never as `instructions`, so a prompt injection cannot inherit
operator authority.

Verified: the documented `agent.py` served over HTTP answers from the shared
entries, names exactly what the page did send when asked about a colleague it
did not, and reports an empty list when `context` arrives empty. Suite is
480 passed / 2 failed, both failures identical on pristine origin/main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 12:27:36 -05:00
Ben Taylor 4ccae6fe20 fix(react-native): keep the polyfill imports in the built barrel (closes OSS-1002) (#6744)
## The bug

`src/polyfills.ts` is five side-effect-only imports plus
`installStreamingFetch()`. The published barrel was 195 bytes:

```js
// node_modules/@copilotkit/react-native/dist/polyfills.mjs — 1.69.2
import { t as installStreamingFetch } from "./streaming-fetch-BnQh3vBz.mjs";
installStreamingFetch();
export {  };
```

Every React Native app following the documented setup died on its first
runtime call:

```
E ReactNativeJS: '[CopilotKit] Error (runtime_info_fetch_failed):',
  [ReferenceError: Property 'ReadableStream' doesn't exist]
```

## Root cause

The `sideEffects` field, but not in the way it first looks. It is
correct for *consumers* and wrong for *this package's own build*:

```json
"sideEffects": ["./dist/index.*", "./dist/headless.*", "./dist/polyfills.*", "./dist/polyfills/**/*"]
```

tsdown/rolldown reads the package's own `sideEffects` while bundling and
matches it against **source** paths. `src/polyfills/streams.ts` matches
none of those `dist` globs, so it is declared side-effect-free — a hard
assertion that lets rolldown drop the import without analysing the
`globalThis` assignments inside.

Reproduced in isolation at the pinned tsdown (0.20.3):

| `sideEffects` | built barrel |
|---|---|
| `["./dist/polyfills.*", "./dist/polyfills/**/*"]` | `export { };` —
empty |
| same + `["./src/polyfills.*", "./src/polyfills/**/*"]` | `import
"./polyfills/streams.mjs";` |
| field absent | `import "./polyfills/streams.mjs";` |

**Wider than the ticket recorded:** `dist/index.mjs` and
`dist/headless.mjs` also had zero polyfill code, so the package's
advertised auto-install on first import did not happen either. Not
RN-specific in principle — but I surveyed every package at `origin/main`
and this is the only one exposed. The other `sideEffects` arrays
(`react-core`, `react-ui`, `react-textarea`) are `["**/*.css"]`, which
matches source and works.

## The fix

Add matching `./src/**` globs. Barrel goes 195B → 362B with all five
imports; `headless.mjs` now leads with `import "./polyfills.mjs"`.

## The test, and why the existing one didn't catch this

`src/__tests__/polyfills.test.ts` has ~20 assertions covering all five
groups and was green the whole time — it imports `"../polyfills"`, the
TypeScript **source**, which vitest transpiles without bundling and
therefore without tree-shaking. It exercises a graph the published
package does not contain.

So the new check runs against `dist/`. Two things it has to get right to
be honest:

- **Node ships these globals natively.** Asserting `ReadableStream` is
"defined" after import passes on an empty barrel. The probe clears all
nine first, emulating Hermes.
- **The two formats need different treatment.** CJS is executed for real
in a child realm. ESM is checked structurally — it cannot be executed
here because `encoding.mjs` takes a named import from CommonJS
`text-encoding`, which Metro rewrites to a `require()` but bare Node ESM
rejects.

It is wired into `build`, so a dead barrel fails the build rather than
reaching npm — which matters, because this shipped through a fully green
suite.

## Docs

Added the `Property 'ReadableStream' doesn't exist` symptom to
troubleshooting, which previously covered only the inverse case (a
polyfill *conflict*).

I deliberately left the reference docs' "auto-installs on first import"
claims and the crypto import-order callout alone: both become **true**
once the build is fixed, and I verified the auto-install behaviourally.

## Verification

- **Red/green proven, not assumed:** reverted the `sideEffects` change,
rebuilt → 5/5 groups FAIL in both formats. Restored → 5/5 PASS. There is
also a test for a *single* group regressing, which a whole-barrel
assertion would wave through.
- **Packed tarball** (`pnpm pack`) verified behaviourally: all nine
globals install.
- 289 vitest + 26 script tests pass; `check-types` clean; `attw` green;
`publint` clean apart from a pre-existing `repository.url` suggestion;
oxfmt/oxlint clean.
- Added `{projectRoot}/scripts/**` to the package's `test` inputs and
confirmed cache invalidation (19/19 cached → 18/19 after touching the
verifier); without it, editing the verifier alone would restore a cached
pass.

**Not verified:** the on-device round trip — no emulator in this
environment. The bare-realm equivalent passes on the packed tarball.

## Follow-up worth its own ticket

`dist/polyfills/encoding.mjs` uses a named import from CommonJS
`text-encoding`. Metro handles it; a true-ESM consumer would not.
Pre-existing and not RN-facing, so left out of this change.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-28 12:24:39 -05:00
Mike Ryan 9e27e10830 feat(runtime): expose Learning Container selector 2026-08-28 10:17:27 -07:00
copilotkit-qa-bot[bot] 67945e2641 Merge remote-tracking branch 'origin/main' into codex/fac-74-tool-lifecycle 2026-08-28 09:34:37 -07:00
copilotkit-qa-bot[bot] 61d232ec63 docs: complete predictive-state tool lifecycle 2026-08-28 09:33:58 -07:00
Benjamin Taylor 465abb0239 docs: correct four pages that contradict shipped code, and document verify
Five onboarding-sweep defects that share one shape: a page states something the
library stopped doing, or never said something the library requires.

Mastra `resourceId` (OSS-936) — `getLocalAgents({ mastra })` does not typecheck
against `@ag-ui/mastra`; `resourceId` is required. It is Mastra's memory-scoping
key, required identically on the local, single-agent and remote option types, so
the snippets were wrong rather than the type over-strict. Fixed at all six doc
sites, including the tracing example that #6663 left behind.

Angular Inspector (OSS-948) — `@copilotkit/angular@0.4.0` ships the auto-mount
with a pinned `@copilotkit/web-inspector`. The Angular Inspector page still
taught a hand-written mount whose unconditional `DestroyRef.onDestroy` tears out
the element the framework now owns. Rewritten as a thin migration page that
points at `/inspector` instead of restating it, and the Angular Open Inspector
snippet — which asserted "Angular does not mount Inspector by default" — is
deleted in favour of the shared one every other web frontend already uses.

Angular runtime port (OSS-950) — say plainly that the runtime is its own
process, and name `PORT` as the way to move it off 8200. `COPILOT_RUNTIME_PORT`
appears nowhere in either repo and is not the mechanism.

`copilotkit verify` (OSS-953) — documented nowhere in the product docs. Added to
the shared CLI snippet, stating what `--round-trip` cannot prove: it records the
answer's character count and tool-call names, never its text, and proves an
agent answered under the declared id, not which deployment. React Native now
links that section rather than restating it, and its claim that the CLI defaults
to `:8200` is corrected to the real default, `:3000`.

A2UI flight example (OSS-944, part) — mark the domain illustrative on the page
the onboarding graph is mandated to fetch. The domain swap itself is not here:
it is 106 files across 21 showcase cells and wants the post-OSS-942 re-run
first.

Also fixes a shipped skill that taught `import { CopilotKitWebInspector }`, an
export that does not exist (OSS-891's failure mode, found in passing).

Two new tests guard the Angular claims, both mutation-checked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 10:58:22 -05:00
Alem Tuzlak 8469e72b30 feat(web-inspector): copy stored threads into Playground from Threads (#6642)
Inspector Threads now has **Try from here**. One click copies a stored
thread into a Playground scratch session. The stored thread does not
change.

If the copy fails, Inspector stays on Threads and keeps the current
Playground scratch. Example tour threads and locked Threads do not show
the button.

## What does this PR do?

Adds **Try from here** on a real stored thread in Inspector Threads. One
click copies messages and thread state into a Playground scratch
session. The stored thread does not change.

If the copy fails, Inspector stays on Threads and keeps the current
Playground scratch. Example tour threads and locked Threads do not show
the button.

## Related PRs and Issues

- Linear: OSS-873
- Playground base: https://github.com/CopilotKit/CopilotKit/pull/6580
(merged)

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked

## Testing

**Commands run**

1. Rebased `feat/oss-873-try-from-here` onto `origin/main` and resolved
6 conflict files.
2. `npx nx run @copilotkit/web-inspector:test` — 626 tests passed (after
the stale-result guard).
3. `npx nx run @copilotkit/web-inspector:check-types` — passed.

**Manual test**

1. Open Inspector on localhost with Intelligence on, so a real stored
thread exists.
2. Open that thread. Confirm **Try from here** is in the thread header.
3. Click **Try from here**. Confirm Inspector opens Playground with the
copied messages and the stored thread is unchanged.
4. Open an example tour thread. Confirm **Try from here** is not shown.
5. Force a copy failure (disconnect runtime). Confirm Inspector stays on
Threads and the prior Playground scratch is unchanged.

**How this PR makes testing easy**

- `packages/web-inspector/src/__tests__/inspector-navigation.spec.ts`
covers the button, copy path, failure path, and a stale click that must
not overwrite Playground.
- `packages/web-inspector/src/lib/__tests__/telemetry.test.ts` covers
`oss.inspector.threads_try_from_here_clicked`.

## Risk / rollback

Risk is limited to Inspector Threads and Playground. A revert of this PR
removes the button and the new telemetry event. No runtime protocol
change.

## Public API change

New Inspector telemetry export and event name:

**Before**

```ts
trackThreadsTabClicked(props);
```

**After**

```ts
trackThreadsTabClicked(props);
trackThreadsTryFromHereClicked({ ...props, outcome: "success" });
```

`CpkThreadInspector` also emits a `tryFromHere` custom event when the
user clicks the button.
2026-08-28 16:10:06 +02:00
Alem Tuzlak 95285be33b feat(web-inspector): copy stored threads into Playground from Threads 2026-08-28 14:24:05 +02:00
Alem Tuzlak 5686a0669e Merge branch 'main' into lukas/oss-904-runtime-connection-status 2026-08-28 14:06:40 +02:00
Alem Tuzlak 1dfc5cdafa refactor(core): remove OSS-904 design comments 2026-08-28 13:27:37 +02:00
Alem Tuzlak a7191e2a12 fix(core): bound recovery /info hang and tighten OSS-904 comments 2026-08-28 13:08:44 +02:00
copilotkit-qa-bot[bot] a1c7146739 docs: persist Deep Agents interrupt names 2026-08-27 13:50:49 -07:00
Ben Taylor b8492e2b70 docs(vue): document the generative-UI path and publish it in the Vue sidebar (closes OSS-1005) (#6743)
## Problem

Vue 3 is a documented frontend and generative UI is the capability that
turns a chat box into the product — every completing showcase cell's
proof is a *card*, not a paragraph. But no page described how a tool
result becomes a rendered surface in Vue.

A showcase run pairing AWS Strands with Vue reached exactly that point,
correctly refused to invent a rendering path, and said so:

> "The official Vue documentation also does not document Strands
generative-UI rendering, so none was invented or claimed."

It shipped a text answer. Vue has 2 recorded runs against Next.js's 42 —
the least-covered frontend is also the one where the most valuable
capability was undocumented, and those reinforce each other.

## The capability was never missing

`packages/vue` already ships the whole surface: `useRenderTool`,
`useDefaultRenderTool`, `A2UIMessageRenderer`,
`A2UISurfaceActivityRenderer`, `OpenGenerativeUIRenderer`,
`MCPAppsActivityRenderer`, a full `src/v2/components/a2ui/` catalog and
adapter, e2e coverage, and two working demo pages under
`examples/v2/vue/demo/`. Notably it is React-free *by design* — the A2UI
code carries comments explaining it duplicates small helpers
specifically to avoid pulling `@copilotkit/a2ui-renderer`'s React
dependencies.

So this is a docs task, not an SDK one.

## But the gap was structural, not editorial

This is the part worth reviewing carefully, because it's why a guide
file alone would not have fixed anything.

**Sidebar.** `getFrontendQuickstartNavTree()` gated its guides branch on
`id === "angular"`. Angular gets its 8 guides; every other frontend got
an empty array plus a "Guides coming soon" placeholder. The new test's
red-check shows Vue's entire sidebar:

```
AssertionError: expected [ '/vue', …(2) ] to include '/vue/guides/generative-ui'
```

Three URLs.

**Routing.** `resolveFrontendDocPage()` serves `/<frontend>/<slug>` only
from a `frontends/<frontend>/<slug>` variant file, or from a doc whose
nearest `meta.json` declares `frontend: universal`.
`generative-ui/meta.json` declares no policy at all, so
`/vue/generative-ui/*` resolves **not-found**. Those pages weren't
merely React-flavored for a Vue reader — they were unreachable in the
Vue namespace.

The irony: `concepts/meta.json` **is** universal, and it holds
`generative-ui-overview`. A Vue developer could reach the page
explaining *what* generative UI is, and no page showing *how*.

## Changes

| File | Change |
| --- | --- |
| `docs/frontends/vue/guides/generative-ui.mdx` | New. The guide. |
| `lib/frontend-page-content.ts` | `VUE_GUIDE_PAGES` + a
`FRONTEND_GUIDE_PAGES` lookup replacing the `id === "angular"` branch,
so a frontend's guides are data rather than a conditional. Angular's
tree is unchanged. |
| `docs/frontends/vue.mdx` | The missing "Where to go next" pointer. |
| `lib/__tests__/frontend-options.test.ts` | Three tests. |

The guide covers `useRenderTool`, `useDefaultRenderTool`,
`useFrontendTool` with a renderer, A2UI (provider-level and
catalog-on-provider), Open Generative UI, and MCP Apps — written from
`packages/vue` source and the in-repo demos, not translated from the
React docs.

Two things it states deliberately:

- **It does not depend on the agent framework.** The reporting run read
the absence as Strands-specific. Generative UI reads AG-UI tool calls;
nothing changes when you swap the agent. The guide says so up front.
- **`useRenderTool` and `useFrontendTool` do not hand their renderers
the same props.** The former normalizes to `parameters` + a string-union
status; the latter passes through to core with `args` + the
`ToolCallStatus` enum. A renderer written for one silently draws nothing
in the other. Verified in source, not inferred.

### One note on the link form

The quickstart links the guide as `/vue/guides/generative-ui`, not the
relative `guides/generative-ui` that `angular.mdx` uses.
`resolveDocsHref` returns any non-root-relative href untouched, and
`next.config.ts` sets no `trailingSlash` — so the relative form would
resolve against `/vue` and land on `/guides/generative-ui`, which
doesn't exist. A test pins the authored href and asserts it both
survives rewriting and resolves. (`angular.mdx:241` uses the relative
form and looks like it has the same problem; not touched here.)

## Verification

- `frontend-options.test.ts` — 25/25. **Red-checked twice**: commenting
out the single nav wiring line fails the sidebar test; reverting the
href to the relative form fails the link test. Both can actually fail.
- Full `shell-docs` suite — 475/476. The one failure
(`llm-text.test.ts`, mastra tool-rendering) **reproduces on unmodified
`origin/main`** with these changes reverted. Pre-existing, unrelated.
- `tsc --noEmit` clean. `oxfmt --check` and `oxlint` clean.
- Search index regenerated: the page parses and is indexed at `href:
"/vue/guides/generative-ui"`, section "Frontends".

## Deliberately out of scope

1. **No Vue redirect map.** Angular's `ANGULAR_DOC_REDIRECTS` maps ~20
`generative-ui/*` slugs onto its guides, so
`/angular/generative-ui/tool-rendering` lands somewhere useful.
`/vue/generative-ui/tool-rendering` still 404s. That's a policy decision
about how much React IA to mirror into Vue.

2. **Backend-scoped variant.** On `/vue/<backend>`, `resolveDocsHref`
rewrites cross-section links — `/generative-ui/a2ui`,
`/generative-ui/mcp-apps`, `/inspector` — into that prefix, where they
resolve not-found. This follows from those sections having no
`frontend:` policy, is the same for every non-Angular frontend page
today, and is not introduced here. The sidebar link to the guide is
correct in both contexts.

3. **`FRONTEND_REFERENCE_SLUGS.vue` left alone — but please look at
it.** Vue's sidebar "Reference docs" link points at `"reference"`, the
**React** reference, despite a complete 25-page `/reference/vue` tree
existing and registered in `reference-items.ts`. It's pinned by an
assertion at `frontend-options.test.ts:538`, so it looks deliberate. If
it's an oversight it compounds this exact bug — a Vue developer sent to
the React reference cannot find `useRenderTool`'s Vue signature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-27 13:04:11 -05:00
Benjamin Taylor a768047532 docs(vue): document the generative-UI path and publish it in the Vue sidebar (closes OSS-1005)
Vue 3 is a documented frontend and generative UI is the capability that turns a chat box
into the product, but no page described how a tool result becomes a rendered surface in
Vue. A run pairing AWS Strands with Vue reached that point, correctly refused to invent a
rendering path, and shipped a text answer instead.

The capability was never missing. packages/vue ships useRenderTool, useDefaultRenderTool,
A2UIMessageRenderer, A2UISurfaceActivityRenderer, OpenGenerativeUIRenderer, a full a2ui/
catalog and adapter, e2e coverage, and two working demo pages. Only the docs were absent.

They were absent structurally, not editorially. getFrontendQuickstartNavTree gated its
guides branch on `id === "angular"`, so every other frontend got an empty list plus a
"Guides coming soon" placeholder -- Vue's whole sidebar was three URLs. Routing matched:
resolveFrontendDocPage serves /<frontend>/<slug> only from a frontends/<frontend>/ variant
or a section marked `frontend: universal`, and generative-ui/meta.json declares no policy,
so /vue/generative-ui/* resolved not-found. concepts/meta.json IS universal, so a Vue
reader could reach the page explaining what generative UI is and no page showing how.

Add the guide, and replace the Angular identity check with a FRONTEND_GUIDE_PAGES lookup
so a frontend's guides are data rather than a branch. Angular's tree is unchanged.

The guide is written from packages/vue source and the in-repo demos rather than translated
from React, states up front that none of this depends on the agent framework, and documents
that useRenderTool and useFrontendTool do not hand their renderers the same props --
`parameters` plus a string-union status versus `args` plus the ToolCallStatus enum -- so a
renderer written for one silently draws nothing in the other.

The quickstart's link to the guide is the fully-qualified /vue/guides/generative-ui rather
than the relative form angular.mdx uses. resolveDocsHref returns non-root-relative hrefs
untouched and next.config sets no trailingSlash, so `guides/generative-ui` would resolve
against /vue and land on /guides/generative-ui. A test pins the authored href and asserts
it both survives rewriting and resolves.

Not addressed here: Vue has no equivalent of ANGULAR_DOC_REDIRECTS, so /vue/generative-ui/*
still 404s rather than landing on this guide, and on the backend-scoped variant of the page
(/vue/<backend>) resolveDocsHref rewrites cross-section links like /generative-ui/a2ui and
/inspector into that prefix, where they do not resolve. Both follow from the missing
`frontend:` policy rather than from this guide. Separately, FRONTEND_REFERENCE_SLUGS.vue
points at the React reference despite a complete /reference/vue tree; it is pinned by a
test assertion, so it is left alone here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:25:11 -05:00
Benjamin Taylor 84dea7bfbb fix(react-native): keep the polyfill imports in the built barrel (closes OSS-1002)
`src/polyfills.ts` is five side-effect-only imports. The `sideEffects` globs only matched
`./dist/**`, and rolldown matches that field against SOURCE paths while bundling, so every
`src/polyfills/*.ts` was declared pure and dropped. Every published version through 1.69.2
shipped a 195-byte barrel installing nothing but streaming fetch, so an app following the
documented setup died on its first runtime call with `Property 'ReadableStream' doesn't exist`.

`dist/index.mjs` and `dist/headless.mjs` lost the same imports, so the package's advertised
auto-install on first import did not happen either.

Add matching `./src/**` globs. The barrel goes 195B to 362B with all five imports, and
`headless.mjs` now leads with `import "./polyfills.mjs"`.

`src/__tests__/polyfills.test.ts` stayed green throughout this, because it imports the source,
which is never bundled and so is never tree-shaken. Add `scripts/verify-polyfill-barrel.mjs`,
which checks `dist/` instead. It clears the nine globals first (Node ships them natively and
Hermes does not, so asserting they are merely "defined" would pass on an empty barrel), then
executes the CJS barrel in a child realm and checks the ESM barrel structurally. ESM cannot be
executed here: the encoding polyfill takes a named import from CommonJS `text-encoding`, which
Metro rewrites to a require() but bare Node ESM rejects.

The check runs from `build`, so a dead barrel fails the build rather than reaching npm.

Also document the `ReadableStream doesn't exist` symptom in troubleshooting, where only the
inverse case (a polyfill *conflict*) was covered before.

Verified: reverting the sideEffects change and rebuilding turns the check red in both formats,
5 of 5 groups; restoring it turns it green. A behavioural check on the packed tarball installs
all nine globals. 289 vitest + 26 script tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:22:02 -05:00
Benjamin Taylor b18f7054af docs(react-core): state that an agent receives useAgentContext value as a JSON string (closes OSS-1003)
useAgentContext stringifies any non-string value before it leaves the
browser, and the AG-UI protocol types Context.value as a string on both
ends. An agent therefore always reads a JSON string, never the object or
array that was registered. None of the four reference pages said so; they
stopped at "serialized automatically", which reads as "the framework
handles it".

An author who believes that writes an agent that reads the object. When
the resulting shape check fails, the agent cannot distinguish "context
arrived JSON-encoded" from "no context was sent" -- the two are
identical -- so it refuses every request while the browser is registering
context correctly. That is what happened on the both-oss
langgraph-python conversion journey, where the agent's
isinstance(value, list) guard could never pass and the journey was dead
on arrival.

Each page now carries a "What the agent receives" section: the wire shape
as literal JSON, json.loads and JSON.parse examples, and a callout naming
the shape check as the trap. The value parameter description and the
Serialization behavior bullet now name the consequence for the agent
author instead of stopping at the browser half.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:18:14 -05:00
Mike Ryan 593fe0bc0b fix(docs): address Agent Framework review 2026-08-27 09:21:37 -07:00
Mike Ryan 6943ca8232 fix(docs): replace retired GitHub Models setup 2026-08-27 09:21:37 -07:00
Ben Taylor 30d4f2af42 docs(react-native): state the version /headless needs, and what to do below it (closes OSS-956) (#6725)
## What does this PR do?

The React Native guide imports `CopilotKitProvider`, `useAgent` and
`useCopilotKit` from `@copilotkit/react-native/headless` and names no
version. That subpath first ships in **1.64.0** (#6142), so a project
pinned to 1.63.x or earlier fails every one of those imports with:

```
Unable to resolve module @copilotkit/react-native/headless
```

On Metro that reads like a broken install rather than a version skew,
and it sends the reader into the package-exports and polyfill debugging
the same guide warns about a few sections later. The actual fix is one
word in an import path.

This states the boundary in the three places a reader meets the subpath.
Prose only — no snippet in this page changed.

### The version boundary, verified against the registry

Not inferred from a changelog — `npm view @copilotkit/react-native@<v>
exports` on each:

| version | `./headless` |
| -- | -- |
| 1.62.0, 1.62.2, 1.62.3 | absent |
| 1.63.0, 1.63.1, 1.63.2 | absent |
| **1.64.0** | **present** |
| 1.64.1+, 1.65.0, 1.69.2 | present |

`./components` and the polyfill subpaths exist across all of the above,
so `/headless` is the only path in the guide that carries a version
boundary. Introduced by 0a582df4dd / #6142.

### What changed

- **Intro line** — `/headless` is marked `1.64.0+` where the three
import surfaces are first introduced.
- **Install step** — a `type="warn"` callout, placed where the resolved
version is actually decided. States the boundary, quotes the exact Metro
error, gives `npm ls @copilotkit/react-native` to check what you
resolved, and covers the fallback.
- **Import surfaces table** — a new "Available since" column.
- **Import surfaces prose** — records what `/headless` *is*, which the
guide never said: a lean alternative entry added so custom-UI consumers
skip the chat and attachment native deps — **not** a replacement for the
root barrel, which remains the package's default full surface and
re-exports everything in `/headless`.

### The fallback advice is deliberately not just "import from the root"

On 1.62.2 and 1.63.2 the root barrel does export all three names
(checked in the shipped tarballs, not assumed). But
`package/dist/index.mjs` on those versions statically imports
`expo-document-picker` and `expo-file-system`. A reader who switches to
the root therefore inherits exactly the peer-dependency resolution
failure that this guide's `/headless` choice exists to avoid:

```
Unable to resolve module expo-document-picker
```

So the callout says to prefer upgrading to 1.64.0+, and if you cannot
(because you are matching a pinned `@copilotkit/runtime`), names the
install-or-stub requirement that comes with the root import rather than
presenting it as a free swap.

### Why not backport `./headless` to 1.62.x

That was the alternative the issue floated, and it looks unnecessary.
`/headless` was never intended as the canonical entry that supersedes
the root — #6142's message, `src/index.ts` (`export * from
"./headless"`, with a root quick-start that uses the root), and
`src/headless.ts` ("existing imports from `@copilotkit/react-native` are
unchanged") all agree it is a lean *alternative*. Adding an entry point
in a patch of an older line would also change what "the pinned set"
means for anyone matching client to runtime.

## Related PRs and Issues

- Closes OSS-956
- #6142 — added the `/headless` subpath in 1.64.0
- #5883 — the `@copilotkit/react-core/v2/headless` entry that #6142
mirrors

## Verification

- MDX compiles via `@mdx-js/mdx` + `remark-gfm`, edited and baseline
both
- 4-column Import surfaces table parses; 19/19 `<Callout>` tags balanced
- `commitlint` exit 0
- `pnpm check:intelligence-env-names` passes
- `.mdx` is not in lefthook's `lint-fix` glob, so oxfmt/oxlint never
applied to this file
- This page carries no `doctest=` fences, and no fence in it changed, so
the guide's snippets stay runnable as they were

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-27 09:31:46 -05:00
Alem Tuzlak 42d3c92fbd chore: merge origin/main into tyler/default-browser-inspector 2026-08-27 12:09:27 +02:00
copilotkit-qa-bot[bot] 17c59fd719 collect Agno persistence regression in CI 2026-08-26 14:56:06 -07:00
copilotkit-qa-bot[bot] 301fa3cc19 Merge remote-tracking branch 'origin/main' into codex/fac-125-agno-db-docs 2026-08-26 14:47:03 -07:00
copilotkit-qa-bot[bot] 235ac1cf8f fix(docs): correct Intelligence CTA redirects 2026-08-26 14:01:28 -07:00
github-actions[bot] 53b2bfb520 style: auto-fix formatting 2026-08-26 20:46:46 +00:00
copilotkit-qa-bot[bot] 09f0482152 document Agno frontend-tool session storage 2026-08-26 13:43:11 -07:00
Benjamin Taylor f467b82502 docs(react-native): state the version /headless needs, and what to do below it (closes OSS-956)
The React Native guide imports `CopilotKitProvider`, `useAgent` and
`useCopilotKit` from `@copilotkit/react-native/headless` and names no version.
That subpath first ships in 1.64.0 (#6142), so a project pinned to 1.63.x or
earlier fails every one of those imports with `Unable to resolve module
@copilotkit/react-native/headless` — which on Metro reads like a broken install
rather than a version skew, and sends the reader into the package-exports and
polyfill debugging the same guide warns about. The actual fix is one word in an
import path.

Verified against the registry rather than inferred: `./headless` is absent from
1.62.0, 1.62.2, 1.62.3, 1.63.0, 1.63.1 and 1.63.2, and present from 1.64.0
onward. `./components` and the polyfill subpaths exist across all of them, so
`/headless` is the only path in the guide with a version boundary.

State the boundary in the three places a reader meets the subpath: the intro
line that introduces the surfaces, a callout in the install step (where the
resolved version is actually decided, with `npm ls` to check it), and an
"Available since" column in the Import surfaces table.

The fallback advice is deliberately not just "import from the root". On 1.62.2
and 1.63.2 the root barrel does export all three names — but its `dist/index.mjs`
statically imports `expo-document-picker` and `expo-file-system`, so a reader who
switches to the root inherits exactly the peer-dependency resolution failure that
this guide's `/headless` choice exists to avoid. The note says so and points at
the stub/install requirement.

Also records what `/headless` is, since the guide never said: a lean alternative
entry added so custom-UI consumers skip the chat and attachment native deps, not
a replacement for the root barrel, which remains the package's default full
surface and re-exports everything in `/headless`.

Prose only — no snippet in this page changed, and the page carries no doctest
fences, so the guide's snippets stay runnable as they were.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 15:29:56 -05:00
copilotkit-qa-bot[bot] 70f15d6ead Merge remote-tracking branch 'origin/main' into codex/fac-127-ms-agent-stable-apis 2026-08-26 12:56:16 -07:00
copilotkit-qa-bot[bot] 0b854047e2 fix(ms-agent-python): preserve Azure AD auth 2026-08-26 12:55:46 -07:00
copilotkit-qa-bot[bot] b0908711ab Merge remote-tracking branch 'origin/main' into codex/fac-72-google-adk-stop-callback 2026-08-26 12:30:08 -07:00
copilotkit-qa-bot[bot] 2ba50f1476 docs(google-adk): keep callback setup concise 2026-08-26 12:29:46 -07:00
Maxim f8e13e675c Remove the banking showcase in favor of reskinnable-demo (#6683)
## What

Sunsets `examples/showcases/banking`. It is superseded by
`examples/showcases/reskinnable-demo`, which ships the same banking
experience as one of its runtime-swappable skins (alongside airline) on
top of a shared shell. Keeping both means maintaining two copies of the
same demo.

160 files deleted, plus the five places that pointed at the app:

| File | Change |
| --- | --- |
| `pnpm-workspace.yaml` | Drops the workspace entry. Also fixes the
adjacent NOTE, which attributed the canary AG-UI pin to "banking's
agent" when it is reskinnable-demo's own Python deep agent that needs
it. |
| `pnpm-lock.yaml` | Regenerated (−919/+12). The 12 additions are
peer-suffix re-keying caused by removing the importer — banking pinned a
different `eslint`/`vitest` peer combination. No dependency version
changes. |
| `examples/README.md` | The banking row becomes a reskinnable-demo row,
so the successor is listed and the showcase count is unchanged. |
| `showcase/shell-docs/src/content/docs/faq.mdx` | The "Banking
Assistant" link retargets to reskinnable-demo instead of 404ing. |
| `.github/config-allowlist.txt` | Drops the deleted `next.config.mjs`.
|

Note that banking was a real pnpm workspace member using `workspace:*`
deps, unlike reskinnable-demo, which sits deliberately outside the
workspace with its own lockfile. That is why the root lockfile has to be
regenerated here.

## Deliberately not changed

- `scripts/migrate-demos.sh` and `scripts/archive-demo-repos.sh` still
name `examples/showcases/banking`. Those are the already-executed
one-shot manifests for the repo consolidation; the path is a historical
record in them, not a live reference.
- `reskinnable-demo`'s `.env.example` and `docker-compose.yml` still
explain their +200 port offset in terms of banking's stack. The offset
stays real, and "was cloned from banking" stays true.
- The `banking` mentions in `test_reskinnable-demo.yml` refer to
reskinnable-demo's **banking skin**, not this app.

## Verification

- `.github/scripts/check-config-allowlist.sh` passes.
- A full `pnpm install` agrees with the regenerated lockfile (no further
diff).
- The lockfile-only regen and the full install produce identical output.

The `test-and-check-packages` pre-commit hook fires on any
`pnpm-lock.yaml` change, so it ran `test,publint,attw` across all 25
packages. Four suites failed locally — `sqlite-runner`, `web-inspector`,
`vue`, `react-core` — in a worktree installed with `--ignore-scripts`,
which skips `better-sqlite3`'s native build. This change touches no
package source, so CI is the gate on those; please confirm they are
green here before merging.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-26 21:27:16 +02:00
copilotkit-qa-bot[bot] 7a24a2d855 fix(ms-agent-python): migrate starter to stable APIs 2026-08-26 12:09:08 -07:00
copilotkit-qa-bot[bot] 1ddc8d5454 Merge remote-tracking branch 'origin/main' into codex/fac-72-google-adk-stop-callback 2026-08-26 11:11:28 -07:00
Lukas Moschitz 4f432848f5 docs(oss-904): correct the claims about thread requests and the error state
Five comments justified routing thread requests through the instrumented fetch
by saying it lets opening a view restore the status after an outage. It does
not: every binding withholds its thread requests until the status is already
connected, so while it is red nothing is sent. The justification is DETECTION
only, which is what the CopilotChat site already said correctly.

Also:

- Documents both meanings of the Error state and the invariant behind them —
  the status reports the last actual contact with the runtime — on the
  connection-status reference page, which described only the startup meaning.
- Renames RUNTIME_PROBE_TIMEOUT_MS to ɵRUNTIME_PROBE_TIMEOUT_MS. core/index.ts
  re-exports agent-registry wholesale, so a constant whose own doc says
  "exported for tests" was public API of @copilotkit/core.
- Guards the Inspector's read of ɵruntimeFetch the way it guards its four other
  internal core accessors. A newer Inspector against an older pinned core was
  handing the thread store `undefined`, which breaks the Threads view outright
  rather than merely losing detection through it.
- Corrects the stop-request comment, which claimed to be the only runtime
  destination off the seam; the suggestion route's stateless path, the memory
  store and /inspector-metadata are too, just not by design.
- Corrects OSS-904-VERIFY.md, which said scenario 4 had real traffic to work
  with and left it off the not-covered list.
2026-08-26 13:25:13 +02:00
Tyler Slaton b3b339f544 Revert "feat(web-inspector): add Event Snippets and save-as-snippet (#6649)"
This reverts commit ba4260ad66, reversing
changes made to 47c5510b49.
2026-08-26 02:11:19 +02:00
Ben Taylor f2390df714 docs: fix typo in Mastra shared state guide (#6686)
## What does this PR do?

Corrects `faciliate` to `facilitate` in the Mastra shared state
documentation.

## Related PRs and Issues

- None.

## Validation

- `codespell
showcase/shell-docs/src/content/docs/integrations/mastra/shared-state/index.mdx`
- `git diff --check`

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/CopilotKit/CopilotKit/blob/main/CONTRIBUTING.md).
- [x] The relevant documentation is updated by this PR.
- [x] "Allow edits by maintainers" is enabled.
2026-08-25 12:32:26 -05:00
Ben Taylor 4319370f7e docs(react-native): say how to prove the integration without a browser (#6685)
## Why

The React Native page covers building the integration thoroughly and
never says how to
establish that it **works**. `verify` appeared zero times in its 646
lines, and the only
verification content was a reactive troubleshooting entry ("no response
from the runtime →
check `/info`").

That gap is sharper here than on the web frontends. There, "open it and
look" is an
unstated fallback that genuinely works. On React Native there is no
browser, so a reader
who follows this page to the end has no proof step at all — and the
obvious substitutes
each prove less than they appear to.

## What this adds

A **Proving it works** section with three checks, explicit that none is
sufficient alone:

1. **`copilotkit verify --round-trip`** — proves an agent answered, with
no browser and no
device. Its limits are stated rather than left to be discovered: it
sends a *fixed*
prompt and records the answer's length, never its text, so it cannot
tell you what came
back; and it proves an agent answered under the declared id, not *which*
deployment
   answered.
2. **A device capture** — `adb exec-out screencap -p`, plus `adb logcat`
for an unresolved
redbox. iOS has no `adb` equivalent short of full Xcode, and the Command
Line Tools do
   not ship `simctl`, so the section says so instead of implying parity.
3. **Checking the answer against the records the app holds** — the only
step that separates
a correct answer from a fluent one about records that do not exist. That
failure is
invisible in a screenshot, in a video, and to any reviewer unfamiliar
with the data.

Two smaller fixes on the same page:

- **`useAgentContext` is now a callout, not a list entry.** It sat in
the shared-hooks list
described as behaving "the same as on the web", which undersells the one
hook whose
absence fails *silently*. Rendering a list puts it in the view tree, not
in the agent's
context — separate steps. An agent missing the second still answers
plausibly, the tool UI
paints, and nothing errors. React Native has no browser console to
notice it in.
- **`@react-native-community/cli` is now a prerequisite.** React Native
0.87 no longer
bundles it, so an *upgraded* app needs it in `devDependencies` or
`react-native bundle`
and `react-native start` refuse to run. A freshly `init`ed app already
has it, which is
  why the quickstart path never surfaced this.

## Notes for review

- **Docs-only.** One `.mdx` file, +78 lines, no code or config touched.
- The three anchor links used (`#connecting-from-a-device-or-bench`,
`#which-hooks-are-shared-and-which-arent`, `#known-limitations`) all
resolve to existing
  headings, and match the anchor style the page already uses elsewhere.
- Prose is unwrapped to single-line paragraphs and callout bodies are
2-space indented, to
  match the file's existing convention.
- `npm run lint` in `docs/` exits 0 with no new warnings. `vitest run`
gives 188 passed / 29
failed-to-load — **identical to a pristine `origin/main` worktree**,
which I ran to confirm;
  those failures are a local module-resolution issue, not this change.
- Deliberately **not** included: documenting `copilotkit verify`
generally. It is currently
undocumented across the whole docs tree (Angular and Vue score zero on
"verif" too), which
wants its own change and probably a shared page rather than a
per-frontend section.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-25 10:35:51 -05:00
Ben Taylor a2e5abb0e6 Make React SPA a supported onboarding path (docs half) (#6675)
Closes the docs half of OSS-938. The Intelligence half (graph node flip,
`frontend/plan.md`, fixture conversion, replacement unsupported cell)
lands as a separate PR in `CopilotKit/Intelligence` — it cannot share a
PR across the repo boundary.

## Why

React SPA was the only frontend the onboarding graph could not route to
a validated outcome, and the gap was exactly one step: **where Copilot
Runtime lives.** Every framework quickstart hosts the runtime in a
Next.js route handler and sets a relative
`runtimeUrl="/api/copilotkit"`. That path resolves only because Next.js
serves the app and the runtime from one origin. A Vite or CRA app has
neither a server nor a shared origin, so the instruction had nowhere to
land.

The rest of the React tree already works unchanged in a SPA —
`/frontend-tools`, `/generative-ui`, `/human-in-the-loop`, `/headless`,
`/prebuilt-components` and `/reference/v2` contain no Next.js-specific
steps. So this adds one page for the one difference and links out for
everything else, rather than forking a parallel React tree.

## What's here

**1. `docs/frontends/react-spa.mdx`** — the standalone Node runtime
server (the `angular.mdx` / `vue.mdx` shape), the absolute `runtimeUrl`
it requires, `cors: true`, the two-dev-server port story, and links back
out to the root React pages.

**2. `react-spa` registered in
`showcase/shared/frontend-registry.json`** — required, not cosmetic.
Frontend route resolution is gated on `isFrontendId`
(`src/app/[framework]/[[...slug]]/page.tsx:96`, and the `/frontends/x` →
`/x` flattening at line 133), and `isFrontendId` reads the registry. An
unregistered MDX file 404s. Vue and React Native are the precedent —
both registered, both a single page, neither with a namespaced subtree —
so this does **not** create the `/react-spa/**` mirror tree OSS-938
rules out. `feature_support_required: false` matches them, so no
feature-support matrix entries are needed.

**3. The `runtimeUrl` sweep — 13 quickstarts**, each getting a callout
on its provider step noting that the relative path assumes a
Next.js-served origin.

## Two things worth a reviewer's attention

**`cors: true` is load-bearing and easy to omit.** `resolveCorsConfig`
(`packages/runtime/src/v2/runtime/core/fetch-handler.ts:784`) is `if
(!cors) return null`, and `createCopilotNodeListener` passes options
straight through to `createCopilotRuntimeHandler`. So CORS is **off by
default** on exactly the adapter a standalone SPA runtime uses — while
Express (`endpoints/express.ts:126`, `cors: corsOption = true`) and Hono
(`endpoints/hono.ts:105`) default permissive. Since the SPA's app and
runtime are on different origins, omitting it fails every request on
preflight. The page calls this out twice.

**The sweep callouts deliberately contain no root-relative links.** My
first attempt linked `/react-spa`, `/vue` and `/react-native`, which
broke `angular-docs-content.test.ts` → "keeps every rendered
backend-specific Angular link in context" with 45 leaks. That test is
right and the links were wrong: `resolveAngularDoc` falls back to
`frameworkContentSlug`, so the Angular surface **reuses these same
integration quickstarts**, and its link contract deliberately keeps
readers inside `/angular/**`. Enumerating three other frontends was also
wrong content for an Angular reader. The callout now names the guide
paths as inline code instead.

The cost is that the sweep no longer hands the reader a clickable link —
discoverability for React SPA comes from the frontend selector entry
instead. Doing both properly needs a frontend-conditional content
component (the `WhenAngularBackend` pattern, but keyed on frontend),
which is more than this sub-task should carry. Worth a follow-up.

## Corrections to the issue found while implementing

- **There is no doctest harness.** OSS-938 says the snippets are
doctest-gated. `shell-docs` runs vitest over `src/**/*.test.{ts,tsx}`
only — MDX code blocks are never executed. The real gates are that suite
plus `tsc --noEmit`.
- **The docs do have a frontend selector**, backed by the registry (6
entries before this change). The issue's "no frontend selector anywhere"
is true only of MDX *tab groups*.
- **The sweep is 13 source files, not 18 pages.** The langgraph,
microsoft-agent-framework and aws-strands variants are tab groups inside
one page each, so `langgraph-fastapi`/`-python`/`-typescript` collapse
to one file, the three `ms-agent-*` to one, and
`strands`/`strands-typescript` to one.
- **The root `/quickstart` needs nothing.** It is a 17-line routing shim
that 308-redirects to `/` and carries no runtime step at all. The issue
counts it among the 18.
- **The issue's page list misses `built-in-agent` and the root-level
`agent-spec/quickstart.mdx`**, both of which do carry the relative
`runtimeUrl`. Both are swept here.
- **Vue and React Native are already done**, in both repos — both ship
the absolute-`runtimeUrl` recipe and both already route to
`credentials/finalize-plan`. The issue defers them as out of scope, but
that also means the sweep fixes the mis-route for one frontend, not
three.

## Testing

Run in the worktree against `origin/main` (`0943c5196e`).

**`tsc --noEmit` — no new errors.** Baselined by setting my changes
aside on a pristine checkout: 8 pre-existing errors, all from
`@clerk/nextjs` / `@testing-library/react` / `jsdom` being undeclared
and uninstalled in `showcase/shell-docs/package.json` (verified absent
in `main` too, so this is repo state, not this branch). With the changes
applied: the same 8, zero added.

The type widening surfaced one real error, now fixed —
`FRONTEND_REFERENCE_SLUGS` in `frontend-page-content.ts` is `satisfies
Record<FrontendPageId, string>` and needed a `react-spa` entry. It maps
to `"reference"`, the root React reference, same as Vue.

**Test suite — no new failures.**

```
$ npx vitest run src/lib src/app
 Test Files  1 failed | 41 passed (42)
      Tests  1 failed | 380 passed (381)
   × renders one dependency-complete canonical tool-rendering example for mastra
```

That mastra failure is pre-existing — reproduced on a pristine
`origin/main` checkout with every change of mine removed:

```
$ git checkout -- <changed files> && mv react-spa.mdx aside
$ npx vitest run src/lib/__tests__/llm-text.test.ts
      Tests  1 failed | 39 passed (40)
   × renders one dependency-complete canonical tool-rendering example for mastra
```

**The new page is covered by an existing registry-driven guard, and the
coverage is real.** `frontend-options.test.ts` → "maps every non-React
frontend to an MDX guide page" iterates `FRONTEND_PAGE_IDS` and asserts
`loadDoc(getFrontendContentSlug(id))?.fm.title`. Mutation-checked rather
than assumed — removing the page fails it, restoring it passes:

```
$ mv src/content/docs/frontends/react-spa.mdx /tmp/ && npx vitest run frontend-options.test.ts
   × maps every non-React frontend to an MDX guide page
      Tests  1 failed | 21 passed (22)
$ mv /tmp/react-spa.mdx src/content/docs/frontends/ && npx vitest run frontend-options.test.ts
      Tests  22 passed (22)
```

**Sweep coverage checked programmatically, not by eye.** For each of the
13 files, asserted exactly one `runtimeUrl="/api/copilotkit"`
occurrence, the callout inserted immediately after that code block's
closing fence, and the `runtimeUrl` line exactly 9 lines above it. Then
re-derived the target set from the tree to confirm nothing was missed —
the only quickstart still carrying an un-annotated relative `runtimeUrl`
is `aws-strands`, which is excluded on purpose.

**Route wiring confirmed live.** `GET /frontends/react-spa` → `301` on
the local dev server, which is the registry-gated flattening redirect
firing for a registered id. Full HTML render could not be verified
locally: the dev server 500s on `@clerk/nextjs` for *every* page
(`/vue.md` fails identically), because that dep is undeclared and
uninstalled — pre-existing and not specific to this branch.

**Every outbound link on the new page resolves** — probed
`/frontend-tools`, `/generative-ui`, `/human-in-the-loop`, `/headless`,
`/prebuilt-components`, `/reference/v2`, `/model-selection`,
`/backend/runtime-endpoints`: all 200 or 301-to-canonical.

**Fixed a stale mock while here.**
`src/app/llms-mdx/[[...slug]]/route.test.ts` hard-codes the frontend
list instead of reading the registry, so it silently omitted
`react-spa`. Added it to both lists; suite passes (15/15). The
hard-coding is still a latent divergence worth a follow-up.

## Not done here

- **`aws-strands/quickstart.mdx` is excluded from the sweep**, per the
standing hands-off arrangement while Mark leads the Strands
rejuvenation. That leaves `strands` and `strands-typescript` carrying
the un-annotated Next.js step.
- **A clickable cross-link in the sweep callouts**, per the
Angular-contract finding above.
- The Intelligence-side changes, as noted at the top.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-25 10:35:35 -05:00
Mike Ryan 21871d8829 docs(mastra): document the remote-agent path and lead with it for existing services (#6663)
## What

`MastraAgent.getRemoteAgents` appeared **nowhere** in this repo — not in
shell-docs, not in an example, not in a snippet. The only wiring the
Mastra docs taught was `getLocalAgents({ mastra })` behind `import {
mastra } from "@/mastra"`.

That was on the **"Use an existing agent"** branch of the quickstart —
the branch for readers who already have a Mastra service. Two steps
earlier the same branch tells you to `npx create-next-app
my-copilot-app`, a *separate* directory. `@/mastra` cannot resolve
across that boundary, and the shape it teaches moves a running Mastra
service into the frontend, deleting the process the reader was trying to
preserve.

All four cells of the 2026-08-21 Mastra × Next.js sweep reached the
agent over HTTP, and all four derived how on their own. `both` filed
"the remote-Mastra API is entirely undocumented" as its largest
friction; `empty` filed it as its worst papercut at ~10 minutes.

## Changes

**`mastra/quickstart.mdx`** (existing-agent branch)
- Route wired with `getRemoteAgents` over a `MastraClient`, so the agent
keeps running as its own process. Passed as a **factory**, so the agent
list is fetched per request — see the note below on why the promise form
is unsafe.
- `MASTRA_BASE_URL` convention, as `.env.local` in the frontend beside
the route that reads it: `process.env.MASTRA_BASE_URL ??
"http://127.0.0.1:4111"`.
- A **"Start your agent"** step, which the branch never had. Its
liveness check is `/api/agents`, not `GET /` — Mastra serves its console
on the agent port and answers 200 whether or not an agent is registered
(straight from the `empty` cell's evidence).
- A warning that `next dev` rewrites the `tsconfig.json` at its own root
— forcing `esModuleInterop`, `isolatedModules`, `resolveJsonModule` and
`jsx`, setting `noEmit: true`, and replacing `include`/`exclude`.
`noEmit` is the sharp one for an agent project that compiles with `tsc`.
A sibling package is why this path goes over HTTP. `agent-only` derived
this independently.

**`mastra/copilot-runtime.mdx`** — a new **"Local vs remote agents"**
section that decides between the two by *where the agent runs*, not by
preference, plus:
- the full `GetRemoteAgentsOptions` contract (`mastraClient`,
`resourceId`, `observationalMemory`, `tracingOptions`);
- why the factory form is the one to use — `agents` does accept the
promise itself, but that starts the HTTP call at module load with
nothing awaiting it, so an agent server that is not up yet produces an
unhandled rejection and **Node terminates the process**. The factory has
no such window: a failure is a 500 and the next request retries, so a
route that started first recovers on its own. Cost is one `listAgents()`
per request;
- the local-only options (`requestContext`, `untilIdle`) — so a run that
needs background tasks has to be embedded.

**CI gating** — the new route fence carries `doctest="component"` with a
mastra `doctest.json`. The old fence could never have been gated:
`@/mastra` does not resolve. Mastra now has its first typechecked route
snippet, 21 gated fences → 22.

## Verified

```
shipped fence, agent down -> up  -> 500, then 200; process survived, no restart needed
promise form, agent down         -> node terminated on an unhandled rejection
next build, NodeNext tsconfig    -> 13 keys written; module/moduleResolution NOT touched
mastra CLI                       -> serverPort 4111, getPort over 4111..4131, apiPrefix /api
doc-test extraction              -> 21 -> 22 fences; mastra sidecar selected, not the root one
extracted fence, runner config   -> tsc exit 0 (runtime 1.68.3; @ag-ui/mastra 1.1.1 and 1.1.2)
mutation: drop resourceId        -> tsc exit 1, TS2741 (the gate is live)
previously documented local shape-> tsc exit 2, resourceId missing
MDX compile, both files          -> OK (mutation-checked: unclosed tag -> FAIL)
validate-intelligence-env-names  -> exit 0
```

The behavioural checks drove the **extracted fence itself** against a
stub agent server, not a paraphrase of it — including confirming it
calls `/api/agents` (the same path the quickstart gives as the liveness
check) and that it honours `MASTRA_BASE_URL`.

The extracted fence was byte-compared against the file that typechecked
green.

**Not run:** the shell-docs vitest suite. No test reads either file,
there are no snapshots, and no page was added or moved — nav, sitemap
and `llms.txt` are unchanged. Lefthook could not run in the worktree
(`tsx: command not found`, no `node_modules`); its one non-skipped gate,
`check:intelligence-env-names`, was run manually against this tree and
passes, and the commit message passes commitlint.

## Second commit

The first commit shipped the promise form and named `moduleResolution:
"NodeNext"` as what `next dev` clobbers. Self-review caught both: the
promise form crashes the process, and `nodenext` is in Next's *accepted*
set for `module` and `moduleResolution`, so it is never rewritten.
`7f068c6` corrects both plus the `MASTRA_BASE_URL` shell, each against a
real run rather than a source read.

## Found along the way, not fixed here

`getLocalAgents({ mastra })` — no `resourceId` — **does not typecheck**
against current `@ag-ui/mastra`; `resourceId` is required in
`GetLocalAgentsOptions`. That shape still ships on four other pages
(`shared-state/` ×3, `background-tasks.mdx`), and
`examples/integrations/mastra/src/agent.ts` carries a `//
@ts-expect-error - ignore for now, typing error` over exactly this call.
Left alone to keep this PR focused; happy to file it or fix it in a
follow-up.

Refs OSS-925.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-25 08:22:17 -07:00
Ben Taylor 37d3616959 Merge branch 'main' into ben1/oss-938-react-spa-supported-path 2026-08-25 09:21:19 -05:00
Sun Han Bing 4990c8027b docs: fix typo in Mastra shared state guide 2026-08-25 21:49:07 +08:00
Benjamin Taylor 2ee4d6bc6b Merge branch 'main' into ben1/oss-925-the-remote-mastra-path-is-undocumented-and-all-four-cells
Resolves the Mastra quickstart runtime step, where this branch's remote-agent
wiring and main's Intelligence wiring landed on the same lines. Kept both: the
per-request `getRemoteAgents` factory now sits alongside `intelligence` and
`identifyUser`, `runner: new InMemoryAgentRunner()` is gone (main dropped it
with the runner), and `resourceId` is derived from the same request header as
`identifyUser` rather than left hardcoded to "user-1", which would have scoped
Mastra's memory and CopilotKit's threads to different users. Both env blocks
and both callouts are preserved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 08:29:48 -05:00
Tyler Slaton c61f0f32ed feat(web-inspector): surface failures on the launcher and open the Inspector on them (#6646) 2026-08-25 06:28:17 -07:00
Benjamin Taylor 06fe1d8232 docs(react-native): say how to prove the integration without a browser
The page tells you how to build the integration and never how to establish that it
works. `verify` appeared zero times in 646 lines, and the only verification content
was a reactive troubleshooting entry. That gap is sharper here than on the web
frontends: there, "open it and look" is an unstated fallback that actually works. On
React Native there is no browser, so a reader following this page to the end has no
proof step at all.

Adds a "Proving it works" section with three checks, and is explicit that none of them
is sufficient alone, because each one looks more conclusive than it is:

- `copilotkit verify --round-trip` proves an agent answered with no browser and no
  device. It sends a fixed prompt and records the answer's length, never its text, so
  it cannot tell you what came back -- and it proves an agent answered under the
  declared id, not which deployment answered.
- A device capture proves the tool UI rendered. Android gets `adb exec-out screencap`;
  iOS has no equivalent short of full Xcode, and the Command Line Tools do not ship
  `simctl`, so that is stated rather than left to be discovered.
- Checking the answer against the records the app holds is the only step that
  separates a correct answer from a fluent one about records that do not exist. That
  failure is invisible in a screenshot, in a video, and to any reviewer unfamiliar
  with the data.

Also on this page:

- `useAgentContext` was listed in the shared-hooks list as behaving "the same as on
  the web", which undersells the one whose absence fails silently. Rendering a list
  puts it in the view tree, not in the agent's context. An agent missing it still
  answers plausibly and nothing errors -- and React Native has no browser console to
  notice it in. Now a callout.
- React Native 0.87 no longer bundles `@react-native-community/cli`, so an upgraded
  app needs it in devDependencies or `bundle` and `start` refuse to run. A freshly
  `init`ed app already has it, which is why the quickstart path never hit this. Now a
  prerequisite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 08:27:30 -05:00
Alem Tuzlak 5391c4886b feat(web-inspector): add view thread in your app (#6562)
## What does this PR do?

Lets a developer open a saved Inspector thread in the live official
chat.

- New header action: **View in your app**
- Official React and Vue chat switch to that thread
- A pinned `threadId` does not block the switch
- **Stop viewing** or an app thread change restores the previous thread
- Example threads have no action
- Production builds hide the action
- Same agent only. No matching official chat shows an error in the
Inspector

Core owns a two-way EventClient bridge
(`@tanstack/devtools-event-client`). The root import is a no-op in
production.

Docs: Inspector guide, section **View a thread in your app**.

## Related PRs and Issues

-
https://linear.app/copilotkit/issue/OSS-871/new-features-add-a-new-view-thread-in-your-app-feature

## Checklist

- [x] I have read the Contribution Guide
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] Allow edits by maintainers is checked
2026-08-25 13:52:52 +02:00
Maxim e3dafff825 chore(examples): remove banking showcase in favor of reskinnable-demo
The banking showcase is superseded by `examples/showcases/reskinnable-demo`,
which ships the same banking experience as one of its runtime-swappable skins
(alongside airline) on top of a shared shell. Keeping both means maintaining
two copies of the same demo, so banking is sunset here.

Removes the app and the things that referenced it:

- `pnpm-workspace.yaml` — drops the workspace entry. Also fixes the adjacent
  NOTE, which attributed the canary AG-UI pin to "banking's agent" when it is
  reskinnable-demo's own Python deep agent that needs it.
- `pnpm-lock.yaml` — regenerated. Only the removed importer and the peer-suffix
  re-keying it caused; no dependency version changes.
- `examples/README.md` — the banking row becomes a reskinnable-demo row, so the
  successor is listed and the showcase count is unchanged.
- `showcase/shell-docs/.../faq.mdx` — the Banking Assistant link retargets to
  reskinnable-demo instead of 404ing.
- `.github/config-allowlist.txt` — drops the deleted `next.config.mjs`.

Not changed: `scripts/migrate-demos.sh` and `scripts/archive-demo-repos.sh`
still name `examples/showcases/banking`. Those are the already-executed one-shot
manifests for the repo consolidation; the path is a historical record there, not
a live reference. reskinnable-demo's `.env.example` and `docker-compose.yml`
likewise still explain their +200 port offset in terms of banking's stack — the
offset stays real, and "was cloned from banking" stays true.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 12:11:48 +02:00
Lukas Moschitz 306ddaa5df Merge remote-tracking branch 'origin/main' into lukas/oss-903-presentation-wire-errors-notifications-to-emanate-from-and
# Conflicts:
#	packages/web-inspector/src/lib/__tests__/telemetry.test.ts
#	packages/web-inspector/src/styles/generated.css
2026-08-25 12:09:52 +02:00