Skip to content

Update dependencies, add GROQ_API_KEY to env, and implement chat comp…#225

Merged
carhartlewis merged 4 commits into
mainfrom
lewis/ai-chat
Mar 28, 2025
Merged

Update dependencies, add GROQ_API_KEY to env, and implement chat comp…#225
carhartlewis merged 4 commits into
mainfrom
lewis/ai-chat

Conversation

@carhartlewis

@carhartlewis carhartlewis commented Mar 28, 2025

Copy link
Copy Markdown
Contributor

…onents

  • Added "@ai-sdk/groq" and "motion" dependencies in package.json and bun.lock.
  • Introduced GROQ_API_KEY in env.mjs for environment configuration.
  • Refactored chat components: created Chat, ChatTextarea, ChatEmpty, and Messages components for improved chat functionality.
  • Implemented AssistantSheet for chat interface management.
  • Enhanced layout components with UserProvider for session management.
  • Removed deprecated ChatButton and ChatInterface components.
  • Added useScrollToBottom hook for automatic scrolling in chat messages.
  • Updated AI tools for organization and vendor management.

Summary by CodeRabbit

  • New Features

    • Launched an enhanced chat experience featuring a dedicated assistant panel that greets users personally, offers a refined text input area with helpful resource links, model selection capabilities, and animated message displays with expandable reasoning details.
    • Added improved markdown rendering and modern iconography to elevate the overall presentation of chat content.
  • Refactor

    • Streamlined authentication and layout consistency to ensure a smoother and more reliable user experience.

…onents

- Added "@ai-sdk/groq" and "motion" dependencies in package.json and bun.lock.
- Introduced GROQ_API_KEY in env.mjs for environment configuration.
- Refactored chat components: created Chat, ChatTextarea, ChatEmpty, and Messages components for improved chat functionality.
- Implemented AssistantSheet for chat interface management.
- Enhanced layout components with UserProvider for session management.
- Removed deprecated ChatButton and ChatInterface components.
- Added useScrollToBottom hook for automatic scrolling in chat messages.
- Updated AI tools for organization and vendor management.
@vercel

vercel Bot commented Mar 28, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 28, 2025 11:17pm
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
comp-portal ⬜️ Skipped (Inspect) Mar 28, 2025 11:17pm

@coderabbitai

coderabbitai Bot commented Mar 28, 2025

Copy link
Copy Markdown

Walkthrough

This pull request introduces new components and state management for the chat and dashboard layouts. A new UserProvider wraps the dashboard layout and an AssistantSheet has been added to integrate an AI chat interface. The API route for chat has been refactored to use organization-based authentication and remove dependency on an external API key. New UI components for chat interactions, icons, markdown rendering, and model selection have been added while legacy chat components have been removed. Additionally, various hooks, environmental variables, and store implementations were updated or simplified.

Changes

