Update dependencies, add GROQ_API_KEY to env, and implement chat comp…#225
Conversation
…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.
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
1 Skipped Deployment
|
WalkthroughThis pull request introduces new components and state management for the chat and dashboard layouts. A new Changes
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
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
Possibly related PRs
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
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 neededThe 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 reusabilityThe component definitions contain several instances of unused destructured props (like
node) and duplicate styling patterns across multiple elements.Consider:
- Removing unused destructured parameters
- Extracting common styles into reusable variables
- 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 consistencyThe
VercelIconcomponent would benefit from explicit type annotations for its props, similar to howSpinnerIconis typed.-export const VercelIcon = ({ size = 17 }) => { +export const VercelIcon = ({ size = 17 }: { size?: number }) => {
125-158: Document CSS class purpose for GroqIconThe 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
modelIDis a nice touch for type safety.Consider these enhancements:
- Add JSDoc comments to explain the purpose of the exports
- Consider making the model name configurable instead of hardcoded
- 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 stateThe 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 usersThe
MODELSconstant 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 flexibleThe 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 considerationsThe hook implementation is clean and handles the core functionality well, using MutationObserver to detect changes and trigger scrolling.
A few points to consider:
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.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.
The MutationObserver is watching numerous aspects (childList, subtree, attributes, characterData), which may cause performance issues with frequent scroll triggering.
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-errorapps/app/src/store/assistant.ts (2)
3-7: Consider renamingsetOpento better reflect its toggle behaviorThe
setOpenmethod 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 liketoggleAssistantwould 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 behaviorThe implementation has been simplified to toggle the assistant state rather than explicitly setting it, which is good. However, the function name
setOpensuggests it would only open the assistant, when it actually toggles the state.Also, consider the implications of removing the previous
setClosemethod - 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 flexibleThe model ID is currently hardcoded. Consider moving this to a configuration file or environment variable for easier updates.
36-36: Improve error handling UIThe 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 logicThe 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 importsThere are unused imports that should be removed.
-import app from "next/app";
41-50: Fix TypeScript error in event handlerThere'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 constantmaxDuration.
maxDurationis 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
AnimatePresenceandmotion.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 inroute.ts). Consistency helps when debugging and interpreting errors.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
bun.lockis excluded by!**/*.lockyarn.lockis 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 strategyGood 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 implementationThe 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
motionlibrary 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=cssLength 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=cssOnce 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/groqcorresponds 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=tsxLength of output: 421
Action Required: Validate GROQ API Integration and Environment Setup
- The dependency
@ai-sdk/groqhas been added inpackage.jsonas per the PR objectives.- Our initial automated lookup for the
GROQ_API_KEYenvironment variable and@ai-sdk/groqimports 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/groqproperly checks and handles error conditions related to API calls.- The
GROQ_API_KEYenvironment 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/groqis imported inapps/app/src/hooks/ai/providers.ts.- Our search did not locate any direct usage of the
GROQ_API_KEYenvironment variable in the JS/TS code.- Please verify that when invoking the GROQ API via the imported
groqfunction, the code properly checks for the presence of a validGROQ_API_KEYand 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 managementThe
AssistantSheetcomponent is well-implemented using theuseQueryStatehook 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-configuredThe configuration of
useQueryStatewith 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 functionalityThe import of
UserProviderandAssistantSheetcomponents aligns with the PR objectives to implement chat components and improve session management.
12-17: Good use of dynamic imports with SSR supportThe updated dynamic import for
HotKeyswith explicit SSR configuration ensures server-side rendering compatibility.
19-37: Well-structured layout component with proper error handlingThe component correctly extracts the session and orgId, with appropriate redirects for missing data, maintaining security.
39-52: Nicely structured component hierarchy with proper context providersThe integration of
UserProviderandAssistantSheetis 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 componentOverall, the
ModelPickercomponent 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 managementThe
useQueryStatehook is well-configured and consistent with the implementation in theAssistantSheetcomponent.
61-64: Properly integrated keyboard shortcut for the assistantThe "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 aliasGood update - changing the relative import path to an absolute path using the module alias improves maintainability and readability.
4-26: Consistent formatting appliedThe 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 layoutThe 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 messagesThe 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 implementationThe 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 storeRemoving 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
rgcommand 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.tsand others) that check forsession.user.organizationId.- Action files (e.g., within
apps/app/src/actions/policies/*andapps/app/src/actions/risk/*) where properties such asorganizationIdandidare 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 componentOverall, 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 forstreamText.
streamTextcan 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 typingThe
ChatEmptycomponent 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 variablesThe 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 environmentThe 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
| 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> | ||
| ); | ||
| } |
There was a problem hiding this comment.
💡 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.
| "noExplicitAny": "off" | ||
| }, | ||
| "a11y": { | ||
| "useValidAriaRole": "off", |
There was a problem hiding this comment.
💡 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 2Length 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 2Length 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",
| selectedModel: modelID; | ||
| setSelectedModel: (model: modelID) => void; | ||
| } |
There was a problem hiding this comment.
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.
| const handleOpenUrl = (url: string) => { | ||
| router.push(url); | ||
| }; |
There was a problem hiding this comment.
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.
| const handleOpenUrl = (url: string) => { | |
| router.push(url); | |
| }; | |
| const handleOpenUrl = (url: string) => { | |
| window.open(url, '_blank', 'noopener,noreferrer'); | |
| }; |
| 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 | ||
| `; |
There was a problem hiding this comment.
🛠️ 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.
| <ReasoningMessagePart | ||
| key={`message-${message.id}-${i}`} | ||
| // @ts-expect-error part | ||
| part={part} | ||
| isReasoning={ | ||
| (message.parts && | ||
| status === "streaming" && | ||
| i === message.parts.length - 1) ?? | ||
| false | ||
| } | ||
| /> | ||
| ); | ||
| } |
There was a problem hiding this comment.
🛠️ 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.
| 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; | ||
| }, | ||
| }); |
There was a problem hiding this comment.
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.
…onents
Summary by CodeRabbit
New Features
Refactor