Skip to content

Use the Kapa AI SDK instead of the Kapa AI widget #2113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open

Conversation

samejr
Copy link
Member

@samejr samejr commented May 28, 2025

This replaces the Kapa AI Javascript widget with their React SDK. This means:

  • It's fully skinned in our style
  • Still works with when triggered via a URL param
  • You can vote on answers which displays in the kapa dashboard
  • You can use the useAskAI hook to trigger it from anywhere in the app and pass it a payload 'answer'
  • Uses hCaptcha instead of reCaptcha (so now more floating captcha UI in the bottom right!)

Testing for Test Cloud

  • It uses a setTimeout delay when opening the DIalog to ensure hCaptcha doesn't think it's a bot. Make sure this works reliably
  • Test hCaptcha works reliability during normal use
  • Test votes come through to the kapa dashboard
  • Test shortcuts work
askai.mp4

Copy link

changeset-bot bot commented May 28, 2025

⚠️ No Changeset found

Latest commit: 3ddce5f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented May 28, 2025

Walkthrough

A new AI-powered chat interface system named "AskAI" was introduced, including React components, context providers, and hooks for managing chat state, modal dialogs, and user interactions. The legacy Kapa AI widget integration and its related hooks and scripts were removed. The navigation and root components were refactored to use the new AskAI system, updating feature detection and modal opening logic. Visual and accessibility improvements were made to dialog and shortcut key components, including styling updates and shortcut handling. A new animated gradient glow utility was added to the CSS. The package manifest was updated to include the @kapaai/react-sdk dependency. Additionally, a new SparkleListIcon React component was added to provide an SVG icon.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5606509 and 3ddce5f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • apps/webapp/app/components/navigation/SideMenu.tsx (4 hunks)
  • apps/webapp/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/webapp/package.json
  • apps/webapp/app/components/navigation/SideMenu.tsx
⏰ Context from checks skipped due to timeout of 90000ms (25)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/webapp/app/components/AskAI.tsx (3)

91-93: Consider making the hCaptcha delay configurable.

The 1000ms delay is hardcoded. Consider making this configurable through props or environment variables to allow for adjustment based on different environments or testing needs.

+const HCAPTCHA_DELAY_MS = process.env.HCAPTCHA_DELAY_MS || 1000;

      // Add a delay to avoid triggering hCaptcha bot detection
      setTimeout(() => {
        openAskAI(decodedAiHelp);
-      }, 1000);
+      }, HCAPTCHA_DELAY_MS);

306-310: Extract duplicate feedback logic into a helper function.

The feedback handling logic is duplicated for upvote and downvote actions.

+                const handleFeedback = (reaction: "upvote" | "downvote") => {
+                  const latestQA = conversation[conversation.length - 1];
+                  if (latestQA?.id) {
+                    addFeedback(latestQA.id, reaction);
+                    setFeedbackGivenForQAs((prev) => new Set(prev).add(latestQA.id));
+                  }
+                };
+
                 <div className="flex items-center">
                   <Button
                     variant="minimal/small"
-                    onClick={() => {
-                      const latestQA = conversation[conversation.length - 1];
-                      if (latestQA?.id) {
-                        addFeedback(latestQA.id, "upvote");
-                        setFeedbackGivenForQAs((prev) => new Set(prev).add(latestQA.id));
-                      }
-                    }}
+                    onClick={() => handleFeedback("upvote")}
                     className="size-8 px-1.5"
                   >
                     <HandThumbUpIcon className="size-4 text-text-dimmed transition group-hover/button:text-success" />
                   </Button>
                   <Button
                     variant="minimal/small"
-                    onClick={() => {
-                      const latestQA = conversation[conversation.length - 1];
-                      if (latestQA?.id) {
-                        addFeedback(latestQA.id, "downvote");
-                        setFeedbackGivenForQAs((prev) => new Set(prev).add(latestQA.id));
-                      }
-                    }}
+                    onClick={() => handleFeedback("downvote")}
                     className="size-8 px-1.5"
                   >

Also applies to: 319-323


539-539: Remove the extra empty line at the end of the file.

-
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 021d6d8 and 5606509.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • apps/webapp/app/assets/icons/SparkleListIcon.tsx (1 hunks)
  • apps/webapp/app/components/AskAI.tsx (1 hunks)
  • apps/webapp/app/components/navigation/SideMenu.tsx (4 hunks)
  • apps/webapp/app/components/primitives/Dialog.tsx (1 hunks)
  • apps/webapp/app/components/primitives/SheetV3.tsx (1 hunks)
  • apps/webapp/app/components/primitives/ShortcutKey.tsx (1 hunks)
  • apps/webapp/app/hooks/useKapaWidget.tsx (0 hunks)
  • apps/webapp/app/root.tsx (2 hunks)
  • apps/webapp/app/tailwind.css (2 hunks)
  • apps/webapp/package.json (4 hunks)
