Skip to content

Commit 449fbfd

Browse files
committed
fix copilotkitwrapper error
1 parent 778858b commit 449fbfd

1 file changed

Lines changed: 52 additions & 188 deletions

File tree

components/CopilotKitWrapper.jsx

Lines changed: 52 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
import "@copilotkit/react-ui/styles.css";
1717
import { useRouter } from "next/router";
1818
import { useCallback, useEffect, useMemo, useState } from "react";
19-
import { fetchAllGithubContent } from "../utils/fetchGithubContent";
2019
import {
2120
NavigationCard,
2221
ProductSelector,
@@ -165,8 +164,6 @@ routes from the PAGE ROUTE MAP above. NEVER invent routes that are not in the ma
165164
// ── Inner component (has access to CopilotKit context) ──────────────────
166165
function AppWithContext({ children }) {
167166
const router = useRouter();
168-
const enableGithubContext =
169-
process.env.NEXT_PUBLIC_ENABLE_GITHUB_CONTEXT === "true";
170167

171168
// ─ state ─────────────────────────────────────────────────────────────
172169
const [docsCtx, setDocsCtx] = useState(null); // parsed docs-context.json
@@ -219,11 +216,38 @@ function AppWithContext({ children }) {
219216
return `## ${currentPage.title} (CURRENT PAGE)\nURL: ${currentPage.url}\n\n${currentPage.content}`;
220217
}, [currentPage]);
221218

222-
// Extract headings from current page for suggestion generation
223-
const currentPageHeadings = useMemo(() => {
224-
if (!currentPage?.content) return [];
225-
const matches = currentPage.content.match(/^#{1,3}\s+.+$/gm) || [];
226-
return matches.map((h) => h.replace(/^#+\s+/, "")).slice(0, 8);
219+
const currentPageRelatedPages = useMemo(() => {
220+
const route = currentPage?.route || "/";
221+
222+
if (route === "/") {
223+
return [
224+
{ route: "/plan-your-integration", title: "Plan Your Integration" },
225+
{ route: "/android-terminals/overview", title: "Android Overview" },
226+
{ route: "/linux-terminals/getting-started", title: "Linux Getting Started" },
227+
];
228+
}
229+
230+
if (route.startsWith("/android-terminals")) {
231+
return [
232+
{ route: "/android-terminals/overview", title: "Android Overview" },
233+
{ route: "/android-terminals/set-up-integration", title: "Set Up Integration" },
234+
{ route: "/android-terminals/accept-card-payment", title: "Accept Card Payment" },
235+
];
236+
}
237+
238+
if (route.startsWith("/linux-terminals")) {
239+
return [
240+
{ route: "/linux-terminals/getting-started", title: "Linux Getting Started" },
241+
{ route: "/linux-terminals/transaction-flow", title: "Transaction Flow" },
242+
{ route: "/linux-terminals/best-practices", title: "Best Practices" },
243+
];
244+
}
245+
246+
return [
247+
{ route: "/plan-your-integration", title: "Plan Your Integration" },
248+
{ route: "/how-terminal-works", title: "How Terminal Works" },
249+
{ route: "/linux-terminals/getting-started", title: "Linux Getting Started" },
250+
];
227251
}, [currentPage]);
228252

229253
// ─ 1. Current page — highest priority ────────────────────────────────
@@ -241,23 +265,7 @@ function AppWithContext({ children }) {
241265
value: docsIndexText || "Loading documentation index…",
242266
});
243267

244-
// ─ 3. GitHub repo content — opt-in only because it is expensive to load ─
245-
useCopilotReadable(
246-
enableGithubContext
247-
? {
248-
description:
249-
"GITHUB REPOSITORY CONTENT — READMEs and key files from official Dspread repos. " +
250-
"Use exact code from this content when users ask about source code.",
251-
value: "GitHub context is enabled, but loaded only when the feature flag is on.",
252-
}
253-
: {
254-
description:
255-
"GITHUB REPOSITORY CONTENT is disabled by default to reduce runtime pressure.",
256-
value: "GitHub context disabled",
257-
}
258-
);
259-
260-
// ─ 4. Product model → category mapping (always available) ────────────
268+
// ─ 3. Product model → category mapping (always available) ────────────
261269
useCopilotReadable({
262270
description:
263271
"PRODUCT MODEL MAPPING — use this to identify which documentation section applies to the user's terminal model.",
@@ -285,21 +293,16 @@ Key differences:
285293
[router],
286294
);
287295

288-
// ─ Navigation action — AI calls this to jump to a docs page ──────────
289-
// Now with AGENTIC UI: renders a styled card inline in the chat.
290296
useCopilotAction({
291297
name: "navigateToPage",
292298
description:
293299
"Navigate the user's browser to a specific documentation page. " +
294-
"Call this EVERY TIME your answer relates to a specific page. " +
295-
"ONLY use routes from the PAGE ROUTE MAP. Valid routes: " +
296-
VALID_ROUTES.join(", "),
300+
"Use this whenever the answer relates to a specific docs route.",
297301
parameters: [
298302
{
299303
name: "route",
300304
type: "string",
301-
description:
302-
'The page route to navigate to. MUST be one of the valid routes from the PAGE ROUTE MAP. Example: "/android-terminals/accept-card-payment"',
305+
description: "The page route to navigate to.",
303306
required: true,
304307
enum: VALID_ROUTES,
305308
},
@@ -310,24 +313,6 @@ Key differences:
310313
required: true,
311314
},
312315
],
313-
handler: ({ route, pageTitle }) => {
314-
// Normalize: strip trailing slash for comparison
315-
const normalized = (route || "").replace(/\/+$/, "") || "/";
316-
if (!VALID_ROUTES.includes(normalized)) {
317-
// Find closest match
318-
const match = VALID_ROUTES.find((r) =>
319-
r.includes(normalized.split("/").pop())
320-
);
321-
if (match) {
322-
router.push(match);
323-
return `Navigated to "${pageTitle}" (${match}) [auto-corrected from ${route}]`;
324-
}
325-
return `Invalid route "${route}". Valid routes: ${VALID_ROUTES.join(", ")}`;
326-
}
327-
router.push(normalized);
328-
return `Navigated to "${pageTitle}" (${normalized})`;
329-
},
330-
// ── Agentic UI: show navigation card in chat ──
331316
render: ({ args, status }) => (
332317
<NavigationCard
333318
route={args?.route || "/"}
@@ -337,93 +322,54 @@ Key differences:
337322
),
338323
});
339324

340-
// ─ Product selector action — interactive product type picker ──────────
341-
// Uses renderAndWaitForResponse: the AI pauses while user picks a product.
342325
useCopilotAction({
343326
name: "selectProductType",
344327
description:
345-
"Show an interactive product type selector card. Call this when you need " +
346-
"the user to choose their product type (Smart POS, mPOS, Linux, Cloud Speaker) " +
347-
"and you want to present a visual picker instead of asking via text. " +
348-
"ONLY call this once at the start of a conversation when the product type is unknown.",
328+
"Show the interactive product selector when the user's device type is unknown.",
349329
parameters: [],
350330
renderAndWaitForResponse: ({ respond, status }) => (
351331
<ProductSelector respond={respond} status={status} />
352332
),
353333
});
354334

355-
// ─ Show related pages action — displays a grid of related pages ───────
356335
useCopilotAction({
357336
name: "showRelatedPages",
358337
description:
359-
"Show a card with related documentation pages. Call this when you want to " +
360-
"recommend multiple pages to the user, for example at the end of an answer. " +
361-
"Pass an array of pages with route and title.",
362-
parameters: [
363-
{
364-
name: "pages",
365-
type: "object[]",
366-
description: "Array of related pages to display",
367-
attributes: [
368-
{
369-
name: "route",
370-
type: "string",
371-
description: "Page route (must be a valid route from PAGE ROUTE MAP)",
372-
required: true,
373-
},
374-
{
375-
name: "title",
376-
type: "string",
377-
description: "Human-readable page title",
378-
required: true,
379-
},
380-
],
381-
required: true,
382-
},
383-
],
384-
handler: ({ pages }) => {
385-
return `Showing ${(pages || []).length} related pages.`;
386-
},
387-
render: ({ args, status }) => (
338+
"Show a lightweight card with related documentation pages.",
339+
parameters: [],
340+
render: ({ status }) => (
388341
<RelatedPagesCard
389-
pages={args?.pages || []}
342+
pages={currentPageRelatedPages}
390343
status={status}
391344
onNavigate={handleNavigate}
392345
/>
393346
),
394347
});
395348

396-
// ─ Progress/guide action — shows step-by-step integration guide ───────
397349
useCopilotAction({
398350
name: "showIntegrationGuide",
399351
description:
400-
"Show a step-by-step progress card for integration guidance. " +
401-
"Use this when walking a user through a multi-step process like " +
402-
"SDK setup, payment integration, or certification. " +
403-
"Provide the list of steps and the current step index (0-based).",
352+
"Show a simple step-by-step progress card for multi-step documentation flows.",
404353
parameters: [
405354
{
406355
name: "title",
407356
type: "string",
408-
description: "Title of the integration guide. E.g. 'Android SDK Setup'",
357+
description: "Guide title.",
409358
required: true,
410359
},
411360
{
412361
name: "steps",
413362
type: "string[]",
414-
description: "List of step descriptions in order.",
363+
description: "Ordered list of steps.",
415364
required: true,
416365
},
417366
{
418367
name: "currentStep",
419368
type: "number",
420-
description: "The index of the current step being worked on (0-based).",
369+
description: "Zero-based step index.",
421370
required: true,
422371
},
423372
],
424-
handler: ({ title, steps, currentStep }) => {
425-
return `Integration guide: "${title}" — step ${currentStep + 1} of ${(steps || []).length}`;
426-
},
427373
render: ({ args, status }) => (
428374
<ProgressCard
429375
title={args?.title || "Guide"}
@@ -434,118 +380,36 @@ Key differences:
434380
),
435381
});
436382

437-
// ─ Dynamic suggestion instructions based on current page ──────────────
438-
const suggestionInstructions = useMemo(() => {
439-
const pageTitle = currentPage?.title || "Overview";
440-
const route = currentPage?.route || "/";
441-
const headings = currentPageHeadings.length > 0
442-
? `\nThis page has these sections: ${currentPageHeadings.join(", ")}`
443-
: "";
444-
445-
// Determine which sibling/related pages to suggest
446-
let relatedSuggestions = "";
447-
if (route === "/" || !currentPage) {
448-
relatedSuggestions = `
449-
Suggest these topics (pick 3-5):
450-
- "I have a Smart POS (D30/D60), how do I start?"
451-
- "How do I set up a Linux terminal?"
452-
- "What's the difference between Smart POS and mPOS?"
453-
- "How do I integrate with a payment gateway?"
454-
- "I need help with EMV L3 certification"
455-
- "How does the Cloud Speaker work?"`;
456-
} else if (route.startsWith("/android-terminals")) {
457-
relatedSuggestions = `
458-
The user is reading Android terminal docs. Suggest questions about:
459-
- Accepting card payments (if not on that page)
460-
- Printing receipts (if not on that page)
461-
- Scanning QR/Bar codes (if not on that page)
462-
- Setting up the SDK (if not on that page)
463-
- Customizing the OS
464-
Also suggest 1-2 questions SPECIFIC to this page's content based on the headings.`;
465-
} else if (route.startsWith("/linux-terminals")) {
466-
relatedSuggestions = `
467-
The user is reading Linux terminal docs. Suggest questions about:
468-
- Getting started with Linux SDK (if not on that page)
469-
- Transaction flow details (if not on that page)
470-
- Common issues and troubleshooting
471-
- Best practices
472-
Also suggest 1-2 questions SPECIFIC to this page's content based on the headings.`;
473-
} else if (route === "/cloud-speaker") {
474-
relatedSuggestions = `
475-
The user is reading Cloud Speaker docs. Suggest questions about:
476-
- How to compile and build firmware
477-
- OTA update process
478-
- Device type configuration
479-
- How to set up the development environment`;
480-
} else if (route.includes("payment-gateway") || route.includes("key-management")) {
481-
relatedSuggestions = `
482-
The user is reading payment/encryption docs. Suggest questions about:
483-
- Decrypting POS terminal data with AWS
484-
- DUKPT key management
485-
- TR-31 key export/import
486-
- How to send encrypted data from the terminal`;
487-
} else if (route === "/emv-l3-testing") {
488-
relatedSuggestions = `
489-
The user is reading EMV L3 testing docs. Suggest questions about:
490-
- Which countries are supported for L3 certification
491-
- How to download test configurations for a specific country
492-
- What terminal models are supported
493-
- Firmware download for certification`;
494-
} else {
495-
relatedSuggestions = `
496-
Suggest 3-5 questions relevant to "${pageTitle}" based on the page content and headings.`;
497-
}
498-
499-
return `The user is currently on the "${pageTitle}" page (route: ${route}).${headings}
500-
501-
Generate 3-5 short suggestion buttons (under 50 characters each) that are SPECIFIC to this page's content.
502-
503-
IMPORTANT: When the user clicks a suggestion, your response MUST:
504-
1. Answer the question using content from the documentation
505-
2. Call the navigateToPage action if the answer relates to a different page
506-
${relatedSuggestions}
507-
508-
Make sure each suggestion is a natural question a developer would ask while reading this specific page.`;
509-
}, [currentPage, currentPageHeadings]);
510-
511-
// ─ Welcome suggestions — static product categories (before first message) ─
512383
useCopilotChatSuggestions({
513384
suggestions: [
514385
{
515386
title: "📱 Smart POS (Android)",
516-
message: "I'm using a Smart POS terminal (D20, D30, D50, D60, D70, D80, D80K). Help me get started with Android SDK integration.",
387+
message:
388+
"I'm using a Smart POS terminal (D20, D30, D50, D60, D70, D80, D80K). Help me get started with Android SDK integration.",
517389
className: "welcome-product-suggestion welcome-smartpos",
518390
},
519391
{
520392
title: "📲 mPOS / Mobile Reader",
521-
message: "I'm using an mPOS mobile reader (QPOS mini, QPOS Cute, CR100, QPOS Plus). Help me connect it to my app.",
393+
message:
394+
"I'm using an mPOS mobile reader (QPOS mini, QPOS Cute, CR100, QPOS Plus). Help me connect it to my app.",
522395
className: "welcome-product-suggestion welcome-mpos",
523396
},
524397
{
525398
title: "🐧 Linux Terminal",
526-
message: "I'm using a Linux terminal (D30-linux, QPOS-linux). Help me set up the Linux SDK.",
399+
message:
400+
"I'm using a Linux terminal (D30-linux, QPOS-linux). Help me set up the Linux SDK.",
527401
className: "welcome-product-suggestion welcome-linux",
528402
},
529403
{
530404
title: "🔊 Cloud Speaker",
531-
message: "I'm using a Cloud Speaker (DS10, DS50, DS200). Help me set up audio payment notifications.",
405+
message:
406+
"I'm using a Cloud Speaker (DS10, DS50, DS200). Help me set up audio payment notifications.",
532407
className: "welcome-product-suggestion welcome-cloudspeaker",
533408
},
534409
],
535410
available: "before-first-message",
536411
});
537412

538-
// ─ Contextual suggestions — dynamically generated per page (after 1st msg) ─
539-
useCopilotChatSuggestions(
540-
{
541-
instructions: suggestionInstructions,
542-
minSuggestions: 3,
543-
maxSuggestions: 5,
544-
available: "after-first-message",
545-
},
546-
[currentPath],
547-
);
548-
549413
return (
550414
<>
551415
<CopilotSidebar

0 commit comments

Comments
 (0)