Skip to content

AI dashboard widget + CLI AI generate fix suggestions #1925

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

Merged
merged 39 commits into from
Apr 30, 2025
Merged

Conversation

matt-aitken
Copy link
Member

@matt-aitken matt-aitken commented Apr 15, 2025

  • Added an AI widget to the dashboard
  • Shortcut keys can now be globally disabled (used by the AI widget when open)
  • You can open the "Shortcuts" slide over from anywhere by pressing "?"
  • The CLI now suggests 💡 Get a fix for this error using AI with a link to find an answer

Summary by CodeRabbit

  • New Features

    • Introduced AI assistance links for build errors, providing direct access to AI-powered help when build failures occur.
    • Added keyboard shortcut (mod + "/") and side menu integration for quick access to AI help within the web app.
    • Implemented a global shortcut management system, allowing shortcuts to be enabled or disabled across the app.
    • Added new icons and visual enhancements for shortcut and AI-related UI elements.
    • Integrated the Kapa AI widget with configurable scripts and automatic open behavior via URL parameters.
  • Improvements

    • Enhanced error reporting with detailed AI help links for build and indexing failures.
    • Updated keyboard shortcut sheet with new shortcuts and improved usability.
    • Refined styling and layout for AI-generated cron field and related components.
    • Improved shortcut handling to respect global enablement state and per-shortcut controls.
  • Bug Fixes

    • Improved error handling and reporting during the build process, including more explicit error messages and event-driven failure notifications.
  • Chores

    • Updated dependency resolution in example package for workspace compatibility.

Copy link

changeset-bot bot commented Apr 15, 2025

🦋 Changeset detected

Latest commit: 2b74932

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

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

Copy link
Contributor

coderabbitai bot commented Apr 15, 2025

Walkthrough

This set of changes introduces AI-assisted help integration across both the web application and CLI tools. In the web app, new components, hooks, and context providers are added to enable an AI help widget, shortcut management, and context-aware keyboard shortcuts. The side menu now offers direct AI assistance, and shortcut sheets are refactored for modularity and auto-opening. On the CLI side, error handling is enhanced: build failures and worker errors now generate terminal links for AI-powered troubleshooting, with a new error class and event bus event for build failures. Several UI icons and layouts receive updates, and workspace dependency references are adjusted in a sample package.

Changes

Files/Paths Change Summary
.changeset/red-chairs-begin.md Added changelog: documents AI assistance link for build errors.
apps/webapp/app/assets/icons/AISparkleIcon.tsx Updated SVG: increased size, replaced gradients with solid fills, simplified structure.
apps/webapp/app/assets/icons/KeyboardEnterIcon.tsx New file: adds KeyboardEnterIcon React component.
apps/webapp/app/components/Shortcuts.tsx Refactored: disables built-in shortcut, extracts content to ShortcutContent, adds ShortcutsAutoOpen, and includes new "Ask AI" shortcut.
apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx Updated: adds disableShortcut prop, changes trigger icon, adjusts shortcut settings.
apps/webapp/app/components/navigation/SideMenu.tsx Enhanced: adds AI help integration via HelpAndAI, uses useKapaWidget, updates footer UI and shortcut support.
apps/webapp/app/components/primitives/Buttons.tsx Added: optional hideShortcutKey prop to button content; renders shortcut key conditionally.
apps/webapp/app/components/primitives/ShortcutKey.tsx Updated: uses KeyboardEnterIcon for "enter" key on Mac, adjusts imports.
apps/webapp/app/components/primitives/ShortcutsProvider.tsx New file: introduces ShortcutsProvider context and useShortcuts hook for managing global shortcut state.
apps/webapp/app/env.server.ts Added: optional KAPA_AI_WEBSITE_ID to environment schema.
apps/webapp/app/hooks/useKapaWidget.tsx New file: provides Kapa AI widget integration, config hook, and script injection component.
apps/webapp/app/hooks/useShortcutKeys.tsx Enhanced: integrates global shortcut enablement, adds enabled prop to shortcuts, updates logic.
apps/webapp/app/root.tsx Refactored: default export, adds Kapa AI scripts, wraps app in ShortcutsProvider, updates loader and styling.
apps/webapp/app/routes/projects.$projectRef.ai-help.ts New route: loader validates user/project, redirects with query to AI help page.
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new.natural-language.tsx UI tweaks: updates icon and container styling for cron field, no logic changes.
apps/webapp/app/routes/storybook.shortcuts/route.tsx Added: DisableTester component for toggling shortcut state, updates storybook demo.
packages/cli-v3/src/build/bundle.ts Added: BundleError class; throws on build failure with error details.
packages/cli-v3/src/cli/common.ts Updated: handles BundleError in command wrapper, changes return type.
packages/cli-v3/src/commands/dev.ts Updated: adds imports for new error classes.
packages/cli-v3/src/dev/devOutput.ts Enhanced: adds build failure handler, generates AI help links for errors, updates error aggregation.
packages/cli-v3/src/dev/devSession.ts Updated: wraps bundling in try-catch, emits build failure events.
packages/cli-v3/src/utilities/cliOutput.ts Added: aiHelpLink function to print AI help URLs for errors.
packages/cli-v3/src/utilities/eventBus.ts Added: buildFailed event type to event bus.
references/hello-world/package.json Changed: dependency versions to workspace references.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SideMenu
    participant HelpAndAI
    participant useKapaWidget
    participant KapaWidget

    User->>SideMenu: Clicks AI Help button or presses shortcut
    SideMenu->>HelpAndAI: Renders AI Help UI
    HelpAndAI->>useKapaWidget: Calls openKapa(query)
    useKapaWidget->>KapaWidget: Opens widget in AI mode with query
    KapaWidget-->>User: Displays AI assistance interface
Loading
sequenceDiagram
    participant CLI_User
    participant CLI
    participant Bundle
    participant EventBus
    participant aiHelpLink

    CLI_User->>CLI: Runs build/dev command
    CLI->>Bundle: Executes bundleWorker
    Bundle-->>CLI: Throws BundleError on failure
    CLI->>EventBus: Emits buildFailed event
    EventBus->>aiHelpLink: Calls with error details
    aiHelpLink-->>CLI_User: Prints AI help link in terminal
Loading

Possibly related PRs

Poem

🐇✨
A sparkle of AI in menu and shell,
Shortcuts now listen, and widgets as well.
When builds go awry, don’t fret or despair—
The rabbit has left you a help link to share!
With icons refreshed and context in tow,
Let’s hop to the future, together we go!
—Your code rabbit 🥕

✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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.

@matt-aitken matt-aitken marked this pull request as ready for review April 29, 2025 16:44
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: 4

🧹 Nitpick comments (2)
apps/webapp/app/components/navigation/SideMenu.tsx (1)

548-599: Remove console.log statement from production code.

There's a console.log statement in the HelpAndAI component that should be removed before deployment.

- console.log("aiHelp", aiHelp);
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)

64-68: Consider standardizing ternary expression formatting

For consistency with other modifiers, consider using the same ternary formatting style throughout the file.

-      return isMac ? (
-        <KeyboardEnterIcon className={className} />
-      ) : (
-        <span className="capitalize">Enter</span>
-      );
+      return isMac ? <KeyboardEnterIcon className={className} /> : <span className="capitalize">Enter</span>;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f579afb and 349adc4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (25)
  • .changeset/red-chairs-begin.md (1 hunks)
  • apps/webapp/app/assets/icons/AISparkleIcon.tsx (1 hunks)
  • apps/webapp/app/assets/icons/KeyboardEnterIcon.tsx (1 hunks)
  • apps/webapp/app/components/Shortcuts.tsx (2 hunks)
  • apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx (2 hunks)
  • apps/webapp/app/components/navigation/SideMenu.tsx (5 hunks)
  • apps/webapp/app/components/primitives/Buttons.tsx (3 hunks)
  • apps/webapp/app/components/primitives/ShortcutKey.tsx (2 hunks)
  • apps/webapp/app/components/primitives/ShortcutsProvider.tsx (1 hunks)
  • apps/webapp/app/env.server.ts (1 hunks)
  • apps/webapp/app/hooks/useKapaWidget.tsx (1 hunks)
  • apps/webapp/app/hooks/useShortcutKeys.tsx (2 hunks)
  • apps/webapp/app/root.tsx (6 hunks)
  • apps/webapp/app/routes/projects.$projectRef.ai-help.ts (1 hunks)
  • apps/webapp/app/routes/resources.kapa-widget.ts (1 hunks)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new.natural-language.tsx (2 hunks)
  • apps/webapp/app/routes/storybook.shortcuts/route.tsx (3 hunks)
  • packages/cli-v3/src/build/bundle.ts (2 hunks)
  • packages/cli-v3/src/cli/common.ts (3 hunks)
  • packages/cli-v3/src/commands/dev.ts (2 hunks)
  • packages/cli-v3/src/dev/devOutput.ts (7 hunks)
  • packages/cli-v3/src/dev/devSession.ts (2 hunks)
  • packages/cli-v3/src/utilities/cliOutput.ts (1 hunks)
  • packages/cli-v3/src/utilities/eventBus.ts (1 hunks)
  • references/hello-world/package.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (10)