File(s) Change Summary
apps/app/src/app/[locale]/(app)/…/layout.tsx Introduced UserProvider to wrap layout; added AssistantSheet within AnimatedLayout; maintained session/org ID checks.
apps/app/src/app/[locale]/layout.tsx Reformatted code for consistent indentation without functional changes.
apps/app/src/app/api/chat/route.ts Refactored POST handler to implement organization-based authentication; removed API key dependency; defined new system prompt; added constant maxDuration.
apps/app/src/components/ai/*.tsx
(chat-empty, chat-text-area, chat, icons, markdown, message, messages, model-picker)
Added multiple new AI chat components for displaying empty states, managing text input, rendering messages (with reasoning animations), providing icon sets, rendering markdown, and selecting models.
apps/app/src/components/animated-layout.tsx Updated import path for cn and improved code formatting.
apps/app/src/components/chat/ChatButton.tsx
ChatInterface.tsx
ChatProvider.tsx
Removed legacy chat components previously used for rendering chat buttons, interfaces, and providers.
apps/app/src/components/hot-keys.tsx Replaced useAssistantStore with useQueryState for managing assistant state on hotkey events.
apps/app/src/components/sheets/assistant-sheet.tsx Introduced new AssistantSheet component that integrates the chat interface and synchronizes open state with URL query parameters.
apps/app/src/env.mjs
turbo.json
package.json
biome.json
Added new environment variable GROQ_API_KEY; updated build environment variables; added dependencies @ai-sdk/groq and motion; introduced a new lint rule for ARIA roles.
apps/app/src/hooks/ai/providers.ts
apps/app/src/hooks/ai/tools.ts
apps/app/src/hooks/chat/useChat.ts
apps/app/src/hooks/use-scroll-to-bottom.ts
Added new providers and tools for AI integration; removed the legacy useChat hook; and introduced useScrollToBottom for handling auto-scroll behavior.
apps/app/src/store/assistant.ts
apps/app/src/store/user/store.ts
Simplified assistant state management by updating method signatures; removed local extended User type in favor of the imported NextAuthUser.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API_Route
    participant Database
    participant streamText
    Client->>API_Route: POST request with messages and selectedModel
    API_Route->>API_Route: Extract session and organization ID
    API_Route->>Database: Query organization details
    Database-->>API_Route: Return organization data or error
    API_Route->>streamText: Call streamText with system prompt & model
    streamText-->>API_Route: Deliver streamed response
    API_Route-->>Client: Respond with streamed data
Loading
sequenceDiagram
    participant User
    participant AssistantSheet
    participant QueryState
    participant ChatComponent
    User->>AssistantSheet: Triggers open event (e.g., via meta+k)
    AssistantSheet->>QueryState: Update "assistant" state in URL query
    QueryState-->>AssistantSheet: Return updated open state
    AssistantSheet->>ChatComponent: Render Chat interface
Loading

Possibly related PRs

Poem

I’m just a rabbit, hopping through the code,
With new components and features in a joyful mode.
UserProvider wraps the layout tight,
AssistantSheet shines like a beacon of light.
Legacy parts removed, the path now is new—
In every line of code, we celebrate what’s true!
🐇✨ Happy hopping and happy coding!

✨ 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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.

@carhartlewis carhartlewis requested review from 7yntax and Marfuen March 28, 2025 23:12
@carhartlewis carhartlewis self-assigned this Mar 28, 2025
@carhartlewis carhartlewis added the enhancement New feature or request label Mar 28, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (22)
apps/app/src/components/ai/markdown.tsx (2)

1-1: Consider removing the eslint-disable comment if not needed

The eslint-disable rule for unused variables may not be necessary as all imported variables appear to be used in the component.

-/* eslint-disable @typescript-eslint/no-unused-vars */

6-97: Simplify component definitions and improve reusability

The component definitions contain several instances of unused destructured props (like node) and duplicate styling patterns across multiple elements.

Consider:

  1. Removing unused destructured parameters
  2. Extracting common styles into reusable variables
  3. Using more concise arrow function syntax for consistency

Example refactor for one component:

-  p: ({ node, children, ...props }) => {
-    return (
-      <p className="mb-4 leading-relaxed" {...props}>
-        {children}
-      </p>
-    );
-  },
+  p: ({ children, ...props }) => (
+    <p className="mb-4 leading-relaxed" {...props}>
+      {children}
+    </p>
+  ),
apps/app/src/components/ai/icons.tsx (2)

5-22: Improve TypeScript type definitions for consistency

The VercelIcon component would benefit from explicit type annotations for its props, similar to how SpinnerIcon is typed.

