Conversation
- Introduced `ToolExecutionCard` component to display the status of tool executions with detailed information including input, output, and error handling. - Created `ToolExecutionList` component to render a list of `ToolExecutionCard` components, allowing for easy management of multiple tool executions. - Implemented `WorkflowExecution` component to manage and display the progress of workflow steps, including pause, resume, and retry functionalities. - Added `WorkflowTimeline` component for visual representation of workflow steps in both vertical and horizontal orientations. - Developed `AnimatedBeam` and `BackgroundBeams` components for enhanced visual effects in the UI. - Introduced `BentoGrid` and `BentoGridItem` components for structured layout of items in a grid format. - Created `BorderBeam` component for animated border effects around elements. - Added `CardSpotlight` and `Spotlight` components for dynamic spotlight effects on hover. - Implemented `TextGenerateEffect` for animated text rendering with staggered effects. - Enhanced UI with various utility functions and styles for better visual consistency and user experience.
|
Keep this PR in a mergeable state → Learn moreAll Green is an AI agent that automatically: ✅ Addresses code review comments ✅ Fixes failing CI checks ✅ Resolves merge conflicts |
There was a problem hiding this comment.
Sorry @ssdeanx, your pull request is larger than the review limit of 150000 diff characters
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughAdds model-awareness to chat context, enhances many agent UI components (chain-of-thought, plan, queue, checkpoints, confirmations, sources, tools), introduces numerous visual/effect components and AI UI widgets, updates landing/product pages and global theme tokens, and restructures navbar/layout. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
|
🤖 Hi @ssdeanx, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
|
🤖 I'm sorry @ssdeanx, but I was unable to process your request. Please see the logs for more details. |
Summary of ChangesHello @ssdeanx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a suite of new, highly interactive UI components designed to enhance the visualization and management of tool executions and complex workflows. It also brings significant improvements to existing chat-related components, providing users with richer feedback and more intuitive controls. The overall user experience is elevated through a redesigned navigation, new product landing pages, and a refined visual theme, making the platform more engaging and informative for managing AI agent interactions. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
|
||
| ## Current Focus (Dec 2025) | ||
|
|
||
| - **[Synced Dec 8, 2025]** Chat Components Production Grade - 11 components improved with enhanced UX. |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when references to undefined definitions are found. Note
|
|
||
| ## Current Focus (Dec 2025) | ||
|
|
||
| - **[Synced Dec 8, 2025]** Chat Components Production Grade - 11 components improved with enhanced UX. |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when shortcut reference links are used. Note
| ## Current Focus (Dec 2025) | ||
|
|
||
| - **[Synced Dec 8, 2025]** Chat Components Production Grade - 11 components improved with enhanced UX. | ||
| - **[Synced Dec 8, 2025]** Workflow System Audit complete - 12 workflows verified, 2 added to frontend config. |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when references to undefined definitions are found. Note
| ## Current Focus (Dec 2025) | ||
|
|
||
| - **[Synced Dec 8, 2025]** Chat Components Production Grade - 11 components improved with enhanced UX. | ||
| - **[Synced Dec 8, 2025]** Workflow System Audit complete - 12 workflows verified, 2 added to frontend config. |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when shortcut reference links are used. Note
| - **[Synced Dec 5, 2025]** AI Elements Integration 92% complete (12/13 tasks). Chat interface fully functional. | ||
| - **[NEW]** Models Configuration System: 150+ models from 6 providers, shared between `/chat` and `/networks`. | ||
| - **[COMPLETED]** Workflows UI 100% complete - 10 workflows with Canvas visualization, input panels, streaming output. | ||
| - **[COMPLETED]** Workflows UI 100% complete - 12 workflows with Canvas visualization, input panels, streaming output. |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when references to undefined definitions are found. Note
| - **[Synced Dec 5, 2025]** AI Elements Integration 92% complete (12/13 tasks). Chat interface fully functional. | ||
| - **[NEW]** Models Configuration System: 150+ models from 6 providers, shared between `/chat` and `/networks`. | ||
| - **[COMPLETED]** Workflows UI 100% complete - 10 workflows with Canvas visualization, input panels, streaming output. | ||
| - **[COMPLETED]** Workflows UI 100% complete - 12 workflows with Canvas visualization, input panels, streaming output. |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when shortcut reference links are used. Note
| # Progress | ||
|
|
||
| ## What's Done **[Synced Dec 5 from dirs/AGENTS.md]** | ||
| ## What's Done **[Synced Dec 8 from session work]** |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when references to undefined definitions are found. Note
| # Progress | ||
|
|
||
| ## What's Done **[Synced Dec 5 from dirs/AGENTS.md]** | ||
| ## What's Done **[Synced Dec 8 from session work]** |
Check notice
Code scanning / Remark-lint (reported by Codacy)
Warn when shortcut reference links are used. Note
There was a problem hiding this comment.
Csslint (reported by Codacy) found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
There was a problem hiding this comment.
Stylelint (reported by Codacy) found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
There was a problem hiding this comment.
Pull request overview
This pull request introduces a comprehensive set of new UI components for tool execution and workflow management, along with significant enhancements to the chat interface and landing page. The PR adds visual effects components (animated beams, spotlights, borders), workflow visualization tools, and production-grade improvements to 11 chat components. Additionally, it includes 2 new workflows (repoIngestionWorkflow and specGenerationWorkflow), bringing the total to 12 workflows.
Key Changes:
- Added 7 new visual effect components for enhanced UI (text-generate, spotlight, card-spotlight, border-beam, bento-grid, background-beams, animated-beam)
- Created 5 new custom AI components for workflow/tool execution (WorkflowExecution, ToolExecutionCard, ThinkingIndicator, CodeEditor, AgentResponse)
- Enhanced 11 chat components with production-grade UX improvements (agent-task, agent-tools, agent-reasoning, agent-chain-of-thought, agent-plan, agent-sources, agent-suggestions, agent-queue, agent-confirmation, agent-checkpoint, chat-input)
- Simplified and modernized navbar and landing page components
- Added 2 new workflows to frontend configuration
Reviewed changes
Copilot reviewed 64 out of 65 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/effects/*.tsx | 7 new visual effect components for animations and styling |
| src/components/ai-elements/custom/*.tsx | 5 new custom AI components with enhanced functionality |
| src/components/ai-elements/custom/index.ts | Barrel export file for custom components |
| src/mastra/index.ts | Added tracer configuration for agents |
| app/workflows/config/workflows.ts | Added 2 new workflow configurations |
| app/workflows/components/workflow-node.tsx | Fixed pending/skipped status bug |
| app/chat/components/*.tsx | Enhanced 11 components with better UX |
| app/components/*.tsx | Simplified and modernized landing/navbar |
| app/layout.tsx | Restructured with global Navbar |
| app/globals.css | Formatting improvements and dark theme updates |
| memory-bank/*.md | Updated progress and context tracking |
| { icon: SparklesIcon, delay: 1, x: -80, y: 60 }, | ||
| { icon: ZapIcon, delay: 1.5, x: 140, y: 40 }, | ||
| ] | ||
| import { MessageSquareIcon, NetworkIcon, GitBranchIcon, ArrowRightIcon } from "lucide-react" |
There was a problem hiding this comment.
Unused imports ArrowRightIcon, GitBranchIcon, MessageSquareIcon, NetworkIcon.
| import { MessageSquareIcon, NetworkIcon, GitBranchIcon, ArrowRightIcon } from "lucide-react" |
| "use client" | ||
|
|
||
| import { useEffect, useRef, useState } from "react" | ||
| import { motion, useAnimation } from "framer-motion" |
There was a problem hiding this comment.
Unused imports motion, useAnimation.
| import { Button } from "@/ui/button"; | ||
| import { BackgroundBeams } from "@/ui/effects/background-beams"; | ||
| import { ChatShowcase } from "@/app/components/features/chat-showcase"; | ||
| import { BentoGrid, BentoGridItem } from "@/ui/effects/bento-grid"; |
There was a problem hiding this comment.
Unused import BentoGridItem.
| import { ChatShowcase } from "@/app/components/features/chat-showcase"; | ||
| import { BentoGrid, BentoGridItem } from "@/ui/effects/bento-grid"; | ||
| import { CardSpotlight } from "@/ui/effects/card-spotlight"; | ||
| import { BotIcon, ZapIcon, BrainIcon, CodeIcon } from "lucide-react"; |
There was a problem hiding this comment.
Unused import BotIcon.
| @@ -0,0 +1,31 @@ | |||
| "use client"; | |||
| import React from "react"; | |||
| import { motion } from "framer-motion"; | |||
There was a problem hiding this comment.
Unused import motion.
| "use client"; | ||
|
|
||
| import React, { useRef, useState, useCallback, useEffect } from "react"; | ||
| import { motion, useSpring, useTransform, MotionValue } from "framer-motion"; |
There was a problem hiding this comment.
Unused imports MotionValue, useTransform.
| }; | ||
|
|
||
| export function Spotlight({ className, fill = "white" }: SpotlightProps) { | ||
| const divRef = useRef<HTMLDivElement>(null); |
There was a problem hiding this comment.
Unused variable divRef.
|
|
||
| export function Spotlight({ className, fill = "white" }: SpotlightProps) { | ||
| const divRef = useRef<HTMLDivElement>(null); | ||
| const [isMounted, setIsMounted] = useState(false); |
There was a problem hiding this comment.
Unused variable isMounted.
| setIsMounted(true); | ||
| }, []); | ||
|
|
||
| const handleMouseMove = useCallback( |
There was a problem hiding this comment.
Unused variable handleMouseMove.
Greptile OverviewGreptile SummaryAdds comprehensive UI component library for tool execution and workflow visualization, including 7 new visual effect components and 5 custom AI elements with rich animations and interactivity. Key Changes:
Issues Found:
Confidence Score: 4/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant User
participant WorkflowUI as Workflow UI
participant Context as WorkflowContext
participant Transport as DefaultChatTransport
participant MastraAPI as Mastra API
participant Workflow as WorkflowEngine
participant Agent as Agent/Tool
User->>WorkflowUI: Select workflow & input data
WorkflowUI->>Context: runWorkflow(inputData)
Context->>Context: Update status to "running"
Context->>Transport: sendMessage(inputData)
Transport->>MastraAPI: POST /workflow/:workflowId
MastraAPI->>Workflow: Execute workflow steps
loop For each step
Workflow->>Agent: Execute step (tool/agent)
Agent-->>Workflow: Step result
Workflow-->>MastraAPI: Stream step progress
MastraAPI-->>Transport: Stream chunk (tool-call, tool-result)
Transport-->>Context: Update messages
Context-->>WorkflowUI: Update step status
WorkflowUI-->>User: Show progress animation
end
Workflow-->>MastraAPI: Workflow complete
MastraAPI-->>Transport: Stream finish chunk
Transport-->>Context: Update status to "completed"
Context-->>WorkflowUI: Render completion state
WorkflowUI-->>User: Show success message
alt Pause requested
User->>WorkflowUI: Click pause
WorkflowUI->>Context: pauseWorkflow()
Context->>Context: Update status to "paused"
Context-->>WorkflowUI: Re-render with resume button
end
alt Error occurs
Agent-->>Workflow: Error
Workflow-->>MastraAPI: Stream error
MastraAPI-->>Transport: Error chunk
Transport-->>Context: Update status to "error"
Context-->>WorkflowUI: Show error state
WorkflowUI-->>User: Show retry option
end
|
| export function Spotlight({ className, fill = "white" }: SpotlightProps) { | ||
| const divRef = useRef<HTMLDivElement>(null); | ||
| const [isMounted, setIsMounted] = useState(false); | ||
|
|
||
| const mouseX = useSpring(0, { stiffness: 500, damping: 100 }); | ||
| const mouseY = useSpring(0, { stiffness: 500, damping: 100 }); | ||
|
|
||
| useEffect(() => { | ||
| setIsMounted(true); | ||
| }, []); | ||
|
|
||
| const handleMouseMove = useCallback( | ||
| ({ currentTarget, clientX, clientY }: React.MouseEvent) => { | ||
| const { left, top } = currentTarget.getBoundingClientRect(); | ||
| const x = clientX - left; | ||
| const y = clientY - top; | ||
| mouseX.set(x); | ||
| mouseY.set(y); | ||
| }, |
There was a problem hiding this comment.
style: Unused variables: divRef, isMounted, mouseX, mouseY, and handleMouseMove are declared but never used in the component.
| export function Spotlight({ className, fill = "white" }: SpotlightProps) { | |
| const divRef = useRef<HTMLDivElement>(null); | |
| const [isMounted, setIsMounted] = useState(false); | |
| const mouseX = useSpring(0, { stiffness: 500, damping: 100 }); | |
| const mouseY = useSpring(0, { stiffness: 500, damping: 100 }); | |
| useEffect(() => { | |
| setIsMounted(true); | |
| }, []); | |
| const handleMouseMove = useCallback( | |
| ({ currentTarget, clientX, clientY }: React.MouseEvent) => { | |
| const { left, top } = currentTarget.getBoundingClientRect(); | |
| const x = clientX - left; | |
| const y = clientY - top; | |
| mouseX.set(x); | |
| mouseY.set(y); | |
| }, | |
| export function Spotlight({ className, fill = "white" }: SpotlightProps) { |
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/effects/spotlight.tsx
Line: 12:30
Comment:
**style:** Unused variables: `divRef`, `isMounted`, `mouseX`, `mouseY`, and `handleMouseMove` are declared but never used in the component.
```suggestion
export function Spotlight({ className, fill = "white" }: SpotlightProps) {
```
How can I resolve this? If you propose a fix, please make it concise.| // Create a portal-like effect or just huge blur | ||
| // Actually, for a pure decorative spotlight usually placed in a container: | ||
| // we need the parent to handle mouse move if it's "following". | ||
| // BUT the common "Spotlight" component (Aceternity style) is fixed and just animates into view. | ||
| // Wait, the USER asked for "Aceternity UI" Spotlight specifically. | ||
| // Aceternity's "Spotlight" is actually a fixed SVG that creates a dramatic cone of light. | ||
| // Aceternity's "HoverBorderGradient" or "CardSpotlight" is what follows the mouse. |
There was a problem hiding this comment.
style: Remove implementation comment that's leftover from development - not needed in production code.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/effects/spotlight.tsx
Line: 34:40
Comment:
**style:** Remove implementation comment that's leftover from development - not needed in production code.
How can I resolve this? If you propose a fix, please make it concise.| className | ||
| )} | ||
| > | ||
| <div className="absolute inset-0 bg-linear-to-b from-transparent via-neutral-950 to-neutral-950 z-0 pointer-events-none" /> |
There was a problem hiding this comment.
syntax: bg-linear-to-b is invalid Tailwind CSS syntax - should be bg-gradient-to-b.
| <div className="absolute inset-0 bg-linear-to-b from-transparent via-neutral-950 to-neutral-950 z-0 pointer-events-none" /> | |
| <div className="absolute inset-0 bg-gradient-to-b from-transparent via-neutral-950 to-neutral-950 z-0 pointer-events-none" /> |
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/effects/background-beams.tsx
Line: 14:14
Comment:
**syntax:** `bg-linear-to-b` is invalid Tailwind CSS syntax - should be `bg-gradient-to-b`.
```suggestion
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-neutral-950 to-neutral-950 z-0 pointer-events-none" />
```
How can I resolve this? If you propose a fix, please make it concise.| <div className="absolute top-1/4 left-1/4 w-[30rem] h-[30rem] bg-pink-500/20 rounded-full blur-[8rem] animate-pulse-glow [animation-delay:2s]" /> | ||
| </div> | ||
| {/* Grid Pattern */} | ||
| <div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20 brightness-100 contrast-150" /> |
There was a problem hiding this comment.
logic: External URL dependency - the noise.svg is loaded from an external domain which could fail or change. Consider hosting this asset locally or making it optional.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/effects/background-beams.tsx
Line: 20:20
Comment:
**logic:** External URL dependency - the noise.svg is loaded from an external domain which could fail or change. Consider hosting this asset locally or making it optional.
How can I resolve this? If you propose a fix, please make it concise.| import React from "react"; | ||
| import { motion } from "framer-motion"; |
There was a problem hiding this comment.
style: motion from framer-motion is imported but never used in this component.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/effects/background-beams.tsx
Line: 2:3
Comment:
**style:** `motion` from framer-motion is imported but never used in this component.
How can I resolve this? If you propose a fix, please make it concise.| return () => { | ||
| window.removeEventListener("resize", resizeCanvas) | ||
| if (requestRef.current) {cancelAnimationFrame(requestRef.current)} | ||
| containerRef.current?.removeEventListener("mousemove", handleMouseMove) |
There was a problem hiding this comment.
logic: Memory leak: accessing containerRef.current in cleanup could reference a stale value - the ref value captured in cleanup might differ from the one where the listener was added.
| containerRef.current?.removeEventListener("mousemove", handleMouseMove) | |
| const container = containerRef.current | |
| container?.addEventListener("mousemove", handleMouseMove) | |
| return () => { | |
| window.removeEventListener("resize", resizeCanvas) | |
| if (requestRef.current) {cancelAnimationFrame(requestRef.current)} | |
| container?.removeEventListener("mousemove", handleMouseMove) | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/components/network-background.tsx
Line: 148:148
Comment:
**logic:** Memory leak: accessing `containerRef.current` in cleanup could reference a stale value - the ref value captured in cleanup might differ from the one where the listener was added.
```suggestion
const container = containerRef.current
container?.addEventListener("mousemove", handleMouseMove)
return () => {
window.removeEventListener("resize", resizeCanvas)
if (requestRef.current) {cancelAnimationFrame(requestRef.current)}
container?.removeEventListener("mousemove", handleMouseMove)
}
```
How can I resolve this? If you propose a fix, please make it concise.| delay: stagger(0.2), | ||
| } | ||
| ); | ||
| }, [scope.current]); |
There was a problem hiding this comment.
logic: Missing dependency in useEffect - animate and filter should be included in the dependency array to avoid stale closures.
| }, [scope.current]); | |
| }, [scope.current, animate, filter, duration]); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/effects/text-generate.tsx
Line: 32:32
Comment:
**logic:** Missing dependency in useEffect - `animate` and `filter` should be included in the dependency array to avoid stale closures.
```suggestion
}, [scope.current, animate, filter, duration]);
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Code Review
This is an impressive pull request that introduces a significant number of high-quality UI components and visual effects, greatly enhancing the user experience for tool execution and workflow management. The refactoring of existing components to be more informative and robust is excellent, and the move to a centralized model management system is a solid architectural improvement. I've identified one high-severity bug related to file uploads that needs to be addressed. Otherwise, this is a fantastic contribution that substantially improves the frontend.
| if (!text.trim() || isLoading) {return} | ||
| setChatError(null) | ||
| aiSendMessage({ text: text.trim() }) |
There was a problem hiding this comment.
The sendMessage function is defined to accept a files argument, but these files are not being passed to the aiSendMessage call. This will prevent file uploads from working, as the useChat hook needs the files to be included in the object passed to its sendMessage function. The initial check should also be updated to allow sending messages that contain only files.
| if (!text.trim() || isLoading) {return} | |
| setChatError(null) | |
| aiSendMessage({ text: text.trim() }) | |
| if ((!text.trim() && (!files || files.length === 0)) || isLoading) {return} | |
| setChatError(null) | |
| aiSendMessage({ text: text.trim(), files }) |
There was a problem hiding this comment.
Actionable comments posted: 70
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (16)
app/components/changelog-list.tsx (2)
55-111: Add TSDoc documentation for the exported component.Per coding guidelines, public APIs must include TSDoc/JSDoc comments with descriptions and usage context. The
ChangelogListcomponent is exported but lacks documentation.Apply this diff to add proper documentation:
+/** + * Renders a timeline-based changelog displaying versioned release notes. + * + * Features: + * - Animated timeline with release entries + * - Categorized changes (feature, fix, improvement, breaking) + * - Color-coded icons for change types + * - Smooth scroll-triggered animations + * + * @returns {JSX.Element} The rendered changelog component + * + * @example + * ```tsx + * <ChangelogList /> + * ``` + */ export function ChangelogList() {
7-53: Define explicit TypeScript types for changelog constants.The constants lack explicit type annotations, forcing type-casting in the component (lines 94–95). Formalizing these types improves type safety, IDE support, and maintainability.
Apply this diff to add type definitions:
+type ChangeType = "feature" | "fix" | "improvement" | "breaking" + +interface ChangelogEntry { + version: string + date: string + type: "release" + changes: Array<{ + type: ChangeType + text: string + }> +} + -const CHANGELOG_ENTRIES = [ +const CHANGELOG_ENTRIES: ChangelogEntry[] = [Then update the icon and color mappings:
-const CHANGE_ICONS = { +const CHANGE_ICONS: Record<ChangeType, React.ComponentType<{ className?: string }>> = { feature: SparklesIcon, fix: BugIcon, improvement: WrenchIcon, breaking: ZapIcon, } -const CHANGE_COLORS = { +const CHANGE_COLORS: Record<ChangeType, string> = { feature: "text-green-500", fix: "text-red-500", improvement: "text-blue-500", breaking: "text-yellow-500", }Then simplify the type-casting in the component (lines 94–95):
-const Icon = CHANGE_ICONS[change.type as keyof typeof CHANGE_ICONS] || SparklesIcon -const colorClass = CHANGE_COLORS[change.type as keyof typeof CHANGE_COLORS] || "text-primary" +const Icon = CHANGE_ICONS[change.type] +const colorClass = CHANGE_COLORS[change.type]memory-bank/activeContext.md (1)
1-12: Resolve line length violations for improved readability.Several lines exceed the 80-character limit specified in the coding guidelines for markdown files. Review and reformat the following lines to improve readability:
- Line 8: ~107 characters ("Models Configuration System: 150+ models...")
- Line 14: ~103 characters ("Next.js 16 frontend with Vercel-style...")
- Lines 344, 352: Similar length violations in later sections
Consider breaking longer bullet points across multiple lines or restructuring content to fit within the 80-character limit for improved readability in plain-text environments.
As an example refactor for line 8:
- - **[NEW]** Models Configuration System: 150+ models from 6 providers, shared between `/chat` and `/networks`. + - **[NEW]** Models Configuration System: 150+ models from 6 providers, + shared between `/chat` and `/networks`.app/components/blog-share.client.tsx (2)
1-7: Rename file to follow PascalCase naming convention.The file is located in the
app/components/directory and should use PascalCase per the coding guidelines. Renameblog-share.client.tsxtoBlogShare.client.tsx.
25-25: Simplify onClick handler.The arrow function wrapper
() => handleShare()can be simplified to direct function referencehandleSharesince no parameters are being passed.- <Button variant="ghost" size="sm" onClick={() => handleShare()}> + <Button variant="ghost" size="sm" onClick={handleShare}>app/components/landing-testimonials.tsx (1)
9-76: Add TypeScript type definitions for testimonials data.The
TESTIMONIALSarray lacks type definitions, reducing type safety and IDE support.Define an interface for the testimonial structure:
interface Testimonial { quote: string; author: string; title: string; company: string; avatar: string; rating: number; highlight: string; industry: string; } const TESTIMONIALS: Testimonial[] = [ // ... existing testimonials ]app/components/docs-layout.tsx (2)
35-46: Remove or use the unused JSON-LD object.The
ldvariable containing JSON-LD structured data is computed but never rendered in the JSX. This is dead code that provides no SEO benefit.If SEO structured data is needed, render it in a script tag:
+ <script + type="application/ld+json" + dangerouslySetInnerHTML={{ __html: JSON.stringify(ld) }} + />Otherwise, remove the unused
useMemoto avoid unnecessary computation.
120-137: Remove unnecessary type assertions.Lines 124 and 131 use
as anyto bypass type checking for thehrefprop. SinceprevPage.hrefandnextPage.hrefare already typed asstringin the interface, these assertions are unnecessary and reduce type safety.Apply this diff to remove the type assertions:
- <Link href={prevPage.href as any}> + <Link href={prevPage.href}> <ArrowLeftIcon className="mr-2 size-4" /> {prevPage.title} </Link>- <Link href={nextPage.href as any}> + <Link href={nextPage.href}> {nextPage.title} <ChevronRightIcon className="ml-2 size-4" /> </Link>app/workflows/config/workflows.ts (1)
1-4: Update outdated workflow count in documentation.The comment states "all 10 Mastra workflows" but the configuration now includes 12 workflows (with the addition of
repoIngestionWorkflowandspecGenerationWorkflow).Update the file header:
/** * Workflow Configuration System - * Centralized configuration for all 10 Mastra workflows with UI metadata. + * Centralized configuration for all 12 Mastra workflows with UI metadata. */app/components/footer.tsx (1)
50-60: Subscription handler lacks error handling and email validation.The
handleSubscribefunction always succeeds (simulated), but when integrated with a real API:
- No
try...catchblock exists for the async operation- No email format validation before submission
- The "error" state is defined but never used
Consider adding proper error handling for production readiness:
const handleSubscribe = async (e: React.FormEvent) => { e.preventDefault() if (!email) {return} + + // Basic email validation + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + setStatus("error") + return + } setStatus("loading") - // Simulate API call - await new Promise((resolve) => setTimeout(resolve, 1000)) - setStatus("success") - setEmail("") - setTimeout(() => setStatus("idle"), 3000) + try { + // Replace with actual API call + await new Promise((resolve) => setTimeout(resolve, 1000)) + setStatus("success") + setEmail("") + setTimeout(() => setStatus("idle"), 3000) + } catch { + setStatus("error") + setTimeout(() => setStatus("idle"), 3000) + } }As per coding guidelines, use
try...catchblocks for handling errors in asynchronous operations.app/layout.tsx (1)
56-63: Redundant meta tags duplicate the metadata export.The
metadataexport (lines 9-47) already definesopenGraphand<head>(lines 59-62) duplicate this configuration.Consider removing the redundant manual tags to maintain a single source of truth:
<head> <meta name="robots" content="index,follow" /> <link rel="canonical" href="https://deanmachines.com/" /> - <meta property="og:title" content="AgentStack | Multi-Agent Framework" /> - <meta property="og:description" content="Production-grade multi-agent framework for AI applications with 22+ agents, 30+ tools." /> - <meta property="og:image" content="https://deanmachines.com/og-image.png" /> - <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:site" content="@ssdeanx" />Note: Keep
twitter:siteas it's not in the metadata export.src/mastra/index.ts (1)
274-279: Use a stable tracer name instead of the literal string "TracingContext.agentId"The tracer name
"TracingContext.agentId"is a static string that will always create/use a tracer literally named that, not the current agent's id. This appears to be an incomplete placeholder. Compare this to other routes likeresearchAgentwhich usetrace.getTracer("researchAgent")— a clear, stable identifier.For consistency and clarity, use a stable name that matches the telemetry context:
- tracer: trace.getTracer("TracingContext.agentId"), + tracer: trace.getTracer("chat-api"),This aligns with the
functionId: "chat-api"already specified above and makes traces easier to reason about.app/networks/components/network-header.tsx (1)
111-149: Defensive handling for possibly missing provider/category keysThe early-return checks assume
modelsByProvider[provider]/networksByCategory[category]are always defined arrays; if a key is ever missing,.lengthwill throw.If the helpers don’t guarantee total coverage, consider a nullish fallback:
- {PROVIDER_ORDER.map((provider) => { - const models = modelsByProvider[provider] - if (models.length === 0) {return null} + {PROVIDER_ORDER.map((provider) => { + const models = modelsByProvider[provider] ?? [] + if (models.length === 0) { return null } const providerConfig = PROVIDER_CONFIGS[provider]and similarly for
networksByCategory[category].Also applies to: 163-182
app/components/landing-trust.tsx (1)
144-153: Addgroupclass so certification icongroup-hoverrotation worksIn the certifications row, the icon uses
group-hover:rotate-12, but the parentmotion.divdoesn’t have agroupclass, so the hover rotation never fires:<cert.icon className="size-4 text-primary transition-transform duration-200 group-hover:rotate-12" />You likely want:
- <motion.div + <motion.div key={cert.name} @@ - className="flex items-center gap-2 rounded-full border border-border bg-card px-5 py-2.5 shadow-sm transition-all duration-200 ease-spring hover:border-primary/30 hover:shadow-md hover:scale-105" + className="group flex items-center gap-2 rounded-full border border-border bg-card px-5 py-2.5 shadow-sm transition-all duration-200 ease-spring hover:border-primary/30 hover:shadow-md hover:scale-105"so the group-hover utility can take effect.
app/components/landing-cta.tsx (1)
178-178: Remove unsafe type assertion.The
as anytype assertion bypasses TypeScript's type checking. The href should be properly typed as a string or use the correct Next.js Link href type.Apply this diff to remove the type assertion:
- href={link.href as any} + href={link.href}If there's a type mismatch, fix the QUICK_LINKS type definition instead of using
as any.app/chat/providers/chat-context.tsx (1)
336-343: Consider using or documenting thefilesparameter.The
filesparameter is declared but not used in the implementation. If file attachments are planned for a future iteration, consider adding a TODO comment or JSDoc explaining this. Otherwise, the parameter signature creates an expectation that file uploads are supported.const sendMessage = useCallback( - (text: string, files?: File[]) => { + (text: string, _files?: File[]) => { + // TODO: Implement file attachment support if (!text.trim() || isLoading) {return} setChatError(null) aiSendMessage({ text: text.trim() }) }, [isLoading, aiSendMessage] )
| const handleCopy = useCallback(async () => { | ||
| await navigator.clipboard.writeText(content); | ||
| setCopied(true); | ||
| onCopy?.(); | ||
| setTimeout(() => setCopied(false), 2000); | ||
| }, [content, onCopy]); |
There was a problem hiding this comment.
Missing error handling for clipboard API.
navigator.clipboard.writeText can throw if permissions are denied or in non-secure contexts. Per coding guidelines, async operations should use try/catch.
const handleCopy = useCallback(async () => {
- await navigator.clipboard.writeText(content);
- setCopied(true);
- onCopy?.();
- setTimeout(() => setCopied(false), 2000);
+ try {
+ await navigator.clipboard.writeText(content);
+ setCopied(true);
+ onCopy?.();
+ setTimeout(() => setCopied(false), 2000);
+ } catch (error) {
+ console.error("Failed to copy to clipboard:", error);
+ }
}, [content, onCopy]);📝 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 handleCopy = useCallback(async () => { | |
| await navigator.clipboard.writeText(content); | |
| setCopied(true); | |
| onCopy?.(); | |
| setTimeout(() => setCopied(false), 2000); | |
| }, [content, onCopy]); | |
| const handleCopy = useCallback(async () => { | |
| try { | |
| await navigator.clipboard.writeText(content); | |
| setCopied(true); | |
| onCopy?.(); | |
| setTimeout(() => setCopied(false), 2000); | |
| } catch (error) { | |
| console.error("Failed to copy to clipboard:", error); | |
| } | |
| }, [content, onCopy]); |
🤖 Prompt for AI Agents
In src/components/ai-elements/custom/agent-response.tsx around lines 158 to 163,
the clipboard write call lacks error handling; wrap
navigator.clipboard.writeText in a try/catch, guard for navigator.clipboard
existence, only setCopied(true) and call onCopy() on successful write, and in
the catch log the error (or report via a provided logger/UX) and ensure copied
state is not left true (reset to false or show failure state); this prevents
uncaught rejections in permission-denied or non-secure contexts and provides a
graceful fallback path.
| {showActions && !isStreaming && ( | ||
| <motion.div | ||
| initial={{ opacity: 0 }} | ||
| animate={{ opacity: 1 }} | ||
| transition={{ delay: 0.3 }} | ||
| className={cn( | ||
| "mt-4 flex items-center gap-1 border-t pt-3", | ||
| "opacity-0 transition-opacity group-hover:opacity-100" | ||
| )} | ||
| > |
There was a problem hiding this comment.
Action bar visibility has competing opacity controls.
The motion.div has both initial={{ opacity: 0 }} and a class opacity-0 transition-opacity group-hover:opacity-100. This creates competing opacity controls that could cause unexpected behavior.
Consider using only one approach for the fade-in effect:
<motion.div
- initial={{ opacity: 0 }}
- animate={{ opacity: 1 }}
- transition={{ delay: 0.3 }}
className={cn(
"mt-4 flex items-center gap-1 border-t pt-3",
"opacity-0 transition-opacity group-hover:opacity-100"
)}
>Or use Framer Motion exclusively and remove the Tailwind opacity classes.
📝 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.
| {showActions && !isStreaming && ( | |
| <motion.div | |
| initial={{ opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| transition={{ delay: 0.3 }} | |
| className={cn( | |
| "mt-4 flex items-center gap-1 border-t pt-3", | |
| "opacity-0 transition-opacity group-hover:opacity-100" | |
| )} | |
| > | |
| {showActions && !isStreaming && ( | |
| <motion.div | |
| className={cn( | |
| "mt-4 flex items-center gap-1 border-t pt-3", | |
| "opacity-0 transition-opacity group-hover:opacity-100" | |
| )} | |
| > |
🤖 Prompt for AI Agents
In src/components/ai-elements/custom/agent-response.tsx around lines 217 to 226,
the action bar uses both Framer Motion opacity controls (initial/animate) and
Tailwind opacity classes (opacity-0 transition-opacity group-hover:opacity-100),
causing conflicting styles; pick one method and remove the other: either remove
the Tailwind opacity classes (opacity-0, transition-opacity,
group-hover:opacity-100) and let Framer Motion handle the fade-in via
initial/animate/transition (or motion variants for hover), or remove the Framer
Motion initial/animate props and keep the Tailwind classes to handle hover/fade
via CSS; update the code so only one opacity mechanism remains and ensure
hover/visibility behavior is implemented consistently (e.g., use Framer Motion
variants if you need animated hover tied to the group).
| duration?: number; | ||
| }) => { | ||
| const [scope, animate] = useAnimate(); | ||
| let wordsArray = words.split(" "); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Use const for immutable variable.
The wordsArray variable is never reassigned and should be declared with const instead of let.
Apply this diff:
- let wordsArray = words.split(" ");
+ const wordsArray = words.split(" ");📝 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.
| let wordsArray = words.split(" "); | |
| const wordsArray = words.split(" "); |
🤖 Prompt for AI Agents
In ui/effects/text-generate.tsx around line 18, the variable declaration "let
wordsArray = words.split(' ');" uses let but the variable is never reassigned;
change the declaration to use const so the immutable variable is correctly
declared as const wordsArray = words.split(" ") and update any tooling/linting
artifacts if needed.
| useEffect(() => { | ||
| animate( | ||
| "span", | ||
| { | ||
| opacity: 1, | ||
| filter: filter ? "blur(0px)" : "none", | ||
| }, | ||
| { | ||
| duration: duration ? duration : 1, | ||
| delay: stagger(0.2), | ||
| } | ||
| ); | ||
| }, [scope.current]); |
There was a problem hiding this comment.
Add missing dependencies to useEffect.
The useEffect hook is missing dependencies: animate, filter, and duration. This violates the exhaustive-deps rule and could cause stale closures.
As per coding guidelines, include a complete dependency array in useEffect hooks.
Apply this diff:
);
- }, [scope.current]);
+ }, [animate, filter, duration]);Note: scope.current should not be in the dependency array as it's a ref property. The hook should re-run when animate, filter, or duration change.
📝 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.
| useEffect(() => { | |
| animate( | |
| "span", | |
| { | |
| opacity: 1, | |
| filter: filter ? "blur(0px)" : "none", | |
| }, | |
| { | |
| duration: duration ? duration : 1, | |
| delay: stagger(0.2), | |
| } | |
| ); | |
| }, [scope.current]); | |
| useEffect(() => { | |
| animate( | |
| "span", | |
| { | |
| opacity: 1, | |
| filter: filter ? "blur(0px)" : "none", | |
| }, | |
| { | |
| duration: duration ? duration : 1, | |
| delay: stagger(0.2), | |
| } | |
| ); | |
| }, [animate, filter, duration]); |
🤖 Prompt for AI Agents
In ui/effects/text-generate.tsx around lines 20 to 32, the useEffect currently
lists only scope.current in its dependency array, causing missing dependencies
(animate, filter, duration) and risking stale closures; update the hook to
remove scope.current (do not depend on ref.current) and include animate, filter,
and duration in the dependency array so the effect reruns when any of those
change, keeping the animate call and options unchanged.
| filter: filter ? "blur(0px)" : "none", | ||
| }, | ||
| { | ||
| duration: duration ? duration : 1, |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Remove redundant ternary expression.
The expression duration ? duration : 1 is redundant because duration has a default value of 0.5. The ternary will always evaluate to the duration value.
Apply this diff:
- duration: duration ? duration : 1,
+ duration: duration,Or simply:
- duration: duration ? duration : 1,
+ duration,📝 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.
| duration: duration ? duration : 1, | |
| duration, |
🤖 Prompt for AI Agents
In ui/effects/text-generate.tsx around line 28, the assignment uses a redundant
ternary "duration ? duration : 1" even though duration already has a default of
0.5; remove the ternary and simply use the duration variable (or replace with a
logical fallback like "duration ?? 1" if a fallback is required) so the code
reads straightforwardly without the unnecessary conditional.
| <SourcesTrigger count={uniqueSources.length}> | ||
| <span className="text-xs text-muted-foreground truncate max-w-48"> | ||
| {primaryDomains.join(", ")} | ||
| {Object.keys(domainCounts).length > 3 && " +more"} | ||
| </span> | ||
| </SourcesTrigger> |
There was a problem hiding this comment.
Trigger content is missing the source count display.
The custom trigger content only shows domain names but omits the count that SourcesTrigger would normally display. The count prop is passed but the default rendering (which shows "Used {count} sources") is overridden by the custom children without including this information.
Consider including the count in the trigger for better UX:
<SourcesTrigger count={uniqueSources.length}>
+ <p className="font-medium text-xs">
+ {uniqueSources.length} source{uniqueSources.length !== 1 ? "s" : ""}
+ </p>
<span className="text-xs text-muted-foreground truncate max-w-48">
{primaryDomains.join(", ")}
{Object.keys(domainCounts).length > 3 && " +more"}
</span>
+ <ChevronDownIcon className="h-4 w-4" />
</SourcesTrigger>Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/chat/components/agent-sources.tsx around lines 68 to 73, the custom
SourcesTrigger children render domain names but omit the source count that
SourcesTrigger normally shows; update the custom trigger to include the count
prop (e.g., render the domains followed by a concise indicator like "• {count}
sources" or include the phrase "Used {count} sources") so the UI displays both
domain names and the total source count and keeps accessibility/visual parity
with the default trigger.
| toRef, | ||
| curvature = 0, | ||
| reverse = false, | ||
| duration = Math.random() * 3 + 4, |
There was a problem hiding this comment.
Hydration mismatch risk with Math.random() in default prop.
Using Math.random() as a default parameter value will produce different values on server vs. client, causing React hydration mismatches. Move the randomization inside the component or accept a deterministic default.
- duration = Math.random() * 3 + 4,
+ duration: durationProp,Then inside the component:
const [duration] = useState(() => durationProp ?? Math.random() * 3 + 4);🤖 Prompt for AI Agents
In ui/effects/animated-beam.tsx around line 35, the default prop uses
Math.random() which can differ between server and client and cause React
hydration mismatches; move the randomization into the component runtime instead
of the default param. Change the prop to accept a deterministic/optional value
(e.g., durationProp) and inside the component initialize state with a stable
value using a lazy initializer that uses Math.random() only on the client (for
example: useState(() => durationProp ?? Math.random() * 3 + 4)). Ensure the prop
signature no longer calls Math.random() by default and that the component uses
the propagated or computed duration from state.
| return ( | ||
| <svg | ||
| fill="none" | ||
| width={svgDimensions.width} | ||
| height={svgDimensions.height} | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| className={cn( | ||
| "pointer-events-none absolute left-0 top-0 transform-gpu stroke-2", | ||
| className | ||
| )} | ||
| > |
There was a problem hiding this comment.
Add accessible title to SVG for screen readers.
The SVG lacks an accessible label, which is flagged by static analysis. Add a <title> element or aria-label for accessibility compliance.
<svg
fill="none"
width={svgDimensions.width}
height={svgDimensions.height}
xmlns="http://www.w3.org/2000/svg"
+ role="img"
+ aria-label="Animated connection beam"
className={cn(
"pointer-events-none absolute left-0 top-0 transform-gpu stroke-2",
className
)}
>
+ <title>Animated connection beam</title>📝 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.
| return ( | |
| <svg | |
| fill="none" | |
| width={svgDimensions.width} | |
| height={svgDimensions.height} | |
| xmlns="http://www.w3.org/2000/svg" | |
| className={cn( | |
| "pointer-events-none absolute left-0 top-0 transform-gpu stroke-2", | |
| className | |
| )} | |
| > | |
| return ( | |
| <svg | |
| fill="none" | |
| width={svgDimensions.width} | |
| height={svgDimensions.height} | |
| xmlns="http://www.w3.org/2000/svg" | |
| role="img" | |
| aria-label="Animated connection beam" | |
| className={cn( | |
| "pointer-events-none absolute left-0 top-0 transform-gpu stroke-2", | |
| className | |
| )} | |
| > | |
| <title>Animated connection beam</title> |
🧰 Tools
🪛 Biome (2.1.2)
[error] 112-121: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
🤖 Prompt for AI Agents
In ui/effects/animated-beam.tsx around lines 111 to 121, the SVG is missing an
accessible label for screen readers; add an accessible title by inserting a
<title> element (with a unique id) as the first child of the SVG and reference
it via aria-labelledby on the SVG (or alternatively add an aria-label prop) so
assistive tech can announce the graphic; ensure the id is unique (e.g., generate
or use component props) and use aria-hidden only if the graphic is decorative.
| const divRef = useRef<HTMLDivElement>(null); | ||
| const [isMounted, setIsMounted] = useState(false); | ||
|
|
||
| const mouseX = useSpring(0, { stiffness: 500, damping: 100 }); | ||
| const mouseY = useSpring(0, { stiffness: 500, damping: 100 }); | ||
|
|
||
| useEffect(() => { | ||
| setIsMounted(true); | ||
| }, []); | ||
|
|
||
| const handleMouseMove = useCallback( | ||
| ({ currentTarget, clientX, clientY }: React.MouseEvent) => { | ||
| const { left, top } = currentTarget.getBoundingClientRect(); | ||
| const x = clientX - left; | ||
| const y = clientY - top; | ||
| mouseX.set(x); | ||
| mouseY.set(y); | ||
| }, | ||
| [mouseX, mouseY] | ||
| ); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Remove unused code.
Lines 13-32 define divRef, isMounted, mouseX, mouseY, and handleMouseMove but none of these are used in the component. The comments on lines 34-41 indicate this was intended for a different interaction pattern.
Apply this diff to clean up the unused code:
export function Spotlight({ className, fill = "white" }: SpotlightProps) {
- const divRef = useRef<HTMLDivElement>(null);
- const [isMounted, setIsMounted] = useState(false);
-
- const mouseX = useSpring(0, { stiffness: 500, damping: 100 });
- const mouseY = useSpring(0, { stiffness: 500, damping: 100 });
-
- useEffect(() => {
- setIsMounted(true);
- }, []);
-
- const handleMouseMove = useCallback(
- ({ currentTarget, clientX, clientY }: React.MouseEvent) => {
- const { left, top } = currentTarget.getBoundingClientRect();
- const x = clientX - left;
- const y = clientY - top;
- mouseX.set(x);
- mouseY.set(y);
- },
- [mouseX, mouseY]
- );
-
- // Create a portal-like effect or just huge blur
- // Actually, for a pure decorative spotlight usually placed in a container:
- // we need the parent to handle mouse move if it's "following".
- // BUT the common "Spotlight" component (Aceternity style) is fixed and just animates into view.
- // Wait, the USER asked for "Aceternity UI" Spotlight specifically.
- // Aceternity's "Spotlight" is actually a fixed SVG that creates a dramatic cone of light.
- // Aceternity's "HoverBorderGradient" or "CardSpotlight" is what follows the mouse.
- // I will implement the "Dramatic Cone" Spotlight first as requested for the HERO sections.
-
return (Also remove the unused imports:
-import React, { useRef, useState, useCallback, useEffect } from "react";
-import { motion, useSpring, useTransform, MotionValue } from "framer-motion";
+import React from "react";
+import { motion } from "framer-motion";📝 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 divRef = useRef<HTMLDivElement>(null); | |
| const [isMounted, setIsMounted] = useState(false); | |
| const mouseX = useSpring(0, { stiffness: 500, damping: 100 }); | |
| const mouseY = useSpring(0, { stiffness: 500, damping: 100 }); | |
| useEffect(() => { | |
| setIsMounted(true); | |
| }, []); | |
| const handleMouseMove = useCallback( | |
| ({ currentTarget, clientX, clientY }: React.MouseEvent) => { | |
| const { left, top } = currentTarget.getBoundingClientRect(); | |
| const x = clientX - left; | |
| const y = clientY - top; | |
| mouseX.set(x); | |
| mouseY.set(y); | |
| }, | |
| [mouseX, mouseY] | |
| ); | |
| import React from "react"; | |
| import { motion } from "framer-motion"; | |
| export function Spotlight({ className, fill = "white" }: SpotlightProps) { | |
| return ( |
🤖 Prompt for AI Agents
In ui/effects/spotlight.tsx around lines 13 to 32, several declarations are
unused: remove the unused divRef, isMounted state and its useEffect, the mouseX
and mouseY springs, and the handleMouseMove callback; also remove any now-unused
imports (e.g., useRef, useState, useEffect, useCallback, and spring-related
imports like useSpring) or adjust imports to only include what the component
actually uses. Ensure no remaining references to these identifiers exist
elsewhere in the file and run a quick linter/type-check to confirm imports and
variables are cleaned up.
| <svg | ||
| className="animate-spotlight pointer-events-none absolute z-[1] h-[160%] w-[138%] lg:w-[84%] opacity-0" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| viewBox="0 0 3787 2842" | ||
| fill="none" | ||
| > | ||
| <g filter="url(#filter)"> | ||
| <ellipse | ||
| cx="1924.71" | ||
| cy="273.501" | ||
| rx="1924.71" | ||
| ry="273.501" | ||
| transform="matrix(-0.822377 -0.568943 -0.568943 0.822377 3631.88 2291.09)" | ||
| fill={fill} | ||
| fillOpacity="0.21" | ||
| /> | ||
| </g> | ||
| <defs> | ||
| <filter | ||
| id="filter" | ||
| x="0.860352" | ||
| y="0.838989" | ||
| width="3785.16" | ||
| height="2840.26" | ||
| filterUnits="userSpaceOnUse" | ||
| colorInterpolationFilters="sRGB" | ||
| > | ||
| <feFlood floodOpacity="0" result="BackgroundImageFix" /> | ||
| <feBlend | ||
| mode="normal" | ||
| in="SourceGraphic" | ||
| in2="BackgroundImageFix" | ||
| result="shape" | ||
| /> | ||
| <feGaussianBlur | ||
| stdDeviation="151" | ||
| result="effect1_foregroundBlur_1065_8" | ||
| /> | ||
| </filter> | ||
| </defs> | ||
| </svg> |
There was a problem hiding this comment.
Add accessibility attribute to decorative SVG.
The SVG is purely decorative and should include aria-hidden="true" to prevent screen readers from announcing it.
Based on the static analysis hint, apply this diff:
<svg
className="animate-spotlight pointer-events-none absolute z-[1] h-[160%] w-[138%] lg:w-[84%] opacity-0"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 3787 2842"
fill="none"
+ aria-hidden="true"
>📝 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.
| <svg | |
| className="animate-spotlight pointer-events-none absolute z-[1] h-[160%] w-[138%] lg:w-[84%] opacity-0" | |
| xmlns="http://www.w3.org/2000/svg" | |
| viewBox="0 0 3787 2842" | |
| fill="none" | |
| > | |
| <g filter="url(#filter)"> | |
| <ellipse | |
| cx="1924.71" | |
| cy="273.501" | |
| rx="1924.71" | |
| ry="273.501" | |
| transform="matrix(-0.822377 -0.568943 -0.568943 0.822377 3631.88 2291.09)" | |
| fill={fill} | |
| fillOpacity="0.21" | |
| /> | |
| </g> | |
| <defs> | |
| <filter | |
| id="filter" | |
| x="0.860352" | |
| y="0.838989" | |
| width="3785.16" | |
| height="2840.26" | |
| filterUnits="userSpaceOnUse" | |
| colorInterpolationFilters="sRGB" | |
| > | |
| <feFlood floodOpacity="0" result="BackgroundImageFix" /> | |
| <feBlend | |
| mode="normal" | |
| in="SourceGraphic" | |
| in2="BackgroundImageFix" | |
| result="shape" | |
| /> | |
| <feGaussianBlur | |
| stdDeviation="151" | |
| result="effect1_foregroundBlur_1065_8" | |
| /> | |
| </filter> | |
| </defs> | |
| </svg> | |
| <svg | |
| className="animate-spotlight pointer-events-none absolute z-[1] h-[160%] w-[138%] lg:w-[84%] opacity-0" | |
| xmlns="http://www.w3.org/2000/svg" | |
| viewBox="0 0 3787 2842" | |
| fill="none" | |
| aria-hidden="true" | |
| > | |
| <g filter="url(#filter)"> | |
| <ellipse | |
| cx="1924.71" | |
| cy="273.501" | |
| rx="1924.71" | |
| ry="273.501" | |
| transform="matrix(-0.822377 -0.568943 -0.568943 0.822377 3631.88 2291.09)" | |
| fill={fill} | |
| fillOpacity="0.21" | |
| /> | |
| </g> | |
| <defs> | |
| <filter | |
| id="filter" | |
| x="0.860352" | |
| y="0.838989" | |
| width="3785.16" | |
| height="2840.26" | |
| filterUnits="userSpaceOnUse" | |
| colorInterpolationFilters="sRGB" | |
| > | |
| <feFlood floodOpacity="0" result="BackgroundImageFix" /> | |
| <feBlend | |
| mode="normal" | |
| in="SourceGraphic" | |
| in2="BackgroundImageFix" | |
| result="shape" | |
| /> | |
| <feGaussianBlur | |
| stdDeviation="151" | |
| result="effect1_foregroundBlur_1065_8" | |
| /> | |
| </filter> | |
| </defs> | |
| </svg> |
🧰 Tools
🪛 Biome (2.1.2)
[error] 53-58: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
🤖 Prompt for AI Agents
In ui/effects/spotlight.tsx around lines 53 to 93, the SVG is decorative and
missing an accessibility attribute; add aria-hidden="true" to the <svg> element
(alongside existing attributes) so screen readers ignore it; ensure the
attribute is added exactly to the outer svg tag and keep all other props
unchanged.
| )} | ||
| > | ||
| <svg | ||
| className="animate-spotlight pointer-events-none absolute z-[1] h-[160%] w-[138%] lg:w-[84%] opacity-0" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find and examine Tailwind configuration
fd -e 'js' -e 'ts' -e 'cjs' -e 'mjs' 'tailwind.config' --exec head -200 {} \;Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Search for spotlight animation definition in CSS and config files
rg -r . 'animate-spotlight|spotlight' -t ts -t js -t css --max-count 20Repository: ssdeanx/AgentStack
Length of output: 869
🏁 Script executed:
#!/bin/bash
# Check if there are any keyframes defined for spotlight
rg '@keyframes.*spotlight|spotlight.*animation' -t css -t ts -t js -A 5Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Read the spotlight.tsx file directly
cat -n ui/effects/spotlight.tsxRepository: ssdeanx/AgentStack
Length of output: 3843
🏁 Script executed:
#!/bin/bash
# Find and read Tailwind configuration
fd 'tailwind.config' --type f -x cat {}Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Search for any CSS or animation definitions in the styles/globals
find . -name "globals.css" -o -name "globals.ts" -o -name "global.css" | head -5 | xargs -I {} cat -n {}Repository: ssdeanx/AgentStack
Length of output: 17888
🏁 Script executed:
#!/bin/bash
# Check package.json for tw-animate-css
fd package.json --type f -x grep -l 'tw-animate-css' {}Repository: ssdeanx/AgentStack
Length of output: 76
🏁 Script executed:
#!/bin/bash
# Look for tw-animate-css in node_modules or package files
find . -name "*animate*css*" -o -name "tw-animate*" 2>/dev/null | head -20Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Check package.json dependencies
cat package.json | grep -A 50 '"dependencies"'Repository: ssdeanx/AgentStack
Length of output: 1969
🏁 Script executed:
#!/bin/bash
# Search for tw-animate-css file in the project
fd 'tw-animate' -o fd '*animate*css*' | grep -v node_modulesRepository: ssdeanx/AgentStack
Length of output: 185
🏁 Script executed:
#!/bin/bash
# Check if there's a tailwind.config file with animation definitions
fd 'tailwind.config' -x cat {}Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Search for animate-spotlight definition anywhere in the codebase
rg 'animate-spotlight' --type ts --type tsx --type css --type js -B 2 -A 2Repository: ssdeanx/AgentStack
Length of output: 89
🏁 Script executed:
#!/bin/bash
# Search for tw-animate-css file anywhere in project
find . -name "*tw-animate*" -o -name "*animate*css*" 2>/dev/null | grep -v node_modulesRepository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Search for animate-spotlight definition
rg 'animate-spotlight' --type-add 'web:*.{css,scss,sass}' -t web -B 2 -A 2Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Check if tailwind.config exists anywhere
find . -name "tailwind.config.*" -type fRepository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Look at the actual import in globals.css more carefully
head -n 20 app/globals.css || head -n 20 styles/globals.css || head -n 20 src/globals.cssRepository: ssdeanx/AgentStack
Length of output: 700
🏁 Script executed:
#!/bin/bash
# Search for tw-animate-css in node_modules
find node_modules -name "*tw-animate*" -o -name "*animate-css*" 2>/dev/null | head -20Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Check all CSS files for animate-spotlight definition
find . -name "*.css" -type f ! -path "*/node_modules/*" -exec grep -l "animate-spotlight\|spotlight" {} \;Repository: ssdeanx/AgentStack
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Look for any file that might define animations
find . -name "*.css" -o -name "*.scss" | grep -v node_modules | xargs grep -l "keyframes\|animation" 2>/dev/null | head -10Repository: ssdeanx/AgentStack
Length of output: 79
Define the animate-spotlight animation or remove the unused class.
Line 54 uses animate-spotlight which is not defined in your Tailwind configuration or CSS files. Either add this animation to your CSS (via @keyframes in globals.css or a Tailwind config extension) or remove the class if it's not needed. Note: The SVG element also has opacity-0 in the same className, which keeps it invisible regardless of animation—verify the intended behavior with the outer motion.div's opacity animation.
🤖 Prompt for AI Agents
In ui/effects/spotlight.tsx around line 54, the className includes
animate-spotlight which isn't defined in Tailwind or CSS and therefore is unused
(and the element already has opacity-0 which also hides it); either add a proper
animation definition (add @keyframes in globals.css or extend Tailwind
animations in tailwind.config.js with a matching animate-spotlight entry and
ensure the element’s initial opacity aligns with the intended animation) or
remove the animate-spotlight class and/or opacity-0 if the outer motion.div
already handles visibility; update the file to reference a defined animation or
clean up the unused class so the behavior is consistent.
- agent-artifact.tsx: Added normalizeLanguage function for better language handling. - agent-chain-of-thought.tsx: Optimized completedCount and activeStep calculations using useMemo. - agent-checkpoint.tsx: Improved timestamp handling and added aria-hidden attributes for better accessibility. - agent-confirmation.tsx: Introduced explicit severity mapping for tools and refined severity inference logic. - agent-queue.tsx: Enhanced formatRelativeTime function to handle edge cases and improved task rendering structure. - agent-sources.tsx: Updated uniqueSources calculation to handle empty sources more gracefully. - docs-nav.tsx: Removed unnecessary type assertion for href. - footer.tsx: Removed unnecessary type assertion for href. - landing-cta.tsx: Removed unnecessary type assertion for href. - landing-features.tsx: Refactored header rendering to use a dedicated FeatureHeader component. - landing-stats.tsx: Updated icon prop type to include strokeWidth. - navbar.tsx: Improved mobile menu handling with animations and accessibility features. - network-background.tsx: Updated requestRef type to allow null values. - networks-list.tsx: Cleaned up unnecessary whitespace in rendering. - page-header.tsx: Simplified badge and children rendering checks.
There was a problem hiding this comment.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
app/chat/components/agent-artifact.tsx (2)
210-212: Inconsistent:normalizeLanguagenot used inAgentArtifactCompact.This component still uses the inline
artifact.language?.toLowerCase() ?? ""pattern instead of the newnormalizeLanguagehelper.const isPreviewable = artifact.type === "code" && - PREVIEWABLE_LANGUAGES.includes(artifact.language?.toLowerCase() ?? "") + PREVIEWABLE_LANGUAGES.includes(normalizeLanguage(artifact.language))
253-255: Inconsistent:normalizeLanguagenot used inArtifactEditorFAB.Same issue as
AgentArtifactCompact— uses inline normalization instead of the helper.const isPreviewable = artifact.type === "code" && - PREVIEWABLE_LANGUAGES.includes(artifact.language?.toLowerCase() ?? "") + PREVIEWABLE_LANGUAGES.includes(normalizeLanguage(artifact.language))app/chat/components/agent-confirmation.tsx (1)
102-153: Clean UI composition with severity-driven styling.The component correctly:
- Passes
classNamethrough to the baseConfirmationcomponent- Dynamically selects button variant based on severity (
destructivefor danger)- Uses proper icon accessibility (though consider adding
aria-hidden="true"to decorative icons)One minor enhancement for accessibility:
- <div className={cn("mt-0.5 shrink-0", config.iconClass)}> - <Icon className="size-5" /> + <div className={cn("mt-0.5 shrink-0", config.iconClass)} aria-hidden="true"> + <Icon className="size-5" /> </div>app/components/footer.tsx (1)
126-126: Incorrect Tailwind gradient class name.The class
bg-linear-to-bris not a valid Tailwind CSS class. This should bebg-gradient-to-brto render the gradient background correctly.Apply this diff:
- <div className="flex size-10 items-center justify-center rounded-lg bg-linear-to-br from-primary to-primary/80 shadow-lg transition-all duration-200 ease-spring group-hover:scale-105 group-hover:shadow-xl"> + <div className="flex size-10 items-center justify-center rounded-lg bg-gradient-to-br from-primary to-primary/80 shadow-lg transition-all duration-200 ease-spring group-hover:scale-105 group-hover:shadow-xl">
♻️ Duplicate comments (16)
app/components/landing-features.tsx (1)
123-135: BentoGrid section lacks entrance animation.The main feature grid renders without animation while the
ADDITIONAL_FEATURESsection usesmotion.divwithcontainerVariantsfor staggered entrance. This creates visual inconsistency.Consider wrapping the BentoGrid in a motion.div for visual consistency:
- <BentoGrid className="mb-24"> + <motion.div + variants={containerVariants} + initial="hidden" + whileInView="visible" + viewport={{ once: true }} + > + <BentoGrid className="mb-24"> {FEATURES.map((feature, i) => ( <BentoGridItem key={i} title={feature.title} description={feature.description} header={feature.header} icon={feature.icon} className={feature.className} /> ))} - </BentoGrid> + </BentoGrid> + </motion.div>app/components/navbar.tsx (1)
153-234: Mobile menu animation is well implemented, but accessibility enhancements from past review not addressed.The AnimatePresence animation and menu structure are good. However, the previous review suggested locking body scroll when the menu is open and adding Escape key support to close the menu - these accessibility improvements are still missing.
Consider adding:
useEffect(() => { if (mobileOpen) { document.body.style.overflow = 'hidden' const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') setMobileOpen(false) } document.addEventListener('keydown', handleEscape) return () => { document.body.style.overflow = '' document.removeEventListener('keydown', handleEscape) } } }, [mobileOpen])app/components/network-background.tsx (5)
4-4: Remove unused imports.The
motionanduseAnimationimports from framer-motion are not used in this component.Apply this diff:
-import { motion, useAnimation } from "framer-motion"
20-20: Store nodes in a ref instead of state.Since nodes are directly mutated in the animation loop (lines 74-125) and never trigger re-renders via
setNodes, they should be stored in a ref rather than state to avoid confusion and potential bugs.This is addressed by the existing review suggesting:
const nodesRef = useRef<Node[]>([])Then initialize with
nodesRef.current = newNodesand access vianodesRef.currentin the animation loop.
74-125: Direct mutation of nodes violates React immutability.The animation loop directly mutates node positions and velocities (lines 76-77, 80-81, 93-94), which is a React anti-pattern. While this works because
setNodesis never called after initialization, it creates technical debt.This is addressed by the existing suggestion to store nodes in a ref rather than state, which makes the mutation pattern explicit and appropriate for animation loops.
145-149: Capture ref value before cleanup to prevent stale reference.Accessing
containerRef.currentin the cleanup function (line 148) may reference a different value than when the listener was added (line 143), potentially causing the listener to not be removed properly.Apply this diff:
animate() const handleMouseMove = (e: MouseEvent) => { if (containerRef.current) { const rect = containerRef.current.getBoundingClientRect() mouseRef.current = { x: e.clientX - rect.left, y: e.clientY - rect.top, } } } // Use global listener to track mouse even if over other elements in the hero + const container = containerRef.current - containerRef.current?.addEventListener("mousemove", handleMouseMove) + container?.addEventListener("mousemove", handleMouseMove) return () => { window.removeEventListener("resize", resizeCanvas) if (requestRef.current) {cancelAnimationFrame(requestRef.current)} - containerRef.current?.removeEventListener("mousemove", handleMouseMove) + container?.removeEventListener("mousemove", handleMouseMove) }
150-150: Remove nodes from dependency array.The
nodesdependency causes the animation loop to restart whenever nodes change. Since nodes are only initialized once and then mutated directly, this dependency is unnecessary and creates potential performance issues.This is addressed by the existing suggestion to use a ref for nodes, which would allow changing the dependency array to
[].app/chat/components/agent-sources.tsx (1)
67-74: Trigger content missing the source count display.The custom trigger content shows domain names but omits the count. The
countprop is passed but the default rendering is overridden. This was flagged in a past review.Consider including the count for better UX:
<SourcesTrigger count={uniqueSources.length}> + <span className="font-medium text-xs mr-1"> + {uniqueSources.length} source{uniqueSources.length !== 1 ? "s" : ""}: + </span> <span className="text-xs text-muted-foreground truncate max-w-48">app/chat/components/agent-queue.tsx (1)
110-126: Missingaria-labelattributes on icon-only action buttons.This was flagged in a past review. Screen reader users cannot identify the purpose of these buttons.
{onView && ( - <QueueItemAction onClick={() => onView(task.id)}> + <QueueItemAction onClick={() => onView(task.id)} aria-label="View task details"> <EyeIcon className="size-3" /> </QueueItemAction> )} {onRetry && task.status === "failed" && ( - <QueueItemAction onClick={() => onRetry(task.id)}> + <QueueItemAction onClick={() => onRetry(task.id)} aria-label="Retry failed task"> <RefreshCwIcon className="size-3" /> </QueueItemAction> )} {onDelete && ( - <QueueItemAction onClick={() => onDelete(task.id)}> + <QueueItemAction onClick={() => onDelete(task.id)} aria-label="Delete task"> <TrashIcon className="size-3" /> </QueueItemAction> )}app/chat/components/agent-confirmation.tsx (1)
62-84: Good implementation addressing previous feedback.The severity inference now uses word-boundary regex patterns (
\b...\b) to reduce false positives, and the explicittoolSeverityMapprovides an escape hatch for precise control. This addresses the earlier review concern about tools likeupdateViewbeing incorrectly flagged.app/chat/components/agent-checkpoint.tsx (4)
18-34: Good documentation addressing previous feedback.The TSDoc block clearly documents props including the
timestamptype flexibility (Date or ISO string) andmessageCountsemantics. This addresses the earlier review concern about clarifying the public API surface.
60-63: Defensive timestamp coercion addresses previous concern.The coercion
typeof timestamp === 'string' ? new Date(timestamp) : timestamphandles both Date objects and ISO strings gracefully, preventing runtime errors when API data is passed directly.
67-101: Accessibility improvements implemented.Decorative icons now have
aria-hidden="true"and the trigger has an explicitaria-label. These changes address the earlier accessibility feedback.
36-50: Time formatting helpers look good; testability suggestion from past review still applicable.The relative time logic is clear. The earlier suggestion to make
formatRelativeTimetestable by accepting an optionalnowparameter was not implemented. This is a minor improvement for unit testing:-function formatRelativeTime(date: Date): string { - const now = new Date() +function formatRelativeTime(date: Date, now: Date = new Date()): string { const diffMs = now.getTime() - date.getTime()app/chat/components/agent-chain-of-thought.tsx (2)
93-107: Good refactor addressing previous feedback.The
ParsedStepinterface has been replaced with a simplerStepTypeunion type, which is cleaner since the full interface was never instantiated.
141-145: Search terms accumulation issue fixed.The code now spreads
currentSearchTermsinto a new array and resets after each step, preventing terms from bleeding across consecutive search steps. This addresses the earlier review concern.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (15)
app/chat/components/agent-artifact.tsx(2 hunks)app/chat/components/agent-chain-of-thought.tsx(4 hunks)app/chat/components/agent-checkpoint.tsx(1 hunks)app/chat/components/agent-confirmation.tsx(3 hunks)app/chat/components/agent-queue.tsx(2 hunks)app/chat/components/agent-sources.tsx(1 hunks)app/components/docs-nav.tsx(1 hunks)app/components/footer.tsx(5 hunks)app/components/landing-cta.tsx(6 hunks)app/components/landing-features.tsx(5 hunks)app/components/landing-stats.tsx(5 hunks)app/components/navbar.tsx(1 hunks)app/components/network-background.tsx(1 hunks)app/components/networks-list.tsx(1 hunks)app/components/page-header.tsx(3 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
**/app/**
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
Use the
app/directory structure for route handlers, server components, and client components (Next.js 13+). Prefer this over thepages/directory for new projects.
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
**/components/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
Use PascalCase for component file names (e.g.,
ComponentName.jsxorComponentName.tsx).
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)
**/*.{js,jsx,ts,tsx}: Usenext/dynamicfor dynamic imports to load components only when needed, improving initial load time.
Usenext/imagecomponent for automatic image optimization, including lazy loading and responsive images.
Use React.memo to prevent unnecessary re-renders of components.
Use the<Link prefetch>tag to prefetch pages that are likely to be visited.
Use getServerSideProps, getStaticProps, or server components for fetching data on the server-side.
Use SWR or React Query for client-side data fetching and caching.
Use CSS Modules, Styled Components, or Tailwind CSS for component-level styling. Prefer Tailwind CSS for rapid development.
Use React Context, Zustand, Jotai, or Recoil for managing global state. Avoid Redux unless necessary.
Usereact-hook-formfor managing forms and validation.
Only fetch the data that is needed by the component to avoid over-fetching.
Avoid long-running synchronous operations in the main thread to prevent blocking.
Always usesetStateor hooks to update state instead of mutating state directly.
Include a complete dependency array inuseEffecthooks to prevent unexpected behavior.
Avoid writing server-side code in client components to prevent exposing secrets or causing unexpected behavior.
Usetry...catchblocks for handling errors in asynchronous operations.
Implement error boundary components usinggetDerivedStateFromErrororcomponentDidCatchlifecycle methods.
Sanitize user input to prevent Cross-Site Scripting (XSS) attacks. Be especially careful when rendering HTML directly from user input.
Store authentication tokens in HTTP-only cookies or local storage securely.
Implement role-based access control to restrict access to sensitive resources.
Clean up event listeners and timers inuseEffecthooks to avoid memory leaks.
Only update state when necessary to reduce the number of re-renders and improve performance.
Use immutable data structures and avoid mutating data directly to prevent unexpected...
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (app/AGENTS.md)
app/**/*.{tsx,ts}: Use Tailwind CSS 4 with oklch color variables for styling in Next.js App Router pages and layouts
Use React 19 latest features in component implementations within the app directory
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
app/chat/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (app/chat/AGENTS.md)
app/chat/components/**/*.{ts,tsx}: Use AI SDK v5 types and patterns in chat components: import types like UIMessage, DynamicToolUIPart, TextUIPart, ReasoningUIPart from 'ai' and use type guard functions like isTextUIPart, isReasoningUIPart, isToolOrDynamicToolUIPart to filter message parts
Access message content through message.parts array using type guards rather than message.content, extracting specific parts like text using const textPart = message.parts?.find(isTextUIPart)
Handle Mastra stream chunk types correctly: use 'text-delta' for streaming text, 'reasoning-delta' for streaming reasoning (NOT 'reasoning'), 'tool-call' for tool invocation, 'tool-result' for tool completion, 'source' for research sources, and 'finish' for completion with usage data
Use AI Elements components (Conversation, Message, PromptInput, ModelSelector, Reasoning, Tool, Sources, Artifact) from the AI Elements library in their respective chat component files as specified in the architecture
Files:
app/chat/components/agent-artifact.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/chat/components/agent-checkpoint.tsx
app/chat/components/agent-artifact.tsx
📄 CodeRabbit inference engine (app/chat/AGENTS.md)
Display code and content artifacts using Artifact AI Elements component with syntax highlighting via CodeBlock component when the artifacts feature flag is enabled for the agent
Files:
app/chat/components/agent-artifact.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never commit API keys or secrets to the repository; use maskSensitiveMessageData() helper from src/mastra/config/pg-storage.ts when logging
**/*.{ts,tsx}: Document interface and type definitions with TSDoc comments explaining their purpose and usage context
Document interface properties with /** */ comments explaining each field's purpose and constraints
Document generic type parameters with @template tags explaining what each type parameter represents
Use type guards with comments explaining the runtime validation logic being performed
Document advanced/complex TypeScript types with explanatory comments about their purpose and use cases
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Next.js 16 App Router with React 19 for frontend development in the app/ directory
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
{app,ui,src/components}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Tailwind CSS 4 with oklch color variables for styling in UI components
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
{app,src/components}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
{app,src/components}/**/*.{ts,tsx}: Use shadcn/ui base components (34 components) located in ui/ directory for common UI elements
Use AI Elements library (30 components) from src/components/ai-elements/ for chat, reasoning, and canvas UIs
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}
📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)
**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}: Write code that speaks for itself. Comment only when necessary to explain WHY, not WHAT. Avoid obvious comments that state what the code literally does.
Avoid redundant comments that simply repeat what the code is doing
Keep comments accurate and up-to-date with code changes. Remove or update outdated comments that no longer match the implementation.
Write comments for complex business logic that explain the WHY behind specific calculations or business rules
Document non-obvious algorithms with comments explaining the algorithm choice and its reasoning
Add comments explaining what regex patterns match, especially for complex patterns
Document API constraints, rate limits, gotchas, and external dependencies with explanatory comments
Avoid commenting out dead code. Use version control instead of maintaining commented code blocks.
Do not maintain code change history or modification logs as comments. Rely on git history and commit messages instead.
Avoid decorative divider comments (e.g., lines of equals signs or asterisks) for section separation
Ensure comments are placed appropriately above or adjacent to the code they describe
Write comments using proper grammar, spelling, and professional language
Prefer self-documenting code with clear variable/function names over adding comments to explain unclear code
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)
**/*.{ts,tsx,js,jsx}: Document public APIs with TSDoc/JSDoc comments including parameter descriptions, return types, examples, and thrown exceptions
Add TSDoc comments to configuration constants and environment variables explaining their source, reasoning, or constraints
Use TSDoc annotation tags (TODO, FIXME, HACK, NOTE, WARNING, PERF, SECURITY, BUG, REFACTOR, DEPRECATED) to mark special comments
Include file headers with @fileoverview, @author, @copyright, and @license tags to document file purpose and ownership
Document function parameters with @param tags, return values with @returns tags, and exceptions with @throws tags in TSDoc comments
Use @see tags in TSDoc comments to reference related functions, methods, or documentation
Include @example tags in public API documentation with code examples showing typical usage
Files:
app/chat/components/agent-artifact.tsxapp/components/navbar.tsxapp/chat/components/agent-chain-of-thought.tsxapp/chat/components/agent-sources.tsxapp/components/network-background.tsxapp/chat/components/agent-queue.tsxapp/chat/components/agent-confirmation.tsxapp/components/docs-nav.tsxapp/components/landing-features.tsxapp/components/networks-list.tsxapp/chat/components/agent-checkpoint.tsxapp/components/landing-stats.tsxapp/components/page-header.tsxapp/components/footer.tsxapp/components/landing-cta.tsx
app/chat/components/agent-sources.tsx
📄 CodeRabbit inference engine (app/chat/AGENTS.md)
Display research sources and citations using Sources AI Elements component when the sources feature flag is enabled for the agent
Files:
app/chat/components/agent-sources.tsx
🧬 Code graph analysis (6)
app/components/navbar.tsx (4)
lib/utils.ts (1)
cn(4-6)ui/link.tsx (1)
Link(22-49)ui/button.tsx (1)
Button(60-60)ui/theme-toggle.tsx (1)
ThemeToggle(14-51)
app/chat/components/agent-chain-of-thought.tsx (2)
src/components/ai-elements/chain-of-thought.tsx (2)
ChainOfThought(45-76)ChainOfThoughtHeader(82-109)ui/badge.tsx (1)
Badge(46-46)
app/chat/components/agent-sources.tsx (2)
src/components/ai-elements/sources.tsx (3)
Sources(14-19)SourcesTrigger(25-42)SourcesContent(46-58)app/chat/providers/chat-context.tsx (1)
Source(20-23)
app/chat/components/agent-queue.tsx (4)
app/chat/providers/chat-context.tsx (1)
QueuedTask(35-40)src/components/ai-elements/queue.tsx (12)
QueueSection(199-205)QueueSectionTrigger(210-227)QueueSectionLabel(236-250)QueueSectionContent(257-262)QueueList(184-194)QueueItem(36-44)QueueItemIndicator(50-65)QueueItemContent(71-86)QueueItemActions(111-116)QueueItemAction(123-137)QueueItemDescription(92-107)Queue(266-274)lib/utils.ts (1)
cn(4-6)ui/badge.tsx (1)
Badge(46-46)
app/chat/components/agent-confirmation.tsx (3)
src/components/ai-elements/confirmation.tsx (6)
Confirmation(66-81)ConfirmationRequest(96-106)ConfirmationAccepted(112-130)ConfirmationRejected(136-154)ConfirmationActions(158-176)ConfirmationAction(180-182)lib/utils.ts (1)
cn(4-6)ui/badge.tsx (1)
Badge(46-46)
app/components/landing-features.tsx (1)
ui/effects/bento-grid.tsx (2)
BentoGrid(3-20)BentoGridItem(22-54)
🪛 Biome (2.1.2)
app/components/navbar.tsx
[error] 57-57: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 70-70: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 98-98: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 128-128: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 167-167: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 179-179: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 206-206: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
app/chat/components/agent-chain-of-thought.tsx
[error] 39-39: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 40-40: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Security Scan
🔇 Additional comments (26)
app/components/docs-nav.tsx (1)
118-118: LGTM! Type safety improvement.Removing the unnecessary
as anycast improves type safety. Thesection.hrefvalues are already properly typed as strings and compatible with Next.js Link's href prop.app/components/landing-features.tsx (2)
149-152: LGTM! Well-structured hover effects.The elevated card design with smooth border, shadow, and translate transitions creates a polished user experience. The icon container properly uses group hover states for coordinated animations.
170-189: LGTM! Stats bar hover effects enhance interactivity.The group hover pattern on stat values provides subtle visual feedback without being distracting. The backdrop-blur and muted background create good visual hierarchy.
app/components/landing-cta.tsx (2)
66-68: LGTM! Theme consistency improved.The badge and icon styling updates successfully align with the new muted color scheme, creating a more cohesive visual appearance across the component.
168-179: No action needed. Thecard-3dclass and container query support are already properly configured in the codebase. Thecard-3dclass is defined inapp/globals.csswith full 3D transform styling, and Tailwind v4 container query breakpoints are configured via the@theme inlineblock. The code at these lines will work as intended.Likely an incorrect or invalid review comment.
app/components/navbar.tsx (4)
1-14: Imports cleaned up from previous review.The unused
ChevronDownIconand other icons from the previous review have been removed. All current imports appear to be used.
16-33: Hooks implementation is correct.The
pathnamevariable is now properly used for active link highlighting, addressing the previous review comment. TheprevPathnameRefpattern for closing the mobile menu on route changes is correctly implemented with proper cleanup.
35-43: Header styling implementation is well done.Good use of the
cnutility for conditional class composition and thesupports-backdrop-filterfallback for progressive enhancement.
116-138: Actions section implementation is clean.Good use of the
asChildpattern with the Button component for semantic HTML. The spacing and visual hierarchy are well organized.app/components/networks-list.tsx (1)
96-103: No substantive changes.These are whitespace-only adjustments with no functional impact.
app/components/page-header.tsx (2)
3-3: Good use of type-only import.Using
import typeforReactNodeis correct since it's only used for type annotations and not at runtime.
79-79: LGTM on badge guard.
Boolean(badge)correctly handles bothundefinedand empty string cases for the optional string prop.app/chat/components/agent-artifact.tsx (2)
58-59: Good addition of thenormalizeLanguagehelper.This addresses the past review feedback to centralize language normalization.
69-71: Correct usage ofnormalizeLanguagehere.The helper is properly applied for the
isPreviewablecheck in the main component.app/chat/components/agent-sources.tsx (3)
19-25: Good defensive URL parsing ingetDomain.The try-catch handles malformed URLs gracefully by falling back to the original string.
27-34:getFaviconhandles errors correctly.Returns empty string for invalid URLs, and the
onErrorhandler on the<img>hides it if the favicon fails to load.
82-94: Favicon handling and fallback rendering look good.The combination of
getDomainfallback for missing titles and theonErrorhandler to hide broken favicon images provides a good user experience.app/components/landing-stats.tsx (3)
20-20: Good extension of the icon type.Adding
strokeWidth?: numberenables consistent icon styling across the component.
76-76: Brace-style early return is fine.No functional change; just formatting consistency.
132-137: Clean styling update for the primary stat cards.The monochrome-to-primary hover transition provides good visual feedback.
app/chat/components/agent-queue.tsx (3)
48-60: Good edge case handling informatRelativeTime.The null/NaN check and future date handling address the past review feedback.
One minor improvement:
date === nullwon't catchundefined. Consider:- if (date === null || isNaN(date.getTime())) { return "unknown" } + if (!date || isNaN(date.getTime())) { return "unknown" }
73-148: Well-structuredTaskSectioncomponent.The refactoring to a reusable section component with proper HTML structure (description as sibling to content) addresses the past review concern about invalid HTML nesting.
157-162: Good use ofuseMemofor task grouping.Avoids recomputing the filtered arrays on every render when
taskshasn't changed.app/chat/components/agent-confirmation.tsx (1)
36-60: Well-structured severity configuration.The
severityConfigmapping cleanly centralizes icon, styling, and label definitions per severity level. This is a good pattern for maintainability.app/components/footer.tsx (2)
158-158: Excellent type safety improvement!Removing the
as anytype assertions strengthens type checking while maintaining functionality. Thelink.hrefproperties are correctly typed as strings and compatible with the Next.js Link component.Also applies to: 175-175, 192-192, 209-209
85-85: The custom easing functions are properly defined inapp/globals.csswithin the@theme inlineblock and are correctly configured for Tailwind CSS v4. In Tailwind v4, theme variables defined via@theme inlineautomatically generate corresponding utility classes (e.g.,.ease-spring,.ease-smooth), so these custom easing functions will work as intended and will not be ignored.
| if (!steps || steps.length === 0) {return null} | ||
|
|
||
| const completedCount = useMemo(() => steps.filter((s) => s.status === "complete").length, [steps]) | ||
| const activeStep = useMemo(() => steps.find((s) => s.status === "active"), [steps]) |
There was a problem hiding this comment.
Critical: Hooks called conditionally violate Rules of Hooks.
The useMemo hooks on lines 39-40 are called after the early return on line 37. React requires hooks to be called unconditionally and in the same order on every render. This will cause bugs and React warnings.
Move the early return after the hooks:
export function AgentChainOfThought({
steps,
isStreaming = false,
defaultOpen = true,
className,
}: AgentChainOfThoughtProps) {
- if (!steps || steps.length === 0) {return null}
-
const completedCount = useMemo(() => steps.filter((s) => s.status === "complete").length, [steps])
const activeStep = useMemo(() => steps.find((s) => s.status === "active"), [steps])
+ if (!steps || steps.length === 0) {return null}
+
return (Note: With this change, the useMemo computations will run even when steps is empty, but the cost is negligible since filtering/finding on an empty array is O(1). The hooks will safely handle undefined/empty steps since filter and find on [] return [] and undefined respectively.
🧰 Tools
🪛 Biome (2.1.2)
[error] 39-39: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 40-40: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
🤖 Prompt for AI Agents
In app/chat/components/agent-chain-of-thought.tsx around lines 37–40, the
useMemo hooks are currently called conditionally after an early return, which
violates the Rules of Hooks; move the early return so hooks are invoked
unconditionally at the top of the component and compute completedCount and
activeStep before returning, and ensure the hooks safely handle undefined/empty
steps (e.g., operate on a default empty array or guard within the memo) so the
logic still returns null when appropriate after the hooks run.
| <ChainOfThoughtHeader className="flex items-center gap-2"> | ||
| <span className="flex-1"> | ||
| {isStreaming | ||
| ? activeStep?.label ?? "Thinking..." | ||
| : "Chain of Thought" | ||
| } | ||
| </span> | ||
| <Badge variant="secondary" className="text-xs font-normal"> | ||
| {completedCount}/{steps.length} | ||
| </Badge> | ||
| </ChainOfThoughtHeader> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd /repo && find . -type f -name "*.tsx" -o -name "*.ts" | head -20Repository: ssdeanx/AgentStack
Length of output: 117
🏁 Script executed:
cd /repo && rg "ChainOfThoughtHeader" -A 10 -B 2Repository: ssdeanx/AgentStack
Length of output: 117
🏁 Script executed:
cd /repo && ast-grep --pattern 'const ChainOfThoughtHeader = $_'Repository: ssdeanx/AgentStack
Length of output: 117
🏁 Script executed:
cd /repo && fd "chain-of-thought" --type fRepository: ssdeanx/AgentStack
Length of output: 117
🏁 Script executed:
git ls-files | grep -E "(component|chat)" | head -20Repository: ssdeanx/AgentStack
Length of output: 777
🏁 Script executed:
rg "ChainOfThoughtHeader" -A 10 -B 2Repository: ssdeanx/AgentStack
Length of output: 12365
🏁 Script executed:
fd "chain-of-thought" --type fRepository: ssdeanx/AgentStack
Length of output: 156
🏁 Script executed:
cat -n src/components/ai-elements/chain-of-thought.tsx | head -100Repository: ssdeanx/AgentStack
Length of output: 3284
🏁 Script executed:
sed -n '85,105p' src/components/ai-elements/chain-of-thought.tsxRepository: ssdeanx/AgentStack
Length of output: 727
Fix children structure to work with ChainOfThoughtHeader's internal layout.
The ChainOfThoughtHeader component wraps children inside a controlled span element (lines 96-98 of src/components/ai-elements/chain-of-thought.tsx), so passing multiple siblings (a span and Badge) will not render as intended. The Badge will appear inside the flex-1 span rather than as a sibling element alongside the text.
Refactor to pass only the text content as children, and place the Badge outside the ChainOfThoughtHeader:
<ChainOfThought>
<div className="flex items-center gap-2">
<ChainOfThoughtHeader>
{isStreaming ? activeStep?.label ?? "Thinking..." : "Chain of Thought"}
</ChainOfThoughtHeader>
<Badge variant="secondary" className="text-xs font-normal">
{completedCount}/{steps.length}
</Badge>
</div>
<ChainOfThoughtContent>
{/* ... */}
</ChainOfThoughtContent>
</ChainOfThought>🤖 Prompt for AI Agents
In app/chat/components/agent-chain-of-thought.tsx around lines 44-54, the
ChainOfThoughtHeader currently receives multiple children (a span and a Badge)
but the header component itself wraps its children in a controlled span, causing
the Badge to be rendered inside that span; move the Badge out of
ChainOfThoughtHeader so the header receives only the text child and place both
header and Badge as siblings inside a wrapper div with the "flex items-center
gap-2" classes (keep Badge props and content as-is), i.e., pass only the string
(isStreaming ? activeStep?.label ?? "Thinking..." : "Chain of Thought") into
ChainOfThoughtHeader and render the Badge next to it in the wrapper container.
| {step.duration && step.status === "complete" && ( | ||
| <span className="flex items-center gap-1 text-xs text-muted-foreground"> | ||
| <ClockIcon className="size-3" /> | ||
| {step.duration}s | ||
| </span> | ||
| )} |
There was a problem hiding this comment.
Duration display has a potential falsy-value bug.
The condition step.duration && step.status === "complete" will not render when duration is 0. If 0 is a valid duration (e.g., a step that completed instantly), this would incorrectly hide it.
If 0 is a valid duration value, use explicit check:
- {step.duration && step.status === "complete" && (
+ {step.duration !== undefined && step.status === "complete" && (
<span className="flex items-center gap-1 text-xs text-muted-foreground">
<ClockIcon className="size-3" />
{step.duration}s
</span>
)}🤖 Prompt for AI Agents
In app/chat/components/agent-chain-of-thought.tsx around lines 70 to 75, the
render condition uses a falsy check (step.duration && step.status ===
"complete") which will hide valid 0 durations; change the condition to an
explicit null/undefined check (for example step.duration != null && step.status
=== "complete" or typeof step.duration === "number" && step.status ===
"complete") so that zero is treated as a valid duration and the span renders
when status is "complete".
| <TaskSection | ||
| title="Completed" | ||
| tasks={completed} | ||
| icon={<CheckCircle2Icon className="size-3 text-green-500" />} |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Hardcoded color text-green-500 instead of semantic token.
Per coding guidelines, prefer oklch color variables or semantic tokens for consistency. Consider using a success-themed semantic class.
- icon={<CheckCircle2Icon className="size-3 text-green-500" />}
+ icon={<CheckCircle2Icon className="size-3 text-success" />}If no text-success token exists, define one or use an existing semantic alternative.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/chat/components/agent-queue.tsx around line 198 the CheckCircle2Icon uses
a hardcoded Tailwind class `text-green-500`; replace it with a semantic success
token (for example `text-success` or a theme class like
`text-[var(--color-success)]`) to follow Oklch/semantic token guidelines. If
`text-success` (or an equivalent) does not exist, add a semantic token in your
theme/tailwind config or CSS variables (e.g., --color-success) and use that
class here, ensuring the naming matches the project's token convention and
retains the same accessible contrast.
| const uniqueSources = useMemo(() => { | ||
| if (sources.length === 0) { | ||
| return [] | ||
| } | ||
| const seen = new Set<string>() | ||
| return sources.filter((source) => { | ||
| if (seen.has(source.url)) {return false} | ||
| seen.add(source.url) | ||
| return true | ||
| }).slice(0, maxVisible) | ||
| }, [sources, maxVisible]) |
There was a problem hiding this comment.
Add null guard for sources before accessing .length.
If sources is undefined or null, sources.length will throw. The component interface shows sources: SourceType[] but callers might pass undefined.
const uniqueSources = useMemo(() => {
- if (sources.length === 0) {
+ if (!sources || sources.length === 0) {
return []
}🤖 Prompt for AI Agents
In app/chat/components/agent-sources.tsx around lines 41 to 51, the code
accesses sources.length directly which will throw if sources is undefined or
null; update the logic to guard against a null/undefined sources (e.g., treat
sources as an empty array via a default value or early return) before using
.length or iterating, then proceed to build the uniqueSources Set/filter and
slice; ensure the useMemo dependencies remain correct and that downstream code
still receives an array.
| interface Node { | ||
| id: number | ||
| x: number | ||
| y: number | ||
| radius: number | ||
| color: string | ||
| velocity: { x: number; y: number } | ||
| connections: number[] | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Add TSDoc documentation for the Node interface.
Per coding guidelines, document interface and type definitions with TSDoc comments explaining their purpose and usage.
Add documentation like:
/**
* Represents a single particle node in the animated network.
* Each node has a position, visual properties, and physics simulation data.
*/
interface Node {
/** Unique identifier for the node */
id: number
/** Current x-coordinate position on the canvas */
x: number
/** Current y-coordinate position on the canvas */
y: number
/** Radius of the node circle in pixels */
radius: number
/** RGBA color string for rendering the node */
color: string
/** Movement velocity vector in pixels per frame */
velocity: { x: number; y: number }
connections: number[]
}🤖 Prompt for AI Agents
In app/components/network-background.tsx around lines 7 to 15, the Node
interface lacks TSDoc comments; add a brief TSDoc block above the interface
describing it as a single particle node in the animated network and add TSDoc
comments for each property: id (unique identifier), x/y (current canvas
coordinates), radius (pixel radius), color (RGBA string used for rendering),
velocity (object with x and y pixel-per-frame components), and connections
(array of connected node ids) so the interface and its fields are documented per
coding guidelines.
🧹 Nitpick | 🔵 Trivial
Consider removing the unused connections field.
The connections field is defined in the Node interface and initialized (line 43) but never populated or used in the animation logic.
If connections are not needed for future functionality, apply this diff:
interface Node {
id: number
x: number
y: number
radius: number
color: string
velocity: { x: number; y: number }
- connections: number[]
}And remove from initialization:
newNodes.push({
id: i,
x: Math.random() * width,
y: Math.random() * height,
radius: Math.random() * 2 + 1,
color: "rgba(255, 255, 255, 0.3)",
velocity: {
x: (Math.random() - 0.5) * 0.5,
y: (Math.random() - 0.5) * 0.5,
},
- connections: [],
})Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/components/network-background.tsx around lines 7 to 15, the Node
interface includes an unused connections field and it's also initialized around
line 43; remove the connections property from the interface and delete its
initialization at line 43 (and any other places where a blank connections array
is assigned) so the type and object creation no longer include this unused
field.
| connections: number[] | ||
| } | ||
|
|
||
| export function NetworkBackground({ className }: { className?: string }) { |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Add TSDoc documentation for the public component.
Per coding guidelines, document public APIs with TSDoc comments including parameter descriptions and examples.
Add documentation like:
/**
* NetworkBackground renders an animated particle network on a canvas.
* Nodes move continuously, connect to nearby nodes, and respond to mouse proximity
* by brightening and gently moving toward the cursor.
*
* @param className - Optional CSS class name to apply to the container div
* @example
* ```tsx
* <NetworkBackground className="opacity-50" />
* ```
*/
export function NetworkBackground({ className }: { className?: string }) {🤖 Prompt for AI Agents
In app/components/network-background.tsx around line 17, the exported
NetworkBackground component lacks TSDoc comments; add a TSDoc block immediately
above the function declaration describing what the component renders/behaves
like, annotate the className parameter (optional CSS class for the container),
and include a short usage example showing <NetworkBackground className="..." />;
ensure the comment uses standard TSDoc tags (e.g., @param and @example) and is
formatted as a /** ... */ block placed directly above the export.
| if (!containerRef.current) {return} | ||
|
|
||
| const { width, height } = containerRef.current.getBoundingClientRect() | ||
| const nodeCount = 40 |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider extracting magic numbers as named constants.
The values 40 (nodeCount) and 200 (interactionRadius) are hardcoded. Extracting them as constants would improve maintainability and make it easier to tune the animation behavior.
Apply this diff:
+const NODE_COUNT = 40
+const MOUSE_INTERACTION_RADIUS = 200
+
export function NetworkBackground({ className }: { className?: string }) {
const canvasRef = useRef<HTMLCanvasElement>(null)
const containerRef = useRef<HTMLDivElement>(null)
const [nodes, setNodes] = useState<Node[]>([])
const requestRef = useRef<number | null>(null)
const mouseRef = useRef<{ x: number; y: number }>({ x: -1000, y: -1000 })
// Initialize nodes
useEffect(() => {
if (!containerRef.current) {return}
const { width, height } = containerRef.current.getBoundingClientRect()
- const nodeCount = 40
+ const nodeCount = NODE_COUNT
const newNodes: Node[] = []And:
const dx = mouseRef.current.x - node.x
const dy = mouseRef.current.y - node.y
const distance = Math.sqrt(dx * dx + dy * dy)
- const interactionRadius = 200
+ const interactionRadius = MOUSE_INTERACTION_RADIUSAlso applies to: 87-87
🤖 Prompt for AI Agents
In app/components/network-background.tsx around lines 29 and 87, the hardcoded
numeric literals `40` (nodeCount) and `200` (interactionRadius) should be
extracted as named constants; add descriptive constants (e.g., const NODE_COUNT
= 40 and const INTERACTION_RADIUS = 200) near the top of the file (or next to
related imports), replace the inline usages at line 29 and line 87 with these
constants, and ensure any related comments/documentation reflect that these
values are configurable for easier tuning and maintenance.
| x: Math.random() * width, | ||
| y: Math.random() * height, | ||
| radius: Math.random() * 2 + 1, | ||
| color: "rgba(255, 255, 255, 0.3)", // Default node color |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Remove obvious comment.
The comment "Default node color" simply states what the code does. Per coding guidelines, avoid comments that repeat what the code literally does.
Apply this diff:
radius: Math.random() * 2 + 1,
- color: "rgba(255, 255, 255, 0.3)", // Default node color
+ color: "rgba(255, 255, 255, 0.3)",
velocity: {📝 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.
| color: "rgba(255, 255, 255, 0.3)", // Default node color | |
| radius: Math.random() * 2 + 1, | |
| color: "rgba(255, 255, 255, 0.3)", | |
| velocity: { |
🤖 Prompt for AI Agents
In app/components/network-background.tsx around line 38, remove the redundant
comment "// Default node color" that merely restates the code; delete the
comment so the line reads color: "rgba(255, 255, 255, 0.3)", and if context is
needed replace it with a brief rationale (e.g., explaining why that
color/opacity was chosen) rather than restating the property.
|
|
||
| {/* Optional children content */} | ||
| {children && ( | ||
| {Boolean(children) && ( |
There was a problem hiding this comment.
Boolean(children) may incorrectly filter valid React children.
ReactNode includes 0, false, and "" which are valid renderable values but evaluate to false under Boolean(). If a consumer passes 0 as children, it won't render.
Consider using the more idiomatic nullish check:
- {Boolean(children) && (
+ {children != null && (Alternatively, if you want to filter all falsy values intentionally, this is acceptable but should be documented.
📝 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.
| {Boolean(children) && ( | |
| {children != null && ( |
🤖 Prompt for AI Agents
In app/components/page-header.tsx around line 117, the guard uses
Boolean(children) which will incorrectly exclude valid React children such as 0
or empty string; change the condition to a nullish check that only filters out
null and undefined (so numeric zero, empty string, and false remain renderable)
and, if the original intent was to filter all falsy values, instead keep the
current Boolean-based check but add a comment in the code and component docs
explaining that all falsy children will be omitted.
ToolExecutionCardcomponent to display the status of tool executions with detailed information including input, output, and error handling.ToolExecutionListcomponent to render a list ofToolExecutionCardcomponents, allowing for easy management of multiple tool executions.WorkflowExecutioncomponent to manage and display the progress of workflow steps, including pause, resume, and retry functionalities.WorkflowTimelinecomponent for visual representation of workflow steps in both vertical and horizontal orientations.AnimatedBeamandBackgroundBeamscomponents for enhanced visual effects in the UI.BentoGridandBentoGridItemcomponents for structured layout of items in a grid format.BorderBeamcomponent for animated border effects around elements.CardSpotlightandSpotlightcomponents for dynamic spotlight effects on hover.TextGenerateEffectfor animated text rendering with staggered effects.