apps/webapp/app/components/primitives/ShortcutKey.tsx (1)
apps/webapp/app/assets/icons/KeyboardEnterIcon.tsx (1)
  • KeyboardEnterIcon (1-12)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new.natural-language.tsx (1)
apps/webapp/app/assets/icons/AISparkleIcon.tsx (1)
  • AISparkleIcon (1-31)
apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug/route.tsx (1)
  • useCurrentPlan (23-30)
apps/webapp/app/components/primitives/Popover.tsx (2)
  • Popover (202-202)
  • PopoverSideMenuTrigger (208-208)
apps/webapp/app/hooks/useKapaWidget.tsx (4)
apps/webapp/app/root.tsx (1)
  • loader (48-70)
apps/webapp/app/hooks/useFeatures.ts (1)
  • useFeatures (5-9)
apps/webapp/app/components/primitives/ShortcutsProvider.tsx (1)
  • useShortcuts (37-39)
apps/webapp/app/hooks/useSearchParam.ts (1)
  • useSearchParams (7-82)
apps/webapp/app/routes/storybook.shortcuts/route.tsx (2)
apps/webapp/app/components/primitives/ShortcutsProvider.tsx (1)
  • useShortcuts (37-39)
apps/webapp/app/components/primitives/Buttons.tsx (1)
  • Button (294-327)
packages/cli-v3/src/dev/devOutput.ts (3)
packages/cli-v3/src/utilities/eventBus.ts (2)
  • EventBusEventArgs (24-24)
  • eventBus (26-26)
packages/cli-v3/src/build/bundle.ts (1)
  • BundleError (54-61)
packages/cli-v3/src/utilities/cliOutput.ts (2)
  • aiHelpLink (119-138)
  • prettyError (73-94)
apps/webapp/app/hooks/useShortcutKeys.tsx (1)
apps/webapp/app/components/primitives/ShortcutsProvider.tsx (1)
  • useShortcuts (37-39)
apps/webapp/app/routes/resources.kapa-widget.ts (1)
apps/webapp/app/root.tsx (1)
  • loader (48-70)
packages/cli-v3/src/dev/devSession.ts (2)
packages/cli-v3/src/build/bundle.ts (1)
  • bundleWorker (63-168)
packages/cli-v3/src/utilities/eventBus.ts (1)
  • eventBus (26-26)
packages/cli-v3/src/cli/common.ts (2)
packages/core/src/v3/apiClient/stream.ts (1)
  • e (210-216)
packages/cli-v3/src/build/bundle.ts (1)
  • BundleError (54-61)
🪛 Biome (1.9.4)
apps/webapp/app/hooks/useKapaWidget.tsx

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

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

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (66)
references/hello-world/package.json (2)

6-6: Workspace protocol for devDependency
Switching trigger.dev to workspace:* ensures this example project consumes the local CLI package during development, keeping it in sync with the monorepo.


9-9: Workspace protocol for runtime dependency
Updating @trigger.dev/sdk to workspace:* aligns the example with the locally built SDK, avoiding drift from published versions.

apps/webapp/app/env.server.ts (1)

717-719: Added Kapa AI integration environment variable.

The addition of the KAPA_AI_WEBSITE_ID environment variable follows the project's pattern for defining optional configuration variables and will be used to configure the Kapa AI widget throughout the application.

packages/cli-v3/src/utilities/eventBus.ts (1)

14-14: Added build failure event for AI assistance integration.

The new buildFailed event type follows the existing pattern and will enable the CLI to emit build failure events that can be used to generate AI-powered help links when build errors occur.

apps/webapp/app/assets/icons/KeyboardEnterIcon.tsx (1)

1-12: Clean implementation of keyboard Enter key icon.

The SVG implementation uses current color for stroke and fill which allows it to inherit color from CSS, making it flexible for different UI themes and states.

apps/webapp/app/assets/icons/AISparkleIcon.tsx (2)

3-10: Improved SVG dimensions and structure.

The icon dimensions have been updated from 18x18 to 24x24 with explicit width and height attributes, which will ensure consistent rendering across the application.


11-28: Enhanced path styling with solid colors.

Replaced gradient fills with solid colors and added fillRule/clipRule attributes, which simplifies the SVG structure and may improve rendering performance.

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.schedules.new.natural-language.tsx (4)

86-87: Improved icon styling with modern class notation

The change from fixed dimensions (h-4 w-4) to the more concise size-4 utility class is a good modernization that maintains the same visual appearance while using Tailwind's newer syntax.


90-91: Enhanced container styling with better spacing and border radius

Adding mt-1 provides appropriate spacing between the label and input field, while changing from rounded-sm to rounded creates a slightly more noticeable border radius that improves visual consistency with other form elements.


93-93: Improved inner container styling with overflow control

