Commit Graph

8571 Commits

Author SHA1 Message Date
Jordan Ritter 73adf05974 fix: google-adk gen-ui/shared-state + langroid adapter rewrite
google-adk gen-ui-tool-based: switch from CopilotSidebar to
CopilotChat so probe selectors find assistant messages.

shared-state fixture: use sequenceIndex matching instead of
toolCallId — Gemini handler synthesizes provider-specific IDs
that don't match fixed fixture strings.

langroid adapter: replace message flattening with proper
OpenAI-format conversion preserving tool_call_id and tool_calls
fields. Direct openai.AsyncOpenAI calls instead of langroid
ChatAgent, enabling aimock toolCallId fixture matching for the
frontend tool execution loop (gen-ui-headless show_card flow).
112 Python tests pass.
2026-04-28 01:56:41 -07:00
Jordan Ritter b07511833f fix: D5 probe fixes across google-adk, spring-ai, agno, llamaindex
google-adk:
- tool-rendering: use v2 `parameters` instead of `args` in render
- hitl-in-app: align tool name to request_user_approval with
  message/context params matching aimock fixtures
- headless-simple: add data-message-role attributes for probe
  selector cascade

spring-ai:
- Derive SPRING_AI_OPENAI_BASE_URL from OPENAI_BASE_URL in
  entrypoint.sh, stripping /v1 suffix

agno:
- Rename book_call parameter from attendee to name to match fixture

llamaindex:
- Add book_call frontend tool to agent router for hitl-text-input
2026-04-28 01:21:23 -07:00
github-actions[bot] 2e77f18732 style: auto-fix formatting 2026-04-28 08:04:40 +00:00
Jordan Ritter 7d57af878e fix: hitl-steps timeout + llamaindex aimock routing
Export HITL_CARD_TIMEOUT_MS (15s) from _hitl-shared and use it in
d5-hitl-steps selectorCascade calls — steps card and confirm button
both need the extended timeout for the full render chain.

Pass explicit api_base to llama_index OpenAI from OPENAI_BASE_URL env
var — the library does not read it automatically, so llamaindex was
bypassing aimock and hitting the real LLM.
2026-04-28 01:03:03 -07:00
Jordan Ritter 180c628efb fix: extend HITL card timeout to 15s, fix llamaindex book_call tool name
pickTimeSlot() was using the default 3s timeout but HITL cards go through
the same async chain (aimock→CopilotKit→frontend-tool→React-render) as
the approval dialog which already had 15s. Unified both to use a single
HITL_CARD_TIMEOUT_MS constant.

llamaindex hitl-in-chat registered "schedule_meeting" but the D5 fixture
sends "book_call" — tool call was silently dropped. Aligned to book_call
with the matching parameter schema (topic, name).
2026-04-28 00:50:31 -07:00
Jordan Ritter 1f3770214d fix: route google-adk through aimock, fix hitl-text-input mapping, add langgraph-python hitl page
- google-adk: all 22 agent files now call get_model() which returns a
  Gemini(base_url=...) instance when GOOGLE_GEMINI_BASE_URL is set,
  routing LLM calls through the aimock proxy on Railway
- d5-feature-mapping: remove gen-ui-interrupt from hitl-text-input
  mapping — gen-ui-interrupt uses useInterrupt (LangGraph interrupt
  events), not useHumanInTheLoop (tool calls), so the book_call fixture
  never fires and the probe always times out
- langgraph-python: add missing /demos/hitl page (StepSelector +
  StepsFeedback) so hitl-steps probe stops getting 404
2026-04-28 00:33:11 -07:00
Jordan Ritter 3072fc7532 fix: probe all-green round 2 — registry routes, qa files, popup selector (#4349)
## Summary

Four more fixes to push remaining probes toward green:

1. **Discovery source filters command-only demos** — `loadDemosMap()`
now skips demos without a `route` field in registry.json (e.g.,
`cli-start` which only has `command:`). Eliminates 8 false failures
across services.

2. **e2e-demos always uses registry resolver** — driver no longer
synthesizes `/demos/<id>` routes from the in-band `input.demos` string
array. Registry resolver is the source of truth for routes. Fixes `hitl`
→ `/demos/hitl` (wrong, should be `/demos/hitl-in-chat`) and
`hitl-in-chat-booking` → `/demos/hitl-in-chat-booking` (wrong, should be
`/demos/hitl-in-chat`).

3. **Missing qa files** — added `hitl.md` and `hitl-in-chat-booking.md`
for langgraph-python (copies of `hitl-in-chat.md` since all three demo
IDs point to the same page).

4. **Popup ready selector** — added
`[data-testid="copilot-chat-toggle"]` to the compound selector so
`prebuilt-popup` demos (where CopilotPopup starts closed with no visible
textarea) pass the structural check.

## Test plan

- [ ] e2e-demos: 28 unit tests pass
- [ ] railway-services discovery: 64 tests pass
- [ ] Docker build succeeds
- [ ] Deploy and trigger all 5 probes
- [ ] e2e-demos: 34/34
- [ ] qa: 1/1
2026-04-27 23:30:41 -07:00
Jordan Ritter b799d91e8c fix: add copilot-chat-toggle to e2e-demos ready selectors for popup demos 2026-04-27 23:29:58 -07:00
Jordan Ritter 63fbac1ea6 fix: add missing qa files for hitl and hitl-in-chat-booking demos 2026-04-27 23:28:06 -07:00
Jordan Ritter 95a53787a9 fix: always use registry resolver for e2e-demos route lookup
The in-band input.demos string array was synthesizing routes as
/demos/<id>, but actual registry routes differ (e.g. "hitl" maps to
/demos/hitl-in-chat). Now the registry resolver is always called first
as the source of truth. The in-band array only serves as a fallback
when the resolver returns empty (test injection path).
2026-04-27 23:27:05 -07:00
Jordan Ritter 1c222d1fb5 fix: filter command-only demos from discovery demos list 2026-04-27 23:24:08 -07:00
Jordan Ritter 2596191007 fix: probe all-green — compound selector, qa manifests, cron stagger (#4347)
## Summary

Three fixes to get all five probe types to green:

1. **e2e-demos compound selector** — replaced sequential selector loop
(where first non-matching selector consumed the full 30s budget) with a
compound CSS selector `READY_SELECTORS.join(", ")`. Headless demos with
`<textarea>` instead of `[data-testid]` now resolve in <5s instead of
timing out.

2. **qa probe Docker manifests** — added `COPY --from=build
/repo/showcase/packages ./showcase/packages` and `ENV QA_REPO_ROOT=/app`
to the Dockerfile runtime stage so the qa driver can find
`manifest.yaml` and `qa/` files.

3. **Cron stagger** — offset e2e-deep to `:05` and e2e-demos to `:10` to
avoid Chromium EAGAIN when co-firing with e2e-smoke's browser pool at
`:00`.

## Test plan

- [ ] e2e-demos compound selector: 28 unit tests pass
- [ ] Docker build succeeds locally (`--platform linux/amd64`)
- [ ] Deploy to Railway, trigger all 5 probes
- [ ] e2e-smoke: 34/34
- [ ] e2e-parity: 34/34
- [ ] e2e-demos: ~34/34
- [ ] qa: 1/1
- [ ] e2e-deep: improved (Category B fixed; Category A pre-existing)
2026-04-27 23:10:06 -07:00
Jordan Ritter 51040ae4f5 fix: stagger e2e-deep and e2e-demos cron to avoid Chromium EAGAIN
e2e-deep :05, e2e-demos :10 — prevents concurrent Chromium launches
with e2e-smoke's browser pool at :00/:30.
2026-04-27 23:07:46 -07:00
Jordan Ritter 2dd0d51c5d fix: use compound CSS selector in e2e-demos runDemo() 2026-04-27 23:02:02 -07:00
Jordan Ritter 4dd3d3d8d3 fix(showcase): wire regression detection, add cell drilldown, fix D5 probe bugs (#4345)
## Summary

- **Regression detection**: Wire up the Regressions tab in
shell-dashboard — `isRegression` in `depth-utils.ts` was hardcoded
`false`; now compares live `deriveDepth()` against
`CatalogCell.max_depth` static high-water-mark. Regressions filter in
cell-matrix shows real data, stats bar shows regression count.

- **Per-cell drilldown**: New `CellDrilldown` component surfaces the
full per-badge breakdown (health, e2e, smoke, d5, d6) with tone
indicators, `fail_count`, `first_failure_at`, and signal payloads on
cell click. Enhanced Gaps filter to include cells where probes are RED
(not just unshipped).

- **D5 probe fixes** (7 bug classes across 8 scripts):
- `hitl-text-input`: Add `data-testid="time-picker-slot"` to slot
buttons across 13 integration packages
- `shared-state`: Fix route mapping (both read/write →
shared-state-read-write), add polling for tool-call-only responses
- `subagents`: Replace one-shot assertion with 30s polling loop, add
`readAssistantTranscript` helper
- `gen-ui-custom`: Integration-aware branching (pie chart vs haiku),
structural assertion per path
- `hitl-approve-deny`: Fix selectors for google-adk approval dialog
overlay, add fallback selectors
- `tool-rendering`: Extract `validateProbe()`, add polling loop (200ms
interval, 10s timeout)
  - `hitl-steps`: Add `:not([disabled])` to confirm button selectors

- **CR fix**: Prevent click-outside handler racing with cell button
toggle in drilldown

## Test plan

- [x] 286 shell-dashboard tests pass (275 real + 4 pre-existing infra
failures)
- [x] 509 showcase-ops tests pass
- [x] 7-agent CR Round 1: 1 bucket (a) finding (click-outside race) —
fixed
- [x] 7-agent CR Round 2 (confirmation): 0 bucket (a) findings —
converged
- [ ] CI green
2026-04-27 23:00:53 -07:00
Jordan Ritter 68e66d6315 fix: copy showcase manifests into Docker runtime for qa probe 2026-04-27 23:00:46 -07:00
github-actions[bot] 9019477e5f style: auto-fix formatting 2026-04-28 05:37:06 +00:00
Jordan Ritter 199ecef079 fix(showcase): prevent click-outside handler racing with cell button toggle
The mousedown-based click-outside handler fired before the cell button's
onClick, clearing selectedCell and preventing the toggle-close path from
executing. Now the handler checks if the click target is inside a cell
button and defers to the button's own onClick for toggle logic.
2026-04-27 22:27:47 -07:00
Jordan Ritter d37aa2cc34 Merge remote-tracking branch 'origin/blitz/showcase-blue/B7' into blitz/showcase-blue/integration 2026-04-27 22:15:11 -07:00
Jordan Ritter 963836c7c3 Merge remote-tracking branch 'origin/blitz/showcase-blue/B6' into blitz/showcase-blue/integration 2026-04-27 22:15:08 -07:00
Jordan Ritter 459163d488 Merge remote-tracking branch 'origin/blitz/showcase-blue/B5' into blitz/showcase-blue/integration 2026-04-27 22:15:03 -07:00
Jordan Ritter 39ffa59527 Merge remote-tracking branch 'origin/blitz/showcase-blue/B4' into blitz/showcase-blue/integration 2026-04-27 22:15:00 -07:00
Jordan Ritter 8557d7fc9a Merge remote-tracking branch 'origin/blitz/showcase-blue/B3' into blitz/showcase-blue/integration 2026-04-27 22:14:57 -07:00
Jordan Ritter 7a71f3d8a3 Merge remote-tracking branch 'origin/blitz/showcase-blue/B2' into blitz/showcase-blue/integration 2026-04-27 22:14:53 -07:00
Jordan Ritter fa43127249 Merge remote-tracking branch 'origin/blitz/showcase-blue/B1' into blitz/showcase-blue/integration 2026-04-27 22:14:50 -07:00
Jordan Ritter 86720d8541 fix(showcase-ops): poll tool-rendering probe for card completion instead of single-shot snapshot
The D5 tool-rendering probe was failing on 6 integrations because the
conversation runner settles on assistant-message count stability, but
the TOOL_CALL_RESULT AG-UI event that transitions the render from
loading to complete may arrive after settlement. The old code did a
single DOM snapshot which caught the card in loading state (no numeric
temperature).

Replace the single-shot assertion with a polling loop (10s timeout,
200ms interval) that retries probeToolCard until all structural
sub-assertions pass (numeric temperature, "Tokyo" label, childCount
>= 1) or the deadline elapses.

Extract validateProbe() so the same validation logic is shared between
the poll loop and unit tests. Add 6 new tests covering the extracted
validator and the retry-on-loading-to-complete race condition (20
total, up from 14).
2026-04-27 22:14:01 -07:00
Jordan Ritter 12fbe96fc3 feat(shell-dashboard): add per-cell drilldown panel, enhance gaps filter, add failure count stat
Add clickable cell drilldown showing all 5 badge dimensions (health,
e2e, smoke, d5, d6) with tone, label, tooltip, and failure metadata
(fail_count, first_failure_at, signal payload) for red/amber badges.

Enhance Gaps filter to surface cells with RED probes as functional
gaps alongside structural gaps (unshipped cells).

Add Failures stat to StatsBar counting cells with red rollup.

Pass connection status through to CellMatrix for drilldown rendering.
2026-04-27 22:10:39 -07:00
Jordan Ritter 6697e49038 fix: resolve D5 gen-ui-custom and gen-ui-headless probe failures
gen-ui-custom (9 failures):
- Root cause: fixture/probe assumed all integrations use
  render_pie_chart (SVG donut), but only langgraph-python does.
  The other 16 integrations use generate_haiku/useFrontendTool
  (HaikuCard div). Fixture tool calls went unrendered.
- Fix: probe now branches on integrationSlug — sends pie chart
  message for LGP, haiku message for all others. Fixture carries
  both tool patterns. Structural assertion validates SVG chart
  shape (LGP) or HaikuCard with children+text (others). Haiku
  path skips narration check since useFrontendTool followUp:false
  prevents second-leg LLM round.

gen-ui-headless (3 failures):
- Fix: relaxed follow-up token check from requiring BOTH "card"
  AND "ada" to requiring EITHER one. The headless surface may
  combine tool-call and narration into a single assistant element,
  making exact token pairs fragile across timing variations.
2026-04-27 22:10:25 -07:00
Jordan Ritter aedbd45e3f fix: exclude disabled buttons from hitl-steps confirm cascade
The StepsFeedback component (rendered via useHumanInTheLoop) gates
its Confirm and Reject buttons with disabled={status !== "executing"}.
The probe's selectorCascade would resolve on the visible-but-disabled
button, then the click would silently no-op because browsers do not
dispatch click events on disabled elements.

Add :not([disabled]) to all three CONFIRM_BUTTON_SELECTORS entries so
the cascade waits for the button to become enabled (when the hook
status transitions to "executing") before resolving.
2026-04-27 22:08:02 -07:00
Jordan Ritter 3aef03c78f fix: driver consistency — abort classification, sideEmit dedup, resolveShape (#4344)
## Summary

Three driver consistency fixes identified during browser-pool CR
(#4343):

- **C5 abort classification**: e2e-deep, e2e-parity, and e2e-smoke
classified errors using `abortSignal.aborted` at catch time, which races
with genuine errors when the abort signal flips between throw and catch.
Now uses `err.name === "AbortError"` matching the pattern established in
e2e-demos.

- **C10 sideEmit dedup**: e2e-deep and e2e-parity logged
"writer-missing" on every `sideEmit` call when `ctx.writer` was absent.
Now uses `makeSideEmit(ctx)` factory with `warnedNoWriter` flag,
limiting to once per `run()` invocation — matching the pattern in
e2e-demos.

- **Shape resolution**: e2e-demos, e2e-deep, e2e-parity, and qa used raw
`input.shape === "starter"` which misses services discovered without an
explicit `shape` field. Now uses `resolveShape()` which also classifies
by service name — matching the pattern in e2e-smoke.

## Test plan

- [ ] 1320/1320 tests pass locally (66 test files)
- [ ] Typecheck clean (`tsc --noEmit`)
- [ ] oxfmt clean
- [ ] CI green
2026-04-27 22:07:19 -07:00
Jordan Ritter 57e0c6082a fix(showcase): add data-testid to time-picker slot buttons for D5 probes
The D5 hitl-text-input probe cascade expects
data-testid="time-picker-slot" on slot buttons inside the
TimePickerCard, but no demo component had this attribute. The
cascade fell through to a Playwright-specific button>>nth=0
selector that doesn't resolve reliably in all environments.

Add data-testid="time-picker-slot" to the slot <button> elements
in all 13 time-picker-card.tsx files across every integration
(ag2, agno, crewai-crews, langgraph-fastapi, langgraph-python x2,
langgraph-typescript, llamaindex, mastra, ms-agent-dotnet,
ms-agent-python, spring-ai, strands).

Also fix google-adk manifest: it declared hitl-in-chat but its
demo page at /demos/hitl renders a StepSelector (steps pattern),
not a TimePickerCard. Change the feature id to hitl so it maps
to the correct D5 hitl-steps probe instead of hitl-text-input.
2026-04-27 22:07:11 -07:00
Jordan Ritter f9e7f540c5 fix(showcase/ops): fix D5 shared-state probe route and tool-call handling
Two root causes fixed:

1. preNavigateRoute routed shared-state-read and shared-state-write to
   /demos/shared-state-read and /demos/shared-state-write respectively,
   but the actual working demo (with the bidirectional set_notes agent
   the fixture exercises) lives at /demos/shared-state-read-write. The
   split paths are either recipe-editor pages (wrong agent) or TODO
   stubs. Both feature types now route to /demos/shared-state-read-write.

2. Assertion readLatestAssistantText was called immediately after the
   conversation runner settled, but tool-call-only responses (where the
   LLM issues a set_notes tool call before producing visible text) can
   cause the runner to settle on a message with empty textContent. Added
   waitForNonEmptyAssistantText that polls for up to 3s when the initial
   read is empty, bridging the gap between the tool-call settle and the
   follow-up text leg matched by aimock's toolCallId fixture.

Manifest removal (fb66e6da7) was intentional: only google-adk and
langgraph-python have real shared-state-read-write implementations;
the other 16 packages had stubs correctly removed.
2026-04-27 22:06:11 -07:00
Jordan Ritter 6f25d7fe1a fix(showcase-ops): align D5 hitl-approve-deny probe selectors with actual component DOM
Three-pronged fix for the 8 failing D5 hitl-approve-deny probes:

1. Add approval-dialog-overlay as the primary selector in the dialog
   cascade. The overlay is the outermost portal'd element (direct child
   of <body>) and appears first in the DOM. Previously the cascade
   started with the inner dialog testid which was nested one level
   deeper.

2. Increase probe timeout for the approval dialog from 3s to 15s. The
   dialog only appears after the full aimock -> CopilotKit -> frontend
   tool handler -> React state -> useEffect -> createPortal chain
   completes. On Railway this regularly exceeded the default 3s
   SELECTOR_PROBE_TIMEOUT_MS. The selectorCascade function now accepts
   an optional timeoutMs parameter; approveOrDeny passes the extended
   APPROVAL_DIALOG_TIMEOUT_MS.

3. Fix google-adk approval-dialog.tsx to use canonical test IDs
   (approval-dialog-overlay, approval-dialog, approval-dialog-approve,
   approval-dialog-reject) matching all other 16 integrations. Also
   added role="dialog" and aria-modal="true" for accessibility parity.

Also added approval-approve / approval-reject to button cascades as
fallback selectors for any integration still running the old google-adk
style test IDs.
2026-04-27 22:05:45 -07:00
Jordan Ritter 2b67b92c6e fix: poll for chained reply text in d5-mcp-subagents probe
The conversation-runner's settle window (1500ms of stable assistant
message count) fires before the full sub-agent tool-call chain
completes because the assistant message element appears early and
its count stays at 1 throughout the chain. The one-shot assertion
then reads partial or empty text and fails.

Replace the one-shot document.body.innerText read with a polling
loop (up to 30s) that checks assistant-message DOM elements using
the canonical CopilotKit selectors, falling back to full page text.
This mirrors the readAssistantTranscript pattern from d5-agentic-chat
and gives the tool-call chain time to complete before failing.

Covers both mcp-apps and subagents feature types (same script).
2026-04-27 22:05:00 -07:00
Jordan Ritter 3b7f76c1b7 feat(shell-dashboard): wire up regression detection in depth ladder and regressions tab
Compare live achieved depth against CatalogCell.max_depth to detect
regressions. Wire the Regressions filter chip to actually filter rows,
compute real regression count in stats bar, and remove the hardcoded
empty state placeholder.
2026-04-27 22:01:48 -07:00
Jordan Ritter acf6874087 fix: use resolveShape for consistent starter classification 2026-04-27 21:48:31 -07:00
Jordan Ritter abf5a80233 fix: deduplicate sideEmit writer-missing warnings per run 2026-04-27 21:45:07 -07:00
Jordan Ritter 7852506f04 fix: classify abort errors by err.name instead of signal state 2026-04-27 21:44:05 -07:00
Jordan Ritter 3210a0a0ff Add source-available license to showcase (#4340)
## Summary

- Adds **CopilotKit Source Available License 1.0** to `showcase/LICENSE`
- Restricts showcase to personal, non-commercial viewing/study only
- Prohibits using the code as reference for building similar or
competitive systems (including clean-room and AI-assisted
reimplementation)
- Commercial use, derivative works, and distribution all require a
separate written license
- No patent rights granted; license is revocable by licensor

## Why

Showcase is the integration factory for CopilotKit — 17 frameworks, test
infrastructure, operational tooling. It lives in the public repo but
needs stronger protection than MIT. ELv2 was considered but is too
permissive (allows derivative works, grants patent rights, no
anti-reference clause).

## Test plan

- [x] LICENSE file renders correctly on GitHub
- [x] Does not affect any build, test, or CI pipeline
2026-04-27 17:37:17 -07:00
Jordan Ritter 9f77874f85 Add source-available license to showcase
CopilotKit Source Available License 1.0 — restricts showcase to
personal non-commercial viewing/study only. Commercial use,
derivative works, and using the code as reference for building
similar or competitive systems all require a separate license.
2026-04-27 17:36:13 -07:00
Sam Julien bb90c998b1 feat(shell-docs): JTBD information-architecture restructure (#4329)
## Summary

Restructures the top-level docs sidebar from feature-primitive sections
(Basics / App Control / Backend / Generative UI / Platform / Premium /
Troubleshooting) into 9 jobs-to-be-done sections that match how readers
describe what they want to build. Adds a 3-page Concepts primer under
Get Started, restores Migration Guides as a first-class section, merges
the docs landing with the legacy `/quickstart` picker into a single
page, collapses the per-framework landing into the same docs-landing
shell, drops the redundant Introduction sidebar entry, fixes
per-framework quickstart resolution, and tightens a few rendering
details that surfaced when the new structure went live.

### New 9-section sidebar

1. **Get Started** — quickstart, coding-agents, + Concepts subgroup (3
primers: architecture, three-types-of-gen-ui, oss-vs-enterprise)
2. **Build Chat UIs** — prebuilt-components, custom-look-and-feel,
multimodal-attachments
3. **Build Generative UI** — nested Controlled / Declarative /
Open-Ended subsections
4. **Give Your App Agent Powers** — frontend-tools, shared-state,
multi-agent/subagents, programmatic-control
5. **Agents & Backends** — built-in-agent (new), copilot-runtime,
custom-agent, ag-ui, runtime-server-adapter
6. **Observe & Operate** — inspector, vs-code-extension, +
Troubleshooting subgroup
7. **Enterprise** — premium/overview, premium/observability,
premium/self-hosting, threads (merged from former Threads section per
product call)
8. **Migrate** — v2, 1.10.X, 1.8.2 (moved out of Troubleshooting and
renamed to drop the redundant `migrate-to-` prefix)
9. **Other** — contributing, telemetry (unchanged)

Reference stays as a separate root-true tree, not surfaced through the
top-level meta.

The Quickstart sidebar entry is hidden until a framework is active
(URL-scoped or stored in localStorage). Without that, clicks on `/`
would land on a routing-shim page; with it, the entry appears as soon as
the user picks a framework and resolves to that framework's real
quickstart.

### Merged docs landing — `/` and `/<framework>` share one shell

`/` becomes the single docs-side entry. Always shown: hero, product
positioning, the `npx copilotkit@latest create` CLI command, three
utility cards (Concepts, API Reference, Generative UI). Below:
`DocsLandingNext` branches on the active framework — null shows "Pick
your agent framework" with the same categorized picker (Popular / Agent
Frameworks / Provider SDKs / Enterprise Platforms / Protocol / Emerging
/ Starter) that the old docs landing had; set shows "Continue with
{name}" + three pointer cards (quickstart for that framework, framework
landing, switch frameworks). The legacy `/quickstart` page is deleted
and 308-redirects to `/`. Per-framework `/<framework>/quickstart` guides
are unchanged.

`/<framework>` now renders the **same** docs-landing shell, with
`DocsLandingNext` reading the URL-active framework so the "Continue with
{name}" branch renders during SSR with no mount flicker. Replaces the
previous bespoke `FrameworkLandingPage` (a "You're viewing docs scoped
to" panel with a hardcoded 4-card grid) that drifted from the docs
landing. Switching framework is now a one-click flow that ends on a
familiar shell.

### Per-framework quickstart resolution

`/<framework>/quickstart` now serves the per-framework MDX from
`integrations/<docsFolder>/quickstart.mdx`. The framework-scoped router
previously resolved root MDX before per-framework overrides — correct
for most pages (root content rendered with per-framework snippets is the
primary path), but the new root `quickstart.mdx` is a routing shim that
exists only to give the sidebar entry a backing page. Special-cased the
`quickstart` slug so the override always wins for framework-scoped URLs.

While there, added the missing `crewai-crews → crewai-flows` docs-folder
mapping. The registry slug was renamed at some point but the docs folder
kept the older name, so `/crewai-crews/quickstart` couldn't find its
override.

### Removed redundant Introduction entries

Each integration's `meta.json` opened with a Getting Started section
containing `index` (rendered as "Introduction") and `quickstart`. The
override filter already drops sections and root-equivalent pages, so
`quickstart` was always filtered (root `quickstart.mdx` exists), but
`index` slipped through and rendered as an Introduction link to
`/<framework>/index` — duplicating `/<framework>` with a marketing-style
`<FrameworkOverview>` panel that didn't fit the new docs-routing shape.

Dropped the entire opening section from every framework's `meta.json`
and deleted the 12 orphaned `index.mdx` files (-849 lines). Also
flattened empty-title wrapper groups in `buildFrameworkOverridesNav` —
`buildNavTree` clears the title on a spread-derived group when the
preceding section header has the same name (so the renderer doesn't
double-print "Generative UI"), but the override filter then drops those
section headers, leaving titleless containers that only added an extra
indent step around their children. "Your Components" et al. now sit at
the level where "Generative UI" used to.

### Other changes

- **Three concept pages filled out** with explanation-layer content
sourced from existing repo material (`learn/architecture`,
`learn/generative-ui`, `learn/intelligence-platform`,
`ag-ui/concepts/architecture`, `premium/overview`) and from two
CopilotKit blog posts. Each page is a 5-minute primer that links into
the deeper `learn/*` pages — Diátaxis explanation tier, not how-to.
- **New built-in-agent.mdx at root** — 1-page summary that places BIA in
Agents & Backends as a peer to copilot-runtime / custom-agent, with a
link out to the full BIA-scoped docs at `/built-in-agent`.
- **Renderer dedup**: `buildNavTree` previously emitted both a section
node and a group node with the same title when a `---X---` header was
followed by `...x` spread. The renderers showed each one — users saw
`BUILD GENERATIVE UI` followed by `Build Generative UI` for the same
content. Now the inner group title is suppressed when it duplicates the
preceding section header.
- **`mergeFrameworkNav` anchor updated** for the renamed sections — the
framework-specific section (`Built-in Agent`, `LangGraph (Python)`,
etc.) lands between Give Your App Agent Powers and Agents & Backends,
same place it was relative to the agent-control region in the pre-JTBD
nav.
- **`framework-categories.ts` extraction** — `FRAMEWORK_CATEGORY_ORDER`
lifted out of `lib/docs-render` into a client-safe module so
`DocsLandingNext` (a client component) can import it without dragging
`fs` into the bundle. `lib/docs-render` re-exports for back-compat.
- **`SidebarLink.hideWhenUnscoped` prop** — when set and no framework is
active (URL or stored), the link returns null. Used for the new
Quickstart sidebar entry.
- **Reconciled gen-UI subgroup naming**: `Open` → `Open-Ended` to match
the concept page and `learn/generative-ui` (the other two subsections,
Controlled and Declarative, were already consistent).
- **5 redirects** in `next.config.ts`:
`/troubleshooting/migrate-to-{v2,1.10.X,1.8.2}` → `/migrate/*` for the
file moves, `/concepts/oss-vs-cloud` → `/concepts/oss-vs-enterprise` for
the rename, `/quickstart` → `/` for the merged landing.

## Test plan

- [ ] `/built-in-agent/quickstart` and `/langgraph-python/quickstart`
show the 9-section sidebar in the order above, with the
framework-specific section (`Built-in Agent` / `LangGraph (Python)`)
sitting between Give Your App Agent Powers and Agents & Backends.
- [ ] Build Generative UI shows nested Controlled / Declarative /
**Open-Ended** subsections (no extra `Build Generative UI` label inside
it).
- [ ] Migrate / Other render with single section labels (no doubled
header).
- [ ] Get Started shows Quickstart, Coding Agents, and a Concepts
subgroup with 3 entries (Architecture, Three Types of Generative UI, OSS
vs Enterprise). On `/` with no stored framework, the Quickstart sidebar
entry is hidden.
- [ ] `/concepts/architecture`, `/concepts/three-types-of-gen-ui`,
`/concepts/oss-vs-enterprise` render with their content; all internal
links inside resolve 200.
- [ ] `/built-in-agent` (root summary page) renders.
- [ ] `/` shows the merged landing: hero, CLI command, 3 utility cards,
then either the categorized framework picker (no stored framework, with
Popular / Agent Frameworks / etc. buckets) or "Continue with {name}"
pointers (stored framework) below.
- [ ] `/<framework>` (e.g. `/langgraph-python`, `/built-in-agent`)
renders the same docs-landing shell as `/` with the "Continue with
{name}" branch — no SSR-then-mount flicker.
- [ ] Clicking "Switch framework" on the merged landing flips back to
the picker.
- [ ] `/<framework>/quickstart` renders the per-framework quickstart MDX
(e.g. `/langgraph-python/quickstart` shows "Turn your LangChain agent
into..."), not the routing-shim copy.
- [ ] `/crewai-crews/quickstart` resolves correctly (docs-folder mapping
fix).
- [ ] Framework sidebar sections do not have an "Introduction" entry,
and "Your Components" sits one level shallower than before (no titleless
wrapper above it).
- [ ] `curl -I http://localhost:3003/quickstart` returns `308` with
`Location: /`.
- [ ] `curl -I http://localhost:3003/troubleshooting/migrate-to-v2`
returns `308` with `Location: /migrate/v2`. Same for the other two
migrate paths and `/concepts/oss-vs-cloud`.
2026-04-27 16:36:54 -07:00
github-actions[bot] 2e95ba75fc style: auto-fix formatting 2026-04-27 23:25:21 +00:00
github-actions[bot] 39d86aa872 style: auto-fix formatting 2026-04-27 16:24:06 -07:00
Sam Julien d1cd9f06a8 feat(shell-docs): collapse framework landing into the docs landing shell
Switching frameworks now lands on the same shell as / does, just with
the framework already URL-active. The /<framework> route renders the
docs-landing hero, CLI command, and utility cards (Concepts / API
Reference / Generative UI), then DocsLandingNext's "Continue with X"
branch with Quickstart / Browse {framework} docs / Switch framework
pointers. Replaces the previous bespoke FrameworkLandingPage that
showed a "You're viewing docs scoped to" panel and a hardcoded 4-card
grid (chat-ui / tool-rendering / frontend-tools / human-in-the-loop)
that drifted from the docs landing.

DocsLandingNext now prefers the URL-active framework over the stored
preference so /<framework> can render the "Continue with X" branch
during SSR with no mount-flicker — the previous storedFramework-only
gating caused a brief picker render before the localStorage effect
caught up.

Delete the orphaned per-framework index.mdx files. They were the
backing for the old sidebar Introduction entry (already removed) and
the URL /<framework>/index, which Next.js's optional catch-all
collapses to the bare framework path anyway. Their FrameworkOverview
content (banner video, init command, supportedFeatures grid) was a
legacy marketing-style landing that doesn't fit the new docs-routing
shape.
2026-04-27 16:23:40 -07:00
Sam Julien 4ab807c334 fix(shell-docs): drop redundant Introduction sidebar entry from framework sections
Each integration's meta.json opened with a "Getting Started" section
containing index (rendered as "Introduction") and quickstart. The
override filter already drops sections and root-equivalent pages, so
quickstart was always filtered (root quickstart.mdx exists), but
index slipped through and rendered as an Introduction link to
/<framework>/index — duplicating /<framework> with the marketing-style
FrameworkOverview content. Drop the entire opening section from every
framework's meta.json so the framework block in the sidebar starts at
the first framework-unique topic.

Also flatten empty-title wrapper groups in buildFrameworkOverridesNav.
buildNavTree clears the title on a spread-derived group when the
preceding section has the same name (so the renderer doesn't double-
print "Generative UI"). The override filter then drops those section
headers, leaving titleless containers that only added an extra indent
step around their children. Inline the children at the wrapper's
level instead, raising "Your Components" up where "Generative UI"
used to sit.
2026-04-27 16:23:40 -07:00
Sam Julien 7d1e806799 feat(shell-docs): hide sidebar Quickstart entry until a framework is active
The root /quickstart page is a routing shim — it has no real content,
just a pointer to the per-framework quickstarts. Showing it in the
sidebar on / leads users into a dead-end click ("This page is a
routing shim..."). Hide the entry until a framework is active in the
URL or stored in localStorage; once either is set, SidebarLink prepends
it and the click lands on real per-framework content.
2026-04-27 16:23:40 -07:00
Sam Julien 4711c7de06 fix(shell-docs): per-framework quickstart wins over routing shim
The framework-scoped route resolves root MDX before per-framework
overrides, which is correct for most pages — root content rendered
with framework-specific snippets is the primary path. But the new
root quickstart.mdx is a routing shim that exists only so the sidebar
entry has a backing page; real quickstart content lives per-framework
at integrations/<framework>/quickstart.mdx. Special-case the
quickstart slug so the override always wins for framework-scoped URLs.

While here, add the missing crewai-crews → crewai-flows docs-folder
mapping. The registry slug was renamed but the docs folder kept the
older name, so /crewai-crews/quickstart couldn't find the override.
2026-04-27 16:23:40 -07:00
Sam Julien b5632286db feat(shell-docs): restore categorized framework picker on docs landing
The merged landing's "no framework selected" branch previously showed a
flat IntegrationGrid. Swap it back to the categorized picker (Popular /
Agent Frameworks / Provider SDKs / …) so the docs root mirrors the same
shape users saw before the merge — the affordance to pick a backend is
unchanged from their perspective.

Also re-add the "Quickstart" sidebar entry so every framework has it.
The page itself is a routing shim; SidebarLink prepends the stored
framework, and direct hits to /quickstart 308 to /.

Extract FRAMEWORK_CATEGORY_ORDER into lib/framework-categories so the
client component can pull the constant without dragging fs-using
helpers from lib/docs-render through the bundle. docs-render
re-exports the constant so existing server-side imports keep working.
2026-04-27 16:23:40 -07:00
Sam Julien 8adbebd30b feat(shell-docs): merge docs landing + /quickstart picker into one page
The docs landing at `/` and the standalone `/quickstart` picker did
overlapping jobs and confused first-time users. "Quickstart" as a
top-level URL was misleading: clicking it from the shell landing or
the docs overview's top-card list led to a 23-line picker rather than
the actual quickstart guide (which lives at `/<framework>/quickstart`,
117–527 lines per framework).

Merge them. `/` becomes the single docs-side landing:

  - Always shown: hero + product positioning, the `npx copilotkit@latest
    create` CLI command (moved up from /quickstart), and three utility
    cards (Concepts, API Reference, Generative UI).
  - Conditional below: a new `DocsLandingNext` client component that
    branches on `storedFramework`. Null → "Pick your agent framework"
    + the integrations grid (the picker). Set → "Continue with
    {name}" + three pointer cards (quickstart for that framework,
    framework landing, switch frameworks).

The standalone `/quickstart` page is deleted; `/quickstart` 301-redirects
to `/`. `/<framework>/quickstart` is unchanged — that's the canonical
per-framework quickstart guide.

Side effects of the merge:

  - The unscoped catch-all's `DocsOverview` was rewritten to drop the
    former two-step "Pick a backend / Or jump into a topic" panels.
    The framework picker is now in `DocsLandingNext` (only when there's
    no stored choice); the topic cards (DOCS_SECTIONS) were a flatter
    duplicate of the new JTBD sidebar and got deleted entirely.
  - `content/docs/index.mdx` was the file that rendered at `/index`
    (reachable from a sidebar entry under Get Started). With the
    merged `/` landing serving as the canonical overview, the
    `/index` URL stops being meaningful — `index.mdx` is deleted and
    the entry is removed from the top-level `meta.json`.
  - `DocsLandingNext` is registered in the MDX components map so
    future pages can drop it inline if useful, but its primary use is
    inside `DocsOverview` itself.

Pairs with PDX-46 (BIA-as-default). Once BIA defaults are in, the
"no framework" branch of `DocsLandingNext` becomes rare and the page
reads as the "what's next" experience for nearly every visitor.

Closes PDX-58.
2026-04-27 16:23:40 -07:00
Sam Julien 3fe20fd9bd fix(shell-docs): rename gen-UI subgroup Open → Open-Ended
The concepts/three-types-of-gen-ui page and the canonical
learn/generative-ui/index page both use "Open-Ended" (with the
suffix) as the third gen-UI category alongside Controlled and
Declarative. The sidebar subsection had been shipped as just "Open"
in the JTBD reorg, leaving readers with three different namings
across the site ("Open" in nav, "Open-Ended" in concept page,
"Open-Ended" / "Fully Generated" in the learn page).

Align the sidebar to the canonical name. The other two subsections
("Controlled" and "Declarative") were already consistent.
2026-04-27 16:23:40 -07:00