Skip to content

Commit 0b4f68f

Browse files
authored
feat(showcase): align demo names + add Show Deprecated toggle (CopilotKit#4745)
Brings the dashboard's gold-standard view in line with the desired naming and surfaces deprecated rows behind a toggle (instead of dropping them at catalog generation). ## Summary - **28 renames in feature-registry.json + 20 in LGP `manifest.yaml`** — `name` and `demos[].name` aligned per the user-provided mapping. Same label everywhere so the dojo and dashboard agree. - **`Show deprecated` toggle in feature-grid.tsx** — checkbox in the matrix header, default OFF. Filters feature rows where `feature.deprecated === true`. Toggle ON surfaces all deprecated features across all integrations (audit trail); toggle OFF hides them so the gold-standard view stays clean. - **Reverted catalog-side filter from CopilotKit#4744** — the catalog now emits cells uniformly for all (integration × feature) pairs (back to 774 cells, 756 metadata.total_cells). Visibility is controlled at the dashboard layer. Toggling on shows complete cross-integration data without missing-cell artifacts. ## Naming highlights | Was | Now | |---|---| | Pre-Built CopilotChat | Pre-Built: CopilotChat | | Headless Chat (Simple/Complete) | Headless UI: Simple/Complete | | Multi-modal / File Uploads | Attachments | | Controlled Gen-UI (Display) | Generative UI: useComponent | | In-Chat HITL (useHumanInTheLoop / useInterrupt) | Human In the Loop: In-chat / Interrupts | | Headless Interrupt | Human in the Loop: Headless Interrupts | | Declarative Generative UI (A2UI — Dynamic / Fixed Schema) | Declarative UI: Dynamic / Fixed A2UI | | Fully Open-Ended Generative UI | Open Generative UI: Default | | Open-Ended Gen UI (Advanced ...) | Open Generative UI: Custom | | Tool Rendering (Default/Custom Catch-all/Specific) | Generative UI: Tool Rendering (...) | | Tool Rendering + Reasoning Chain | Generative UI: Rendering multiple tools | | Agentic Generative UI (...) | Generative UI: Agent State | | Frontend Tools (In-app / Async) | Frontend Tools: In-app Actions / Async | | In-App Human in the Loop (Frontend Tools + async HITL) | Human in the Loop: In-app | | Shared State (Read + Write / Recipe Editor) | Shared State: Read + Write / Read-only | | State Streaming | Shared State: Streaming | | Readonly State (Agent Context) | Shared State: Frontend Context | | BYOC Hashbrown / json-render | Declarative UI: Hashbrown / json-render | ## Deprecated toggle behavior 4 features marked `deprecated: true` in feature-registry.json: `agentic-chat-reasoning`, `hitl`, `hitl-in-chat-booking`, `reasoning-default-render`. - **OFF (default)**: rows hidden across the matrix - **ON**: rows render with normal cells. LGP shows N/A (unshipped) for the 4 since LGP doesn't declare them; other integrations show their actual probe state Header text shows `(N deprecated hidden)` when toggle is off. Toggle only renders when `deprecatedCount > 0`. ## Test plan - [x] `pnpm vitest run` in `showcase/scripts/__tests__/` → **18 / 18 passing** - [x] `pnpm vitest run` in `showcase/harness/` → **1588 / 1588 passing** - [x] `npx tsx showcase/scripts/validate-fixture-tool-surface.ts` → clean - [x] `npx tsx showcase/scripts/generate-registry.ts` → 18 integrations, 38 wired LGP, 774 cells - [ ] Verify the toggle on Vercel preview — it should appear in the matrix header, default unchecked, click expands rows by 4 (the 4 deprecated features rendering as new cells) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2 parents 7f50464 + 80a7f9a commit 0b4f68f

6 files changed

Lines changed: 126 additions & 124 deletions

File tree

showcase/integrations/langgraph-python/manifest.yaml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ demos:
7777
- chat-ui
7878
command: "npx copilotkit@latest init --framework langgraph-python"
7979
- id: agentic-chat
80-
name: "Prebuilt: CopilotChat"
80+
name: "Pre-Built: CopilotChat"
8181
description: Natural conversation with frontend tool execution
8282
tags:
8383
- chat-ui
@@ -100,7 +100,7 @@ demos:
100100
- src/app/demos/chat-customization-css/theme.css
101101
- src/app/api/copilotkit/route.ts
102102
- id: tool-rendering-default-catchall
103-
name: "Generative UI: Tool Rendering - Default"
103+
name: "Generative UI: Tool Rendering (Default)"
104104
description: Out-of-the-box tool rendering — backend defines the tools; the frontend adds zero custom renderers and relies on CopilotKit's built-in default UI
105105
tags:
106106
- generative-ui
@@ -111,7 +111,7 @@ demos:
111111
- src/agents/tool_rendering_agent.py
112112
- src/app/api/copilotkit/route.ts
113113
- id: tool-rendering-custom-catchall
114-
name: "Generative UI: Tool Rendering - Custom Default"
114+
name: "Generative UI: Tool Rendering (Custom default)"
115115
description: Single branded wildcard renderer via useDefaultRenderTool — the same app-designed card paints every tool call
116116
tags:
117117
- generative-ui
@@ -123,7 +123,7 @@ demos:
123123
- src/agents/tool_rendering_agent.py
124124
- src/app/api/copilotkit/route.ts
125125
- id: frontend-tools
126-
name: "Frontend Tools: In-App Actions"
126+
name: "Frontend Tools: In-app Actions"
127127
description: Agent invokes client-side handlers registered with useFrontendTool
128128
tags:
129129
- interactivity
@@ -146,7 +146,7 @@ demos:
146146
- src/app/demos/frontend-tools-async/notes-card.tsx
147147
- src/app/api/copilotkit/route.ts
148148
- id: hitl-in-chat
149-
name: "Human in the Loop: In-chat"
149+
name: "Human In the Loop: In-chat"
150150
description: Time-slot picker rendered inline in the chat via `useHumanInTheLoop` — the agent requests user input, the frontend renders a TimePickerCard, and the user's choice resumes the agent.
151151
tags:
152152
- interactivity
@@ -158,7 +158,7 @@ demos:
158158
- src/agents/hitl_in_chat_agent.py
159159
- src/app/api/copilotkit/route.ts
160160
- id: hitl-in-app
161-
name: "Human in the Loop: In-App"
161+
name: "Human in the Loop: In-app"
162162
description: Agent requests approval via useFrontendTool with an async handler; the approval UI pops up as an app-level modal OUTSIDE the chat, and a completion callback resolves the pending tool Promise with the user's decision
163163
tags:
164164
- interactivity
@@ -170,7 +170,7 @@ demos:
170170
- src/app/demos/hitl-in-app/approval-dialog.tsx
171171
- src/app/api/copilotkit/route.ts
172172
- id: tool-rendering
173-
name: "Generative UI: Tool Rendering - Specific"
173+
name: "Generative UI: Tool Rendering (Specific)"
174174
description: Custom per-tool renderers (WeatherCard, FlightListCard) plus a wildcard catch-all for every other tool
175175
tags:
176176
- generative-ui
@@ -183,7 +183,7 @@ demos:
183183
- src/app/demos/tool-rendering/flight-list-card.tsx
184184
- src/app/api/copilotkit/route.ts
185185
- id: tool-rendering-reasoning-chain
186-
name: "Generative UI: Tool Rendering + Reasoning Chain"
186+
name: "Generative UI: Rendering multiple tools"
187187
description: "Per-tool renderers (WeatherCard, FlightListCard, custom catchall) interleaved with a reasoningMessage slot rendering the agent's reasoning tokens — combines reasoning-display + tool-rendering in one chat surface."
188188
tags:
189189
- generative-ui
@@ -247,7 +247,7 @@ demos:
247247
- src/app/demos/shared-state-read-write/notes-card.tsx
248248
- src/app/api/copilotkit/route.ts
249249
- id: shared-state-read
250-
name: "Shared State: Read-Only Recipe Editor"
250+
name: "Shared State: Read-only"
251251
description: "Recipe editor publishes form state via agent.setState; the agent reads the recipe context but does not mutate it (no backend tool — neutral default agent)."
252252
tags:
253253
- agent-state
@@ -291,7 +291,7 @@ demos:
291291
- src/app/demos/prebuilt-popup/page.tsx
292292
- src/app/api/copilotkit/route.ts
293293
- id: chat-slots
294-
name: Chat Customization (Slots)
294+
name: "Chat Customization: Slots"
295295
description: Customize CopilotChat via its slot system
296296
tags:
297297
- chat-ui
@@ -354,7 +354,7 @@ demos:
354354
- src/agents/reasoning_agent.py
355355
- src/app/api/copilotkit/route.ts
356356
- id: gen-ui-interrupt
357-
name: "Human in the Loop: Interrupt based"
357+
name: "Human in the Loop: Interrupts"
358358
description: Interactive component rendered inline in the chat via the lower-level `useInterrupt` primitive — direct control over the LangGraph interrupt lifecycle
359359
tags:
360360
- interactivity
@@ -366,7 +366,7 @@ demos:
366366
- src/app/demos/gen-ui-interrupt/_components/time-picker-card.tsx
367367
- src/app/api/copilotkit/route.ts
368368
- id: interrupt-headless
369-
name: "Human in the Loop: Headless Interrupt"
369+
name: "Human in the Loop: Headless Interrupts"
370370
description: "Same interrupt(...) backend pattern as gen-ui-interrupt, but the time-picker mounts in a separate app-surface pane (left) instead of inline inside the chat — uses useHeadlessInterrupt (custom-event subscribe + manual runAgent forwardedProps.command.resume)."
371371
tags:
372372
- interactivity
@@ -377,7 +377,7 @@ demos:
377377
- src/app/demos/interrupt-headless/page.tsx
378378
- src/app/api/copilotkit/route.ts
379379
- id: declarative-gen-ui
380-
name: "Declarative UI: A2UI"
380+
name: "Declarative UI: Dynamic A2UI"
381381
description: Canonical A2UI BYOC — custom catalog (Card/StatusBadge/Metric/InfoRow/PrimaryButton) wired via a2ui.catalog on the provider; runtime injects the render_a2ui tool automatically
382382
tags:
383383
- generative-ui
@@ -391,7 +391,7 @@ demos:
391391
- src/app/demos/declarative-gen-ui/a2ui/renderers.tsx
392392
- src/app/api/copilotkit/route.ts
393393
- id: a2ui-fixed-schema
394-
name: "Declarative UI: A2UI (Fixed Schema)"
394+
name: "Declarative UI: Fixed A2UI"
395395
description: Render an A2UI tree from a fixed, server-side schema — the agent streams data into a pre-authored component tree
396396
tags:
397397
- generative-ui
@@ -417,7 +417,7 @@ demos:
417417
- src/app/demos/mcp-apps/page.tsx
418418
- src/app/api/copilotkit-mcp-apps/[[...slug]]/route.ts
419419
- id: readonly-state-agent-context
420-
name: Frontend Context Sharing
420+
name: "Shared State: Frontend Context"
421421
description: Frontend provides read-only context to the agent via useAgentContext
422422
tags:
423423
- agent-state
@@ -464,7 +464,7 @@ demos:
464464
- src/app/demos/beautiful-chat/hooks/use-generative-ui-examples.tsx
465465
- src/app/api/copilotkit-beautiful-chat/route.ts
466466
- id: multimodal
467-
name: Multimodal Attachments
467+
name: Attachments
468468
description: Image and PDF uploads via CopilotChat attachments, processed by a vision-capable agent
469469
tags:
470470
- chat-ui
@@ -518,7 +518,7 @@ demos:
518518
- src/app/demos/open-gen-ui/page.tsx
519519
- src/app/api/copilotkit-ogui/route.ts
520520
- id: open-gen-ui-advanced
521-
name: "Open Generative UI: Advanced"
521+
name: "Open Generative UI: Custom"
522522
description: Agent-authored UI that can invoke frontend sandbox functions from inside the iframe
523523
tags:
524524
- generative-ui
@@ -531,7 +531,7 @@ demos:
531531
- src/app/demos/open-gen-ui-advanced/suggestions.ts
532532
- src/app/api/copilotkit-ogui/route.ts
533533
- id: voice
534-
name: Voice Input
534+
name: Voice
535535
description: Speech-to-text via @copilotkit/voice with a bundled sample audio button
536536
tags:
537537
- chat-ui

showcase/scripts/__tests__/generate-catalog.test.ts

Lines changed: 18 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -109,22 +109,20 @@ describe("Catalog Generator", () => {
109109
(c: any) => c.manifestation === "starter",
110110
);
111111

112-
// 43 features x 18 integrations = 774 nominal, but 4 deprecated
113-
// features (agentic-chat-reasoning, hitl, hitl-in-chat-booking,
114-
// reasoning-default-render) are filtered when an integration's
115-
// manifest doesn't declare them — see deprecatedFeatureIds in
116-
// generate-registry.ts. LGP doesn't declare any of the 4 (gold-
117-
// standard reference uses the modern shape), so 4 LGP cells are
118-
// dropped: 774 - 4 = 770.
119-
expect(integrated.length).toBe(770);
112+
// 43 features × 18 integrations = 774 cells. The catalog emits cells
113+
// uniformly for all (integration × feature) pairs; deprecated-feature
114+
// visibility is controlled at the dashboard layer via the "Show
115+
// deprecated" toggle in feature-grid.tsx so the catalog stays
116+
// shape-stable.
117+
expect(integrated.length).toBe(774);
120118
expect(starters.length).toBe(0);
121-
expect(catalog.cells.length).toBe(770);
119+
expect(catalog.cells.length).toBe(774);
122120
// total_cells excludes docs-only features (currently 1 feature x 18 integrations = 18)
123-
expect(catalog.metadata.total_cells).toBe(752);
121+
expect(catalog.metadata.total_cells).toBe(756);
124122
expect(catalog.metadata.docs_only).toBe(18);
125123
});
126124