The addition of overflow-hidden properly contains the child elements, preventing any potential content spillover, while the change to rounded-sm simplifies the border radius implementation.


108-109: Enhanced button spacing for better visual balance

The additional left padding (pl-1.5) and increased icon spacing (gap-1.5) improve the visual balance between the icon and text, creating a more polished appearance for the generate button.

.changeset/red-chairs-begin.md (1)

1-5: Properly documented AI assistance feature in changeset

The changeset correctly documents the addition of AI assistance links for build errors, which aligns with the code changes in the CLI to support error handling and AI help generation. This ensures proper version tracking for the feature.

packages/cli-v3/src/commands/dev.ts (2)

4-9: Enhanced error handling with additional imports

The restructured import statement now includes SkipLoggingError, which supports the improved error handling for build failures mentioned in the changeset.


20-20: Added BundleError import for build failure handling

The import of BundleError supports capturing build failures during the development process, enabling the CLI to provide AI-powered assistance when builds fail. This is a key component of the feature described in the changeset.

apps/webapp/app/components/primitives/Buttons.tsx (3)

180-180: Added option to hide shortcut keys in buttons

The new hideShortcutKey boolean prop gives developers more control over button rendering, supporting use cases where shortcut indicators should be conditionally hidden.


196-197: Destructured the hideShortcutKey prop for use in the component

Correctly added the new prop to the destructuring pattern, making it available for use in the component's rendering logic.


207-208: Updated shortcut key rendering condition

The rendering condition now properly checks both for the existence of a shortcut and that the shortcut display isn't explicitly hidden, providing more flexible control over the UI.

packages/cli-v3/src/cli/common.ts (2)

12-12: Appropriate import for the new error handling

The import of the newly created BundleError class is necessary for the error handling updates in this file.


58-58: Improved type accuracy

The return type now includes undefined to properly reflect that the function might not return a value when process.exit() is called during a BundleError.

packages/cli-v3/src/utilities/cliOutput.ts (1)

119-138: Looks good - clean implementation of the AI help link generator.

The aiHelpLink function effectively builds a URL for the AI help feature while taking proper precautions with the query parameter length.

packages/cli-v3/src/dev/devSession.ts (1)

176-203: Good error handling implementation.

The try-catch block ensures that build failures are properly reported through the event bus while still letting the error propagate up. This effectively integrates with the new AI help feature.

apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx (2)

7-7: Icon update and import addition look good.

The import changes are correctly implemented to support the updated UI components.

Also applies to: 15-15


26-42: Good implementation of shortcut disabling feature.

The component now properly handles disabling shortcuts based on the new disableShortcut prop, and the updated icon provides better visual consistency. The shortcut configuration with enabledOnInputElements: false is appropriate to prevent shortcuts from triggering when users are typing in form fields.

apps/webapp/app/routes/storybook.shortcuts/route.tsx (3)

1-7: Correct imports added for the new shortcut management functionality.

The imports have been properly updated to support the new shortcut management features.


21-32: Successfully integrated the shortcut tester into the storybook layout.

The integration of the DisableTester component into the main Story component is clean and well-organized.


76-104: Excellent implementation of the shortcut management tester.

The DisableTester component provides a clear demonstration of how to use the new shortcut management functionality. It effectively shows:

  1. How to access the shortcut context using the useShortcuts hook
  2. How to toggle the global shortcut state
  3. How to visualize the current shortcut state
  4. A practical example with an increment counter that can be triggered via shortcut
apps/webapp/app/hooks/useShortcutKeys.tsx (5)

3-3: Good job adding the necessary import.

The addition of the useShortcuts import is appropriate for integrating with the global shortcut enablement system.


10-11: Good addition of the optional enabled property.

The optional enabled property adds more granular control for individual shortcuts, complementing the global enablement state.


34-35: Correctly integrating global shortcuts enablement.

The hook now properly consumes the global shortcuts enablement state from the ShortcutsProvider context.


41-42: Well-structured enablement logic.

The implementation correctly combines multiple factors for determining if a shortcut is enabled:

  1. Not disabled via the prop
  2. Global shortcuts are enabled
  3. The individual shortcut is not explicitly disabled

This provides complete flexibility while maintaining backward compatibility.


49-54: Consistent application of the enablement flag.

You've consistently applied the isEnabled flag throughout the hook options, ensuring that all aspects of shortcut handling respect the enablement state.

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

20-20: Good addition of useLocation for AI help parameter handling.

Adding useLocation is necessary for implementing the URL parameter-based AI help functionality.


23-23: Appropriate icon import for AI feature.

The AISparkleIcon import aligns with the new AI assistance feature being added.


59-59: Good hook import for Kapa widget integration.

The import of useKapaWidget from the correct relative path is appropriate for managing the AI widget state.


73-76: Appropriate imports for shortcut functionality.

Adding the ShortcutKey and ShortcutsAutoOpen imports supports the keyboard shortcut integration for the AI feature.


283-285: Good implementation of help and AI component in side menu.

The HelpAndAI component is appropriately placed and structured in the side menu footer.


548-563: Well-implemented URL parameter handling for AI help.

The component correctly extracts the aiHelp parameter from the URL, removes it to prevent repeated triggering, and passes it to the Kapa widget.


564-597: Good integration of AI widget with shortcut system.

The component:

  1. Properly includes ShortcutsAutoOpen for keyboard shortcut sheet access
  2. Passes the appropriate disableShortcut prop to HelpAndFeedback
  3. Conditionally renders the AI button based on widget availability
  4. Sets up the correct keyboard shortcut (mod+/) with appropriate tooltip

This creates a cohesive user experience with the new AI feature.

apps/webapp/app/components/primitives/ShortcutsProvider.tsx (3)

1-14: Well-structured context and types for shortcuts management.

The ShortcutsProvider implementation:

  1. Defines a clear type for the context value
  2. Properly initializes the context with null
  3. Has appropriate props type definition

This creates a solid foundation for the global shortcuts management.


15-31: Excellent provider implementation with proper state management.

The provider implementation:

  1. Initializes the shortcut enablement state to true by default
  2. Uses useCallback for the state modification functions to prevent unnecessary re-renders
  3. Memoizes the context value to prevent unnecessary re-renders of consumers
  4. Correctly provides the value to all children

This follows React best practices for context providers.


33-39: Good error handling for missing provider.

The implementation:

  1. Provides a clear error message when the hook is used outside a provider
  2. Uses the nullish coalescing operator for concise error handling
  3. Exports a clean hook API for consumers

This ensures proper usage of the shortcuts context throughout the application.

apps/webapp/app/components/Shortcuts.tsx (5)

14-15: Appropriate hook imports for shortcut functionality.

Adding useState and useShortcutKeys imports supports the new automatic shortcut opening functionality.


28-28: Good use of the new shortcut enabled property.

Setting enabled: false explicitly disables the built-in shortcut trigger, which is now handled by the ShortcutsAutoOpen component.


35-35: Clean refactoring to use the extracted ShortcutContent.

The component now uses the extracted ShortcutContent component, which keeps the code DRY.


40-55: Well-implemented ShortcutsAutoOpen component.

The ShortcutsAutoOpen component:

  1. Manages its own open state with useState
  2. Uses useShortcutKeys to listen for the keyboard shortcut
  3. Opens the sheet when the shortcut is triggered
  4. Passes the open state to the Sheet component

This creates a clean separation of concerns between shortcut handling and UI display.


57-167: Good extraction of ShortcutContent for reusability.

The ShortcutContent component:

  1. Properly extracts all the shortcut content from the original component
  2. Includes the new "Ask AI" shortcut with appropriate key binding
  3. Maintains the same structure and styling as before

This extraction improves code organization and enables the new ShortcutsAutoOpen functionality.

packages/cli-v3/src/dev/devOutput.ts (5)

50-65: Nice implementation of AI help for build failures

You've added a well-structured event handler for build failures that extracts error details and generates an AI help link. This provides a helpful developer experience when builds fail.


111-116: Good enhancement to error handling with AI assistance

You've improved the error aggregation for import errors and added AI help link generation. This enhancement makes debugging import errors easier for developers.


125-129: Well-implemented AI help for task metadata errors

Adding AI help for task metadata parse errors is a good improvement to the developer experience.


135-139: Good error handling for generic build failures

You've consistently applied the AI help approach to generic build errors as well, which ensures comprehensive error assistance.


222-222: Proper event registration and cleanup

The buildFailed event handler is correctly registered and deregistered, maintaining clean event handling.

Also applies to: 234-234

apps/webapp/app/routes/projects.$projectRef.ai-help.ts (4)

9-11: Good use of Zod schema for parameter validation

Using a schema to validate route parameters is a robust approach that ensures type safety.


13-36: Well-implemented authentication and project access control

The loader properly enforces authentication and verifies the user has access to the project. The error handling is also appropriate with 404 responses for not found cases.


38-43: Good validation of query parameter

The code correctly checks for the presence of the query parameter and returns an appropriate error response when missing.


45-51: Well-designed redirection to AI help

The URL construction and redirection logic effectively passes the query to the environment page with the aiHelp parameter, creating a seamless user experience.

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

54-56: Good integration of Kapa AI configuration

Adding the Kapa configuration to the loader data is a clean approach for making the widget ID available throughout the application.


115-115: Clean integration of Kapa scripts

The KapaScripts component is properly added to the head section and receives the websiteId from the loader data.


118-121: Good implementation of ShortcutsProvider

Wrapping the application with ShortcutsProvider enables global shortcut management, which is necessary for the AI widget integration.

apps/webapp/app/hooks/useKapaWidget.tsx (4)

10-18: Good TypeScript declaration for the Kapa API

The global window interface extension properly types the Kapa function API, improving type safety when interacting with the widget.


87-115: Comprehensive widget lifecycle management

The effect properly handles widget rendering, event subscription, and cleanup. The aiHelp parameter processing is well-implemented with URL parameter cleanup after processing.


118-136: Well-designed widget open function

The openKapa function properly handles feature flags and configuration before opening the widget. The integration with the shortcuts system to disable keyboard shortcuts when the widget is open is a good UX consideration.


138-142: Clean API for widget integration

The hook returns a well-designed API that makes it easy for components to interact with the widget while respecting feature flags.

packages/cli-v3/src/build/bundle.ts (2)

54-61: Well-structured error class implementation

This new BundleError class provides a mechanism to capture and propagate build errors with their associated messages, which will improve error reporting.


141-141: Good enhancement to error reporting

Replacing the generic error with the new BundleError class allows passing the detailed error messages from esbuild, which can help with debugging and AI-assisted error resolution.

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

6-6: Good type import refactoring and new icon integration

The explicit type imports improve code clarity, and the new icon import will be used for rendering the Enter key.

Also applies to: 9-9


64-68: Improved visual representation of Enter key

Replacing the Unicode character with a custom SVG icon for the Enter key creates a more consistent and visually appealing shortcut display on Mac platforms.

Comment on lines +20 to +59
export function KapaScripts({ websiteId }: { websiteId?: string }) {
if (!websiteId) return null;

return (
<>
<script
async
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id={websiteId}
data-project-name={"Trigger.dev"}
data-project-color={"#6366F1"}
data-project-logo={"https://content.trigger.dev/trigger-logo-circle.png"}
data-render-on-load={"false"}
data-button-hide={"true"}
data-modal-disclaimer-bg-color={"#D7D9DD"}
data-modal-header-bg-color={"#2C3034"}
data-modal-title-color={"#D7D9DD"}
></script>
<script
dangerouslySetInnerHTML={{
__html: `
(function () {
let k = window.Kapa;
if (!k) {
let i = function () {
i.c(arguments);
};
i.q = [];
i.c = function (args) {
i.q.push(args);
};
window.Kapa = i;
}
})();
`,
}}
/>
</>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Security consideration with inline script

The KapaScripts component uses dangerouslySetInnerHTML to initialize the Kapa command queue. While this is a common pattern for third-party widget integration, it introduces potential security risks.

Consider if the inline script initialization can be moved to an external file or if there's an alternative approach recommended by Kapa. If not, add a comment explaining why this approach is necessary.


🏁 Script executed:

#!/bin/bash
# Check if Kapa provides documentation on safer initialization methods
echo "Checking for alternative initialization methods in Kapa documentation..."
curl -s https://docs.kapa.ai/widget | grep -A 10 "initialization" || echo "Documentation not found or doesn't mention alternative initialization methods"

Length of output: 388


Add explanatory comment for inline script initialization

The KapaScripts component requires an inline script to set up the window.Kapa command queue before the external widget bundle loads. Kapa’s public docs (https://docs.kapa.ai/widget) don’t offer an alternative initialization method, so this use of dangerouslySetInnerHTML is necessary. Please add a code comment in apps/webapp/app/hooks/useKapaWidget.tsx around the dangerouslySetInnerHTML block to explain:

  • Why we must inline this script (queueing commands before the widget bundle loads)
  • That no external or safer init approach is documented by Kapa

File: apps/webapp/app/hooks/useKapaWidget.tsx
Location: lines 37–59 (the dangerouslySetInnerHTML section)

🧰 Tools
🪛 Biome (1.9.4)

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

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

(lint/security/noDangerouslySetInnerHtml)

import { type LoaderFunctionArgs } from "@remix-run/node";

export async function loader({ request }: LoaderFunctionArgs) {
const response = await fetch("https://widget.kapa.ai/kapa-widget.bundle.js");
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify content security policy compatibility

Make sure your app's Content Security Policy allows loading and executing scripts from the kapa.ai domain.


🏁 Script executed:

#!/bin/bash
# Check if there are any CSP-related headers or meta tags in the codebase

# Look for CSP headers in server-side code
echo "Checking for CSP headers in server responses..."
rg -A 3 -B 3 "Content-Security-Policy" --type ts --type tsx

# Look for CSP meta tags in HTML
echo "Checking for CSP meta tags in HTML/JSX/TSX files..."
rg -A 3 -B 3 '<meta http-equiv="Content-Security-Policy"' --type html --type jsx --type tsx

Length of output: 427


🏁 Script executed:

#!/bin/bash
# Broad search for CSP in all files
echo "Searching for Content-Security-Policy occurrences across the entire codebase..."
rg -A3 -B3 "Content-Security-Policy" .

# Broad search for CSP meta tags
echo "Searching for <meta http-equiv=\"Content-Security-Policy\" tags..."
rg -A3 -B3 '<meta http-equiv="Content-Security-Policy"' .

Length of output: 901


Update Content Security Policy to Allow Kapa Widget Script

The app currently sets only a frame-ancestors CSP directive. You’ll need to explicitly whitelist the Kapa domain in your script-src policy so the external widget can load. For example, in apps/webapp/app/entry.server.tsx where you have:

responseHeaders.set(
  "Content-Security-Policy",
  "frame-ancestors 'self'"
);

update to something like:

responseHeaders.set(
  "Content-Security-Policy",
  "frame-ancestors 'self'; script-src 'self' https://widget.kapa.ai;"
);

• File: apps/webapp/app/entry.server.tsx
• Location: where Content-Security-Policy is set

Comment on lines 3 to 13
export async function loader({ request }: LoaderFunctionArgs) {
const response = await fetch("https://widget.kapa.ai/kapa-widget.bundle.js");
const script = await response.text();

return new Response(script, {
headers: {
"Content-Type": "application/javascript",
"Cache-Control": "public, max-age=86400", // Cache for 1 day
},
});
}
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

Add error handling to the loader function

The loader function fetches an external script but doesn't handle potential network failures or server errors.

export async function loader({ request }: LoaderFunctionArgs) {
-  const response = await fetch("https://widget.kapa.ai/kapa-widget.bundle.js");
-  const script = await response.text();
+  try {
+    const response = await fetch("https://widget.kapa.ai/kapa-widget.bundle.js");
+    
+    if (!response.ok) {
+      throw new Error(`Failed to fetch Kapa widget: ${response.status} ${response.statusText}`);
+    }
+    
+    const script = await response.text();
+    
+    return new Response(script, {
+      headers: {
+        "Content-Type": "application/javascript",
+        "Cache-Control": "public, max-age=86400", // Cache for 1 day
+      },
+    });
+  } catch (error) {
+    console.error("Error loading Kapa widget:", error);
+    // Return an empty script with error logging to prevent page load failures
+    return new Response("console.error('Failed to load Kapa widget');", {
+      headers: {
+        "Content-Type": "application/javascript",
+        "Cache-Control": "no-cache",
+      },
+    });
+  }
-
-  return new Response(script, {
-    headers: {
-      "Content-Type": "application/javascript",
-      "Cache-Control": "public, max-age=86400", // Cache for 1 day
-    },
-  });
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function loader({ request }: LoaderFunctionArgs) {
const response = await fetch("https://widget.kapa.ai/kapa-widget.bundle.js");
const script = await response.text();
return new Response(script, {
headers: {
"Content-Type": "application/javascript",
"Cache-Control": "public, max-age=86400", // Cache for 1 day
},
});
}
export async function loader({ request }: LoaderFunctionArgs) {
try {
const response = await fetch("https://widget.kapa.ai/kapa-widget.bundle.js");
if (!response.ok) {
throw new Error(`Failed to fetch Kapa widget: ${response.status} ${response.statusText}`);
}
const script = await response.text();
return new Response(script, {
headers: {
"Content-Type": "application/javascript",
"Cache-Control": "public, max-age=86400", // Cache for 1 day
},
});
} catch (error) {
console.error("Error loading Kapa widget:", error);
// Return an empty script with error logging to prevent page load failures
return new Response("console.error('Failed to load Kapa widget');", {
headers: {
"Content-Type": "application/javascript",
"Cache-Control": "no-cache",
},
});
}
}

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: 0

♻️ Duplicate comments (1)
apps/webapp/app/hooks/useKapaWidget.tsx (1)

38-56: ⚠️ Potential issue

Add security comment for inline script initialization.

The use of dangerouslySetInnerHTML is flagged by static analysis tools as a potential security risk. While this implementation is necessary for the Kapa widget initialization, you should add a comment explaining why this approach is used.

Add a comment explaining that this inline script is required to set up the command queue before the external widget bundle loads, and that Kapa doesn't provide an alternative initialization method:

      <script
        dangerouslySetInnerHTML={{
+         // This inline script is necessary to initialize the Kapa command queue before the widget bundle loads
+         // Kapa's documentation doesn't provide an alternative initialization method that avoids dangerouslySetInnerHTML
          __html: `
                    (function () {
                      let k = window.Kapa;
                      if (!k) {
🧰 Tools
🪛 Biome (1.9.4)

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

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

(lint/security/noDangerouslySetInnerHtml)

🧹 Nitpick comments (1)
apps/webapp/app/hooks/useKapaWidget.tsx (1)

103-107: Consider alternative to setTimeout for widget initialization.

The comment indicates that a delay is required for the Kapa browser verification to succeed. While the current implementation works, using a fixed timeout may be fragile.

Consider using a more robust approach if possible:

  • Check if Kapa provides an event or callback when verification is complete
  • Implement a retry mechanism with increasing delays instead of a fixed timeout
  • Add error handling in case the verification fails
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c08a0d5 and 2b74932.

📒 Files selected for processing (2)
  • apps/webapp/app/components/navigation/SideMenu.tsx (5 hunks)
  • apps/webapp/app/hooks/useKapaWidget.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
apps/webapp/app/hooks/useKapaWidget.tsx

[error] 39-39: 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 (4)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: units / 🧪 Unit Tests
  • GitHub Check: typecheck / typecheck
🔇 Additional comments (5)
apps/webapp/app/components/navigation/SideMenu.tsx (2)

283-285: Clean restructuring of the footer section.

The new flex container provides better layout control for the HelpAndAI component. The use of justify-between ensures proper spacing between elements.


548-586: Well-implemented AI assistance component.

The new HelpAndAI component properly integrates the AI widget functionality into the side menu with:

  • Conditional rendering based on feature flags (isKapaEnabled)
  • Appropriate keyboard shortcut handling
  • Clear tooltips showing the shortcut (mod + "/")
  • Disabling of conflicting shortcuts when the AI widget is open

The implementation follows good patterns using the hooks API and existing UI components.

apps/webapp/app/hooks/useKapaWidget.tsx (3)

119-139: Proper shortcut management in openKapa function.

The openKapa function correctly disables shortcuts when opening the widget and properly handles conditional logic based on feature flags. The callback dependencies are also correctly specified.


87-117: Good cleanup of event handlers on component unmount.

The useEffect hook properly registers event handlers for the Kapa widget's modal open and close events, and cleans them up on unmount. The dependency array is correctly specified to re-register handlers when relevant dependencies change.


19-59:

❓ Verification inconclusive

Verify Kapa widget URL and configuration parameters.

The Kapa widget script is loaded from a fixed URL and configured with several parameters. Ensure that these are the correct parameters for your integration.


🏁 Script executed:

#!/bin/bash
# Check for valid Kapa widget configuration parameters

echo "Checking Kapa widget documentation for configuration parameters..."
curl -s https://docs.kapa.ai/widget | grep -A 20 "data-" || echo "Documentation not found or doesn't mention configuration parameters"

echo -e "\nVerifying that the Kapa widget URL is accessible..."
curl -s -I https://widget.kapa.ai/kapa-widget.bundle.js | grep "HTTP/" || echo "URL is not accessible"

Length of output: 8838


I’ll verify the correct “Website Widget” docs page and extract the expected script parameters.


🏁 Script executed:

#!/bin/bash
echo "Checking integration docs status..."
curl -sI https://docs.kapa.ai/integrations/website-widget | grep HTTP/ || echo "Integration docs URL not accessible"

echo -e "\nExtracting Kapa widget script snippet..."
curl -s https://docs.kapa.ai/integrations/website-widget \
  | grep -A20 "<script src=\"https://widget.kapa.ai/kapa-widget.bundle.js\"" \
  || echo "Widget snippet not found in integration docs"

Length of output: 17264


Kapa widget script and parameters verified

The widget bundle URL returns HTTP 200 and the “Website Widget” docs at /integrations/website-widget confirm the standard snippet. Before merging, please double-check that your custom settings match your integration:

  • data-website-id – must be your actual widget ID from app.kapa.ai
  • data-project-name, data-project-color, data-project-logo – ensure these reflect your brand/integration
  • Custom flags (data-render-on-load, data-button-hide, data-modal-disclaimer-bg-color, data-modal-header-bg-color, data-modal-title-color) – verify they’re supported and behave as intended
  • Optional features – if you need search mode, analytics or bot protection, include data-search-mode-enabled, data-user-analytics-fingerprint-enabled, data-bot-protection-mechanism, etc.

No functional changes to the URL or core snippet are needed—just confirm these parameters align with your Kapa integration.

🧰 Tools
🪛 Biome (1.9.4)

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

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

(lint/security/noDangerouslySetInnerHtml)

@matt-aitken matt-aitken merged commit 7fe111a into main Apr 30, 2025
13 checks passed
@matt-aitken matt-aitken deleted the kapa-ai-widget branch April 30, 2025 10:11
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.

4 participants