💤 Files with no reviewable changes (1)
  • apps/webapp/app/hooks/useKapaWidget.tsx
🧰 Additional context used
🧬 Code Graph Analysis (5)
apps/webapp/app/components/primitives/SheetV3.tsx (1)
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)
  • ShortcutKey (38-55)
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)
apps/webapp/app/utils/cn.ts (1)
  • cn (30-32)
apps/webapp/app/root.tsx (1)
apps/webapp/app/components/AskAI.tsx (1)
  • AskAIProvider (60-125)
apps/webapp/app/components/primitives/Dialog.tsx (1)
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)
  • ShortcutKey (38-55)
apps/webapp/app/components/navigation/SideMenu.tsx (4)
apps/webapp/app/hooks/useFeatures.ts (1)
  • useFeatures (5-9)
apps/webapp/app/root.tsx (1)
  • loader (42-64)
apps/webapp/app/components/AskAI.tsx (1)
  • useAskAI (47-53)
apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx (1)
  • HelpAndFeedback (26-191)
🪛 Biome (1.9.4)
apps/webapp/app/components/AskAI.tsx

[error] 256-256: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (23)
apps/webapp/app/assets/icons/SparkleListIcon.tsx (1)

1-14: LGTM! Clean and well-structured icon component.

The implementation follows React best practices with proper TypeScript typing, optional className prop for styling flexibility, and uses currentColor for theme compatibility. The SVG structure is well-formed with appropriate paths and rectangles.

apps/webapp/app/tailwind.css (2)

8-12: LGTM! Proper CSS custom property definition.

The @property syntax is correctly used to define the --gradient-angle custom property with appropriate syntax, initial value, and inheritance behavior.


49-83: LGTM! Well-implemented animated gradient utility.

The animated gradient glow utility is well-structured with:

  • Proper positioning and overflow handling
  • Efficient pseudo-element approach for the background effect
  • Smooth conic-gradient animation with reasonable performance characteristics
  • Appropriate use of pointer-events: none to prevent interaction issues
  • Good balance of blur and opacity for the glow effect
apps/webapp/app/components/primitives/SheetV3.tsx (1)

94-104: LGTM! Platform-specific shortcut structure improves consistency.

The update to use explicit windows and mac shortcut definitions enhances consistency with the ShortcutKey component's capabilities, even though both platforms use the same "esc" key in this case. This provides better clarity and maintains consistency with other shortcut usage patterns.

apps/webapp/app/components/primitives/ShortcutKey.tsx (2)

16-16: LGTM! Improved semantic color naming for small variant.

The change from border-dimmed/40 to border-text-dimmed/40 (and corresponding hover effects) improves semantic naming and maintains visual consistency.


17-17: LGTM! Proper use of utility function for class composition.

Using the cn utility to combine the base medium styles with the additional hover effect (group-hover:border-charcoal-550) is the correct approach for composing Tailwind CSS classes while handling potential conflicts.

apps/webapp/app/root.tsx (3)

3-3: Clean import optimization.

Good removal of unused imports (useMatches, useTypedMatchesData, KapaScripts) as part of the migration from the old Kapa widget to the new AskAI system.


9-9: Proper integration of AskAIProvider.

The import aligns with the new AI chat system implementation.


111-116: Well-structured provider integration.

The AskAIProvider is properly positioned at the root level and correctly receives the websiteId from the loader data. The conditional || null ensures type safety when kapa.websiteId is undefined. The nested component structure maintains the existing hierarchy while providing the new AI context.

apps/webapp/app/components/primitives/Dialog.tsx (1)

53-67: Excellent UI improvements to the dialog close button.

The refactoring brings several enhancements:

  • Simplified structure by removing unnecessary wrapper div
  • Better hover coordination using group and group-hover: classes
  • More explicit shortcut key definition with platform-specific variants
  • Improved positioning and spacing with right-2 top-[0.5625rem]
  • Enhanced visual feedback with transition effects on the icon

The change from variant="small" to variant="medium" for ShortcutKey aligns with the broader UI consistency improvements mentioned in the AI summary.

apps/webapp/package.json (2)

58-58: Essential dependency for AskAI integration.

The addition of @kapaai/react-sdk is necessary for the new AI chat interface that replaces the previous Kapa widget integration. The version ^0.1.2 appears reasonable for this new integration.


49-61: Good dependency organization.

The reordering of dependencies like @internal/redis, @internal/tracing, @trigger.dev/redis-worker, and @opentelemetry/api-logs improves maintainability without changing functionality.

