Skip to content

Commit b02a0f6

Browse files
marthakellyclaude
andcommitted
fix(shell-docs): fix broken prebuilt-components and HITL code examples across 6 integrations
6 prebuilt-components pages were missing their PrebuiltComponents import, causing the inlineSnippets regex to skip them and drop the framework prop (iframe URLs defaulted to langgraph). 8 HITL pages had copy-pasted code examples using the deprecated v1 parameters array format instead of Zod schemas. Added a component-imports validation check to verify-shell-docs.ts to catch missing snippet imports going forward. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 14bb968 commit b02a0f6

15 files changed

Lines changed: 151 additions & 108 deletions

File tree

showcase/scripts/verify-shell-docs.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,101 @@ function aliasExists(importPath: string): boolean {
297297
);
298298
}
299299

300+
const SNIPPET_COMPONENTS = new Set([
301+
"A2UI",
302+
"AgUI",
303+
"AGUI",
304+
"CodingAgents",
305+
"CommonIssues",
306+
"CopilotRuntime",
307+
"CustomAgent",
308+
"DebugMode",
309+
"DisplayOnly",
310+
"ErrorDebugging",
311+
"FrontendTools",
312+
"FrontEndToolsImpl",
313+
"GenerativeUISpecsOverview",
314+
"HeadlessUI",
315+
"Inspector",
316+
"Interactive",
317+
"MCPApps",
318+
"MCPSetup",
319+
"MigrateTo",
320+
"MigrateTo1100",
321+
"MigrateTo182",
322+
"MigrateToV",
323+
"MigrateToV2",
324+
"Observability",
325+
"ObservabilityConnectors",
326+
"Overview",
327+
"PrebuiltComponents",
328+
"ProgrammaticControl",
329+
"ReasoningMessages",
330+
"SelfHosting",
331+
"Slots",
332+
"Threads",
333+
"ToolRenderer",
334+
"ToolRendering",
335+
"DefaultToolRendering",
336+
]);
337+
338+
// Matches the same shape that inlineSnippets() in docs-render.tsx can
339+
// resolve at render time: <Component /> or <Component components={...} />.
340+
// Any snippet component usage that doesn't match this pattern AND lacks
341+
// an explicit import will silently render nothing.
342+
const INLINE_SNIPPETS_RE = /<([A-Z]\w*)\s*(?:components=\{[^}]*\}\s*)?\/>/g;
343+
344+
// Catches snippet component usages with extra props (e.g. framework="...")
345+
// that the inlineSnippets regex can't handle.
346+
const SNIPPET_WITH_PROPS_RE = /<([A-Z]\w*)\s+[^>]*(?:>|\/>)/g;
347+
348+
const MDX_IMPORT_NAME_RE = /^\s*import\s+(\w+)\s+from\s+["']@\/snippets\//gm;
349+
350+
export function checkComponentImports(pages: PageInput[]): CheckResult {
351+
const failures: string[] = [];
352+
for (const page of pages) {
353+
const body = strip(page.body);
354+
355+
const imported = new Set<string>();
356+
MDX_IMPORT_NAME_RE.lastIndex = 0;
357+
let im: RegExpExecArray | null;
358+
while ((im = MDX_IMPORT_NAME_RE.exec(page.body)) !== null) {
359+
imported.add(im[1]);
360+
}
361+
362+
// Collect component usages that inlineSnippets() would handle
363+
const handledByInline = new Set<string>();
364+
INLINE_SNIPPETS_RE.lastIndex = 0;
365+
let m: RegExpExecArray | null;
366+
while ((m = INLINE_SNIPPETS_RE.exec(body)) !== null) {
367+
handledByInline.add(m[1]);
368+
}
369+
370+
// Find snippet components used with extra props
371+
SNIPPET_WITH_PROPS_RE.lastIndex = 0;
372+
const flagged = new Set<string>();
373+
while ((m = SNIPPET_WITH_PROPS_RE.exec(body)) !== null) {
374+
const name = m[1];
375+
if (
376+
SNIPPET_COMPONENTS.has(name) &&
377+
!imported.has(name) &&
378+
!handledByInline.has(name) &&
379+
!flagged.has(name)
380+
) {
381+
flagged.add(name);
382+
failures.push(
383+
`${page.path}: <${name}> used with props but missing snippet import`,
384+
);
385+
}
386+
}
387+
}
388+
return {
389+
name: "component-imports",
390+
status: failures.length === 0 ? "pass" : "fail",
391+
messages: failures,
392+
};
393+
}
394+
300395
async function main() {
301396
const skipBuild = process.argv.includes("--skip-build");
302397
const pages = loadPages();
@@ -310,6 +405,7 @@ async function main() {
310405
checkSnippetRegions({ pages, demoContent }),
311406
checkInternalLinks({ pages, knownRoutes }),
312407
checkImportPaths({ pages, existsOnDisk: aliasExists }),
408+
checkComponentImports(pages),
313409
runEssentialContentCheck(pages),
314410
];
315411

showcase/shell-docs/src/content/docs/integrations/adk/human-in-the-loop.mdx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,19 @@ Use frontend tools when you need your agent to interact with client-side primiti
5050
prompts the user for approval.
5151

5252
```tsx title="page.tsx"
53+
import { useHumanInTheLoop } from "@copilotkit/react-core/v2" // [!code highlight]
54+
import { z } from "zod"
5355

5456
export function Page() {
5557
// ...
5658

5759
useHumanInTheLoop({
5860
name: "offerOptions",
5961
description: "Give the user a choice between two options and have them select one.",
60-
parameters: [
61-
{
62-
name: "option_1",
63-
type: "string",
64-
description: "The first option",
65-
required: true,
66-
},
67-
{
68-
name: "option_2",
69-
type: "string",
70-
description: "The second option",
71-
required: true,
72-
},
73-
],
62+
parameters: z.object({
63+
option_1: z.string().describe("The first option"),
64+
option_2: z.string().describe("The second option"),
65+
}),
7466
render: ({ args, respond }) => {
7567
if (!respond) return <></>;
7668
return (

showcase/shell-docs/src/content/docs/integrations/ag2/human-in-the-loop.mdx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,27 +58,18 @@ Use frontend tools when you need your agent to interact with client-side primiti
5858

5959
```tsx title="page.tsx"
6060
import { useHumanInTheLoop } from "@copilotkit/react-core/v2" // [!code highlight]
61+
import { z } from "zod"
6162

6263
export function Page() {
6364
// ...
6465

6566
useHumanInTheLoop({
6667
name: "offerOptions",
6768
description: "Give the user a choice between two options and have them select one.",
68-
parameters: [
69-
{
70-
name: "option_1",
71-
type: "string",
72-
description: "The first option",
73-
required: true,
74-
},
75-
{
76-
name: "option_2",
77-
type: "string",
78-
description: "The second option",
79-
required: true,
80-
},
81-
],
69+
parameters: z.object({
70+
option_1: z.string().describe("The first option"),
71+
option_2: z.string().describe("The second option"),
72+
}),
8273
render: ({ args, respond }) => {
8374
if (!respond) return <></>;
8475
return (

showcase/shell-docs/src/content/docs/integrations/agent-spec/human-in-the-loop.mdx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,19 @@ Use frontend tools when you need your agent to interact with client-side primiti
6464
prompts the user for approval.
6565

6666
```tsx title="page.tsx"
67+
import { useHumanInTheLoop } from "@copilotkit/react-core/v2" // [!code highlight]
68+
import { z } from "zod"
6769

6870
export function Page() {
6971
// ...
7072

7173
useHumanInTheLoop({
7274
name: "offerOptions",
7375
description: "Give the user a choice between two options and have them select one.",
74-
parameters: [
75-
{
76-
name: "option_1",
77-
type: "string",
78-
description: "The first option",
79-
required: true,
80-
},
81-
{
82-
name: "option_2",
83-
type: "string",
84-
description: "The second option",
85-
required: true,
86-
},
87-
],
76+
parameters: z.object({
77+
option_1: z.string().describe("The first option"),
78+
option_2: z.string().describe("The second option"),
79+
}),
8880
render: ({ args, respond }) => {
8981
if (!respond) return <></>;
9082
return (

showcase/shell-docs/src/content/docs/integrations/agno/human-in-the-loop.mdx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,18 @@ Use frontend tools when you need your agent to interact with client-side primiti
8787

8888
```tsx title="page.tsx"
8989
import { useHumanInTheLoop } from "@copilotkit/react-core/v2" // [!code highlight]
90+
import { z } from "zod"
9091

9192
export function Page() {
9293
// ...
9394

9495
useHumanInTheLoop({
9596
name: "offerOptions",
9697
description: "Give the user a choice between two options and have them select one.",
97-
parameters: [
98-
{
99-
name: "option_1",
100-
type: "string",
101-
description: "The first option",
102-
required: true,
103-
},
104-
{
105-
name: "option_2",
106-
type: "string",
107-
description: "The second option",
108-
required: true,
109-
},
110-
],
98+
parameters: z.object({
99+
option_1: z.string().describe("The first option"),
100+
option_2: z.string().describe("The second option"),
101+
}),
111102
render: ({ args, respond }) => {
112103
if (!respond) return <></>;
113104
return (

showcase/shell-docs/src/content/docs/integrations/agno/prebuilt-components.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ icon: "lucide/SendHorizontal"
44
description: "Drop-in chat components for your Agno agent."
55
---
66

7-
<SharedContent framework="agno" />
7+
import PrebuiltComponents from "@/snippets/shared/basics/prebuilt-components.mdx";
8+
9+
<PrebuiltComponents components={props.components} framework="agno" />

showcase/shell-docs/src/content/docs/integrations/aws-strands/prebuilt-components.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ title: "Prebuilt Components"
33
icon: "lucide/SendHorizontal"
44
description: "Drop-in chat components for your AWS Strands agent."
55
---
6+
import PrebuiltComponents from "@/snippets/shared/basics/prebuilt-components.mdx";
7+
68
<PrebuiltComponents components={props.components} framework="aws-strands" />

showcase/shell-docs/src/content/docs/integrations/crewai-flows/prebuilt-components.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ icon: "lucide/SendHorizontal"
44
description: "Drop-in chat components for your CrewAI Flows agent."
55
---
66

7+
import PrebuiltComponents from "@/snippets/shared/basics/prebuilt-components.mdx";
8+
79
<PrebuiltComponents components={props.components} framework="crewai" />

showcase/shell-docs/src/content/docs/integrations/llamaindex/human-in-the-loop.mdx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,27 +94,18 @@ Use frontend tools when you need your agent to interact with client-side primiti
9494

9595
```tsx title="page.tsx"
9696
import { useHumanInTheLoop } from "@copilotkit/react-core/v2" // [!code highlight]
97+
import { z } from "zod"
9798

9899
export function Page() {
99100
// ...
100101

101102
useHumanInTheLoop({
102103
name: "offerOptions",
103104
description: "Give the user a choice between two options and have them select one.",
104-
parameters: [
105-
{
106-
name: "option_1",
107-
type: "string",
108-
description: "The first option",
109-
required: true,
110-
},
111-
{
112-
name: "option_2",
113-
type: "string",
114-
description: "The second option",
115-
required: true,
116-
},
117-
],
105+
parameters: z.object({
106+
option_1: z.string().describe("The first option"),
107+
option_2: z.string().describe("The second option"),
108+
}),
118109
render: ({ args, respond }) => {
119110
if (!respond) return <></>;
120111
return (

showcase/shell-docs/src/content/docs/integrations/llamaindex/prebuilt-components.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ title: "Prebuilt Components"
33
icon: "lucide/SendHorizontal"
44
description: "Drop-in chat components for your LlamaIndex agent."
55
---
6-
<PrebuiltComponents components={props.components} />
6+
import PrebuiltComponents from "@/snippets/shared/basics/prebuilt-components.mdx";
7+
8+
<PrebuiltComponents components={props.components} framework="llamaindex" />

0 commit comments

Comments
 (0)