-
-
Notifications
You must be signed in to change notification settings - Fork 724
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
base: main
Are you sure you want to change the base?
Conversation
|
WalkthroughA 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 📜 Recent review detailsConfiguration used: CodeRabbit UI ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms (25)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
⛔ 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
andmac
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
toborder-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 basemedium
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 thewebsiteId
from the loader data. The conditional|| null
ensures type safety whenkapa.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
andgroup-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"
tovariant="medium"
forShortcutKey
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
, anduseAskAI
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
anduseTypedMatchesData
to access root loader data- Leverages
useFeatures
for feature flag detection- Extracts
websiteId
andopenAskAI
from the newuseAskAI
hook- Maintains the same
isKapaEnabled
logic usingfeatures.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 toopenAskAI()
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
andonAnswerGenerationCompleted
both callopenAskAI()
without parameters, which only setsinitialQuery
toundefined
. 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[]; |
There was a problem hiding this comment.
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.
<div | ||
className="prose prose-invert max-w-none text-text-dimmed" | ||
dangerouslySetInnerHTML={{ __html: marked(qa.answer) }} | ||
/> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
# Conflicts: # apps/webapp/package.json
This replaces the Kapa AI Javascript widget with their React SDK. This means:
useAskAI
hook to trigger it from anywhere in the app and pass it a payload 'answer'Testing for Test Cloud
askai.mp4