Also applies to: 108-108

apps/webapp/app/components/navigation/SideMenu.tsx (4)

21-21: Clean migration from useKapaWidget to useAskAI.

The import changes properly reflect the transition from the old Kapa widget integration to the new AskAI system. The addition of useMatches, useFeatures, useTypedMatchesData, and useAskAI provides the necessary hooks for the refactored component logic.

Also applies to: 27-27, 30-30, 33-33, 36-36, 84-84


576-583: Well-structured data fetching for AI feature detection.

The refactored approach properly:

  • Uses useMatches and useTypedMatchesData to access root loader data
  • Leverages useFeatures for feature flag detection
  • Extracts websiteId and openAskAI from the new useAskAI hook
  • Maintains the same isKapaEnabled logic using features.isManagedCloud && websiteId

This approach is more explicit and maintainable than the previous implementation.


588-588: Simplified HelpAndFeedback usage.

The removal of the disableShortcut prop suggests that shortcut handling is now managed at a higher level or within the component itself, which aligns with the overall UI improvements in this PR.


600-600: Streamlined onClick handler.

The simplification from a block function calling openKapa() to a direct call to openAskAI() reflects the cleaner API of the new AskAI system.

apps/webapp/app/components/AskAI.tsx (7)

1-36: LGTM!

The imports are well-organized and appropriate for the functionality implemented.


38-53: LGTM!

The context setup follows React best practices with proper typing and error handling.


113-116: Verify the KapaProvider callback implementation.

The callbacks onQuerySubmit and onAnswerGenerationCompleted both call openAskAI() without parameters, which only sets initialQuery to undefined. This seems redundant since the dialog is already open when these callbacks fire.

Please verify if these callbacks are intended to perform specific actions or if they can be removed.


127-157: LGTM!

The dialog component is well-structured with proper state management and styling.


380-488: LGTM!

The ChatInterface component is well-implemented with proper state management, form handling, and animation effects.


490-512: LGTM!

The GradientSpinnerBackground component provides a nice visual effect for the loading states.


514-538: LGTM!

The AskAIButton component is simple and effective, with proper tooltip integration.

error,
addFeedback,
}: {
conversation: any[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace any types with proper TypeScript interfaces.

Using any types reduces type safety and makes the code harder to maintain.

+interface ConversationItem {
+  id?: string;
+  question: string;
+  answer: string;
+}

function ChatMessages({
  conversation,
  isPreparingAnswer,
  isGeneratingAnswer,
  onReset,
  onExampleClick,
  error,
  addFeedback,
}: {
-  conversation: any[];
+  conversation: ConversationItem[];
  isPreparingAnswer: boolean;
  isGeneratingAnswer: boolean;
  onReset: () => void;
  onExampleClick: (question: string) => void;
  error: string | null;
-  addFeedback: (questionAnswerId: string, reaction: "upvote" | "downvote", comment?: any) => void;
+  addFeedback: (questionAnswerId: string, reaction: "upvote" | "downvote", comment?: string) => void;
}) {

Also applies to: 175-175

🤖 Prompt for AI Agents
In apps/webapp/app/components/AskAI.tsx at lines 168 and 175, the use of the
`any` type for the `conversation` array reduces type safety. Define a proper
TypeScript interface that describes the shape of the conversation objects and
replace `any[]` with this interface array type to improve maintainability and
type checking.

Comment on lines +254 to +258
<div
className="prose prose-invert max-w-none text-text-dimmed"
dangerouslySetInnerHTML={{ __html: marked(qa.answer) }}
/>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Sanitize markdown output to prevent XSS attacks.

Using dangerouslySetInnerHTML with AI-generated content poses a security risk. Consider using a sanitization library like DOMPurify to clean the HTML output from marked.

+import DOMPurify from 'dompurify';
+
            <div
              className="prose prose-invert max-w-none text-text-dimmed"
-              dangerouslySetInnerHTML={{ __html: marked(qa.answer) }}
+              dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(marked(qa.answer)) }}
            />

Don't forget to install the dependency:

npm install dompurify
npm install --save-dev @types/dompurify
🧰 Tools
🪛 Biome (1.9.4)

[error] 256-256: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🤖 Prompt for AI Agents
In apps/webapp/app/components/AskAI.tsx around lines 254 to 258, the code uses
dangerouslySetInnerHTML with marked output, which can lead to XSS
vulnerabilities. To fix this, install the dompurify library and its types, then
import and use DOMPurify to sanitize the HTML generated by marked before passing
it to dangerouslySetInnerHTML. This ensures the rendered HTML is safe from
malicious scripts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant