Commit Graph

1435 Commits

Author SHA1 Message Date
Maxim edee011099 Merge branch 'main' into refactor/rn-render-tool-hooks 2026-09-09 21:20:48 +02:00
Tyler Slaton 5d084123ea fix(react-core): improve Inspector message shortcuts (#6974)
## Problem

Inspector message shortcuts do not consistently follow Inspector
visibility.

## Why

The shortcuts should respect local development restrictions and
visibility settings.

## Fix

- Add a wrench shortcut with a hover menu and a hide-until-reload
action.
- Add `CopilotChat.inspectorTools`, with provider settings taking
precedence.
- Keep shortcuts in sync with Inspector visibility and restrict
Inspector to local development.

Includes tests and API documentation.
2026-09-09 21:18:23 +02:00
Sam Julien baa2be051d docs: curate the default LLM index (#6963)
## Summary

The same onboarding prompt supports greenfield projects, brownfield
applications or agent backends, and existing CopilotKit OSS projects
connecting to Intelligence. The index states these starting points
explicitly and explains where to run the prompt.

Replace the exhaustive default `/llms.txt` expansion with a curated
index that exposes the canonical onboarding prompt, then routes readers
to their existing agent framework. The prompt is imported from the same
template used by the docs copy button, with instructions to create a
fresh run ID per onboarding session. Research-only readers are directed
to the documentation links.

Every visible external framework in the docs registry receives an
overview and quickstart link in a dedicated section. This includes the
LangGraph variants, Google ADK, Claude Agent SDK, Strands, Microsoft
Agent Framework, and other published integrations; hidden integrations
remain excluded.

The following section covers chat, generative UI, human-in-the-loop
workflows, Rich Threads, Automatic Learning, Intelligence, Channels, and
thread imports. Built-in Agent quickstart, model selection, and server
tools are explicitly labeled. Readers are directed to framework-specific
implementation guides instead of assuming root instructions apply to
every backend. `/llms-full.txt` remains available for exhaustive
retrieval.

Channels has two prominent canonical entries, with descriptions covering
native messages, approvals, and managed connection availability.
Repeated framework-specific channel guides remain in the full index.
Regression coverage now requires Slack and Teams entry points instead of
excluding every channel route.

## Validation

- Focused index tests cover the shared onboarding prompt, deterministic
output, every visible framework's canonical overview and quickstart,
hidden exclusions, ordering, and duplicates.
- Explicit TypeScript check passed after adding the onboarding prompt.
- Changed-file formatting and diff checks passed.
- Both canonical Slack and Teams documentation URLs returned HTTP 200.
- The initial implementation passed typecheck, lint, production build,
and commit hooks.

## Existing verification failures

The broader Nx `verify-shell-docs:fast` check reported existing unknown
snippet regions, internal dead links, and essential-content findings.
The unchanged Mastra LLM rendering test also expects a `createTool`
import absent from an existing generated snippet. These failures are
recorded separately from the passing index contract tests.

Linear: PDX-332


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Updated `/llms.txt` with a curated documentation index covering key
capabilities, interfaces, agent workflows, persistence, and supported
channels.
- Added dynamically generated entries for supported external agent
frameworks and integration quickstarts.
- Added onboarding instructions for connecting CopilotKit with a coding
agent.
  - Clarified built-in agent documentation labels.
  - Linked to `/llms-full.txt` for the complete documentation inventory.

- **Bug Fixes**
- Improved index consistency through validated ordering, uniqueness, and
visibility checks.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-09 11:58:44 -07:00
Maxim f99378d34f Merge branch 'main' into refactor/rn-render-tool-hooks 2026-09-09 20:57:50 +02:00
Tyler Slaton bba4113b8e fix(react-core): improve Inspector message shortcuts 2026-09-09 11:49:42 -07:00
Sam Julien 102599afa5 docs: align promoted API guidance 2026-09-09 13:41:32 -05:00
Ben Taylor 55981b3f64 docs: fix MCP endpoint and native Codex setup (#6955)
The documented Codex command connects `mcp-remote` to the server root,
which returns 404 for both HTTP and SSE. Use the working `/mcp` endpoint
with Codex's native Streamable HTTP support. Correct the same root-URL
error in the shared HTTP/stdio examples, and add `-y` to the remaining
npx bridge commands.

The guide now explains how to replace the old configuration and verify
an actual search, since `codex mcp list` only verifies registration.

Validation:
- Reproduced the old command failing with `Cannot POST /` and SSE 404.
- Live `/mcp` initialization and tool discovery succeeded.
- Codex CLI 0.153.4 successfully called `search-docs` and `explore-docs`
against `/mcp` (only those read tools preapproved for the noninteractive
smoke test).
- Docs content generation and 47 tests passed across docs-render, .NET
guidance, frontend-tool coverage, and setup-concept suites.
- Updated MDX compiles and every JSON example parses; commit hooks
passed.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Updated MCP setup examples with the correct endpoint URL.
  * Added automatic confirmation to relevant npx commands.
* Revised Codex instructions to use Streamable HTTP MCP servers
directly.
* Updated Codex configuration examples to use URL-based server entries.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-09 13:40:24 -05:00
Sam Julien 5a62ca1f79 docs: clarify onboarding starting points in LLM index 2026-09-09 11:15:18 -07:00
Sam Julien 1097a98474 docs: expose canonical onboarding prompt in LLM index 2026-09-09 11:12:29 -07:00
Maxim e69a7c08e2 docs(react-native): cite the shim's removal issue in its deprecation notes
@BenTaylorDev noted that "removal in the next minor" appeared 11 times across
5 files with no issue behind it, which is how a shim becomes permanent. Filed
as CopilotKit/CopilotKit#6976 and Linear OSS-1148, and cited in the shim's
JSDoc, the entry-point comment, and the reference page.

The runtime warning text is deliberately unchanged — a test asserts on it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 19:32:46 +02:00
Maxim ab9376ac49 docs(react-native): correct the wildcard mechanism and stop denying the silent path
Three corrections to the `useRenderTool` reference, matching the code changes
in the preceding commit.

The wildcard section said `name: "*"` on the old hook "advertised it to the
model on every run". It never did — core filters the name `*` out of the tool
list it hands the agent. Replaced with what actually happened: `*` is core's
catch-all handler name, and because the tool-result insertion and the
follow-up-turn request sit outside the check for whether the wildcard tool has
a `handler`, a display-only `*` tool answered every otherwise-unanswered tool
call with an empty tool result and asked for another turn. Includes the
one-turn measurement (2 turns and an empty result before, 1 turn and no result
after) and states the bound: a call whose result has already arrived was never
affected.

"What the warning does not cover" claimed a call with neither `description` nor
`handler` "says nothing, because there is nothing to say". There was. That
shape was unreachable for TypeScript callers (`description` was required) but
perfectly reachable from plain JS, where it registered and advertised a real
tool — so it lost registration and advertisement silently, through the one
shape routing cannot discriminate. That bullet is gone, the section is down to
three gaps, and a new "The shape routing cannot discriminate" section explains
why the warning now fires on that route and what to do about it.

Also: the route table gains a "Registers in" column recording that the
renderer-only routes land in `useEffect` where `useFrontendTool` uses
`useLayoutEffect`, so a call that used to register in the layout phase now
registers one phase later — untyped-JS callers only, and it matches core's web
behaviour. The migration table's renderer-only row no longer says "silent".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015XyonXjic9ZEuPTpzgN2uS
2026-09-09 19:32:46 +02:00
Maxim 95c9c0a5a0 docs(react-native): make the render-tool docs true of the shim, not of the deletion
The deprecated `useRenderTool` shim landed after these pages were written, so
they described a harder break than the code delivers — "React Native has no
render-tool API of its own", and a migration table presenting the old hook as
simply gone.

reference/react-native/hooks/useRenderTool:

- The overview and the migration narrative now say what actually happens: the
  name still exists, still works this release, routes by shape, warns, and goes
  away in the next minor. The routing table is the shim's three rules verbatim
  (src/hooks/useRenderTool.ts `routeFor`), including the unconditional wildcard
  and why it is unconditional.
- The warning is quoted from the source string rather than paraphrased, and gets
  its own "What the warning does not cover" section: dev-only gate, per-name
  dedup for the module's lifetime, silent when no old field is present, and
  emitted from an effect so an unmounted screen never warns.
- "Three shapes the compiler does not catch" is kept, not deleted. It is now
  framed as what the shim exists to route — and as what to audit by hand anyway,
  because the notice is development-only and because all three go back to
  degrading silently once the shim is removed.
- Two new migration rows for losses the table omitted: bare `RenderToolProps`
  is now `TS2314` (core's `S` has no default where RN's `T` did), and the
  `args` -> `parameters` render-prop rename is still `TS2339` even through the
  shim — verified with tsc, the shim restores the old CONFIG fields only. The
  `RenderToolFunction<T>` row now points somewhere instead of saying "gone".
- `parameters` was documented as `Partial<T> | T`, using a generic this page
  renamed to `S` and explicitly warns is the schema rather than the arguments.
  It is `Partial<InferSchemaOutput<S>> | InferSchemaOutput<S>`
  (react-core/src/v2/hooks/use-render-tool.tsx:9-31).

reference/react-native/hooks/useFrontendTool had zero mentions of `ReactElement`,
`ReactNode` or `FlatList` despite being where the migration sends people. It now
documents that its `render` is a `React.ComponentType` and therefore accepts a
bare string that throws on a device, and points at the opt-in
`FrontendToolRenderFunction<T>`.

docs/frontends/react-native and packages/react-native/USAGE.md (which ships in
the npm tarball — no `files` array, no `.npmignore`) get the same corrections at
their own length.

Every code sample added here was typechecked by pasting it into the package and
running `tsc --noEmit`, including the ones asserted to FAIL. Internal links and
heading anchors were checked mechanically against the content tree.
2026-09-09 19:32:45 +02:00
Maxim 62cf3878d7 docs(react-native): document core's useRenderTool as React Native's own
Rewrites the RN reference page for core's hook, points tool-plus-renderer users
at `useFrontendTool`, and carries the migration table. That table is the actual
consumer-facing channel for this break: the release-note collector
(scripts/release/lib/changes.ts) reads `git log --format=%H %s` into a
`{ hash, subject }` type, so a `BREAKING CHANGE:` footer has nowhere to land
(#6479).

The migration's loud-failure guarantee is stated precisely rather than
absolutely, because the absolute form is false. TypeScript's excess-property
check rejects an old call site (`TS2769` on `description`) only when the config
is a fresh object literal with those fields written inline; the renamed render
prop gives `TS2339`. Three shapes escape it, each named on the page: a hoisted
config whose `render` ignores its props, the same fields arriving via a spread,
and an untyped or `@ts-nocheck` call site. The last is the one to worry about —
core's bridge spreads `{ ...props, parameters: props.args }`, so `args` still
arrives at runtime and an old renderer keeps painting correctly while the tool
has silently stopped being registered.

Retires three § Known limitations entries this convergence closes (the wildcard,
`followUp`/`available` forwarding, and `handler`'s missing context argument) and
leaves the unrelated ones intact.

Deletes a false claim the previous docs shipped: that comparing `status` against
a bare string literal does not typecheck. A string-enum member is assignable to
its own literal type, so the comparison compiles and narrows in every direction
— verified with tsc in all four combinations. RN's `status` moves from the
`ToolCallStatus` enum to core's string-literal union, and that is explicitly not
a break; no migration work follows from it.

Also updates packages/react-native/USAGE.md, which still taught the deleted API.
That file ships in the published tarball — package.json declares no `files` array
and there is no .npmignore — so the package was documenting an API the package no
longer has. Its remaining samples were compiled against the shipped overloads.

Corrects the primary guide's claim that a `ReactElement | null` render return is
React-Native-specific: it is identical on the web. What is RN-specific is the
consequence of `useFrontendTool`'s looser render type, where a bare string
typechecks and then throws inside a `FlatList`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 19:32:43 +02:00
copilotkit-qa-bot[bot] f712369889 Merge remote-tracking branch 'origin/main' into codex/fac-197-state-snapshot-docs 2026-09-09 10:01:14 -07:00
Sam Julien a5b8b1f0fa docs: prioritize existing agent frameworks in LLM discovery 2026-09-09 09:51:30 -07:00
copilotkit-qa-bot[bot] be5315556c docs(crewai): verify AG-UI endpoint before cloud setup 2026-09-09 09:24:28 -07:00
Sam Julien 49dc0d2c4d docs: include Channels in the curated LLM index 2026-09-09 08:54:46 -07:00
Mike Ryan b17e238aa3 docs: show the component tool imports for the built-in agent (#6959)
The Components as Tools page shows a `useComponent` call without its
import. An onboarding run using the built-in agent had to inspect
installed type declarations to find it (friction report R16).

Show the `@copilotkit/react-core/v2` hook import and Zod import directly
on the shared page, including the built-in agent route.

Validation:
- `npm run typecheck` and `npm run build` passed in
`showcase/shell-docs`.
- `npm run test -- src/lib/__tests__/docs-render.test.ts
src/lib/__tests__/setup-concept.test.ts --maxWorkers=1` — 39 tests
passed.
- Browser smoke against the production build verified the visible
imports at `/built-in-agent/generative-ui/tool-based` and the same
import in its `.md` response.
- `pnpm exec oxlint showcase/shell-docs` — zero errors, existing
warnings remain; commit hooks and `git diff --check` passed.
- The broad docs test suite hit unrelated navigation/search UI failures
and excessive worker memory use; it was stopped. No application behavior
changed in this PR.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added guidance for importing `useComponent` and Zod when registering
tools for tool-based Generative UI.
* Clarified that the same approach applies to the built-in agent, which
does not require backend tool registration.
  * Included a TypeScript example showing the required imports.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 20:22:15 -07:00
Benjamin Taylor 274983d4f8 fix(docs): make the redirect suffix-aware and repair dead links the regeneration surfaced
Self-review follow-ups on the reference-docs regeneration.

The LangGraphAgent redirect only covered the bare path. A raw Markdown request
reaches redirects before the .md/.mdx rewrite, so a request for
/reference/v1/sdk/python/LangGraphAgent.md would have 404'd for the LLM routes.
Use permanentRedirectsWithSuffixes, which is what the rest of the redirect
table does.

Refreshing the pages also republishes their JSDoc links, and three of those
pointed at pages that do not exist. They were invisible while the pages were
frozen; regenerating makes them live 404s, so fix them at the source:

- use-coagent-state-render.ts linked to /coagents/videos/perplexity-clone, a
  legacy URL with no content, no redirect and no rewrite. Point at
  /generative-ui/state-rendering, the canonical guide the published page
  already named.
- copilotkit-props.tsx linked to
  /coagents/shared/guides/langgraph-platform-authentication, which likewise
  does not exist. Point at /auth, which is how the rest of the docs link to
  that guide.
- use-copilot-chat.ts was flipped to
  /reference/v2/hooks/useCopilotChatHeadless_c by the URL canonicalization in
  33f669ba7b, but there is no v2 page of that name — reference/hooks has no
  headless entry. Restore the v1 page, which exists and is what the published
  page links to today. If v1 readers should be pushed to a v2 page instead,
  that page has to be written first.

Every internal link the regeneration newly publishes now resolves to a content
file.

The three package edits are JSDoc comment lines only; no code changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 21:58:48 -05:00
Benjamin Taylor c11329c5dd fix(docs): stop the internal v1 deprecation banner leaking into reference pages
The v1 deprecation notice added in #6582 is a source-file banner for IDEs and
coding agents, including the line "AI CODING AGENTS: Never copy, suggest, or
generate these v1 APIs." It sits in the leading trivia of the first statement
of every public v1 source file, which is the same place the reference-docs
generator reads real JSDoc from, so regenerating embedded it as visible body
text on 20 published pages. That made regeneration unpublishable: no JSDoc
correction to a v1 source could land without also shipping the banner.

Skip the notice wherever the generator enumerates comment ranges, keyed off its
stable opening delimiter.

Also repoint the six SDK reference entries. Their pages moved to
reference/v1/sdk/ in ec239b15f7 and the old copies were deleted in a8d43a9c2e,
but files.ts still wrote to reference/sdk/, so the generator refreshed a
directory the docs site never served while the live pages went stale. Those
pages regain the upstream LangGraphAgent -> LangGraphAGUIAgent rename and the
copilotkit_emit_tool_call tool_call_id parameter. The renamed page replaces the
orphaned LangGraphAgent page, whose source file no longer exists, with a
permanent redirect for the old URL.

Regenerating is now idempotent: a second run leaves the tree clean.

Fixes #6939

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 21:44:18 -05:00
Ben Taylor f7192ee40c docs: persist the reader's code-tab choice, and link out to provider key pages (#6925)
Two independent docs-frontend improvements in `showcase/shell-docs`.
Rebased onto current `main` (the branch was 158 commits behind).

## 1. `<Tabs persist>` now actually persists

101 tab groups in the content tree are authored as `<Tabs groupId="..."
persist>`. The wrapper accepted both props and ignored them — the
comment in `docs-tabs.tsx` said so outright:

> `groupId` and `persist` are accepted and currently ignored

So every page reopened on its own default. A reader working through the
LangGraph guide in TypeScript had to reselect TypeScript on each page.

Fumadocs holds tab selection in local component state and exposes no
persistence hook, so the wrapper takes over the controlled
`value`/`onValueChange` pair and mirrors the pick into `localStorage`
under `shell-docs.tab.<groupId>`.

**Selection precedence**, strongest first:

| # | Source | Where it comes from |
|---|--------|---------------------|
| 1 | `urlDefault` | The framework-route override the page shell derives
from the URL (`TAB_DEFAULTS_BY_SLUG`) |
| 2 | Stored pick | `localStorage`, same `groupId` |
| 3 | `default=` | The author's value in the MDX |
| 4 | First item | Fallback |

The page shell passes its URL-derived value as a **separate `urlDefault`
prop** rather than overwriting `default`. This matters: 45 of the 101
`persist` groups also carry an author `default=`. Collapsing the two
sources into one prop ranks the author's default above storage, which
would leave the stored pick unreachable on almost half of the pages the
feature exists for. `language_langgraph_agent` appears both ways (30
sites with `default="Python"`, 8 without), so the same group would have
behaved inconsistently within one guide.

Two details worth noting for review:

- The stored value is read in an **effect**, not in the initial state,
so server and client render identical markup and hydration stays clean.
- Every `localStorage` read and write is wrapped in `try`/`catch`.
Private mode and quota errors leave the tabs fully working, just without
persistence.

## 2. API-key hints under `.env` snippets

The LangGraph quickstart tells the reader to put `OPENAI_API_KEY` in
`.env` and leaves them to go find the key page. `<ApiKeyHint
provider="openai" />` renders a muted one-line link under the snippet.

The component maps a provider id to a label and URL — `openai`,
`anthropic`, `google`, `langsmith`, `copilotkit`. An unknown id renders
nothing, so a typo degrades to today's behaviour instead of throwing. It
is navigational only: it neither reads nor writes a key. Both `.env`
steps on the LangGraph quickstart use it.

## Removed from this branch

The earlier revision led the LangGraph quickstart with a `<InlineDemo
demo="agentic-chat" />` block under a "See it working" heading. That is
gone, along with the `inline-demo.test.tsx` file that covered it —
`InlineDemo` is pre-existing `main` code this PR no longer touches.

Two tests in `docs-page-view-toc.test.tsx` were also dropped rather than
kept. They were named for this PR's components but did not exercise
them: `docs-page-view-toc.test.tsx` asserts on `DocsPage` props, and the
page body is never rendered. Verified by mutation — deleting
`ApiKeyHint` from the MDX registry left the test titled `renders the
LangGraph quickstart (InlineDemo + ApiKeyHint) without errors`
**passing**. Real coverage lives in `api-key-hint.test.tsx` instead.

## Testing

No CI job runs the `showcase/shell-docs` vitest suite.
`test_unit-showcase.yml` covers only `harness` and `shell-dashboard`;
`showcase_validate.yml` runs vitest only in `showcase/scripts`.
Everything below was therefore run locally.

**Full suite, branch vs. pristine `origin/main` in the same
environment** — `main` carries 6 pre-existing failures here, so the
failure *set* is the comparison, not zero:

```
base   (origin/main)  843 tests, 6 failed
branch (this PR)      858 tests, 6 failed
NEW failures: none
```

The 6 are identical on both sides: `brand-nav` layout cap, 3 ×
`angular-docs-content`, `llm-text` mastra, `ms-agent-python-stable-api`.

**Mutation checks** — every new test was verified to fail when the
mechanism it claims to cover is broken:

| Mutation | Result |
|----------|--------|
| `canPersist = false` (persistence off) | ✅ `persists a groupId pick
and reapplies it on a fresh mount` fails |
| Author `default` outranks storage (the pre-fix precedence) | ✅ `ranks
a stored pick above the author's MDX default` fails |
| `urlDefault` demoted below author `default` | ✅ `ranks a urlDefault
above the author's MDX default` fails |
| `ApiKeyHint` removed from the MDX registry | ✅ `is registered as an
MDX component` fails |
| `href={meta.url}` → `href={undefined}` | ✅ 5 of 7 `ApiKeyHint` tests
fail |

**End-to-end render** — `ApiKeyHint` was rendered through the real
`MDXRemote` pipeline (same `remarkGfm` options, nested in
`<Steps>/<Step>` as the quickstart uses it) to confirm the `provider`
prop survives compilation and the anchor reaches the HTML:

```
✓ ApiKeyHint through the real MDX pipeline > survives compilation with its provider prop
  expect(html).toContain("https://platform.openai.com/api-keys")
```

**Typecheck and lint** (`showcase/shell-docs`):

```
$ npx tsc --noEmit      → exit 0
$ npx oxlint .          → Found 28 warnings and 0 errors
$ npx oxfmt --check <touched files>  → All matched files use the correct format
```

The 28 lint warnings are pre-existing. The only two in a file this PR
touches (`mdx-registry.tsx`) are `iframe-missing-sandbox` on
pre-existing `InlineDemo` iframes, untouched here.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added inline API key guidance below relevant documentation code
blocks, with links to provider credential pages.
* Added tab selection persistence across documentation pages, with
support for URL and author-defined defaults.
  * Added API key guidance to the LangGraph quickstart.
* **Tests**
* Added coverage for tab persistence, selection precedence, invalid
values, disabled persistence, and API key hint behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 21:12:51 -05:00
Benjamin Taylor 0868314acd test(shell-docs): cover the CTACards page wiring
A self-review of the previous commit found three gaps.

- Nothing tested that the page wires the fixes up. A new test walks the
  rendered `DocsPageView` tree, asserts `blockJS` is off in the page's
  own MDXRemote options, and renders the registered `CTACards` override
  to confirm it prefixes card hrefs with the framework being read.
  Removing either the option or the override fails it.
- The compile test asserted `grid-cols-1`, which the two-column class
  also contains, so the `columns` half of that test proved nothing. It
  now asserts the absence of the `sm:` variant.
- The per-page test guarded the extracted href count but not the title
  count, so a regex that matched no titles would have passed silently.

Also correct the component comment: four content files author the
block, but the pydantic-ai one is shadowed by a sibling leaf file and
renders nowhere.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 20:41:35 -05:00
Benjamin Taylor d083d8a7a4 fix(shell-docs): let the authored CTACards props reach the component
The component fix alone was inert on the real page. next-mdx-remote 6
defaults `blockJS` to true, which runs a remark plugin that deletes
every JSX attribute whose value is an expression. On the docs route
`<CTACards columns={2} cards={[...]} />` reached the component with no
props at all, so it still rendered an empty grid. The unit tests passed
because they call the component directly and skip the MDX pipeline.

- Turn `blockJS` off for the docs route. Every source there is
  first-party content from `src/content`. `blockDangerousJS` keeps its
  default. The other MDXRemote call sites keep the default too, because
  `ag-ui/introduction.mdx` authors inline `onMouseEnter` handlers that
  the stripping currently keeps out of a server component.
- Resolve each card href against the framework being read. The cards
  render through the registry `Card`, so they never reached the
  href-resolving `Card` override, and a reader on
  `/ms-agent-python/human-in-the-loop` was redirected to the .NET page.
  Content now authors the hrefs root-relative.
- Stack the grid to one column below the `sm` breakpoint. An inline
  `grid-template-columns` cannot be overridden by a class, so the two
  cards stayed 157px wide side by side on a 390px viewport.
- Pass each description through the `Card` `description` prop, the same
  as every other card grid in the docs.
- Match `iconKey` against own properties only.
- Add a test that compiles the four authored blocks through the MDX
  pipeline, which is the check the earlier tests were missing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 20:41:35 -05:00
Benjamin Taylor 22cc2bf303 fix(shell-docs): render the CTACards a page actually authors
`CTACards` accepted only `children`, but every call site in content
authors `<CTACards columns={n} cards={[...]} />` self-closing. Both
props were dropped, so the grid rendered empty and the pages lost
their links with no error anywhere.

Four human-in-the-loop landing pages are affected: crewai-flows,
mastra, pydantic-ai, and microsoft-agent-framework.

The component now renders each entry through the shared `Card`, honors
`columns` in the grid template, and falls back to wrapping `children`
so legacy `<CTACards>...</CTACards>` authoring keeps working — the same
prop-or-children contract `EcosystemTable` uses in this file.

`iconKey` values on these cards are lucide names, not the framework
keys in `customIcons`, so they get their own lookup. An unregistered
key renders the card without an icon rather than throwing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 20:41:34 -05:00
Benjamin Taylor a04f0f7640 feat(docs): link out to the provider key page from .env snippets
The LangGraph quickstart tells the reader to put `OPENAI_API_KEY` in
`.env` and leaves them to find the key page themselves. `<ApiKeyHint
provider="openai" />` renders a muted one-line link under the snippet.

The component maps a provider id to a label and a URL, covering openai,
anthropic, google, langsmith and copilotkit. An unknown id renders
nothing, so a typo degrades to the current behaviour instead of
throwing. It is navigational only: it neither reads nor writes a key.

Both `.env` steps on the LangGraph quickstart use it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 20:41:24 -05:00
Benjamin Taylor 9157f27f9b feat(docs): persist the reader's code-tab choice across pages
`<Tabs groupId="..." persist>` is written on 101 tab groups in the docs
content tree, but the wrapper accepted both props and ignored them: the
comment in docs-tabs.tsx said so outright. Every page therefore reopened
on its own default, so a reader working through the LangGraph guide in
TypeScript had to reselect TypeScript on each page.

Fumadocs holds tab selection in local component state and exposes no
persistence hook, so the wrapper takes over the controlled
`value`/`onValueChange` pair and mirrors the pick into localStorage
under `shell-docs.tab.<groupId>`.

Selection precedence, strongest first:

  1. `urlDefault` — the framework-route override the docs page shell
     derives from the URL via TAB_DEFAULTS_BY_SLUG.
  2. A stored pick for the same `groupId`.
  3. The author's `default=` written in the MDX.
  4. The first item.

The page shell now passes its URL-derived value as a separate
`urlDefault` prop instead of overwriting `default`. Collapsing the two
into one prop would rank the author's default above storage, and 45 of
the 101 `persist` groups carry an author `default=` — the stored pick
would have been unreachable on almost half the pages the feature exists
for.

The stored value is read in an effect rather than in the initial state,
so server and client render the same markup. Reads and writes are
wrapped in try/catch: private-mode and quota errors leave the tabs
working without persistence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 20:41:24 -05:00
Ben Taylor 862ff3c180 fix(react-core): name the agent on CopilotKitProvider, warn when threads meet single-route (#6892)
Fixes OSS-1133

Rebased onto `main`. The branch was 205 commits behind, and two of its
three changes did not survive contact with current `main`. Both are
corrected here, so this description replaces the original one rather
than adding to it.

## What changed on `main` under this branch

**The single-route warning is gone.** The branch added a `useThreads`
development warning on the premise that "the thread routes live outside
the single-route envelope, so the list stays empty". That premise is no
longer true. `main` now carries thread, memory, and annotation
operations through the single-route endpoint with a `resource/request`
envelope (`fetch-handler.ts:405`), advertises it as
`singleRoute.resourceOperations` (`get-runtime-info.ts:177`), and the
client reads the thread endpoints from there (`agent-registry.ts:1367`).
A current single-route runtime serves threads, so the warning fired on a
working configuration.

Narrowing it does not rescue it either: when the transport is `single`
and the endpoints are still unavailable, the cause is a missing
Intelligence or thread backend, not the transport — the client cannot
tell those apart. The hook already surfaces the knowable fact through
`threadEndpointsError`. The warning, its three tests, and the
`useThreads.mdx` callout are dropped; `use-threads.tsx` and its test
file are now byte-identical to `main`.

**The docs' `useSingleEndpoint` claim is stale.** Both pages said
released versions of `<CopilotKit>` pin the flag to `true`. `dc73af1dc4`
removed that pin and is an ancestor of the `v1.70.2` release, which is
what `npm` serves today. Corrected on both pages.

## What this PR does

### `agentId` on `CopilotKitProvider`

```tsx
<CopilotKitProvider runtimeUrl="/api/copilotkit" agentId="my_agent">
```

`CopilotKitProvider` carries no agent prop at all, so the only way to
name an agent at the provider level is the v1 compatibility component.
The reporter had to read the installed type definitions to find that
`agentId` lives on `<CopilotChat>` instead.

The prop publishes a bare string context (`CopilotKitAgentIdContext` in
`src/v2/context.ts`) that is the **last** fallback before
`DEFAULT_AGENT_ID`. Five resolution sites consult it:
`CopilotChatConfigurationProvider` (which covers everything nested
inside a chat), `CopilotChat`, `CopilotThreadsDrawer`, `useAgent`, and
`useSuggestions`. An explicit `agentId` still wins at every one of them.

### Why not a root `CopilotChatConfigurationProvider`

The original branch published the default by rendering a
`CopilotChatConfigurationProvider` at the root. That provider also owns
a thread: it resolves a `threadId` (minting a UUID when none is given),
and the top-most one owns the imperative active-thread override.
Wrapping the application in one hands every descendant chat the same
inherited `threadId`, so two sibling chats share a transcript.

Measured on the original branch with `randomUUID` mocked to increment:

| | sibling chat 1 | sibling chat 2 |
| -- | -- | -- |
| `<CopilotKitProvider>` | `uuid-1` | `uuid-2` |
| `<CopilotKitProvider agentId="my_agent">` | `uuid-1` | `uuid-1` |

A bare string context carries the agent default and nothing else, so the
second row now matches the first.

### Docs

- `reference/components/CopilotKit.mdx`: the callout now says it is the
v1 provider and points at `CopilotKitProvider`, followed by the
agent-prop table. The `useSingleEndpoint` row is replaced by a sentence
saying both providers negotiate the transport, with the pre-1.70.2
behavior named as history.
- `docs/backend/runtime-endpoints.mdx`: the prop rename (`agent` →
`agentId`), and the transport table and its surrounding prose corrected
for the removed pin.
- `reference/hooks/useThreads.mdx`: back to `main` (see above).

I did not rewrite the integration quickstarts that show `<CopilotKit
agent=...>`. They already carry a "Which provider goes with which
handler?" callout and pass `useSingleEndpoint={false}` explicitly, so
they are correct as written; swapping the provider in all of them is a
docs sweep of its own.

## Testing

This worktree has its own full `pnpm install` and a rebuilt workspace
`dist`, so these numbers come from a clean environment on the rebased
tree.

### Whole-package suite

Both rows are real runs in this worktree on the same rebase base, taken
by checking `main`'s `packages/react-core/src` in and out around the
run:

| | Test files | Tests | Failed |
| -- | -- | -- | -- |
| `origin/main` (31d0cda168) | 146 passed | 1639 | 0 |
| This branch | 146 passed | **1646** | 0 |

Exactly +7. Comparing the two runs' JSON reports file by file,
`CopilotKitProvider.test.tsx` (39 → 46) is the only file whose count
moved.

### The 7 new tests

```
✓ CopilotKitProvider > agentId > becomes the default agent for a chat that does not name one
✓ CopilotKitProvider > agentId > lets a nested chat configuration override it
✓ CopilotKitProvider > agentId > leaves the global default in place when the prop is omitted
✓ CopilotKitProvider > agentId > publishes no chat configuration of its own
✓ CopilotKitProvider > agentId > follows a changed agentId
✓ CopilotKitProvider > agentId > thread isolation > gives sibling chats their own thread when agentId is set
✓ CopilotKitProvider > agentId > thread isolation > matches the no-agentId tree
```

### Mutation checks

| Mutation | Result |
| -- | -- |
| drop the `providerAgentId` fallback in
`CopilotChatConfigurationProvider` | `becomes the default agent for a
chat that does not name one` and `follows a changed agentId` fail (2
failed / 44 passed) |
| publish the default through a root `CopilotChatConfigurationProvider`
instead of the bare context | `publishes no chat configuration of its
own` and both `thread isolation` tests fail (3 failed / 43 passed) |

The second mutation is the original branch's implementation, so the
thread-isolation tests fail against the code they were written to catch.

### Build, typecheck, lint, format, MDX

- `nx build @copilotkit/react-core --skip-nx-cache`: succeeds.
`context-singleton-preflight: OK — src/v2/context.ts bundled only into 4
allowed target(s)` — the new `CopilotChatConfigurationProvider` →
`../context` import does not add a bundle target.
- `tsc --noEmit -p packages/react-core/tsconfig.json`: 0 errors.
- `oxlint` on the 7 changed source files: 0 errors, and the same 9
warnings before and after (measured by checking `main`'s copies into the
same tree).
- Formatted with `oxfmt`.
- Both changed `.mdx` files compile through `@mdx-js/mdx` with
`remark-gfm`, and all 9 string assertions in `docs-render.test.ts`
against `runtime-endpoints.mdx` still hold.
- `nx test @copilotkit/react-native --skip-nx-cache`: 26 passed, 0
failed (it consumes `react-core`).

## Unrelated CI fix carried here

`doc-tests` went red on this branch for a reason that has nothing to do
with it. `@ag-ui/mastra@1.1.3` was published on 2026-09-08 at 23:19:48Z
and raised its peer range for `@ag-ui/client`/`@ag-ui/core` to
`>=0.0.58`. The Mastra doctest pins both at `0.0.57` and left the
adapter floating, so npm takes 1.1.3 and the install fails with
`ERESOLVE`. Every other open PR's `doc-tests` run that passed completed
before that timestamp — the latest at 23:13:15Z — and this branch's run
at 23:45:20Z is the first one after it, so the break lands on every PR
from here.

The second commit pins the adapter at `1.1.2`, whose peer range
(`>=0.0.44`) the existing pins already satisfy. Bumping the client and
core instead does not work: `@copilotkit/runtime@1.68.3` hard-depends on
`@ag-ui/client@0.0.57`, so raising the snippet to `0.0.59` puts two
copies of `AbstractAgent` in the tree and the snippet fails `tsc
--noEmit` with `TS2769`. Measured locally both ways — version bump
21/22, adapter pin **22/22**.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added provider-level default agent selection through the `agentId`
prop on `<CopilotKitProvider>`.
- Descendant chats, threads, suggestions, and agent hooks now inherit
the provider’s agent unless overridden locally.
  - Preserved separate thread identities for sibling chats.

- **Documentation**
- Updated provider migration guidance, agent naming, and automatic
endpoint detection behavior.
- Added examples for provider, subtree, and per-chat agent
configuration.

- **Chores**
  - Pinned the Mastra integration example dependency to version 1.1.2.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 20:40:39 -05:00
Sam Julien 3d7258d1ba docs(shell-docs): curate default LLM index 2026-09-08 18:13:46 -07:00
Tyler Slaton 902d0faea5 Point the Channels docs at an SDK pair that can render components (#6952)
## The problem

Every Channels page that tells a reader what to install named a pair
that is four minors stale:

```sh
npm install --save-exact @copilotkit/channels@0.6.1 @copilotkit/runtime@1.65.0
```

That pin is not merely old, it is load-bearing in the wrong direction.
`@copilotkit/channels@0.6.1`
does not export `defineChannelComponent`. Compiling an agent-rendered
component against the version
our own quickstart installs fails outright:

```
error TS2724: '"@copilotkit/channels"' has no exported member named
'defineChannelComponent'. Did you mean 'ChannelComponent'?
```

The export listing confirms where the boundary sits.
`@copilotkit/channels-core@0.6.1` ships
`defineChannelCommand` and `defineChannelTool` and nothing else in that
family; `defineChannelComponent`
first appears in the 0.6.2 canary line and first ships stable in 0.7.0.

So the two halves of our own documentation disagree. The Channels setup
guide gates success on "at
least one `defineChannelComponent` must render," while the reference
page and both provider
quickstarts hand the reader a version in which that success criterion
cannot be satisfied. A builder
following the docs faithfully reaches a compile error, and the error
blames their code rather than
our pin. The bad trade they make next is guessing — dropping
`--save-exact`, reaching for `@latest`,
or abandoning agent-rendered components entirely, each of which discards
the tested-pair guarantee
the pin existed to provide.

The timing is what makes this worth a same-day fix rather than a queued
one. The "Agents, Everywhere"
global hackathon runs Saturday 12 September 2026 across 51 cities with
CopilotKit as a global
sponsor, and these are precisely the pages participants will open first.

## The approach

Every pinned pair in the Channels docs moves to
`@copilotkit/channels@0.9.2` +
`@copilotkit/runtime@1.70.2`, the current published pair as of
2026-09-08. Five install lines across
the reference index, the direct-adapters reference, the
deploy-and-operate how-to, and the Slack and
Teams quickstarts.

**The pin is what changes, not the prose.** Where a page's guidance
implies agent-rendered components
are available, that guidance was already correct — it was the version
underneath it that was wrong.
Nothing about the described behaviour is edited.

**The direct-adapters availability note moves too.** It read "their
direct adapters already ship in
`@copilotkit/channels@0.6.1`," an availability claim rather than a
first-shipped-in claim, sitting
directly above an install block that now names 0.9.2. Leaving it would
make the page contradict
itself within fifteen lines.

**The SDK reference index gains the tested-pair framing it was
missing.** The quickstarts and the
deploy-and-operate page already explain that the two packages ship as a
tested pair and must be
upgraded together; the reference index pinned exact versions while
explaining nothing, which is how a
pin decays into a number nobody knows they may not touch.

**One file outside the docs content changes, and the cost is worth
naming.**
`src/lib/__tests__/channels-docs.test.ts` asserts the quickstarts
contain the exact tested install
string, so it hard-codes the pair. Updating the docs without it produces
a red PR. Only the two
version constants move; no assertion is added, removed, or loosened.

## What is not covered

- **No recording.** The change is text in six files with no runtime
surface to demonstrate. The
durable evidence is the export listing above, which is reproducible from
the registry rather than
  from this branch.
-
`showcase/shell-docs/src/content/reference/channels/functions/createChannel.mdx:114`
still reads
"Channels 0.6.1 warns when enumerable fields are dropped." This is a
behaviour-provenance note, not
an install pin, and rewriting the number would change a factual claim
about when the behaviour
changed. It needs a maintainer to say whether it means "as of 0.6.1" or
"in 0.6.1."
- `skills/setup-slack-channel/SKILL.md:81` and
`skills/setup-slack-channel/references/troubleshooting.md:8`
reference `@copilotkit/channels@0.6.0` and `@copilotkit/runtime@1.65.0`
— an even older pin, and one
the guard test explicitly calls "the broken Channels 0.6.0 release."
Same class of bug, outside docs
  content, left for a separate decision.
- The three `doctest.json` files pin `@copilotkit/runtime@1.68.3`, also
stale, also a different
  purpose.
- `CopilotKit/channels-sdk` carries the same stale install line in
  `.agents/skills/build-channels-agent/SKILL.md`. Different repository.
- The docs do not document `defineChannelComponent` anywhere, despite
the setup guide gating success
  on it. That gap is not addressed here.
- The guard test could ratchet against 0.6.1 and 1.65.0 the way it
already ratchets against 0.5.0,
0.6.0, and 1.64.2, which would stop this recurring. Deliberately not
added, to keep the diff to the
  bug.

## Verification

Registry state re-checked at edit time: `npm view @copilotkit/channels
version` → `0.9.2`,
`npm view @copilotkit/runtime version` → `1.70.2`.

Export boundary confirmed by unpacking the published tarballs:
`channels-core@0.6.1` has no
`defineChannelComponent`; `0.6.2-canary.1785779327`, `0.7.0`, `0.7.1`,
and `0.9.2` all have it.

All 10 assertions in the `channels-docs` guard test's install and
Node-version blocks were replayed
against the edited files for both provider quickstart slugs — 20 checks,
all passing. The `--save-exact`
negative lookaheads still hold: the docs contain no unpinned
`@copilotkit/channels` or
`@copilotkit/runtime` install, no `@latest` or `@next` tag, and none of
the previously blocked 0.5.0,
0.6.0, or 1.64.2 versions.

`grep` across `showcase/shell-docs/src` returns no remaining
`channels@0.6.1` or `runtime@1.65.0`.

No new test files. No source, config, or lockfile changes.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated channel, Slack, Teams, and direct adapter setup guides with
the latest pinned SDK versions.
* Updated the channel reference documentation to reflect the current
package versions.

* **Tests**
* Updated documentation checks to validate the newer SDK versions in
provider quickstarts.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-09 03:04:42 +02:00
Benjamin Taylor edfc7c3e17 ci(doc-tests): pin @ag-ui/mastra so the quickstart snippet resolves
`@ag-ui/mastra@1.1.3` was published on 2026-09-08 and raised its peer range
for `@ag-ui/client` and `@ag-ui/core` to `>=0.0.58`. The Mastra doctest pins
both at `0.0.57` and left the adapter floating, so npm took 1.1.3 and every
doc-tests run after the publish failed with ERESOLVE. Runs that completed
before it passed; the break is not specific to any branch.

Pin the adapter at `1.1.2`, whose peer range (`>=0.0.44`) the existing pins
satisfy, rather than bumping the client and core. `@copilotkit/runtime@1.68.3`
hard-depends on `@ag-ui/client@0.0.57`, so raising the snippet to 0.0.59 puts
two copies of `AbstractAgent` in the tree and the snippet then fails
`tsc --noEmit` with TS2769 instead. Verified both ways locally: with the
version bump 21/22 pass, with this pin 22/22 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 18:54:04 -05:00
Benjamin Taylor e823409f96 fix(react-core): name the agent on CopilotKitProvider
`@copilotkit/react-core/v2` re-exports the v1 `<CopilotKit>` provider, and that
was the only provider carrying an agent prop. So a v2 application that wanted
to name its agent at the provider level had to reach for the v1 compatibility
component, and the reporter had to read the installed type definitions to find
that the v2 equivalent lives on `<CopilotChat agentId>` instead.

Accept `agentId` on `CopilotKitProvider`. It publishes a bare string context
that is the last fallback before `DEFAULT_AGENT_ID`, so `<CopilotChat agentId>`,
`<CopilotChatConfigurationProvider agentId>`, and an explicit `agentId` argument
to `useAgent`/`useSuggestions` all still win.

The default deliberately does NOT arrive through a root
`CopilotChatConfigurationProvider`. That provider also owns a thread: it
resolves a threadId, minting a UUID when none is given, and the top-most one
owns the imperative active-thread override. Wrapping the application in one
hands every descendant chat the same inherited threadId, so two sibling chats
share a transcript. A test renders two sibling chats under the provider and
pins that they keep their own threads.

Docs: say plainly on the `CopilotKit` reference page that it is the v1
provider, and note the prop rename on the provider-and-handler-pairs page.
Both pages claimed that released versions of `<CopilotKit>` pin
`useSingleEndpoint` to `true`; that pin was removed in 1.70.2, so both
providers now negotiate the transport when the prop is omitted.

Fixes OSS-1133

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 18:40:40 -05:00
Mike Ryan 591b3bcd53 docs: show the component tool imports for the built-in agent 2026-09-08 15:52:18 -07:00
Ben Taylor 407249d4fc fix(react-core): let a custom catch-all renderer return null (#6942)
## Summary

`useDefaultRenderTool`'s `render` was typed to return
`React.ReactElement`. A caller who wants to render only *some* tool
calls therefore could not return `null` to suppress the built-in default
for the rest — the value flowed through correctly at runtime, but the
type rejected it.

This widens the public `render` return type, and the wrapper local that
carries the user's value, to `React.ReactElement | null`.

```diff
-    render?: (props: DefaultRenderProps) => React.ReactElement;
+    render?: (props: DefaultRenderProps) => React.ReactElement | null;
```

The reference page hand-writes the same signature, so it is updated to
match, with one behavior bullet describing what `null` does.

## Scope, and its relationship to #6533

#6533 already widens the same return type to `React.ReactElement | null`
in `defineToolCallRenderer.ts` and `use-render-tool.tsx`. It does
**not** touch `use-default-render-tool.tsx`, which is the remaining gap
and the whole of this PR. There is **no file overlap**, so the two can
land in either order.

A structural sweep of `react-core/src/v2` for renders still typed `=>
React.ReactElement` with no `| null` confirms this leaves nothing behind
on this surface:

```
types/defineToolCallRenderer.ts:40,48,56   <- #6533
hooks/use-render-tool.tsx:41,72,109        <- #6533
hooks/use-default-render-tool.tsx:152      <- the deliberate bridge cast, below
hooks/use-interrupt.tsx:89                 <- different surface, out of scope
components/chat/CopilotChatMessageView.tsx:418  <- different surface, out of scope
```

The `as unknown as` cast into `useRenderTool` is deliberately left in
place: `useRenderTool` still requires a `ReactElement` return on `main`
(verified again after the rebase — `use-render-tool.tsx:41`). Once #6533
lands, that cast can be tightened. The bridge comment is updated to say
so.

`DefaultToolCallRenderer`'s own return type stays `React.ReactElement` —
the built-in default always renders an element.

The Vue counterpart needs no equivalent change: its `render` already
returns `VNodeChild`, which admits `null`, and
`reference/vue/hooks/useDefaultRenderTool.mdx` already matches.

## Why the guard is a type test, not a runtime test

TypeScript types are erased, so a `null`-returning render forwards
identically before and after the widening. The runtime test passes
against un-widened source, which makes it worthless as a guard for this
change. So the real guard is `use-default-render-tool-types.test-d.ts`,
using the `expectTypeOf` + `toEqualTypeOf` convention already documented
in `v2/__tests__/headless-type-exports.test-d.ts`.

`toEqualTypeOf` is required rather than assignability: a function
returning `ReactElement` **is** assignable to one returning
`ReactElement | null`, so an assignability check would pass against the
un-widened type and assert nothing.

The `.test-d.ts` basename is outside vitest's `include` globs, so
nothing there executes; `tsc --noEmit` (`check-types`) is what reads it.
Confirmed on this base:

```
$ vitest list --filesOnly | grep -c "test-d"
0
$ grep -n include -A4 packages/react-core/vitest.config.mjs
    include: [
      "src/**/__tests__/**/*.{test,spec}.{ts,tsx}",
      "src/**/*.{test,spec}.{ts,tsx}",
    ],
$ grep include packages/react-core/tsconfig.json
  "include": ["src/**/*"],
```

The runtime test is kept as well, since it still covers prop adaptation
and forwarding.

## Testing

All numbers below were re-measured after the rebase onto `main`
(`42494df`).

**Mutation check of the type guard** — revert the widening in the
source, confirm the guard goes red:

```
########## RUN A: rebased HEAD as-is ##########
total errors: 63
--- errors in touched files ---
  none

########## RUN B: MUTATION - widening reverted in source ##########
total errors: 65
--- guard file errors (expect FAIL) ---
use-default-render-tool-types.test-d.ts(26,3): error TS2344:
  Type '((props: DefaultRenderProps) => ReactElement<...> | null) | undefined'
  does not satisfy the constraint
  '"Expected: undefined, Actual: never" | "Expected: function, Actual: never"'.
use-default-render-tool.test.tsx(150,30): error TS2322:
  Type 'Mock<({ status }: DefaultRenderProps) => null>' is not assignable to
  type '(props: DefaultRenderProps) => ReactElement<...>'.
  Type 'null' is not assignable to type 'ReactElement<...>'.
```

The guard fails when the widening is reverted, and the two new errors
are exactly the guard plus the runtime test's own use of it. Nothing
else moves.

**Typecheck** (`tsc -p packages/react-core --noEmit`) — error set
byte-identical to pristine `origin/main` in the same worktree, none in
the touched files:

```
########## RUN C: pristine origin/main baseline ##########
total errors on pristine main: 63
=== diff: pristine-main errors vs HEAD errors ===
IDENTICAL -> the change introduces no new type errors
```

The 63 are pre-existing worktree noise: `react-core` resolves
`@copilotkit/core` and `@copilotkit/shared` from a sibling checkout's
`dist`, so unrelated exports read as missing. They are present on
pristine `origin/main` in the same worktree, which is what the diff
above shows.

**Target test file:**

```
 ✓ src/v2/hooks/__tests__/use-default-render-tool.test.tsx (13 tests) 38ms
 Test Files  1 passed (1)
      Tests  13 passed (13)
```

**Broader `src/v2/hooks` + `src/v2/types`** — failure counts identical
to pristine `origin/main` in the same worktree, plus exactly the one new
passing test:

```
=== BASELINE (pristine origin/main in this worktree) ===
 Test Files  22 failed | 17 passed (39)
      Tests  9 failed | 201 passed (210)

=== WITH my change ===
 Test Files  22 failed | 17 passed (39)
      Tests  9 failed | 202 passed (211)
```

**Lint:** `oxlint packages/react-core/src/v2/hooks/` — `Found 62
warnings and 0 errors.` (all pre-existing exhaustive-deps warnings, none
in the touched files).

**Formatting:** `oxfmt --check` on the three source/test files — `All
matched files use the correct format.` `oxfmt` does not process `.mdx`,
so the reference page is out of its scope.

**Public-API manifest:** no regeneration needed —
`scripts/release/public-api/manifest.v1.json` records no type signatures
and does not mention `useDefaultRenderTool` (`grep -c ReactElement` →
`0`).

## Provenance

Extracted from #5509 (@ataibarkai), which is 3915 commits behind `main`
and being closed. That PR also changed `defineToolCallRenderer`'s schema
default from `def.name === "*" && !def.args ? z.any() : def.args` to
`def.args ?? z.any()`. **That change is deliberately not carried here**
— it alters runtime behavior for named renderers declared without `args`
(from `args: undefined` to `args: z.any()`) and deserves its own PR and
its own verification.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Custom renderers can now return `null` to suppress output when no UI
should be displayed.

* **Documentation**
* Updated `useDefaultRenderTool` guidance to describe null-return
behavior and selectively rendering tool calls.

* **Tests**
* Added coverage confirming null-render behavior and forwarded renderer
properties.
  * Added compile-time validation for supported renderer return types.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 17:27:44 -05:00
Mike Ryan d950f00340 docs: fix MCP endpoint and native Codex setup 2026-09-08 15:24:47 -07:00
Benjamin Taylor 82cd7c01f7 fix(react-core): let a custom catch-all renderer return null
`useDefaultRenderTool`'s `render` was typed to return `React.ReactElement`,
so a caller who wanted to render only some tool calls could not return
`null` to suppress the built-in default for the rest. The value already
flowed through correctly at runtime; only the type rejected it.

Widen the public `render` return type, and the wrapper local that carries
the user's value, to `React.ReactElement | null`. The `as unknown as` cast
into `useRenderTool` stays, because `useRenderTool` still requires a
`ReactElement` return on main; PR #6533 widens that hook, after which the
cast can be tightened.

Guarded by a `.test-d.ts` assertion rather than a runtime test: types are
erased, so a null-returning render forwards identically before and after
the widening and a runtime test would assert nothing.

Extracted from #5509, which is otherwise stale.

Co-authored-by: Atai Barkai <atai.barkai@gmail.com>
2026-09-08 16:39:06 -05:00
Ben Taylor 30aba6b959 docs(showcase): state the frontend-tool requirement for the last nine frameworks (closes OSS-1036) (#6874)
## Problem

`generative-ui/tool-based` is the terminal page every onboarding run
fetches, on every framework route (OSS-1034). Its `## How it works in
code` section is one `<FrameworkSetup concept="frontend-tools-setup" />`
call that resolves a per-framework snippet. Nine frameworks shipped no
snippet, so the section rendered nothing and the `.md` output emitted
`<!-- setup skipped: ... -->`. That silence meant two different things
at once: "this framework needs no agent-side wiring" and "it needs
wiring and nobody wrote it down".

Verified on the live host before the change: all nine emitted the skip
comment, at ~2.4KB per page.

One of the nine is `built-in-agent`, which is `ROOT_FRAMEWORK`. So the
page carrying the gap included the unscoped default,
`https://docs.copilotkit.ai/generative-ui/tool-based.md`.

## Solution

A snippet for each of the nine. Each verdict was read out of the pinned
adapter rather than out of the docs, which is what the ticket asked for.

**Nothing to wire on the agent** — confirmed in the adapter:

| framework | the line that decides it |
| --- | --- |
| `ag2` | `autogen/ag_ui/adapter.py` `run_stream` builds `client_tools`
from `command.incoming.tools` |
| `mastra` | `@ag-ui/mastra@1.1.0` reduces `input.tools` into
`clientTools` for `agent.stream()` |
| `strands` | `ag_ui_strands@0.2.2` calls
`sync_proxy_tools(agent.tool_registry, input_data.tools, ...)` |
| `strands-typescript` | `@ag-ui/aws-strands@0.2.3` registers a proxy
tool per forwarded tool in `toolRegistry` |

Both Strands adapters refuse to overwrite a native tool of the same
name, so each snippet says to keep the `useComponent` name distinct.

**Real wiring:**

- `agno`. Its AG-UI interface never reads `RunAgentInput.tools`. Checked
against `agno==2.6.19`: the only tool path out of
`agno/os/interfaces/agui/` is
`RunPausedEvent.tools_awaiting_external_execution`. So a component needs
a declared `@tool(external_execution=True)` stub and the `Agent` needs a
`db` to hold the paused run.
- `deepagents`. `sdk-python/copilotkit/copilotkit_lg_middleware.py`
merges `copilotkit.actions` into `request.tools` inside
`wrap_model_call`, so `middleware=[CopilotKitMiddleware()]` is
load-bearing. Its snippet lives in the docs-only tree, because
`deepagents` has no integration package.

**Mode-dependent:**

- `built-in-agent`. Config mode merges `input.tools` for you
(`packages/runtime/src/agent/index.ts`). A factory owns the model call
and forwards nothing, so it has to pass them itself. Both halves are in
the snippet, plus the collision rule: a frontend tool whose name matches
a server tool is dropped in favor of the server executor.

**In-repo evidence only:**

- `ms-agent-dotnet`, `ms-agent-harness-dotnet`. Their own
`gen-ui-tool-based` agents render charts with an empty tool list
(`tools: []` / `Tools = []`) and their instructions name the chart
tools. No .NET SDK was available here to read
`Microsoft.Agents.AI.Hosting.AGUI.AspNetCore` directly.

Six of the nine snippets also carry the "Tell the model when to call it"
step, which is not filler. `GEN_UI_TOOL_BASED_PROMPT` in
`showcase/integrations/built-in-agent/src/lib/factory/demo-prompts.ts`
records what happens without it: the model emits `value: 0` for every
point and renders a chart with no bars.

## Tests

- `REQUIREMENT_NOT_ESTABLISHED` is now empty, and the docblock says a
new framework arriving without a snippet is fixed with a snippet, not
with a name.
- The shape test pins all six auto-forwarding frameworks, plus the three
that do not fit that shape (`agno`, `deepagents`, `built-in-agent`).
- `setup-concept.test.ts` used `ag2` as its example of an unbundled
concept, so closing the last gap would have turned it red for the right
reason. It now uses a concept name that is deliberately never bundled.

## The gate never ran in CI

Second commit. No workflow runs the shell-docs vitest suite:
`test_integration-docs.yml` runs exactly one test file,
`test_unit-showcase.yml` covers harness and shell-dashboard only, and
`showcase_build_check.yml` matches `showcase/**` but only builds images.
Neither path filter listed the snippet files either. So the ratchet
added in #6777 was local-only.

Added a scoped job and widened both filters. The job runs only the two
setup-concept files on purpose: the full shell-docs suite is not green
on `main`, and gating every snippet change on unrelated failures would
be worse than no gate.

## Verification

Ran against a local `shell-docs` dev server on this branch. Expected
`setup skipped` count is 0 everywhere:

```
ag2                        skip=0 bytes=3825
agno                       skip=0 bytes=4299
deepagents                 skip=0 bytes=3786
mastra                     skip=0 bytes=3857
ms-agent-dotnet            skip=0 bytes=3706
ms-agent-harness-dotnet    skip=0 bytes=4236
strands                    skip=0 bytes=4026
strands-typescript         skip=0 bytes=4001
built-in-agent (root path) skip=0 bytes=4723
```

`vitest run` on the two setup-concept files: 12 passed. `npm run
typecheck` and `npm run lint` both exit 0.

Four tests fail in the full shell-docs suite (`llm-text.test.ts` mastra
tool-rendering, three in `angular-docs-content.test.ts`). All four fail
identically at the pre-change baseline in the same worktree, so they are
pre-existing on `main` and untouched by this branch.

## Two findings this turned up, not fixed here

1. **The `agno` showcase demo contradicts its own snippet.** Every
`useFrontendTool` tool in agno's demos has a matching
`external_execution` stub, but the `useComponent` ones do not:
`render_bar_chart`, `render_pie_chart`, `query_notes` and
`highlight_note` have no backend declaration, and
`_run_main_agent_hitl_aware` in `src/agent_server.py` cannot forward
them. Its e2e spec cannot catch this, because it asserts only that an
`svg` is visible inside an assistant message, which any icon satisfies.
2. **Four frameworks redirect the HTML page away.** For `ag2`, `agno`,
`deepagents` and `mastra`, `/<slug>/generative-ui/tool-based` 301s to
`/<slug>/generative-ui/tool-rendering`. Confirmed on the live host as
well as locally, so it predates this branch. Their `.md` output serves
the page normally, which is the path onboarding runs fetch, but a human
browsing those four never reaches it.

Closes OSS-1036.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Added frontend tool setup guides for AG2, Agno, Built-in Agent,
Mastra, Microsoft Agent integrations, Strands, and Deep Agents.
- Documented tool registration, prompting, execution behavior,
persistence, and middleware configuration.

- **Tests**
- Expanded coverage for frontend tool setup documentation across
supported integrations.
- Updated setup concept tests to use a stable, intentionally unbundled
example.

- **Chores**
- Added automated workflow coverage for setup documentation and related
tooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 16:36:44 -05:00
Ben Taylor b0c0b50826 docs(microsoft-agent-framework): document backend approval interrupts (#6922)
Closes #2770.

## Problem

Our Microsoft Agent Framework human-in-the-loop page taught exactly one
pattern: register a frontend tool whose name matches a backend tool.
That is why #2770 was filed asking for a feature we already ship, and
why two more people asked for an update on it.

Backend-raised approvals have worked for months. Mark a tool with
`approval_mode="always_require"` (Python) or wrap it in
`ApprovalRequiredAIFunction` (.NET), and the agent ends the run with an
AG-UI interrupt that `useInterrupt` renders. No name matching. Nothing
on the docs site said so.

## What changed

Split the page the way Mastra's already is, and add the missing half:

- `human-in-the-loop/index.mdx` — picks between the two patterns. It
keeps `/microsoft-agent-framework/human-in-the-loop` resolving, so the
three existing pages that link there need no edit.
- `human-in-the-loop/interrupt-flow.mdx` — new; the approval path.
- `human-in-the-loop/tool-based.mdx` — the old page, retitled, content
unchanged.
- `custom-look-and-feel/headless-ui.mdx` — one sentence pointing backend
approvals at the new page.

The new page records four details that are easy to get wrong from
reading the source. I got each of them wrong myself before running it:

- `reason` is `"tool_call"`, not `"approval"`.
- The tool name and arguments live under `metadata.agent_framework`
**only on Python**. .NET sends no such field and names the tool in
`message`.
- `cancel()` and `resolve({ approved: false })` both leave the tool
unrun, but cancel ends the run while a false approval lets the agent
keep talking.
- `renderInChat` defaults to `true`, so the UI renders nothing —
silently, no warning — unless a `<CopilotChat />` is mounted.

## Testing

Every claim on the new page was executed, not inferred.

**End to end against a real agent.** Published `@copilotkit/react-core`
over real HTTP against a real Microsoft Agent Framework agent on
released `agent-framework-ag-ui` 1.2.2, with a tool marked
`approval_mode="always_require"`, served through the real AG-UI FastAPI
endpoint. A deterministic stub chat client stands in for the model, so
no API key is needed.

```
✓ CopilotKit <-> real Microsoft Agent Framework approval (2 tests)
  ✓ renders the backend approval and, on approve, the backend runs the tool
  ✓ on cancel, the backend does not run the tool
  Tests  2 passed (2)
```

Approving produced `TOOL_CALL_RESULT ... "content":"Deleted notes.txt."`
from the backend and surfaced it in the frontend. Cancelling produced no
tool result.

**Version floors are measured, not read off a changelog.** The same test
passes on `@copilotkit/react-core` 1.61.2 and fails on 1.61.1 (`Unable
to find an element by: [data-testid="reason"]`), which is where the
1.61.2 in the requirements table comes from. `agent-framework-ag-ui`
1.2.0 ships byte-identical interrupt-conversion logic to the 1.2.2 I
ran. `AGUI.Server` 0.0.6's shipped DLL contains the `tool_call` reason
and the `Approval required for tool call` message, and ag-ui's own
verified .NET baseline shows the same wire shape.

**Mutation-checked.** Changing the backend tool's return string fails
the approve test; clicking Approve in the cancel test fails it. An
earlier version of the cancel test passed under that mutation — it
settled with a bare `setTimeout` outside `act()` — so it was rewritten
to poll with `waitFor` and require a timeout.

**Docs suite.** Generators plus the node-environment tests that cover
routing and the nav tree:

```
 Test Files  4 passed (4)
      Tests  30 passed (30)
```
(`sitemap`, `page-tree-bridge`, `llms.txt`, `llms-mdx`)

All three routes appear in the generated search index, including the
preserved index URL:

```
microsoft-agent-framework/human-in-the-loop
microsoft-agent-framework/human-in-the-loop/interrupt-flow
microsoft-agent-framework/human-in-the-loop/tool-based
```

The jsdom-environment tests could not run locally — this checkout's
`showcase/shell-docs` install predates `jsdom`, and it resolves through
symlinks to the main checkout. CI covers them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added a Human-in-the-Loop section for Microsoft Agent Framework
integrations.
* Documented interrupt-based and tool-based workflows, including
approval, denial, cancellation, and frontend interaction guidance.
* Added details on approval-gated backend tools, interrupt payloads, and
rendering requirements.
  * Updated the tool-based guide’s title and description.
* Added the new section and page ordering to the documentation
navigation.
* Clarified how headless UI examples should render backend-tool
approvals.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 16:36:40 -05:00
Jerel John Velarde 1822de72da docs(channels): bump the tested SDK pair to channels 0.9.2 / runtime 1.70.2
The Channels pages pinned @copilotkit/channels@0.6.1 with
@copilotkit/runtime@1.65.0, four minors behind the current release.
Anyone following them installs a Channels version that predates
defineChannelComponent, which landed in 0.7.0, so agent-rendered
components cannot compile.

Update every pinned pair in the Channels docs to
@copilotkit/channels@0.9.2 + @copilotkit/runtime@1.70.2, refresh the
direct-adapters availability note that named 0.6.1, and add the
tested-pair framing to the SDK reference index, which pinned versions
without explaining that the two ship and upgrade together.

Also updates the pinned constants in the shell-docs guard test, which
asserts the quickstarts contain the exact tested install string.
2026-09-08 14:25:12 -07:00
Benjamin Taylor 0748b1a8e8 docs(showcase): explain the AgentCore 401 "Missing Authentication Token" (closes #2912)
Reporters following a framework quickstart and then pointing the runtime at a
deployed AgentCore endpoint hit `HTTP 401: Missing Authentication Token` with no
guidance anywhere in the docs. The string is AWS's own response to an unsigned
request or an unmatched route, so it reads like a CopilotKit failure when it is
not.

Add a Troubleshooting section covering the four causes: an unset
AGENTCORE_ACCESS_TOKEN interpolating to `Bearer undefined`, an expired Cognito
token, an AGENTCORE_ENDPOINT_URL that stops short of /invocations, and a browser
calling AgentCore directly instead of going through Copilot Runtime.

The AgentCore guide exists as two near-duplicate copies -- docs/deploy/agentcore.mdx
serves /deploy/agentcore, and snippets/integrations/agentcore/index.mdx is what
<Content framework="..." /> renders at /strands/deploy-agentcore and
/langgraph/deploy-agentcore. Both are live, so the section lands in both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 16:22:45 -05:00
Benjamin Taylor 5f8da811d9 docs(microsoft-agent-framework): document backend approval interrupts
Our Microsoft Agent Framework HITL page taught only the frontend-tool
approach, where the frontend registers a tool whose name matches a backend
tool. Backend-raised approvals have worked for months -- mark a tool with
approval_mode="always_require" (Python) or ApprovalRequiredAIFunction (.NET)
and the agent raises an AG-UI interrupt that useInterrupt renders -- but no
page said so, so readers kept reaching for name matching (issue #2770).

Split the page the way Mastra's is split and add the missing half:

- human-in-the-loop/index.mdx picks between the two patterns. It keeps the
  existing /microsoft-agent-framework/human-in-the-loop URL working, so the
  three pages linking there are untouched.
- human-in-the-loop/interrupt-flow.mdx documents the approval path.
- human-in-the-loop/tool-based.mdx is the old page, retitled.

The interrupt page records details that are easy to get wrong from reading
the code: reason is "tool_call" rather than "approval"; the tool name and
arguments sit under metadata.agent_framework only on Python, while .NET
names the tool in message; cancel() and resolve({approved:false}) both skip
the tool but end the turn differently; renderInChat defaults to true and
renders nothing, silently, with no chat mounted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 16:22:34 -05:00
github-actions[bot] 700fb1496b style: auto-fix formatting 2026-09-08 16:22:29 -05:00
Benjamin Taylor cf060da900 docs(showcase): state the frontend-tool requirement for the last nine frameworks (closes OSS-1036)
`generative-ui/tool-based` is the terminal page every onboarding run fetches,
and its `## How it works in code` section renders a per-framework snippet.
Nine frameworks shipped no snippet, so the section rendered nothing and the
silence meant both "no agent-side wiring is needed" and "wiring is needed and
nobody wrote it down".

Each verdict was read out of the pinned adapter rather than the docs:

- ag2: `run_stream` builds `client_tools` from `incoming.tools`.
- mastra: the adapter reduces `input.tools` into `clientTools`.
- strands, strands-typescript: a proxy tool per forwarded tool is registered
  in the agent's tool registry, and a native tool of the same name wins.
- agno: its AG-UI interface never reads `RunAgentInput.tools`, so a component
  needs an `external_execution=True` stub and a `db` for the paused run.
- deepagents: `CopilotKitMiddleware` merges `copilotkit.actions` into
  `request.tools`, so the middleware is load-bearing.
- built-in-agent: config mode forwards for you, a factory does not. It is also
  the root framework, so this is the unscoped default page.

The two .NET columns rest on their own demo agents, which render charts with
an empty tool list. No .NET SDK was available to read the NuGet hosting
package.

REQUIREMENT_NOT_ESTABLISHED is now empty. The shape test pins each snippet,
and setup-concept.test.ts no longer depends on ag2 being an open gap.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 16:22:29 -05:00
copilotkit-qa-bot[bot] 0f997c706e docs(strands): render subagent state in text export 2026-09-08 10:26:10 -07:00
Doniyor 62c895fee2 fix(react-core): default attachment uploads to one at a time
`maxConcurrentUploads` defaulted to 3, which changed when a public
`onUpload` is called with no code change on the app's side: a handler
written when uploads were serial could suddenly see the next file start
before the previous one finished. Concurrency is now something the app
asks for, and `maxConcurrentUploads: 3` restores the pool.

Queueing the whole selection up front is kept at every limit — it shows
the user what they picked rather than changing a contract.

The default test now pins one-at-a-time; a separate test pins that
`maxConcurrentUploads: 3` really runs three. Docs, the `AttachmentsConfig`
JSDoc and the react-core skill reference say `1`.
2026-09-07 15:02:30 +05:00
Doniyor c237f29dbb fix(react-core): share the upload pool across processFiles calls
The worker pool was per `processFiles` call, so a paste landing while a
dropped selection was still uploading opened its own set of workers —
two overlapping selections could run 2× the limit, and
`maxConcurrentUploads: 1` gave one upload per call rather than one at a
time.

Move the queue and the worker count onto the hook: workers are counted,
not owned by a call, and a call tops the pool up to the limit instead of
starting a fresh one. Each call still resolves when its own files have
settled.

Also pin `Infinity` as "no limit" with a test, and say in the docs that
the limit covers everything in flight rather than each batch.
2026-09-07 15:02:30 +05:00
Doniyor 62067b76d1 feat(react-core): upload attachments concurrently
`processFiles` walked the valid files in a `for` loop and awaited each
upload inside it, so `onUpload` was called for one file only after the
previous had finished — attaching 8 files to a chat cost 8 sequential
round trips to whatever storage the app uploads to.

Queue the whole selection first, then drain it with a bounded worker
pool: `maxConcurrentUploads` on `AttachmentsConfig` sets the bound and
defaults to 3, and `1` restores one-at-a-time uploads for an endpoint
that wants them. `onUpload` may now be called concurrently.

Queueing up front also means a file waiting for a free slot is already
visible as `uploading` rather than appearing once its upload starts.

The Vue and Angular bindings read the same config type and still upload
serially; they can follow separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 15:02:30 +05:00
Rainer Hahnekamp 0d46ef5fe7 Merge branch 'main' into feat/angular-copilot-activity 2026-09-06 21:53:17 +02:00
Tyler Slaton 9173ab479c fix(docs): address search accessibility and indexing review findings
Announce recommendation selection without invalid active descendants, omit
missing controlled elements, and cover empty-result and result-slot behavior.
Report snippet expansion failures and reject partially staged content roots
before either search index is overwritten.

Validation: 829 tests pass; three Angular/Mastra content failures already
reported in PR #6887 remain. Typecheck and lint pass (existing lint warnings).
Browser-verified local search, keyboard selection, and recommendation navigation.
2026-09-05 03:05:49 +02:00
Lukas Moschitz 45ac1b482b feat(docs): improve search ranking and recommend Intelligence guides 2026-09-05 03:05:49 +02:00
Lukas Moschitz c1086fe5fa fix(docs): index reachable pages across docs build contexts 2026-09-05 03:05:49 +02:00