127-
it("LGP has 39 cells: 38 wired + 1 stub (deprecated features filtered)", () => {
125+
it("LGP has 43 cells: 38 wired + 1 stub + 4 unshipped (deprecated features included; dashboard hides them by default)", () => {
128126
runGenerator();
129127
const catalog = readCatalog();
130128

@@ -133,49 +131,19 @@ describe("Catalog Generator", () => {
133131
c.integration === "langgraph-python" &&
134132
c.manifestation === "integrated",
135133
);
136-
// 39 = 39 features in LGP manifest (the 4 deprecated features are
137-
// filtered out at catalog-generation time since LGP doesn't declare
138-
// them — see deprecatedFeatureIds in generate-registry.ts).
139-
expect(lgpCells.length).toBe(39);
134+
// 43 = 39 LGP-declared features + 4 deprecated features (cells
135+
// emitted as `unshipped` since LGP doesn't declare them in its
136+
// manifest). The dashboard's `Show deprecated` toggle in
137+
// feature-grid.tsx hides those rows by default.
138+
expect(lgpCells.length).toBe(43);
140139

141140
const wired = lgpCells.filter((c: any) => c.status === "wired");
142141
const stub = lgpCells.filter((c: any) => c.status === "stub");
143142
const unshipped = lgpCells.filter((c: any) => c.status === "unshipped");
144143

145144
expect(wired.length).toBe(38);
146145
expect(stub.length).toBe(1);
147-
expect(unshipped.length).toBe(0);
148-
});
149-
150-
it("deprecated features are emitted only for integrations that declare them", () => {
151-
runGenerator();
152-
const catalog = readCatalog();
153-
154-
// 4 features marked deprecated:true in feature-registry.json. LGP
155-
// doesn't declare any of them (modern-shape reference); other
156-
// integrations that DO declare them still get a cell so the
157-
// cross-integration audit trail is preserved.
158-
const deprecated = [
159-
"agentic-chat-reasoning",
160-
"hitl",
161-
"hitl-in-chat-booking",
162-
"reasoning-default-render",
163-
];
164-
165-
for (const feat of deprecated) {
166-
const lgpCell = catalog.cells.find(
167-
(c: any) => c.integration === "langgraph-python" && c.feature === feat,
168-
);
169-
expect(lgpCell).toBeUndefined();
170-
}
171-
172-
// ag2 declares agentic-chat-reasoning + hitl + reasoning-default-render
173-
// (per its manifest), so those cells exist.
174-
const ag2Acr = catalog.cells.find(
175-
(c: any) =>
176-
c.integration === "ag2" && c.feature === "agentic-chat-reasoning",
177-
);
178-
expect(ag2Acr).toBeDefined();
146+
expect(unshipped.length).toBe(4);
179147
});
180148

181149
it("stub detection: LGP/cli-start has stub status (demo exists, no route)", () => {
@@ -237,10 +205,8 @@ describe("Catalog Generator", () => {
237205
const catalog = readCatalog();
238206

239207
expect(catalog.metadata).toBeDefined();
240-
// total_cells excludes docs-only features (and deprecated-feature cells
241-
// that were filtered during catalog generation when an integration
242-
// didn't declare them).
243-
expect(catalog.metadata.total_cells).toBe(752);
208+
// total_cells excludes docs-only features
209+
expect(catalog.metadata.total_cells).toBe(756);
244210

245211
// Headline counts exclude docs-only cells; must sum to total_cells.
246212
expect(
@@ -340,7 +306,7 @@ describe("Catalog Generator", () => {
340306
);
341307
expect(lgpAgenticChat).toBeDefined();
342308
expect(lgpAgenticChat.integration_name).toBe("LangGraph (Python)");
343-
expect(lgpAgenticChat.feature_name).toBe("Pre-Built CopilotChat");
309+
expect(lgpAgenticChat.feature_name).toBe("Pre-Built: CopilotChat");
344310
expect(lgpAgenticChat.category_name).toBe("Chat & UI");
345311

346312
// All integrated cells must have non-null display names

showcase/scripts/generate-registry.ts

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -317,18 +317,13 @@ function generateCatalog(
317317

318318
// Deprecated features — consolidated/replaced patterns that LGP (the
319319
// gold-standard reference integration) intentionally does NOT implement,
320-
// but legacy integrations still serve. We only EMIT a cell for a
321-
// deprecated feature when the integration's manifest actively declares
322-
// it; integrations that don't claim it (notably the gold-standard
323-
// reference) get no row at all, so the dashboard's gold-standard view
324-
// doesn't render confusing X-marked rows for patterns LGP intentionally
325-
// skipped. The cross-integration audit trail is preserved on the
326-
// integrations that DO declare the feature.
327-
const deprecatedFeatureIds = new Set(
328-
featureRegistry.features
329-
.filter((f) => f.deprecated === true)
330-
.map((f) => f.id),
331-
);
320+
// but legacy integrations still serve. The catalog emits cells for all
321+
// (integration × feature) pairs uniformly; visibility is controlled at
322+
// the dashboard layer via a "Show deprecated" toggle that filters whole
323+
// FEATURE ROWS based on `feature.deprecated`. That way toggle-on
324+
// surfaces both the audit trail (integrations that declare these
325+
// legacy patterns) and the empty cells (LGP shows N/A for them) in one
326+
// pass without missing-data artifacts.
332327

333328
// Step 1: Cross-join to produce integrated cells and collect wired features
334329
// and unsupported features per integration.
@@ -345,16 +340,6 @@ function generateCatalog(
345340
for (const featureId of allFeatureIds) {
346341
const status = determineCellStatus(featureId, integration);
347342

348-
// Deprecated-feature filter: skip emitting the cell entirely when
349-
// the feature is deprecated AND this integration's manifest does
350-
// NOT declare it. The cell would otherwise render as an
351-
// unshipped/X row that's misleading — it implies LGP is missing
352-
// something it intentionally doesn't have. Integrations that DO
353-
// declare the deprecated feature still get their row (audit trail).
354-
if (deprecatedFeatureIds.has(featureId) && status === "unshipped") {
355-
continue;
356-
}
357-
358343
if (status === "wired") {
359344
wiredFeatures.add(featureId);
360345
}

0 commit comments

Comments
 (0)