-export const VercelIcon = ({ size = 17 }) => {
+export const VercelIcon = ({ size = 17 }: { size?: number }) => {

125-158: Document CSS class purpose for GroqIcon

The GroqIcon component has a specific className="pt-1" but the purpose of this padding isn't clear. Consider adding a comment to explain why this padding is needed.

-      className="pt-1"
+      className="pt-1" /* Adds top padding to properly align the Groq logo with other elements */
apps/app/src/hooks/ai/providers.ts (1)

1-19: Good implementation of custom model provider with reasoning middleware.

The code effectively sets up a language model provider using Groq's "deepseek-r1-distill-llama-70b" model with reasoning extraction middleware. The TypeScript type export for modelID is a nice touch for type safety.

Consider these enhancements:

  1. Add JSDoc comments to explain the purpose of the exports
  2. Consider making the model name configurable instead of hardcoded
  3. Implement error handling for API connection failures
+/**
+ * Custom AI provider configuration using Groq's language models
+ * with reasoning extraction middleware.
+ */
 export const model = customProvider({
 	languageModels: {
 		"deepseek-r1-distill-llama-70b": wrapLanguageModel({
 			middleware: extractReasoningMiddleware({
 				tagName: "think",
 			}),
 			model: groq("deepseek-r1-distill-llama-70b"),
 		}),
 	},
 });

+/**
+ * Type representing the valid model IDs that can be used
+ * with the language model provider.
+ */
 export type modelID = Parameters<(typeof model)["languageModel"]>["0"];
apps/app/src/components/sheets/assistant-sheet.tsx (1)

15-19: Consider handling empty content state

The component correctly handles the null case for isOpen, but you might want to add a loading state or placeholder when the Chat component is initializing.

 <Sheet open={isOpen ?? false} onOpenChange={(open) => setIsOpen(open)}>
   <SheetContent>
-    <Chat />
+    <Chat />
   </SheetContent>
 </Sheet>
apps/app/src/components/ai/model-picker.tsx (2)

17-19: Consider displaying model-friendly names to users

The MODELS constant maps IDs to descriptive strings, but these friendly names aren't used in the UI.

 <SelectGroup>
   {Object.entries(MODELS).map(([modelId]) => (
     <SelectItem key={modelId} value={modelId}>
-      {modelId}
+      {MODELS[modelId as modelID]}
     </SelectItem>
   ))}
 </SelectGroup>

26-41: Consider making the positioning more flexible

The absolute positioning at bottom-left might not be ideal in all contexts where this component could be used.

Consider making the positioning configurable through props or using a relative positioning approach that can adapt to different container contexts.

-<div className="absolute bottom-2 left-2 flex flex-col gap-2">
+<div className="relative flex flex-col gap-2">
apps/app/src/hooks/use-scroll-to-bottom.ts (1)

1-32: Well-implemented scroll-to-bottom hook with a few considerations

The hook implementation is clean and handles the core functionality well, using MutationObserver to detect changes and trigger scrolling.

A few points to consider:

  1. The TypeScript error suppression on line 30 should be addressed properly rather than using @ts-expect-error. The return type declaration matches the actual return value, so there shouldn't be a need for this.

  2. Consider the user experience with instant scrolling. While "instant" behavior works, it might be jarring for users. Using "smooth" could provide a better experience when new content is added.

  3. The MutationObserver is watching numerous aspects (childList, subtree, attributes, characterData), which may cause performance issues with frequent scroll triggering.

  4. Consider implementing conditional scrolling - only auto-scroll if the user is already near the bottom to avoid disrupting manual scrolling to read previous messages.

- end.scrollIntoView({ behavior: "instant", block: "end" });
+ // Only auto-scroll if user is already near the bottom
+ const { scrollTop, scrollHeight, clientHeight } = container;
+ const isNearBottom = scrollTop + clientHeight >= scrollHeight - 100;
+ if (isNearBottom) {
+   end.scrollIntoView({ behavior: "smooth", block: "end" });
+ }
- // @ts-expect-error error
+ // The return type matches the declared type, no need for ts-expect-error
apps/app/src/store/assistant.ts (2)

3-7: Consider renaming setOpen to better reflect its toggle behavior

The setOpen method signature has been simplified, but its name no longer accurately reflects its behavior. Since it now toggles the open state instead of explicitly setting it, a name like toggleAssistant would be more appropriate.

interface AssistantState {
	isOpen: boolean;
	message?: string;
-	setOpen: (message?: string) => void;
+	toggleAssistant: (message?: string) => void;
}

9-13: Simplified implementation, but function name doesn't match behavior

The implementation has been simplified to toggle the assistant state rather than explicitly setting it, which is good. However, the function name setOpen suggests it would only open the assistant, when it actually toggles the state.

Also, consider the implications of removing the previous setClose method - any components that relied on explicitly closing the assistant will need to be updated.

export const useAssistantStore = create<AssistantState>()((set) => ({
	isOpen: false,
	message: undefined,
-	setOpen: (message) => set((state) => ({ isOpen: !state.isOpen, message })),
+	toggleAssistant: (message) => set((state) => ({ isOpen: !state.isOpen, message })),
}));

If maintaining separate open/close methods is preferred:

export const useAssistantStore = create<AssistantState>()((set) => ({
	isOpen: false,
	message: undefined,
	setOpen: (message?: string) => set({ isOpen: true, message }),
	setClose: () => set({ isOpen: false, message: undefined }),
}));
apps/app/src/components/ai/chat.tsx (3)

15-17: Consider making model selection more flexible

The model ID is currently hardcoded. Consider moving this to a configuration file or environment variable for easier updates.


36-36: Improve error handling UI

The current error display lacks styling and context that would help users understand what went wrong.

-  if (error) return <div>{error.message}</div>;
+  if (error) return (
+    <div className="max-w-xl mx-auto p-4 bg-red-50 dark:bg-red-900/10 border border-red-200 dark:border-red-800 rounded-md text-red-700 dark:text-red-400 mt-4">
+      <h3 className="font-medium mb-1">Error</h3>
+      <p>{error.message}</p>
+    </div>
+  );

43-43: Improve name extraction logic

The current implementation for extracting the first name could be more robust.

-            <ChatEmpty firstName={session?.user?.name?.split(" ").at(0) ?? ""} />
+            <ChatEmpty firstName={session?.user?.name ? session.user.name.split(" ")[0] : "there"} />
apps/app/src/components/ai/chat-text-area.tsx (2)

6-7: Remove unused imports

There are unused imports that should be removed.

-import app from "next/app";

41-50: Fix TypeScript error in event handler

There's a TypeScript error being suppressed with a comment. This should be fixed properly.

        onKeyDown={(e) => {
          if (e.key === "Enter" && !e.shiftKey) {
            e.preventDefault();
            if (input.trim() && !isLoading) {
-              // @ts-expect-error err
-              const form = e.target.closest("form");
+              const form = (e.target as HTMLElement).closest("form");
              if (form) form.requestSubmit();
            }
          }
        }}
apps/app/src/app/api/chat/route.ts (2)

16-16: Unused constant maxDuration.

maxDuration is declared but never used. Either remove it if unnecessary or add a comment explaining its planned usage to avoid confusion.


26-37: Standardize error responses and status codes.

You return a plain string "Unauthorized" or "Organization not found" with numeric status codes. For improved consistency and clarity, consider returning structured JSON error objects (e.g., { error: "...", code: 401 }) and centralize error response logic.

apps/app/src/components/ai/message.tsx (3)

32-60: Ensure animations are accessible.

The collapsible reasoning content uses AnimatePresence and motion.div. Verify that users with reduced motion settings or assistive technologies can access the content without difficulty. Provide appropriate ARIA attributes if needed.


74-92: Improve button accessibility.

The expand/collapse button uses an icon only. Consider adding an 'aria-label' or 'title' for screen reader support to clarify the button’s purpose.


236-245: Validate the memoization strategy.

Your custom comparison logic stops re-renders if certain props do not change. Confirm it suits all edge cases (e.g., partial object mutations). Otherwise, consider alternative patterns or specialized memoization.

apps/app/src/hooks/ai/tools.ts (1)

7-35: Ensure consistency in error handling.

You return { error: "Unauthorized" } instead of a 401 status. Check alignment with the rest of the codebase, which sometimes returns HTTP responses (e.g., 401, 404 in route.ts). Consistency helps when debugging and interpreting errors.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between da75d8c and 6452e5d.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (27)
  • apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/layout.tsx (1 hunks)
  • apps/app/src/app/[locale]/layout.tsx (1 hunks)
  • apps/app/src/app/api/chat/route.ts (1 hunks)
  • apps/app/src/components/ai/chat-empty.tsx (1 hunks)
  • apps/app/src/components/ai/chat-text-area.tsx (1 hunks)
  • apps/app/src/components/ai/chat.tsx (1 hunks)
  • apps/app/src/components/ai/icons.tsx (1 hunks)
  • apps/app/src/components/ai/markdown.tsx (1 hunks)
  • apps/app/src/components/ai/message.tsx (1 hunks)
  • apps/app/src/components/ai/messages.tsx (1 hunks)
  • apps/app/src/components/ai/model-picker.tsx (1 hunks)
  • apps/app/src/components/animated-layout.tsx (1 hunks)
  • apps/app/src/components/chat/ChatButton.tsx (0 hunks)
  • apps/app/src/components/chat/ChatInterface.tsx (0 hunks)
  • apps/app/src/components/chat/ChatProvider.tsx (0 hunks)
  • apps/app/src/components/hot-keys.tsx (2 hunks)
  • apps/app/src/components/sheets/assistant-sheet.tsx (1 hunks)
  • apps/app/src/env.mjs (2 hunks)
  • apps/app/src/hooks/ai/providers.ts (1 hunks)
  • apps/app/src/hooks/ai/tools.ts (1 hunks)
  • apps/app/src/hooks/chat/useChat.ts (0 hunks)
  • apps/app/src/hooks/use-scroll-to-bottom.ts (1 hunks)
  • apps/app/src/store/assistant.ts (1 hunks)
  • apps/app/src/store/user/store.ts (1 hunks)
  • biome.json (1 hunks)
  • package.json (2 hunks)
  • turbo.json (1 hunks)
💤 Files with no reviewable changes (4)
  • apps/app/src/components/chat/ChatProvider.tsx
  • apps/app/src/components/chat/ChatButton.tsx
  • apps/app/src/hooks/chat/useChat.ts
  • apps/app/src/components/chat/ChatInterface.tsx
🧰 Additional context used
🧬 Code Definitions (5)
apps/app/src/components/sheets/assistant-sheet.tsx (1)
apps/app/src/components/ai/chat.tsx (1)
  • Chat (12-63)
apps/app/src/components/ai/model-picker.tsx (1)
apps/app/src/hooks/ai/providers.ts (2)
  • modelID (19-19)
  • model (8-17)
apps/app/src/components/ai/messages.tsx (2)
apps/app/src/hooks/use-scroll-to-bottom.ts (1)
  • useScrollToBottom (3-32)
apps/app/src/components/ai/message.tsx (1)
  • Message (236-245)
apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/layout.tsx (5)
apps/app/src/components/hot-keys.tsx (1)
  • HotKeys (8-67)
apps/app/src/context/sidebar-context.tsx (1)
  • SidebarProvider (12-31)
apps/app/src/components/animated-layout.tsx (1)
  • AnimatedLayout (9-27)
apps/app/src/components/sidebar.tsx (1)
  • Sidebar (11-58)
apps/app/src/components/sheets/assistant-sheet.tsx (1)
  • AssistantSheet (7-21)
apps/app/src/components/ai/chat-text-area.tsx (1)
apps/app/src/hooks/ai/providers.ts (2)
  • modelID (19-19)
  • model (8-17)
🔇 Additional comments (30)
apps/app/src/components/ai/markdown.tsx (1)

101-112: Well-implemented memoization strategy

Good use of React memo with a custom comparison function to prevent unnecessary re-renders when the markdown content hasn't changed.

apps/app/src/components/ai/icons.tsx (1)

24-95: Well-structured SpinnerIcon implementation

The SpinnerIcon is well-implemented with opacity variations to create a spinner effect. The SVG structure is clean and uses best practices with clip paths and defs.

package.json (2)

44-44:

Details

❓ Verification inconclusive

Verify motion library implementation

The motion library has been added, likely for animation purposes. Ensure that it's properly implemented with fallbacks for users who prefer reduced motion.


🏁 Script executed:

#!/bin/bash
# Check for motion usage and accessibility considerations
echo "Checking for imports of the motion library..."
rg -i 'from\s+["\']motion["\']' --type=js --type=jsx --type=ts --type=tsx
echo "Checking for prefers-reduced-motion usage..."
rg -i 'prefers-reduced-motion' --type=js --type=jsx --type=ts --type=tsx --type=css

Length of output: 217


Below is an updated verification script with corrected quoting for checking both the motion library imports and the use of reduced–motion fallbacks. Please run this script manually and verify that the codebase imports the motion library as expected and that it implements any necessary fallbacks (e.g., by checking for "prefers-reduced-motion" usage):

#!/bin/bash
echo "Checking for imports of the motion library with corrected quoting..."
rg -i "from\s+[\"']motion[\"']" --type=js --type=jsx --type=ts --type=tsx
echo "Checking for prefers-reduced-motion usage..."
rg -i "prefers-reduced-motion" --type=js --type=jsx --type=ts --type=tsx --type=css

Once you’ve re-run the script, please manually verify the following in your codebase:

  • The motion library is imported where needed.
  • There is an accessibility fallback (e.g., handling for "prefers-reduced-motion").

After confirming these points, you can update the review accordingly.

Action Required: Please run the above script and check the results to ensure the implementation meets accessibility standards.


30-30:

Details

❓ Verification inconclusive

Verify GROQ API usage and environment variables

The addition of @ai-sdk/groq corresponds to the GROQ_API_KEY mentioned in the PR objectives. Ensure proper error handling is implemented when using this dependency and that the environment variable is properly configured.


🏁 Script executed:

#!/bin/bash
# Check for usage of @ai-sdk/groq and related environment variables
echo "Checking for GROQ_API_KEY in environment configuration..."
rg -i 'GROQ_API_KEY' --type=js --type=jsx --type=ts --type=tsx
echo "Checking for imports of @ai-sdk/groq..."
rg -i 'from\s+["\']@ai-sdk/groq["\']' --type=js --type=jsx --type=ts --type=tsx

Length of output: 421


Action Required: Validate GROQ API Integration and Environment Setup

  • The dependency @ai-sdk/groq has been added in package.json as per the PR objectives.
  • Our initial automated lookup for the GROQ_API_KEY environment variable and @ai-sdk/groq imports in JS/TS/TSX files was inconclusive. (The search encountered issues with file type recognition and quoting.)
  • Please run the improved script above, or manually verify that:
    • The code using @ai-sdk/groq properly checks and handles error conditions related to API calls.
    • The GROQ_API_KEY environment variable is correctly set and consumed in the appropriate parts of the codebase.

🏁 Script executed:

#!/bin/bash
# Improved checks for potential GROQ API usage with corrected file globbing
echo "Searching for GROQ_API_KEY occurrences in JS/JSX/TS/TSX files..."
rg -g '*.{js,jsx,ts,tsx}' -i 'GROQ_API_KEY'

echo "Searching for @ai-sdk/groq imports in JS/JSX/TS/TSX files..."
rg -g '*.{js,jsx,ts,tsx}' -i 'from\s+["'"'"']@ai-sdk/groq["'"'"']'

Length of output: 574


Ensure Robust Integration of @ai-sdk/groq and GROQ_API_KEY

  • The dependency @ai-sdk/groq is imported in apps/app/src/hooks/ai/providers.ts.
  • Our search did not locate any direct usage of the GROQ_API_KEY environment variable in the JS/TS code.
  • Please verify that when invoking the GROQ API via the imported groq function, the code properly checks for the presence of a valid GROQ_API_KEY and gracefully handles any errors (e.g., missing or invalid API key).
apps/app/src/components/sheets/assistant-sheet.tsx (2)

1-21: Well-structured component with appropriate state management

The AssistantSheet component is well-implemented using the useQueryState hook to synchronize the sheet's open state with the URL query parameters. This approach allows for deep-linking to the assistant and preserving its state during navigation.


8-12: URL state management is well-configured

The configuration of useQueryState with history, parse, and serialize options is appropriate for managing boolean state in the URL.

apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/layout.tsx (4)

9-10: Good additions for user state management and chat functionality

The import of UserProvider and AssistantSheet components aligns with the PR objectives to implement chat components and improve session management.


12-17: Good use of dynamic imports with SSR support

The updated dynamic import for HotKeys with explicit SSR configuration ensures server-side rendering compatibility.


19-37: Well-structured layout component with proper error handling

The component correctly extracts the session and orgId, with appropriate redirects for missing data, maintaining security.


39-52: Nicely structured component hierarchy with proper context providers

The integration of UserProvider and AssistantSheet is well-implemented, maintaining the existing functionality while adding new features.

apps/app/src/components/ai/model-picker.tsx (1)

1-43: Well-structured model selection component

Overall, the ModelPicker component is well-implemented with proper type definitions and follows a controlled component pattern.

apps/app/src/components/hot-keys.tsx (2)

6-14: Good implementation of URL-based state management

The useQueryState hook is well-configured and consistent with the implementation in the AssistantSheet component.


61-64: Properly integrated keyboard shortcut for the assistant

The "meta+k" hotkey handler correctly uses the new state management approach to open the assistant sheet.

apps/app/src/components/animated-layout.tsx (2)

1-1: Import path updated to use module alias

Good update - changing the relative import path to an absolute path using the module alias improves maintainability and readability.


4-26: Consistent formatting applied

The formatting changes improve code readability and maintain consistent style throughout the codebase while preserving the component's functionality.

apps/app/src/app/[locale]/layout.tsx (1)

14-109: Consistent formatting applied to metadata and layout

The formatting changes improve readability and maintain consistent style while preserving functionality. The indentation is now more uniform throughout the file.

apps/app/src/components/ai/messages.tsx (1)

1-34: Well-implemented component for rendering chat messages

The Messages component is cleanly structured and handles dynamic rendering of the message list with auto-scrolling capability.

For future consideration, you might want to implement virtualization if the chat history grows large, as rendering all messages at once could impact performance.

apps/app/src/components/ai/chat.tsx (1)

1-63: Overall well-structured chat component implementation

The component successfully implements the chat functionality using the AI SDK and integrates well with the session management.

apps/app/src/store/user/store.ts (2)

1-22: Good simplification of the user store

Removing the custom User type in favor of the standard NextAuth User type makes the code cleaner and more maintainable.


1-1:

Details

❓ Verification inconclusive

Verify type compatibility across codebase

You've removed a custom User type extension in favor of using the standard NextAuth User type. This is a good simplification, but ensure all necessary properties are available in the standard type.


🏁 Script executed:

#!/bin/bash
# Check for any references to removed User properties in the codebase
echo "Searching for potential references to custom User properties that might now be missing..."
rg -F "user." --type=typescript -A 2 -B 2 apps/app/src/

Length of output: 279


I'm noticing that the previous rg command failed due to an unrecognized file type error for "typescript." To verify that there are no lingering references to custom User properties, I'd like to re-run the search using file glob patterns for TypeScript files. Please run the updated shell script below and share the output:

Once we have a clear output (or if it shows no problematic references), we'll be in a stronger position to finalize the review comment. Please run this script and provide the results.


🏁 Script executed:

#!/bin/bash
echo "Searching for references to 'user.' in TypeScript files using glob filters..."
rg -F "user." --glob "*.ts" --glob "*.tsx" apps/app/src/

Length of output: 54243


Attention: Verify NextAuth User Augmentation for Extended Properties

While replacing the custom User type with NextAuth’s standard User is a good simplification, our search indicates that numerous code references (e.g., to user.organizationId) assume the availability of custom properties. Please double-check that these extended properties are correctly provided—likely via module augmentation of NextAuth’s User type—so that type compatibility is maintained across the codebase. Key areas to review include:

  • Multiple hooks and components (e.g., in apps/app/src/hooks/use-notifications.ts and others) that check for session.user.organizationId.
  • Action files (e.g., within apps/app/src/actions/policies/* and apps/app/src/actions/risk/*) where properties such as organizationId and id are used as if they’re part of the User.

Ensure that the standard NextAuth User type is properly augmented to include these properties.

apps/app/src/components/ai/chat-text-area.tsx (1)

1-117: Good implementation of the chat textarea component

Overall, the component provides a well-designed input interface for the chat with proper event handling and UI elements.

apps/app/src/app/api/chat/route.ts (2)

19-22: Add request payload validation.

Currently, the request payload is destructured without validation. Consider using a schema (e.g., zod) or manual checks to ensure the payload is safe and valid before proceeding.


56-72: Consider robust error handling for streamText.

streamText can fail if the model is invalid or network issues occur. It might be prudent to wrap this call in a try/catch or gracefully handle downstream errors to ensure consistent responses.

apps/app/src/components/ai/message.tsx (1)

174-209: Implementation looks good.

The tool invocation UI logic is concise and robust, displaying loading and completion states correctly. Good work!

apps/app/src/hooks/ai/tools.ts (3)

208-232: General approach looks fine.

Listing the policies by organization is straightforward and doesn’t reveal overly sensitive data. No immediate issues identified.


234-280: Confirm policy content visibility requirements.

Full policy content is returned, which may be sensitive. Verify your permissions logic and whether certain users should only see partial policy data.


333-361: Cloud test retrieval appears appropriate.

Returning test results and statuses is valid, and no obvious PII is exposed. This is consistent with your patterns for organization-based filtering.

apps/app/src/components/ai/chat-empty.tsx (1)

1-18: Well-structured component with good TypeScript typing

The ChatEmpty component is implemented cleanly with proper TypeScript typing and responsive design considerations. The component has a clear single responsibility and follows React best practices.

turbo.json (1)

40-41: Successfully added GROQ_API_KEY to build environment variables

The GROQ API key has been correctly added to the environment variables list for the build task, which will make it available during the build process.

apps/app/src/env.mjs (1)

29-29: GROQ_API_KEY properly configured in environment

The GROQ API key has been correctly added to both the server validation schema and the runtime environment. The implementation follows the same pattern as other API keys in the application.

Also applies to: 67-67

Comment on lines +111 to +123
export function StarButton() {
return (
<Link
href="https://github.com/vercel-labs/ai-sdk-preview-reasoning"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-700 dark:hover:text-zinc-300"
>
<Github className="size-4" />
<span className="hidden sm:inline">Star on GitHub</span>
</Link>
);
}

Copy link
Copy Markdown

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 GitHub repository link relevance

The StarButton component links to "vercel-labs/ai-sdk-preview-reasoning" which may not be related to this project (comp). Consider updating the link to point to your own repository.


🏁 Script executed:

#!/bin/bash
# Check if the repository name in package.json matches the GitHub link in StarButton
PROJECT_NAME=$(cat package.json | grep '"name"' | head -1 | awk -F'"' '{print $4}')
echo "Current project name: $PROJECT_NAME"
echo "GitHub link in StarButton: https://github.com/vercel-labs/ai-sdk-preview-reasoning"

Length of output: 331


Update GitHub Repository Link in StarButton
The StarButton component (located in apps/app/src/components/ai/icons.tsx, lines 111-123) currently points to https://github.com/vercel-labs/ai-sdk-preview-reasoning, but package.json indicates the project name is comp. Please update the link to reference the correct repository for the project.

Comment thread biome.json
"noExplicitAny": "off"
},
"a11y": {
"useValidAriaRole": "off",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Document reason for disabling ARIA role validation

Disabling the useValidAriaRole rule reduces accessibility enforcement. Consider adding a comment explaining why this rule was disabled or explore alternatives that maintain accessibility standards.


🏁 Script executed:

#!/bin/bash
# Search for custom ARIA roles in the codebase that might be causing validation issues
echo "Searching for aria-role attributes in the codebase..."
rg -i 'aria-role|role=' --type=jsx --type=tsx -A 2 -B 2

Length of output: 202


ACTION REQUIRED: Document Disabled ARIA Role Validation
• In biome.json at line 18, add a comment explaining why the useValidAriaRole rule is turned off.
• Since our initial search using the linter’s file type flags failed (causing an “unrecognized file type: jsx” error), please re-run the attached script (or verify manually) to confirm that there aren’t custom ARIA role usages that would otherwise enforce accessibility.
• If custom roles aren’t found and disabling the rule is intentional (e.g., to support legacy or third‑party code), documenting that rationale will aid future maintainers.


🏁 Script executed:

#!/bin/bash
# Re-run search for ARIA role attributes in JSX/TSX files using explicit file globs
echo "Re-running search for ARIA role attributes in .jsx and .tsx files using globs..."
rg -i 'aria-role|role=' --glob '*.jsx' --glob '*.tsx' -A 2 -B 2

Length of output: 5100


ACTION REQUIRED: Document the Rationale for Disabling useValidAriaRole

It appears that disabling the useValidAriaRole rule was an intentional choice—likely to avoid false positives with valid ARIA roles, as our search confirms that components are using standard roles (e.g., "presentation", "alert", "region", "group", etc.). To help future maintainers understand this decision, please add an inline comment in biome.json (around line 18) explaining why this rule was turned off. For example, you might note that the linter was flagging valid ARIA usages from our UI components and that disabling the rule prevents misleading errors while preserving accessibility standards.

File: biome.json (line 18)

  • Add a comment such as:
    // Disabled "useValidAriaRole" because the linter was flagging valid ARIA roles used in our components,
    // which produce false positives. This decision helps avoid unnecessary warnings while keeping our UI accessible.
    "useValidAriaRole": "off",

Comment on lines +15 to +17
selectedModel: modelID;
setSelectedModel: (model: modelID) => void;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Model selection props are unused

The component accepts selectedModel and setSelectedModel props but doesn't use them anywhere. Either implement the model selection UI or remove these props if they're not needed.

Comment on lines +30 to +32
const handleOpenUrl = (url: string) => {
router.push(url);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix URL navigation for external links

The current implementation uses Next.js router for external URLs, which is not the correct approach.

-  const handleOpenUrl = (url: string) => {
-    router.push(url);
-  };
+  const handleOpenUrl = (url: string) => {
+    window.open(url, '_blank', 'noopener,noreferrer');
+  };
📝 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
const handleOpenUrl = (url: string) => {
router.push(url);
};
const handleOpenUrl = (url: string) => {
window.open(url, '_blank', 'noopener,noreferrer');
};

Comment on lines +40 to +54
const systemPrompt = `
You are an expert in governance, risk, and compliance.

You're a helpful assistant in Comp AI, a platform that helps companies
get compliant with frameworks like SOC 2, ISO 27001 and GDPR - similar to Vanta and Drata.

You have access to various tools to help gather information. You can:
1. Use multiple tools in sequence to gather comprehensive information
2. Chain tool calls together to get more detailed information
3. Use tools to verify or expand upon information from previous tool calls

When using tools:
- Start with broader queries to get an overview
- Then use specific queries to get detailed information
`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract the system prompt into a dedicated configuration.

The multi-line system prompt could be moved to a separate file or constants configuration, improving readability and maintainability—especially if it grows further or requires updates.

Comment on lines +212 to +224
<ReasoningMessagePart
key={`message-${message.id}-${i}`}
// @ts-expect-error part
part={part}
isReasoning={
(message.parts &&
status === "streaming" &&
i === message.parts.length - 1) ??
false
}
/>
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid @ts-expect-error usage.

The @ts-expect-error suppresses type checks for part. Define a specific type union or fix the method signature to ensure correctness and maintainable typings.

Comment on lines +80 to +157
export const getVendorDetailsTool = tool({
description: "Get detailed information about a specific vendor",
parameters: z.object({
vendorId: z.string(),
}),
execute: async ({ vendorId }) => {
const session = await auth();

if (!session?.user.organizationId) {
return { error: "Unauthorized" };
}

const vendor = await db.vendor.findFirst({
where: {
id: vendorId,
organizationId: session.user.organizationId,
},
select: {
id: true,
name: true,
description: true,
category: true,
status: true,
inherentRisk: true,
residualRisk: true,
createdAt: true,
updatedAt: true,
owner: {
select: {
name: true,
email: true,
},
},
contacts: {
select: {
name: true,
email: true,
phone: true,
},
},
tasks: {
select: {
id: true,
title: true,
description: true,
status: true,
dueDate: true,
completedAt: true,
owner: {
select: {
name: true,
email: true,
},
},
},
},
comments: {
select: {
content: true,
createdAt: true,
owner: {
select: {
name: true,
email: true,
},
},
},
},
},
});

if (!vendor) {
return { error: "Vendor not found" };
}

return vendor;
},
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential PII exposure in vendor details.

Phone numbers, emails, and other sensitive data are returned. Consider restricting or redacting sensitive fields based on user roles or implementing additional data access controls if needed to comply with data privacy policies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant