-
Notifications
You must be signed in to change notification settings - Fork 487
refactor: sidebar #210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: sidebar #210
Conversation
- Rename App.tsx to app.tsx (kebab-case naming convention) - Add barrel exports (index.ts) for src/hooks/ - Add barrel exports (index.ts) for src/components/dialogs/ - Add barrel exports (index.ts) for src/components/layout/ - Update renderer.tsx import to use lowercase app.tsx This is Phase 1 of folder-pattern.md compliance: establishing proper file naming conventions and barrel export patterns. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Move dialogs to src/components/dialogs/ folder: - delete-session-dialog.tsx - delete-all-archived-sessions-dialog.tsx - new-project-modal.tsx - workspace-picker-modal.tsx - Update all imports to reference new dialog locations - Create barrel export (index.ts) for board-view/components/kanban-card/ - Create barrel exports (index.ts) for all 11 settings-view subfolders: - api-keys/, api-keys/hooks/, appearance/, audio/, cli-status/ - components/, config/, danger-zone/, feature-defaults/ - keyboard-shortcuts/, shared/ This is Phase 2 of folder-pattern.md compliance: organizing dialogs and establishing consistent barrel export patterns across all view subfolders. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extract inline components and organize sidebar structure: - Create sidebar/ subfolder structure (components/, hooks/, dialogs/) - Extract types.ts: NavSection, NavItem, component prop interfaces - Extract constants.ts: theme options, feature flags - Extract 3 inline components into separate files: - sortable-project-item.tsx (drag-and-drop project item) - theme-menu-item.tsx (memoized theme selector) - bug-report-button.tsx (reusable bug report button) - Update sidebar.tsx to import from extracted modules - Reduce sidebar.tsx from 2323 to 2187 lines (-136 lines) This is Phase 3 (partial) of folder-pattern.md compliance: breaking down the monolithic sidebar.tsx into maintainable, reusable components. Further refactoring (hooks extraction, dialog extraction) can be done incrementally to avoid disrupting functionality. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extract 3 simple hooks with no UI dependencies: - use-theme-preview.ts: Debounced theme preview on hover - use-sidebar-auto-collapse.ts: Auto-collapse on small screens - use-drag-and-drop.ts: Project reordering drag-and-drop Benefits: - Reduced sidebar.tsx by 88 lines (-4%) - Improved testability (hooks can be tested in isolation) - Removed unused imports (DragEndEvent, PointerSensor, useSensor, useSensors) - Created hooks/ barrel export pattern Next steps: Extract 10+ remaining hooks and 10+ UI sections to reach target of 200-300 lines (current: 2099 lines, need to reduce ~1800 more) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Introduced new hooks: useRunningAgents, useTrashOperations, useProjectPicker, useSpecRegeneration, and useNavigation for improved state management and functionality. - Created CollapseToggleButton component for sidebar collapse functionality, enhancing UI responsiveness. - Refactored sidebar.tsx to utilize the new hooks and components, improving code organization and maintainability. - Updated sidebar structure to streamline project selection and navigation processes. This refactor aims to enhance user experience and maintainability by modularizing functionality and improving the sidebar's responsiveness.
…ility Extract logo, header, actions, and navigation into separate components: - AutomakerLogo: SVG logo with collapsed/expanded states - SidebarHeader: Logo section with bug report button - ProjectActions: New/Open/Trash action buttons - SidebarNavigation: Navigation items with active states Reduces sidebar.tsx from 1551 to 1442 lines (-109 lines) Improves code organization and component reusability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ionality - Extracted new components: ProjectSelectorWithOptions, SidebarFooter, TrashDialog, and OnboardingDialog to improve code organization and reusability. - Introduced new hooks: useProjectCreation, useSetupDialog, and useTrashDialog for better state management and modularity. - Updated sidebar.tsx to utilize the new components and hooks, reducing complexity and improving maintainability. - Enhanced project creation and setup processes with dedicated dialogs and streamlined user interactions. This refactor aims to enhance the user experience and maintainability of the sidebar by modularizing functionality and improving the overall structure.
…nd documentation - Updated type imports for `icon` and `content` in the `WikiSection` interface to use `ElementType` and `ReactNode` for better clarity and type safety. - Expanded the content description in the WikiView to include shared libraries and updated technology stack details. - Revised the directory structure representation for clarity and completeness, reflecting the current organization of the codebase. - Adjusted file paths in the feature list for better accuracy and organization. These changes aim to improve the documentation and type safety within the WikiView component, enhancing developer experience and understanding of the project structure.
|
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. WalkthroughAdds extensive server unit tests for ClaudeUsageService and a large UI refactor: Sidebar decomposed into many new components, hooks, dialogs, and barrels; several component props/signatures expanded; widespread string-quote normalization and small API signature tweaks across UI libraries and tests. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Sidebar as Sidebar UI
participant Hooks as Sidebar Hooks
participant Store as App Store
participant Electron as Electron API
Note over User,Sidebar: user interacts with sidebar (clicks, drag, create)
User->>Sidebar: click "New Project" / reorder project / open item
Sidebar->>Hooks: delegate (useProjectCreation / useDragAndDrop / useNavigation)
Hooks->>Electron: invoke FS/clone/spec-regeneration/open-folder
Electron-->>Hooks: result (success / error / events)
Hooks->>Store: update state (projects, modal flags, theme preview)
Store-->>Sidebar: new state
Sidebar-->>User: render updated UI / show toast
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
Comment |
Summary of ChangesHello @Shironex, 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 significant refactoring of the UI application's folder structure, aiming to enhance code organization and maintainability. It involves relocating various components, particularly dialogs and sidebar-related logic, into more granular and semantically grouped subdirectories. This restructuring simplifies navigation, reduces cognitive load for developers, and sets a foundation for future feature development by promoting a cleaner, more modular codebase. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. 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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This is a significant and well-executed refactoring that greatly improves the structure of the Sidebar component by breaking it down into smaller, more manageable components and hooks. It also reorganizes component files into a more logical folder structure. While the refactoring is a huge improvement, I've found a critical regression in the project creation logic that was extracted into the new useProjectCreation hook. Additionally, this has led to duplicated and inconsistent project creation logic between the Sidebar and the WelcomeView. My review focuses on these two key issues to ensure the refactoring doesn't negatively impact core functionality.
- Updated the project creation logic to write a detailed app_spec.txt file in XML format, including project name, overview, technology stack, core capabilities, and implemented features. - Improved handling for projects created from templates and custom repositories, ensuring relevant information is captured in the app_spec.txt. - Enhanced user feedback with success messages upon project creation, improving overall user experience. These changes aim to provide a clearer project structure and facilitate better integration with AI analysis tools.
- Deleted the pnpm-lock.yaml file as part of project cleanup. - Introduced comprehensive unit tests for the ClaudeUsageService, covering methods for checking CLI availability, parsing reset times, and handling usage output. - Enhanced test coverage for both macOS and Windows environments, ensuring robust functionality across platforms. These changes aim to streamline project dependencies and improve the reliability of the Claude usage tracking service through thorough testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/ui/src/components/layout/sidebar.tsx (1)
168-226: Missing dependencies inhandleOpenFoldercallback.The callback uses
setSetupProjectPath(line 205) andsetShowSetupDialog(line 206) fromuseSetupDialog, but these are not included in the dependency array. While React state setters are typically stable, these come from a custom hook's return value. If the hook ever returns new setter references, this could cause stale closure bugs.🔎 Suggested fix
}, [trashedProjects, upsertAndSetCurrentProject, currentProject, globalTheme]); + }, [trashedProjects, upsertAndSetCurrentProject, currentProject, globalTheme, setSetupProjectPath, setShowSetupDialog]);
♻️ Duplicate comments (1)
apps/ui/src/components/views/welcome-view.tsx (1)
227-525: Project creation logic remains duplicated.As noted in the previous review, the project creation handlers (
handleCreateBlankProject,handleCreateFromTemplate,handleCreateFromCustomUrl) in this component duplicate logic that should be centralized in theuseProjectCreationhook. The previous reviewer noted that this implementation is actually more correct than the hook version.Consider consolidating this logic into the
useProjectCreationhook to ensure consistent behavior across the application and reduce maintenance burden.Based on previous review comments.
🧹 Nitpick comments (15)
apps/ui/src/components/views/wiki-view.tsx (1)
139-567: LGTM! Consistent string normalization and content improvements.The section data has been updated with:
- Consistent single-quote string literals throughout
- Improved wiki content for clarity
- Updated file paths and descriptions
The changes maintain functionality while improving code style consistency.
Optional: Verify linter/formatter configuration.
To prevent future inconsistencies with quote styles, consider verifying that your ESLint or Prettier configuration enforces single quotes:
Example ESLint/Prettier configuration
ESLint (.eslintrc.json):
{ "rules": { "quotes": ["error", "single", { "avoidEscape": true }] } }Prettier (.prettierrc):
{ "singleQuote": true }apps/server/tests/unit/services/claude-usage-service.test.ts (1)
109-127: Consider reusing theserviceinstance frombeforeEach.These tests create new
ClaudeUsageService()instances, but there's already aservicevariable initialized inbeforeEach(line 18). This pattern is repeated throughout many test blocks (lines 140, 149, 160, 172, 183, 195, 208, 218, 228, 250, 259, 273, 296, 305, 315, 326, 354, 369, 390).🔎 Example fix
describe('stripAnsiCodes', () => { it('should strip ANSI color codes from text', () => { - const service = new ClaudeUsageService(); const input = '\x1B[31mRed text\x1B[0m Normal text'; // @ts-expect-error - accessing private method for testing const result = service.stripAnsiCodes(input); expect(result).toBe('Red text Normal text'); }); it('should handle text without ANSI codes', () => { - const service = new ClaudeUsageService(); const input = 'Plain text'; // @ts-expect-error - accessing private method for testing const result = service.stripAnsiCodes(input); expect(result).toBe('Plain text'); }); });apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (1)
17-30: Refactor the z-index to use a more reasonable value.The
z-9999on line 20 is an extremely high z-index that suggests z-index management issues. This can lead to stacking context problems and makes it difficult to layer UI elements predictably.Consider using a more reasonable z-index value (e.g., 50, 100, or 1000) or defining z-index levels in a centralized CSS/design tokens file.
💡 Suggested approach
Define z-index constants in your theme or design tokens:
// In a central location like lib/z-index.ts or theme config export const Z_INDEX = { SIDEBAR_TOGGLE: 50, MODAL: 100, TOOLTIP: 1000, } as const;Then use it:
- 'hidden lg:flex absolute top-[68px] -right-3 z-9999', + 'hidden lg:flex absolute top-[68px] -right-3 z-50',apps/ui/src/components/layout/sidebar/components/sortable-project-item.tsx (1)
46-51: Add keyboard accessibility to the project selection area.The clickable div on line 47 is not keyboard accessible. Users navigating with keyboard cannot select projects since the div is not focusable and has no keyboard event handlers.
Consider making this interactive element keyboard accessible to comply with accessibility best practices.
💡 Suggested fix
- <div className="flex items-center gap-2.5 flex-1 min-w-0" onClick={() => onSelect(project)}> + <div + role="button" + tabIndex={0} + className="flex items-center gap-2.5 flex-1 min-w-0" + onClick={() => onSelect(project)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + onSelect(project); + } + }} + >Alternatively, wrap the content in a
<button>element styled to match the current div appearance.apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
29-49: Consider unique SVG gradient IDs to avoid potential conflicts.The gradient and filter IDs (
bg-collapsed,bg-expanded,iconShadow-collapsed,iconShadow-expanded) are hardcoded. If multiple instances of this component are rendered on the same page, these IDs could conflict, causing incorrect rendering.Since this is a logo component likely rendered once, this is probably not an issue in practice, but for maximum safety you could generate unique IDs using React's
useId()hook.🔎 Example refactor using useId()
+import { useId } from 'react'; import type { NavigateOptions } from '@tanstack/react-router'; import { cn } from '@/lib/utils'; export function AutomakerLogo({ sidebarOpen, navigate }: AutomakerLogoProps) { + const id = useId(); + const bgCollapsedId = `bg-collapsed-${id}`; + const bgExpandedId = `bg-expanded-${id}`; + const shadowCollapsedId = `iconShadow-collapsed-${id}`; + const shadowExpandedId = `iconShadow-expanded-${id}`; + return ( // ... then use these IDs in the SVG elements: - <linearGradient id="bg-collapsed" ...> + <linearGradient id={bgCollapsedId} ...> // ... and in fill/filter references: - fill="url(#bg-collapsed)" + fill={`url(#${bgCollapsedId})`} ); }Also applies to: 74-95
apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts (2)
31-64: Consider replacing window.confirm with a proper dialog component.The
window.confirmcalls (lines 33 and 71) provide functional confirmation but have UX limitations:
- Blocks the UI thread
- Uses native browser styling (inconsistent with app design)
- Limited accessibility support
Consider creating a dedicated confirmation dialog component for better user experience and consistency with the rest of the application's design system.
That said, the defensive check for
api.trashItemavailability (lines 41-43) is excellent and prevents runtime errors in environments where the API might not be available.
66-83: Consider replacing window.confirm with a proper dialog component.Similar to
handleDeleteProjectFromDisk, thewindow.confirmcall (lines 71-73) would benefit from being replaced with a custom confirmation dialog for better UX and design consistency.apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)
58-60: Consider defensive date parsing.If
project.trashedAtcontains an invalid date string,new Date(project.trashedAt).toLocaleString()will display "Invalid Date". Consider adding a fallback or validation if the data source isn't fully trusted.🔎 Example defensive approach
- <p className="text-[11px] text-muted-foreground/80"> - Trashed {new Date(project.trashedAt).toLocaleString()} - </p> + <p className="text-[11px] text-muted-foreground/80"> + Trashed {(() => { + const date = new Date(project.trashedAt); + return isNaN(date.getTime()) ? 'Unknown date' : date.toLocaleString(); + })()} + </p>apps/ui/src/components/layout/sidebar/components/sidebar-navigation.tsx (1)
121-121: Potential fragiledata-testidgeneration.Using
item.label.toLowerCase()directly may produce inconsistent test IDs if labels contain spaces or special characters (e.g., "Running Agents" → "running agents"). Consider using a slug or the existingitem.idfor consistency.🔎 Suggested fix
- data-testid={`sidebar-tooltip-${item.label.toLowerCase()}`} + data-testid={`sidebar-tooltip-${item.id}`}apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (2)
256-271: Review theme selection side effects.When selecting "Use Global" (
value === ''),setTheme(globalTheme)is called, which may trigger unnecessary re-renders if the theme is already the global theme. Consider checking if a theme change is actually needed.🔎 Suggested optimization
onValueChange={(value) => { if (currentProject) { setPreviewTheme(null); - if (value !== '') { - setTheme(value as ThemeMode); - } else { - setTheme(globalTheme); - } + // Only update theme if it's actually changing + const newTheme = value === '' ? globalTheme : (value as ThemeMode); + setTheme(newTheme); setProjectTheme( currentProject.id, value === '' ? null : (value as ThemeMode) ); } }}
146-160: Addaria-labelfor accessibility.The search input has a placeholder but lacks an accessible label for screen readers. Adding
aria-label="Search projects"would improve accessibility.🔎 Suggested fix
<input ref={projectSearchInputRef} type="text" placeholder="Search projects..." + aria-label="Search projects" value={projectSearchQuery}apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (1)
87-101: Consider resettinggenerateFeatures,analyzeProject, andfeatureCounton skip.When the user skips setup,
projectOverviewandsetupProjectPathare reset, but the toggle/select states (generateFeatures,analyzeProject,featureCount) are preserved. If a user skips, then later opens the dialog for a different project, these stale values may not be appropriate defaults.🔎 Suggested improvement
const handleSkipSetup = useCallback(() => { setShowSetupDialog(false); setProjectOverview(''); setSetupProjectPath(''); + setGenerateFeatures(true); + setAnalyzeProject(true); + setFeatureCount(50); // Clear onboarding state if we came from onboarding if (newProjectPath) { setNewProjectName(''); setNewProjectPath(''); } toast.info('Setup skipped', { description: 'You can set up your app_spec.txt later from the Spec view.', }); - }, [newProjectPath, setNewProjectName, setNewProjectPath]); + }, [newProjectPath, setNewProjectName, setNewProjectPath, setGenerateFeatures, setAnalyzeProject, setFeatureCount]);apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (3)
67-73: Consider extracting duplicated theme resolution logic.The theme resolution pattern is duplicated in three places:
finalizeProjectCreation(lines 68-72)handleCreateFromTemplate(lines 164-168)handleCreateFromCustomUrl(lines 233-237)🔎 Suggested helper function
// Add inside the hook, before the handlers const resolveEffectiveTheme = useCallback( (projectPath: string): ThemeMode => { const trashedProject = trashedProjects.find((p) => p.path === projectPath); return ( (trashedProject?.theme as ThemeMode | undefined) || (currentProject?.theme as ThemeMode | undefined) || globalTheme ); }, [trashedProjects, currentProject, globalTheme] ); // Then use it in handlers: const effectiveTheme = resolveEffectiveTheme(projectPath);Also applies to: 163-169, 232-238
125-189:handleCreateFromTemplateduplicates finalization logic instead of usingfinalizeProjectCreation.This handler performs the same post-creation steps (initialize project, write app_spec, resolve theme, update state, show onboarding, toast) that
finalizeProjectCreationhandles. The only difference is the template-specificapp_spec.txtcontent.Consider refactoring
finalizeProjectCreationto accept an optionalappSpecContentparameter, allowing template/custom URL flows to reuse it while providing custom content.
191-258: Same duplication issue inhandleCreateFromCustomUrl.This handler also duplicates the finalization logic. The same refactoring approach would reduce maintenance burden and ensure consistent behavior across all creation paths.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (55)
apps/server/tests/unit/services/claude-usage-service.test.ts(1 hunks)apps/ui/src/app.tsx(2 hunks)apps/ui/src/components/dialogs/delete-all-archived-sessions-dialog.tsx(2 hunks)apps/ui/src/components/dialogs/delete-session-dialog.tsx(2 hunks)apps/ui/src/components/dialogs/index.ts(1 hunks)apps/ui/src/components/dialogs/new-project-modal.tsx(21 hunks)apps/ui/src/components/dialogs/workspace-picker-modal.tsx(5 hunks)apps/ui/src/components/layout/index.ts(1 hunks)apps/ui/src/components/layout/sidebar.tsx(6 hunks)apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/index.ts(1 hunks)apps/ui/src/components/layout/sidebar/components/project-actions.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/sidebar-navigation.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/sortable-project-item.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/theme-menu-item.tsx(1 hunks)apps/ui/src/components/layout/sidebar/constants.ts(1 hunks)apps/ui/src/components/layout/sidebar/dialogs/index.ts(1 hunks)apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx(1 hunks)apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx(1 hunks)apps/ui/src/components/layout/sidebar/hooks/index.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-drag-and-drop.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-project-picker.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-project-theme.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-theme-preview.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-trash-dialog.ts(1 hunks)apps/ui/src/components/layout/sidebar/hooks/use-trash-operations.ts(1 hunks)apps/ui/src/components/layout/sidebar/types.ts(1 hunks)apps/ui/src/components/session-manager.tsx(24 hunks)apps/ui/src/components/views/board-view/components/kanban-card/index.ts(1 hunks)apps/ui/src/components/views/settings-view/api-keys/hooks/index.ts(1 hunks)apps/ui/src/components/views/settings-view/api-keys/index.ts(1 hunks)apps/ui/src/components/views/settings-view/appearance/index.ts(1 hunks)apps/ui/src/components/views/settings-view/audio/index.ts(1 hunks)apps/ui/src/components/views/settings-view/cli-status/index.ts(1 hunks)apps/ui/src/components/views/settings-view/components/index.ts(1 hunks)apps/ui/src/components/views/settings-view/config/index.ts(1 hunks)apps/ui/src/components/views/settings-view/danger-zone/index.ts(1 hunks)apps/ui/src/components/views/settings-view/feature-defaults/index.ts(1 hunks)apps/ui/src/components/views/settings-view/keyboard-shortcuts/index.ts(1 hunks)apps/ui/src/components/views/settings-view/shared/index.ts(1 hunks)apps/ui/src/components/views/welcome-view.tsx(32 hunks)apps/ui/src/components/views/wiki-view.tsx(14 hunks)apps/ui/src/hooks/index.ts(1 hunks)apps/ui/src/renderer.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (22)
apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (2)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
useRunningAgents(4-4)apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)
apps/ui/src/components/layout/sidebar/hooks/use-project-picker.ts (2)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
useProjectPicker(6-6)apps/ui/src/lib/electron.ts (1)
setCurrentProject(2713-2719)
apps/ui/src/components/layout/sidebar/components/theme-menu-item.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
ThemeMenuItem(2-2)apps/ui/src/components/layout/sidebar/types.ts (1)
ThemeMenuItemProps(22-31)
apps/ui/src/components/layout/sidebar/components/sortable-project-item.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
SortableProjectItem(1-1)apps/ui/src/components/layout/sidebar/types.ts (1)
SortableProjectItemProps(15-20)
apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts (1)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
useSidebarAutoCollapse(2-2)
apps/ui/src/components/layout/sidebar/hooks/use-drag-and-drop.ts (1)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
useDragAndDrop(3-3)
apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
AutomakerLogo(5-5)
apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
CollapseToggleButton(4-4)apps/ui/src/store/app-store.ts (1)
formatShortcut(77-122)
apps/ui/src/components/dialogs/workspace-picker-modal.tsx (1)
apps/ui/src/components/dialogs/index.ts (1)
WorkspacePickerModal(6-6)
apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
BugReportButton(3-3)apps/ui/src/components/layout/sidebar/types.ts (1)
BugReportButtonProps(33-36)
apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (2)
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
useNavigation(8-8)apps/ui/src/components/layout/sidebar/types.ts (2)
NavSection(3-6)NavItem(8-13)
apps/ui/src/components/layout/sidebar/constants.ts (1)
apps/ui/src/config/theme-options.ts (2)
darkThemes(340-340)lightThemes(343-343)
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (5)
apps/ui/src/components/layout/sidebar/components/index.ts (2)
ProjectSelectorWithOptions(9-9)ThemeMenuItem(2-2)apps/ui/src/store/app-store.ts (2)
useAppStore(838-2265)formatShortcut(77-122)apps/ui/src/components/layout/sidebar/hooks/index.ts (3)
useProjectPicker(6-6)useDragAndDrop(3-3)useProjectTheme(12-12)apps/ui/src/components/layout/sidebar/hooks/use-project-theme.ts (1)
useProjectTheme(7-25)apps/ui/src/components/layout/sidebar/constants.ts (2)
PROJECT_DARK_THEMES(3-8)PROJECT_LIGHT_THEMES(10-15)
apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (2)
apps/ui/src/components/layout/sidebar/components/index.ts (3)
SidebarHeader(6-6)AutomakerLogo(5-5)BugReportButton(3-3)apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
AutomakerLogo(9-117)
apps/server/tests/unit/services/claude-usage-service.test.ts (2)
apps/server/src/services/claude-usage-service.ts (1)
ClaudeUsageService(17-452)init.mjs (1)
lines(83-83)
apps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (2)
apps/ui/src/lib/electron.ts (2)
TrashedProject(2696-2699)getElectronAPI(568-577)apps/ui/src/lib/project-init.ts (1)
initializeProject(43-143)
apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (2)
apps/ui/src/components/views/spec-view/types.ts (1)
FeatureCount(2-2)apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)
apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)
apps/ui/src/lib/electron.ts (1)
TrashedProject(2696-2699)
apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1)
apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)
apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1)
apps/ui/src/components/layout/sidebar/dialogs/index.ts (1)
OnboardingDialog(2-2)
apps/ui/src/components/views/welcome-view.tsx (2)
apps/server/src/services/auto-mode-service.ts (1)
analyzeProject(1107-1190)apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)
apps/ui/src/components/session-manager.tsx (1)
apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)
⏰ 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: e2e
🔇 Additional comments (62)
apps/ui/src/components/views/settings-view/config/index.ts (1)
1-2: LGTM! Clean barrel export pattern.The re-exports follow TypeScript best practices and align with the PR's folder pattern compliance objectives. This centralized entry point will make imports cleaner for consumers of the config module.
apps/ui/src/components/views/settings-view/keyboard-shortcuts/index.ts (1)
1-1: LGTM! Barrel export improves module organization.This barrel export simplifies imports for consumers and aligns with the refactoring goal of improving code organization and maintainability.
apps/ui/src/components/views/settings-view/components/index.ts (1)
1-4: LGTM! Barrel exports support modularization effort.These barrel exports consolidate component imports into a single entry point, directly supporting the refactoring goal of breaking down the 2,100+ line sidebar into modular, maintainable components. The consistent export pattern improves code organization.
apps/ui/src/components/views/settings-view/cli-status/index.ts (1)
1-1: LGTM! Clean barrel export pattern.This barrel export follows standard TypeScript conventions and aligns with the PR's modularization goals. The single re-export keeps the module focused and provides a clean public API surface.
apps/ui/src/components/views/settings-view/danger-zone/index.ts (1)
1-1: LGTM! Clean barrel export implementation.The barrel export follows standard TypeScript/React patterns and aligns perfectly with the PR's folder pattern compliance objective. This simplifies imports by allowing consumers to import from the
danger-zonefolder rather than the specific file.apps/ui/src/components/views/settings-view/feature-defaults/index.ts (1)
1-1: LGTM! Clean barrel export pattern.This re-export correctly establishes a public API for the
FeatureDefaultsSectioncomponent, aligning with the PR's modularization objectives and the project's barrel export conventions.apps/ui/src/components/views/board-view/components/kanban-card/index.ts (1)
1-7: LGTM! Clean barrel export pattern.The barrel export file follows best practices by consolidating the public API of the Kanban card package. The named exports are well-organized and enable consumers to import these components from a single entry point, which aligns with the folder pattern compliance objectives of this refactoring.
apps/ui/src/components/views/settings-view/shared/index.ts (1)
1-2: LGTM! Clean barrel export pattern.The barrel export approach is appropriate for organizing shared types and simplifies imports for consumers. Using
export typesyntax is the correct best practice for type-only exports. All exported types exist in their source files and the exports are complete with no missing shared types.apps/ui/src/components/views/wiki-view.tsx (4)
1-1: LGTM! Modern type import pattern.The import statement correctly uses TypeScript's
typemodifier for type-only imports ofReactNodeandElementType. This aligns with React 19 best practices and improves tree-shaking.
29-30: LGTM! Type references correctly updated.The interface properties now use the imported
ElementTypeandReactNodetypes directly, which is cleaner and consistent with the updated imports.
89-89: LGTM! Consistent type usage.The props type correctly uses
ElementTypeto match the updated import pattern.
115-115: LGTM! Consistent string literal style.The state initialization now uses single quotes, aligning with the string literal normalization throughout the file.
apps/ui/src/components/views/settings-view/api-keys/hooks/index.ts (1)
1-1: Barrel export is correctly structured.The export properly references the target file, and the
useApiKeyManagementhook is correctly exported fromuse-api-key-management.ts.apps/ui/src/components/views/settings-view/api-keys/index.ts (1)
1-4: Component barrel exports are well-structured.All four component re-exports follow consistent naming conventions and properly reference existing components that export the expected named exports.
apps/ui/src/components/views/settings-view/appearance/index.ts (1)
1-1: LGTM! Clean barrel export pattern.The barrel export correctly centralizes the public export for
AppearanceSection. The underlying file exists and properly exports the component.apps/ui/src/components/views/settings-view/audio/index.ts (1)
1-1: LGTM! Consistent barrel export pattern.The barrel export is consistent with the pattern established in other settings-view sections. The referenced
./audio-sectionfile exists and exportsAudioSectioncorrectly.apps/server/tests/unit/services/claude-usage-service.test.ts (8)
16-42: LGTM!The test setup is well-structured with proper mock initialization for both
child_process.spawnandnode-ptyprocesses, and correctly clears mocks between tests.
44-107: LGTM!The
isAvailabletests comprehensively cover success, failure, error, and cross-platform scenarios. The Windows test correctly instantiates a new service after mockingos.platform()to ensureisWindowsis set appropriately at construction time.
129-237: LGTM!Comprehensive test coverage for
parseResetTimeincluding duration formats (hours/minutes), AM/PM time formats, date formats with month/day, 12am/12pm edge cases, and fallback behavior for unparseable text.
239-269: LGTM!The
getDefaultResetTimetests correctly verify both session (5 hours from now) and weekly (next Monday) default behaviors using a controlled timestamp.
271-322: LGTM!Good coverage for
parseSectionincluding percentage conversion (left vs used), missing sections, timezone stripping, and case-insensitive matching.
324-404: LGTM!Thorough test coverage for
parseUsageOutputincluding complete output parsing, ANSI code handling, alternative section names (Opus), and graceful defaults for missing sections.
406-509: LGTM!Good test coverage for macOS/Linux command execution including successful output handling, authentication error detection, and timeout behavior.
590-636: LGTM!The Windows authentication error and timeout tests are well-structured, correctly simulating the respective error conditions and verifying expected behavior.
apps/ui/src/app.tsx (1)
1-35: LGTM! Quote normalization aligns with coding style.The changes consistently normalize string literals and import statements to use single quotes throughout the file, with no functional modifications.
apps/ui/src/components/dialogs/delete-all-archived-sessions-dialog.tsx (1)
1-55: LGTM! Consistent quote style and improved readability.The import statement updates and dialog description consolidation maintain functionality while improving code consistency.
apps/ui/src/components/dialogs/delete-session-dialog.tsx (1)
1-48: LGTM! Style normalization with no functional impact.Import and JSX formatting changes align with project conventions while preserving all behavior and styling.
apps/ui/src/components/layout/sidebar/constants.ts (1)
1-24: LGTM! Well-structured constants with good type safety.The theme transformations and feature flags are clearly defined:
- Consistent Icon→icon property normalization for API surface
- Proper use of
as constfor type-level guarantees on feature flags- Clean separation of dark/light theme data
apps/ui/src/components/layout/sidebar/hooks/use-theme-preview.ts (1)
1-53: LGTM! Well-implemented debounced theme preview.The hook properly handles:
- Debouncing with a one-frame delay to prevent excessive re-renders
- Cleanup of pending timeouts on unmount
- Smart prevention of preview clearing when moving between theme items (line 29)
The use of
relatedTargetand the CSS attribute selector ensures smooth hover transitions without flickering.apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1)
1-23: LGTM! Clean button component with proper accessibility.The component correctly handles conditional positioning and test IDs based on sidebar state, with good hover states and a descriptive title attribute for accessibility.
apps/ui/src/components/layout/sidebar/hooks/use-drag-and-drop.ts (1)
10-41: LGTM!The drag-and-drop logic is well-implemented with appropriate guards:
- Checks that
overexists before proceeding- Ensures the dragged item moved to a different position
- Validates both indices before calling
reorderProjects- Properly memoized with correct dependencies
apps/ui/src/hooks/index.ts (1)
1-9: LGTM!Clean barrel export pattern for centralized hook imports.
apps/ui/src/components/layout/sidebar/types.ts (1)
1-36: LGTM!Well-structured type definitions with:
- Clear interface naming
- Appropriate use of optional properties
- Proper typing for React components (
React.ComponentType)- Good separation of concerns
apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (1)
38-211: LGTM!Well-structured navigation hook with:
- Proper conditional rendering logic for nav items based on visibility flags
- Appropriate guards for keyboard shortcuts (only enabled when conditions are met)
- Correct memoization with comprehensive dependency arrays
- Clean separation between nav sections and keyboard shortcuts
The cascading memoization (navSections computed first, then used in navigationShortcuts) is correctly implemented.
apps/ui/src/components/layout/index.ts (1)
1-1: LGTM!Clean barrel export for the Sidebar component.
apps/ui/src/components/layout/sidebar/hooks/use-trash-dialog.ts (1)
12-40: LGTM!Clean composition pattern that:
- Adds dialog state management to existing trash operations
- Properly delegates to
useTrashOperations- Returns a unified interface for dialog + operations
This is a good example of hook composition.
apps/ui/src/components/layout/sidebar/dialogs/index.ts (1)
1-2: LGTM!Clean barrel export pattern for dialog components.
apps/ui/src/components/dialogs/workspace-picker-modal.tsx (1)
1-141: LGTM!Formatting and style consistency changes only. The functional behavior remains unchanged.
apps/ui/src/components/layout/sidebar/hooks/use-project-theme.ts (1)
1-25: LGTM! Clean hook composition.The hook effectively composes theme state management from the app store with preview handlers from
useThemePreview, providing a unified interface for theme-related functionality.apps/ui/src/components/layout/sidebar/components/theme-menu-item.tsx (1)
1-27: LGTM! Clean component implementation.The memoized
ThemeMenuItemcomponent is well-structured with proper event handlers for theme preview functionality. The use ofmemois appropriate for this presentational component that receives stable props.apps/ui/src/components/session-manager.tsx (1)
1-577: LGTM!Formatting and style consistency changes only. The functional behavior of the session manager remains unchanged.
apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (1)
23-48: LGTM! Robust event subscription pattern.The hook properly handles the case when
autoModeis unavailable, subscribes to relevant auto-mode events for real-time updates, and correctly cleans up the subscription on unmount. The event filtering logic appropriately refreshes the count on feature lifecycle events.apps/ui/src/renderer.tsx (1)
3-3: The import path is correct.The actual file is named
app.tsx(lowercase), so the importfrom './app'matches the actual filename and is necessary for the code to work on case-sensitive file systems.Likely an incorrect or invalid review comment.
apps/ui/src/components/dialogs/new-project-modal.tsx (1)
1-459: LGTM! Formatting changes only.The changes in this file are purely formatting adjustments (quote normalization and consistent string literals) with no behavioral modifications. The logic, event handlers, and data flow remain unchanged.
apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1)
1-40: LGTM! Clean component separation.The SidebarHeader component is well-structured with clear props and conditional rendering based on sidebar state. The dual rendering of BugReportButton for expanded/collapsed states is intentional for different layout contexts.
apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1)
28-36: Verify the onSkip behavior on dialog close.The
onOpenChangehandler callsonSkip()whenever the dialog is closed (Line 32), regardless of how it was closed (backdrop click, ESC key, X button, etc.). This means users who simply want to dismiss the dialog temporarily will trigger the skip action.Verify this is the intended behavior. If users should be able to close the dialog without skipping (e.g., to think about it), consider adding a separate close handler or tracking whether the user explicitly clicked "Skip for now" vs. other close methods.
apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1)
17-78: LGTM! Proper event subscription handling.The hook correctly subscribes to spec regeneration events, filters by project path, handles both success and error cases, and properly cleans up the subscription. The comprehensive dependency array (lines 68-77) is necessary since the setters are passed as props and ensures the effect stays synchronized with the latest callbacks.
apps/ui/src/components/layout/sidebar/hooks/use-project-picker.ts (1)
1-105: LGTM! Well-structured project picker hook.The hook provides comprehensive project picker functionality with search filtering, keyboard navigation, and proper focus management. The
setTimeout(0)pattern (line 47) for focusing the input is a common and acceptable approach for ensuring the DOM is ready. The keyboard handling properly prevents conflicts between search input and global shortcuts (lines 77-83).apps/ui/src/components/layout/sidebar/components/project-actions.tsx (1)
1-91: LGTM! Clean action button component.The component provides a clear interface for project actions with appropriate visual feedback. The trash count badge (lines 83-87) correctly displays the count with a "9+" overflow indicator, and the conditional rendering ensures it only appears when there are trashed projects.
apps/ui/src/components/dialogs/index.ts (1)
1-6: LGTM! Clean barrel export structure.The barrel export file provides a centralized access point for dialog components, improving import organization and maintainability.
apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx (1)
1-269: Well-structured modular component with good separation of concerns.The component cleanly encapsulates the footer navigation logic with appropriate props for configuration and callbacks. The badge count capping at 99 is a good UX pattern, and the conditional rendering for Wiki/Running Agents is implemented correctly.
A few observations:
- The button styling pattern is heavily repeated across the three navigation items. Consider extracting a shared
FooterNavButtoncomponent if this pattern grows or needs maintenance.- The custom tooltip implementation using absolute-positioned spans works but may have accessibility gaps compared to using a proper tooltip component with ARIA attributes.
apps/ui/src/components/layout/sidebar/hooks/index.ts (1)
1-12: Clean barrel export structure.The barrel file correctly consolidates all sidebar hooks for streamlined imports. The consistent naming convention and alphabetical-ish grouping aids discoverability.
apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)
98-111: ReviewDialogFooterlayout withjustify-between.When
trashedProjects.length === 0, only the Close button renders, andjustify-betweenhas no effect on a single child. However, when both buttons render, they'll be pushed to opposite ends as intended. This is likely fine, but verify the visual alignment matches the design intent for the empty state.apps/ui/src/components/layout/sidebar/components/sidebar-navigation.tsx (1)
1-140: Clean implementation of navigation rendering.The component properly handles all states (no project, project selected, expanded/collapsed) with appropriate visual feedback. The section-based organization and shortcut display integration are well done.
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (1)
44-92: Good use of composition and early returns.The component properly delegates logic to specialized hooks (
useProjectPicker,useDragAndDrop,useProjectTheme) and exits early when rendering is unnecessary. This keeps the component focused on presentation while maintaining clean separation of concerns.apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (2)
1-27: Well-structured hook with clear state management.The hook properly encapsulates setup dialog state and exposes a clean API. State initialization and type imports are correct.
32-82: Solid async handler with optimistic UI and proper error recovery.The
handleCreateInitialSpechandler follows good patterns:
- Optimistic state update before async operation
- Defensive check for API availability
- Proper error handling with state rollback
- Conditional parameter passing for
featureCountapps/ui/src/components/layout/sidebar/hooks/use-project-creation.ts (1)
40-65: Previous issue resolved:app_spec.txtpath is now correct.The path
${projectPath}/.automaker/app_spec.txtand the<project_specification>XML root tag are both correct, addressing the regression flagged in the previous review.apps/ui/src/components/layout/sidebar/components/index.ts (1)
1-10: Clean barrel exports enabling modular imports.This consolidates the sidebar component exports, supporting the PR's refactoring goal of reducing sidebar.tsx from 2,100+ lines.
apps/ui/src/components/layout/sidebar.tsx (3)
13-33: Clean modular imports supporting the refactoring goal.The sidebar now composes from well-organized local imports: components, dialogs, constants, and hooks. This structure supports maintainability and testability.
70-118: Good separation of concerns with dedicated hooks.The sidebar now delegates state and logic to
useProjectCreationanduseSetupDialoghooks, significantly reducing component complexity. The hook composition and prop passing looks correct.
255-375: Well-composed JSX with clear component boundaries.The sidebar render tree is now clean and readable. Each child component receives focused props, and dialogs are properly positioned at the end of the component. The refactoring achieves the stated goal of reducing complexity.
apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts
Show resolved
Hide resolved
- Updated ESLint configuration to include support for `.mjs` and `.cjs` file types, adding necessary global variables for Node.js and browser environments. - Introduced a new `vite-env.d.ts` file to define environment variables for Vite, improving type safety. - Refactored error handling in `file-browser-dialog.tsx`, `description-image-dropzone.tsx`, and `feature-image-upload.tsx` to omit error parameters, simplifying the catch blocks. - Removed unused bug report button functionality from the sidebar, streamlining the component structure. - Adjusted various components to improve code readability and maintainability, including updates to type imports and component props. These changes aim to enhance the development experience by improving linting support and simplifying error handling across components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (1)
189-196: Add nullish coalescing for thinking level default.When a model supports thinking but
editingFeature.thinkingLevelis undefined, line 194 will assignundefinedinstead of defaulting to'none'. For consistency with the logic inhandleUpdate(lines 151-153), consider:🔎 Proposed fix
setEditingFeature({ ...editingFeature, model, - thinkingLevel: modelSupportsThinking(model) ? editingFeature.thinkingLevel : 'none', + thinkingLevel: modelSupportsThinking(model) ? (editingFeature.thinkingLevel ?? 'none') : 'none', });apps/ui/src/components/ui/description-image-dropzone.tsx (2)
126-199: MissingsetPreviewImagesin dependency array.The
processFilescallback usessetPreviewImagesat line 184 but doesn't include it in the dependency array (lines 189-198). This violates the rules of hooks and could cause the function to close over a stale version ofsetPreviewImages, leading to incorrect state updates.🔎 Suggested fix
[ disabled, isProcessing, images, maxFiles, maxFileSize, onImagesChange, previewImages, saveImageToTemp, + setPreviewImages, ]
254-264: MissingsetPreviewImagesin dependency array.The
removeImagecallback usessetPreviewImagesat line 257 but doesn't include it in the dependency array (line 263). This could cause stale closures.🔎 Suggested fix
}, - [images, onImagesChange] + [images, onImagesChange, setPreviewImages] );
♻️ Duplicate comments (2)
apps/ui/src/components/views/welcome-view.tsx (1)
227-525: Centralize project creation logic to eliminate duplication.This component contains substantial project creation logic across three functions (
handleCreateBlankProject,handleCreateFromTemplate,handleCreateFromCustomUrl) totaling nearly 300 lines. A previous review noted that auseProjectCreationhook was introduced to centralize this logic, but this component still maintains its own implementation.Having duplicate implementations across multiple components creates maintenance overhead and increases the risk of inconsistent behavior. All project creation logic should be consolidated into the
useProjectCreationhook, and this component should consume that hook instead.Based on learnings, this duplication concern was previously raised and remains unaddressed.
apps/ui/src/components/layout/sidebar.tsx (1)
74-92: Critical: Project creation regression already flagged.A previous review identified a critical regression in the
useProjectCreationhook:
- Incorrect
app_spec.txtpath (should be in.automaker/subdirectory)- Simplified XML content loses template-specific details
- Root XML tag changed from
<project_specification>to<project>This issue breaks project creation functionality and must be resolved before merge.
🧹 Nitpick comments (17)
apps/ui/src/components/views/board-view/kanban-board.tsx (2)
14-17: Consider using proper types from@dnd-kit/coreinstead ofany.Using
anyforsensors,collisionDetectionStrategy, and the drag event handlers loses type safety. The@dnd-kit/corelibrary exports appropriate types:
SensorDescriptor<any>[]for sensorsCollisionDetectionfor collision strategyDragStartEvent/DragEndEventfor handlers🔎 Suggested type improvements
+import { DndContext, DragOverlay, CollisionDetection, DragStartEvent, DragEndEvent, SensorDescriptor } from '@dnd-kit/core'; interface KanbanBoardProps { - sensors: any; - collisionDetectionStrategy: (args: any) => any; - onDragStart: (event: any) => void; - onDragEnd: (event: any) => void; + sensors: SensorDescriptor<any>[]; + collisionDetectionStrategy: CollisionDetection; + onDragStart: (event: DragStartEvent) => void; + onDragEnd: (event: DragEndEvent) => void;
13-51: Large prop surface area — consider grouping related callbacks.The component accepts 38 props, many of which are feature action callbacks (
onEdit,onDelete,onVerify, etc.). This prop drilling can become unwieldy as the component evolves.A potential improvement would be to group related callbacks into a single
featureActionsobject prop or leverage React Context for feature operations if these callbacks are used across multiple descendant components.apps/ui/src/config/api-providers.ts (2)
44-58: Interface requires unused
ProviderConfigParamsmandates abuildProviderConfigsignores it. Callers must still construct and pass a fullConsider making
🔎 Proposed fix
export interface ProviderConfigParams { apiKeys: ApiKeys; anthropic: { value: string; setValue: Dispatch<SetStateAction<string>>; show: boolean; setShow: Dispatch<SetStateAction<boolean>>; testing: boolean; onTest: () => Promise<void>; result: { success: boolean; message: string } | null; }; - google: { + google?: { value: string; setValue: Dispatch<SetStateAction<string>>; show: boolean; setShow: Dispatch<SetStateAction<boolean>>; testing: boolean; onTest: () => Promise<void>; result: { success: boolean; message: string } | null; }; }
85-110: Consider removing or tracking commented-out Google provider code.This 25-line commented block adds maintenance burden. If Google provider support is planned, consider tracking it in an issue and removing the commented code. If it's not planned, removing it keeps the codebase clean—it can always be retrieved from version control.
apps/ui/src/lib/utils.ts (1)
12-15: Consider simplifying or documenting the unused parameter.The function unconditionally returns
trueand never uses the_modelparameter. While the underscore prefix correctly signals it's unused, consider either:
- Removing the parameter entirely if all models will always support thinking, or
- Adding a comment explaining why the parameter is retained (e.g., for API compatibility or future use)
apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx (1)
1-399: Quote standardization looks good.The conversion from double quotes to single quotes is applied consistently throughout the file with no functional changes. All imports, type literals, and string literals are correctly updated.
Since this is part of a project-wide style standardization, consider adding or updating ESLint rules (e.g.,
quotes: ['error', 'single']) to automatically enforce single quotes and prevent inconsistencies in future commits.Optional: Verify consistency across the codebase
#!/bin/bash # Check if there are other files in the UI app that still use double quotes inconsistently # Search for remaining double-quoted imports in TypeScript/TSX files echo "=== Files with double-quoted imports ===" rg --type=ts --type-add 'tsx:*.tsx' -g '*.{ts,tsx}' -g '!node_modules' "^import .* from \"" apps/ui/src/ | head -20 # Search for type literals with double quotes echo -e "\n=== Type literals with double quotes ===" rg --type=ts --type-add 'tsx:*.tsx' -g '*.{ts,tsx}' -g '!node_modules' "type \w+ = \"" apps/ui/src/ | head -20apps/ui/src/components/views/setup-view/steps/welcome-step.tsx (1)
18-19: Optional: Polish the user-facing text.While the reflow itself is fine, consider improving the text quality:
- The "either...or" construction is grammatically awkward. Consider: "To get started, we'll need to verify that either the Claude Code CLI is installed or you have Anthropic API keys."
- Capitalize product names: "Claude Code CLI" instead of "claude code cli"
- Capitalize acronyms: "API keys" instead of "api keys"
apps/ui/tests/utils/views/board.ts (1)
193-219: Consider escaping branch names in RegExp (optional improvement).The static analysis tool correctly identifies that constructing RegExp from variables can theoretically lead to ReDoS issues. While the risk is minimal in test utilities with controlled input, you could eliminate the warning by escaping special regex characters.
🔎 Optional refactor to escape special characters
export async function selectWorktreeBranch(page: Page, branchName: string): Promise<void> { - const branchButton = page.getByRole('button', { - name: new RegExp(branchName, 'i'), - }); + const escapedBranch = branchName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const branchButton = page.getByRole('button', { + name: new RegExp(escapedBranch, 'i'), + }); await branchButton.click(); await page.waitForTimeout(500); // Wait for UI to update }Apply the same pattern to
isWorktreeBranchVisible:export async function isWorktreeBranchVisible(page: Page, branchName: string): Promise<boolean> { - const branchButton = page.getByRole('button', { - name: new RegExp(branchName, 'i'), - }); + const escapedBranch = branchName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const branchButton = page.getByRole('button', { + name: new RegExp(escapedBranch, 'i'), + }); return await branchButton.isVisible().catch(() => false); }apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (1)
119-119: Optional: Explicit cast may be redundant.The explicit
as ThinkingLevelcast appears unnecessary due to TypeScript's control flow narrowing after the condition on line 115. However, it's defensive and doesn't cause any issues.apps/ui/src/components/views/settings-view/api-keys/authentication-status-display.tsx (1)
48-58: Quote normalization applied successfully.The string literals now consistently use single quotes throughout the authentication method display logic.
Optional: Consider refactoring the nested ternary for readability.
The 6-level nested ternary, while logically correct, can be challenging to parse. A future refactor could use a lookup map or helper function to improve maintainability.
💡 Optional refactor to improve readability
+const AUTH_METHOD_LABELS: Record<string, string> = { + oauth_token: 'Using stored OAuth token (subscription)', + api_key_env: 'Using ANTHROPIC_API_KEY', + api_key: 'Using stored API key', + credentials_file: 'Using credentials file', + cli_authenticated: 'Using Claude CLI authentication', +}; + <span> - {claudeAuthStatus.method === 'oauth_token' - ? 'Using stored OAuth token (subscription)' - : claudeAuthStatus.method === 'api_key_env' - ? 'Using ANTHROPIC_API_KEY' - : claudeAuthStatus.method === 'api_key' - ? 'Using stored API key' - : claudeAuthStatus.method === 'credentials_file' - ? 'Using credentials file' - : claudeAuthStatus.method === 'cli_authenticated' - ? 'Using Claude CLI authentication' - : `Using ${claudeAuthStatus.method || 'detected'} authentication`} + {AUTH_METHOD_LABELS[claudeAuthStatus.method] || + `Using ${claudeAuthStatus.method || 'detected'} authentication`} </span>apps/ui/eslint.config.mjs (1)
28-91: Consider using theglobalspackage for better maintainability.The manual declaration of 60+ globals is verbose and harder to maintain. Modern ESLint flat configs typically leverage the
globalspackage, which provides predefined sets likeglobals.browser,globals.node, etc.🔎 Refactor to use the globals package
First, ensure the
globalspackage is installed:npm install -D globalsThen refactor the config:
+import globals from "globals"; import { defineConfig, globalIgnores } from "eslint/config"; import js from "@eslint/js"; import ts from "@typescript-eslint/eslint-plugin"; import tsParser from "@typescript-eslint/parser"; const eslintConfig = defineConfig([ js.configs.recommended, { files: ["**/*.mjs", "**/*.cjs"], languageOptions: { - globals: { - console: "readonly", - process: "readonly", - require: "readonly", - __dirname: "readonly", - __filename: "readonly", - }, + globals: globals.node, }, }, { files: ["**/*.ts", "**/*.tsx"], languageOptions: { parser: tsParser, parserOptions: { ecmaVersion: "latest", sourceType: "module", }, - globals: { - // Browser/DOM APIs - window: "readonly", - document: "readonly", - navigator: "readonly", - Navigator: "readonly", - localStorage: "readonly", - sessionStorage: "readonly", - fetch: "readonly", - WebSocket: "readonly", - File: "readonly", - FileList: "readonly", - FileReader: "readonly", - Blob: "readonly", - atob: "readonly", - crypto: "readonly", - prompt: "readonly", - confirm: "readonly", - getComputedStyle: "readonly", - requestAnimationFrame: "readonly", - // DOM Element Types - HTMLElement: "readonly", - HTMLInputElement: "readonly", - HTMLDivElement: "readonly", - HTMLButtonElement: "readonly", - HTMLSpanElement: "readonly", - HTMLTextAreaElement: "readonly", - HTMLHeadingElement: "readonly", - HTMLParagraphElement: "readonly", - HTMLImageElement: "readonly", - Element: "readonly", - // Event Types - Event: "readonly", - KeyboardEvent: "readonly", - DragEvent: "readonly", - PointerEvent: "readonly", - CustomEvent: "readonly", - ClipboardEvent: "readonly", - WheelEvent: "readonly", - DataTransfer: "readonly", - // Web APIs - ResizeObserver: "readonly", - AbortSignal: "readonly", - Audio: "readonly", - ScrollBehavior: "readonly", - // Timers - setTimeout: "readonly", - setInterval: "readonly", - clearTimeout: "readonly", - clearInterval: "readonly", - // Node.js (for scripts and Electron) - process: "readonly", - require: "readonly", - __dirname: "readonly", - __filename: "readonly", - NodeJS: "readonly", - // React - React: "readonly", - JSX: "readonly", - // Electron - Electron: "readonly", - // Console - console: "readonly", - }, + globals: { + ...globals.browser, + ...globals.node, + }, }, plugins: { "@typescript-eslint": ts, },This approach:
- Reduces config size and complexity
- Provides comprehensive, battle-tested global definitions
- Makes it easier to adjust environments in the future
- Reduces the risk of missing or incorrectly defining globals
apps/ui/src/components/ui/sheet.tsx (1)
1-150: Consider using automated tooling for quote style enforcement.This file demonstrates consistent quote style normalization (double to single quotes). To ensure this style is maintained project-wide and prevent future inconsistencies, consider configuring ESLint or Prettier with quote style rules.
Example ESLint configuration:
{ "rules": { "quotes": ["error", "single", { "avoidEscape": true }], "@typescript-eslint/quotes": ["error", "single"] } }apps/ui/src/components/views/agent-view.tsx (1)
196-196: Replace deprecatedsubstrwithsubstringorslice.
String.prototype.substr()is deprecated. Usesubstring()orslice()instead.🔎 Proposed fix
- id: `img-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, + id: `img-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,apps/ui/src/lib/file-picker.ts (1)
68-73: Consider gating verbose logging behind a debug flag.The
[FilePicker]logs are helpful for debugging but may be noisy in production. Consider using a debug flag or removing them before release.Example approach
const DEBUG = process.env.NODE_ENV === 'development'; function log(...args: unknown[]) { if (DEBUG) console.log('[FilePicker]', ...args); } // Usage: log('Change event fired');apps/ui/src/components/ui/accordion.tsx (2)
7-7: Consider using theAccordionTypealias inAccordionProps.The
AccordionTypealias is defined but thetypeprop inAccordionPropsrepeats the literal union. Using the alias improves maintainability.🔎 Proposed fix
interface AccordionProps extends React.HTMLAttributes<HTMLDivElement> { - type?: 'single' | 'multiple'; + type?: AccordionType; value?: string | string[];Also applies to: 19-19
1-1: Use type aliases to eliminate the need for eslint-disable.The empty interfaces on lines 142 and 180 require the
eslint-disabledirective. Using type aliases achieves the same result without suppressing the linter.🔎 Proposed fix
Remove line 1:
-/* eslint-disable @typescript-eslint/no-empty-object-type */Replace the empty interfaces with type aliases:
-interface AccordionTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {} +type AccordionTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;-interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {} +type AccordionContentProps = React.HTMLAttributes<HTMLDivElement>;Also applies to: 142-142, 180-180
apps/ui/src/components/ui/description-image-dropzone.tsx (1)
55-69: Consider removinglocalPreviewImagesfrom the dependency array.Including
localPreviewImages(a state variable) in the dependency array causes this callback to be recreated on every state update, which undermines the purpose ofuseCallback. The callback should remain stable across renders. The current implementation will work correctly but may cause unnecessary re-renders of child components.🔎 Suggested improvement
const setPreviewImages = useCallback( (updater: Map<string, string> | ((prev: Map<string, string>) => Map<string, string>)) => { if (onPreviewMapChange) { - const currentMap = previewMap !== undefined ? previewMap : localPreviewImages; + const currentMap = previewMap !== undefined ? previewMap : new Map(); const newMap = typeof updater === 'function' ? updater(currentMap) : updater; onPreviewMapChange(newMap); } else { setLocalPreviewImages((prev) => { const newMap = typeof updater === 'function' ? updater(prev) : updater; return newMap; }); } }, - [onPreviewMapChange, previewMap, localPreviewImages] + [onPreviewMapChange, previewMap] );Note: If parent provides
previewMap, use it; otherwisesetLocalPreviewImagesreceivesprevdirectly from React, solocalPreviewImagesisn't needed in the closure.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (40)
apps/ui/eslint.config.mjs(2 hunks)apps/ui/src/components/dialogs/file-browser-dialog.tsx(16 hunks)apps/ui/src/components/layout/sidebar.tsx(6 hunks)apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx(1 hunks)apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx(1 hunks)apps/ui/src/components/layout/sidebar/types.ts(1 hunks)apps/ui/src/components/ui/accordion.tsx(9 hunks)apps/ui/src/components/ui/description-image-dropzone.tsx(13 hunks)apps/ui/src/components/ui/feature-image-upload.tsx(12 hunks)apps/ui/src/components/ui/image-drop-zone.tsx(6 hunks)apps/ui/src/components/ui/sheet.tsx(6 hunks)apps/ui/src/components/views/agent-view.tsx(37 hunks)apps/ui/src/components/views/analysis-view.tsx(32 hunks)apps/ui/src/components/views/board-view/board-header.tsx(3 hunks)apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx(8 hunks)apps/ui/src/components/views/board-view/dialogs/agent-output-modal.tsx(11 hunks)apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx(15 hunks)apps/ui/src/components/views/board-view/kanban-board.tsx(7 hunks)apps/ui/src/components/views/context-view.tsx(31 hunks)apps/ui/src/components/views/settings-view/api-keys/authentication-status-display.tsx(2 hunks)apps/ui/src/components/views/settings-view/components/delete-project-dialog.tsx(2 hunks)apps/ui/src/components/views/setup-view/steps/claude-setup-step.tsx(22 hunks)apps/ui/src/components/views/setup-view/steps/complete-step.tsx(1 hunks)apps/ui/src/components/views/setup-view/steps/welcome-step.tsx(2 hunks)apps/ui/src/components/views/terminal-view.tsx(29 hunks)apps/ui/src/components/views/welcome-view.tsx(35 hunks)apps/ui/src/config/api-providers.ts(2 hunks)apps/ui/src/lib/file-picker.ts(10 hunks)apps/ui/src/lib/http-api-client.ts(38 hunks)apps/ui/src/lib/utils.ts(3 hunks)apps/ui/src/lib/workspace-config.ts(3 hunks)apps/ui/src/routes/__root.tsx(1 hunks)apps/ui/src/vite-env.d.ts(1 hunks)apps/ui/tests/feature-lifecycle.spec.ts(16 hunks)apps/ui/tests/spec-editor-persistence.spec.ts(13 hunks)apps/ui/tests/utils/components/toasts.ts(5 hunks)apps/ui/tests/utils/git/worktree.ts(17 hunks)apps/ui/tests/utils/views/board.ts(11 hunks)apps/ui/tests/utils/views/setup.ts(1 hunks)
✅ Files skipped from review due to trivial changes (9)
- apps/ui/src/components/views/setup-view/steps/claude-setup-step.tsx
- apps/ui/src/components/views/board-view/board-header.tsx
- apps/ui/src/components/dialogs/file-browser-dialog.tsx
- apps/ui/src/components/views/analysis-view.tsx
- apps/ui/src/components/ui/image-drop-zone.tsx
- apps/ui/tests/utils/views/setup.ts
- apps/ui/src/lib/http-api-client.ts
- apps/ui/src/components/views/context-view.tsx
- apps/ui/tests/utils/git/worktree.ts
🧰 Additional context used
🧬 Code graph analysis (12)
apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (3)
apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)apps/ui/src/lib/agent-context-parser.ts (2)
formatModelName(35-40)DEFAULT_MODEL(30-30)apps/ui/src/lib/utils.ts (1)
cn(5-7)
apps/ui/src/components/views/terminal-view.tsx (2)
apps/ui/src/lib/utils.ts (1)
cn(5-7)apps/ui/src/store/app-store.ts (1)
TerminalPanelContent(282-289)
apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (3)
apps/ui/src/components/ui/description-image-dropzone.tsx (1)
ImagePreviewMap(9-9)apps/ui/src/store/app-store.ts (3)
PlanningMode(216-216)AgentModel(216-216)ThinkingLevel(216-216)apps/ui/src/lib/utils.ts (1)
modelSupportsThinking(12-15)
apps/ui/tests/feature-lifecycle.spec.ts (2)
apps/ui/tests/utils/git/worktree.ts (2)
createTempDirPath(52-55)TestRepo(19-22)apps/ui/tests/utils/views/board.ts (1)
confirmAddFeature(158-164)
apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (4)
apps/ui/src/components/layout/sidebar/components/index.ts (3)
SidebarHeader(6-6)AutomakerLogo(5-5)BugReportButton(3-3)apps/ui/src/lib/utils.ts (1)
cn(5-7)apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx (1)
AutomakerLogo(9-117)apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1)
BugReportButton(10-33)
apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (3)
apps/ui/src/components/layout/sidebar/components/index.ts (1)
BugReportButton(3-3)apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)apps/ui/src/lib/utils.ts (1)
cn(5-7)
apps/ui/src/components/ui/accordion.tsx (1)
apps/ui/src/lib/utils.ts (1)
cn(5-7)
apps/ui/src/components/ui/feature-image-upload.tsx (1)
apps/ui/src/lib/utils.ts (1)
cn(5-7)
apps/ui/src/components/ui/description-image-dropzone.tsx (3)
apps/ui/src/lib/http-api-client.ts (1)
saveImageToTemp(306-318)apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)apps/ui/src/lib/utils.ts (1)
cn(5-7)
apps/ui/src/components/ui/sheet.tsx (1)
apps/ui/src/lib/utils.ts (1)
cn(5-7)
apps/ui/src/components/layout/sidebar.tsx (12)
apps/ui/src/components/layout/sidebar/constants.ts (1)
SIDEBAR_FEATURE_FLAGS(17-24)apps/ui/src/components/layout/sidebar/hooks/use-setup-dialog.ts (1)
useSetupDialog(14-147)apps/ui/src/components/layout/sidebar/hooks/use-sidebar-auto-collapse.ts (1)
useSidebarAutoCollapse(8-30)apps/ui/src/components/layout/sidebar/hooks/use-running-agents.ts (1)
useRunningAgents(4-53)apps/ui/src/components/layout/sidebar/hooks/use-spec-regeneration.ts (1)
useSpecRegeneration(17-78)apps/ui/src/components/layout/sidebar/hooks/use-navigation.ts (1)
useNavigation(38-211)apps/ui/src/components/layout/sidebar/components/collapse-toggle-button.tsx (1)
CollapseToggleButton(11-60)apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1)
SidebarHeader(11-39)apps/ui/src/components/layout/sidebar/components/project-actions.tsx (1)
ProjectActions(16-91)apps/ui/src/components/layout/sidebar/components/sidebar-footer.tsx (1)
SidebarFooter(18-269)apps/ui/src/components/layout/sidebar/dialogs/trash-dialog.tsx (1)
TrashDialog(25-116)apps/ui/src/components/layout/sidebar/dialogs/onboarding-dialog.tsx (1)
OnboardingDialog(20-122)
apps/ui/src/components/views/welcome-view.tsx (1)
apps/ui/src/lib/electron.ts (1)
getElectronAPI(568-577)
🪛 ast-grep (0.40.0)
apps/ui/tests/utils/views/board.ts
[warning] 194-194: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(branchName, 'i')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 217-217: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(branchName, 'i')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
⏰ 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: e2e
🔇 Additional comments (56)
apps/ui/src/lib/workspace-config.ts (1)
6-9: LGTM! Formatting standardization applied correctly.All changes are purely stylistic—normalizing string literals to single quotes across imports, constants, and error messages. No functional impact.
Also applies to: 11-11, 20-21, 23-24, 84-85
apps/ui/src/components/views/settings-view/components/delete-project-dialog.tsx (2)
1-3: LGTM! Import improvements follow best practices.The quote style normalization to single quotes and the use of
import typefor the Project type are excellent improvements. Type-only imports enable better tree-shaking and make the distinction between runtime and type-only dependencies clearer.
42-43: LGTM! Clean JSX formatting.Collapsing the multi-line JSX to single-line improves readability and maintains consistency across the codebase.
apps/ui/src/routes/__root.tsx (1)
17-17: LGTM! Clean refactor of unused destructured properties.Removing
themeandpreviewThemefrom the destructuring is appropriate since the file obtains the theme via thegetEffectiveTheme()method call at line 61. This aligns with the PR's goal of centralizing theme logic in dedicated hooks elsewhere in the UI.apps/ui/src/components/views/board-view/kanban-board.tsx (3)
1-11: Formatting updates look good.The quote normalization (double → single) and inline expression consolidation are consistent with the PR's standardization goals. No behavioral changes introduced.
Also applies to: 88-88, 110-110, 121-121, 166-167, 180-180, 187-187, 190-192, 205-205
163-168: Shortcut key assignment logic is correct.The logic correctly assigns keys
1–9for indices 0–8 and0for index 9, covering the first 10 in-progress cards as intended.
202-223: Drag overlay implementation is clean.The
DragOverlaywith custom drop animation and preview card rendering follows@dnd-kitbest practices. The visual feedback (rotation, shadow, blur) provides good UX during drag operations.apps/ui/src/config/api-providers.ts (2)
1-4: LGTM!Import statements and type definition are clean. Single-quote standardization is consistent with the broader formatting changes in this PR.
59-84: LGTM!Anthropic provider configuration is well-structured with clear test IDs and descriptive labels. Single-quote standardization is consistent.
apps/ui/src/lib/utils.ts (3)
1-7: LGTM! Formatting standardization looks good.The quote normalization and semicolon additions are consistent with the PR's project-wide style cleanup.
20-27: LGTM! Quote normalization applied consistently.String literal formatting updated to match project style.
43-45: LGTM! Quote normalization with correct escape handling.The regex escape sequence remains properly handled after the quote style change.
apps/ui/src/components/ui/feature-image-upload.tsx (1)
1-282: LGTM! Consistent quote normalization across the file.All changes are purely stylistic, converting double-quoted strings to single quotes throughout imports, string literals, error messages, and template literals. The logic and functionality remain unchanged. The removal of the unused error parameter in the catch block (line 90) is also a nice cleanup.
apps/ui/src/components/views/setup-view/steps/welcome-step.tsx (2)
1-2: LGTM! Consistent formatting applied.The import statements have been updated to use single quotes, aligning with the project-wide formatting standardization mentioned in the PR objectives.
16-16: LGTM! Formatting cleanup.The h2 element has been reformatted to a single line without any functional changes.
apps/ui/src/components/views/terminal-view.tsx (1)
1-707: LGTM! Clean formatting normalization.All changes in this file are purely stylistic—normalizing double-quoted strings to single quotes across imports, literals, JSX attributes, and object properties. No functional logic or behavior has been altered. This is consistent with the PR's refactoring objectives.
apps/ui/tests/utils/components/toasts.ts (1)
1-85: LGTM! Formatting consistency applied.The string literal normalization (double quotes → single quotes) is consistent with the PR's stated objectives and improves code style uniformity across the test utilities.
apps/ui/tests/spec-editor-persistence.spec.ts (1)
1-361: LGTM! Consistent formatting normalization applied.The comprehensive string literal normalization (double quotes → single quotes) aligns with the project-wide refactoring goals. The simplified
catchclause on line 100 is valid modern syntax and improves code clarity when the error object is unused.apps/ui/tests/feature-lifecycle.spec.ts (1)
1-459: LGTM! Formatting consistency and improved test isolation.The string literal normalization is consistent with project-wide refactoring goals. The addition of per-test lifecycle hooks (lines 60-70) that create and cleanup a fresh test repository for each test is a valuable improvement—this prevents test interference and enhances reliability by ensuring each test runs in complete isolation.
apps/ui/tests/utils/views/board.ts (2)
1-89: LGTM! Formatting improvements enhance consistency.The string-quote normalization and inline comment formatting align well with the PR's refactoring objectives and improve code consistency across the test utilities.
114-164: LGTM! Test logic preserved with improved formatting.The formatting updates maintain the existing test behavior while improving readability through consistent quote usage and inline expressions.
apps/ui/src/components/views/board-view/components/kanban-card/agent-info-panel.tsx (1)
1-259: LGTM! Clean and consistent formatting refactor.The string quote normalization from double to single quotes is applied consistently throughout the file. All imports, string literals, and conditional comparisons have been updated without altering any logic or component behavior.
apps/ui/src/components/views/settings-view/api-keys/authentication-status-display.tsx (2)
1-2: LGTM! Import formatting normalized.The import statements now consistently use single quotes, aligning with the PR's string-quote normalization objective.
36-36: LGTM! UI text formatting improved.The status header and authentication text have been collapsed to single-line spans, improving code readability without affecting the displayed content.
Also applies to: 43-43
apps/ui/eslint.config.mjs (1)
8-19: LGTM!The Node.js globals for
.mjsand.cjsfiles are appropriate and correctly configured.apps/ui/src/components/ui/sheet.tsx (3)
1-7: LGTM: Quote style normalization in imports.The import statements have been updated to use single quotes consistently. This aligns with the broader quote style normalization across the file.
31-31: LGTM: Type annotation quote normalization.The
'data-slot'type annotations have been consistently updated from double to single quotes across SheetOverlay, SheetContent, SheetTitle, and SheetDescription components.Also applies to: 55-55, 115-115, 130-130
46-46: LGTM: String literal union type quote normalization.The
sideproperty type has been updated to use single quotes, making it consistent with the default value on line 53.apps/ui/src/components/views/agent-view.tsx (1)
1-873: Formatting normalization changes look good.This file contains primarily quote style normalization (double → single quotes) and minor formatting adjustments with no runtime behavior changes, aligning with the PR's broader code style standardization effort. The core functionality for session management, message rendering, image handling, and drag-and-drop remains intact.
apps/ui/src/lib/file-picker.ts (4)
1-29: Documentation and interface definition look good.The formatting adjustments are consistent with the project-wide standardization, and the documentation accurately describes browser security constraints around file path access.
30-141: Formatting changes applied correctly to directory picker logic.The core logic for extracting directory information from file inputs remains intact. The dual-method approach (checking
file.pathfirst, then falling back towebkitRelativePath) handles cross-browser compatibility well.
142-189: Cancellation detection logic formatted consistently.The focus/blur event pattern for detecting dialog cancellation is a reasonable workaround given browser limitations. The
{ once: true }option prevents listener accumulation, and the extended timeout accommodates Windows file dialog processing delays.
192-277: File picker function formatting updated consistently.The multi-line function signature format (lines 197-200) improves readability. The path extraction logic correctly handles both the non-standard
file.pathproperty and the fallback tofile.name.apps/ui/src/components/views/setup-view/steps/complete-step.tsx (3)
1-2: LGTM! Nice UI enhancement with the Sparkles icon.The Sparkles icon addition to the "Start Building" button is a good visual touch that reinforces the AI-powered theme. The import is properly added and the icon is correctly sized and positioned.
Also applies to: 29-30
16-16: LGTM! Text content is clear and properly formatted.The heading and description text are well-written and user-friendly. The use of
'for the apostrophe is the correct JSX approach.Also applies to: 18-19
11-11: No action needed. Thebg-linear-to-brandbg-linear-to-rclasses are standard Tailwind CSS v4 utilities and are correctly used with thefrom-*andto-*color stop utilities. No custom class definitions are required.Likely an incorrect or invalid review comment.
apps/ui/src/components/ui/accordion.tsx (3)
26-98: LGTM!The
Accordioncomponent is well-implemented with proper controlled/uncontrolled pattern, correct memoization dependencies, and clean handling of single/multiple modes with collapsible behavior.
111-140: LGTM!The
AccordionItemcomponent correctly calculatesisOpenstate for both single and multiple accordion modes, with proper context validation and memoization.
182-225: LGTM!The
AccordionContentcomponent usesResizeObservereffectively for smooth height animations with proper cleanup. The animation logic correctly handles both open and closed states.apps/ui/src/components/views/board-view/dialogs/edit-feature-dialog.tsx (2)
1-56: LGTM! Clean formatting normalization.The import statement formatting changes (switching to single quotes) are consistent and improve code style uniformity.
262-528: LGTM! Consistent quote style normalization.The JSX formatting changes throughout this section maintain functional equivalence while standardizing on single quotes. The logic for default values, status checks, and conditional rendering remains correct.
apps/ui/src/vite-env.d.ts (1)
8-11: TheImportMetainterface redeclaration in this file is necessary and not redundant. Vite's recommended pattern requires declaring both ImportMetaEnv (for custom env variables) and ImportMeta with the env property, as omitting the ImportMeta declaration causes TypeScript errors.apps/ui/src/components/views/welcome-view.tsx (6)
1-35: LGTM: Import reorganization aligns with refactoring.The quote normalization and updated import paths for dialog components are consistent with the broader UI reorganization described in the PR objectives.
68-68: LGTM: Consistent quote normalization.String literals normalized from double quotes to single quotes throughout the file. This is consistent with the project-wide string-quote normalization mentioned in the PR summary.
Also applies to: 74-74, 78-79, 82-82, 85-85, 102-103, 128-129, 134-136, 140-140, 142-144, 177-177, 182-182, 189-189, 221-221, 236-238, 245-247, 254-256, 264-266, 307-309, 320-323, 350-352, 362-364, 405-407, 421-424, 447-449, 459-461, 502-504, 518-521
573-576: LGTM: Minor UI text refinements.Text formatting and wording adjustments are minor and improve consistency. The changes maintain the same semantic meaning while being more concise.
Also applies to: 620-623, 645-646, 689-692, 719-725, 729-730, 756-762, 794-794
115-115: LGTM: Store action usage appears correct.Calling
upsertAndSetCurrentProjectwithout capturing the return value is appropriate, as the function is a store action that handles state updates internally.
541-541: No changes needed. Thebg-linear-to-*classes are standard Tailwind CSS utilities in v4.0+ (released January 2025), wherebg-gradient-*was officially renamed tobg-linear-*for linear gradients. The project uses Tailwind v4.1.18, and this code correctly implements the current syntax.Likely an incorrect or invalid review comment.
244-244: The API structure change is correctly implemented. Bothstat()usages in the codebase consistently access the nestedstats.isDirectoryproperty according to theStatResultinterface definition. No inconsistencies or missing updates found.apps/ui/src/components/layout/sidebar/types.ts (1)
1-32: LGTM! Well-structured type definitions.The new interfaces provide clear, type-safe contracts for the modularized sidebar components. The type definitions are appropriately scoped and use proper React types for component props.
apps/ui/src/components/layout/sidebar/components/bug-report-button.tsx (1)
1-33: LGTM! Clean component implementation.The BugReportButton component correctly handles both expanded and collapsed sidebar states with appropriate styling transitions and test identifiers. The use of
useCallbackwith an empty dependency array is correct since the click handler has no external dependencies.apps/ui/src/components/layout/sidebar/components/sidebar-header.tsx (1)
1-39: LGTM! Clear component composition.The header component cleanly composes the logo and bug report button with appropriate conditional layout logic for expanded/collapsed states. The dual placement strategy ensures optimal positioning in both sidebar modes.
apps/ui/src/components/layout/sidebar/components/project-selector-with-options.tsx (2)
44-374: Well-architected component with rich interactions.This component effectively consolidates project selection, theming, history navigation, and trash operations into a cohesive UI. The integration of drag-and-drop reordering, type-ahead search, and keyboard navigation provides excellent UX.
247-254: Remove redundant pointer leave handlers on submenu wrapper.The submenu has two unconditional
onPointerLeavehandlers (lines 250 and 275) that both callsetPreviewTheme(null). However,handlePreviewLeavein the hook already contains the necessary logic to check if the pointer remains within theme elements usingrelatedTarget.closest(). The direct handlers bypass this check and are redundant—keep only the smart handler passed to ThemeMenuItem components.apps/ui/src/components/layout/sidebar.tsx (3)
14-33: Excellent modularization of sidebar architecture.The refactor successfully decomposes a 2100+ line monolithic sidebar into well-organized components, dialogs, hooks, and constants. This improves maintainability, testability, and reusability across the codebase.
58-59: Good practice: centralized feature flags.Using
SIDEBAR_FEATURE_FLAGSobject instead of direct environment variable reads improves discoverability and creates a single source of truth for configuration.
249-366: Clean component composition maintains functionality.The sidebar rendering successfully composes the new modular components while maintaining the original feature set. Each component receives well-defined props, and dialogs are properly wired with their respective state handlers.
… callback - Added an `afterEach` hook to clean up after tests in `claude-usage-service.test.ts`. - Updated the mock for `onExit` to include an exit callback, ensuring proper handling of process termination. - Modified the `fetchUsageData` test to await the promise resolution, preventing unhandled promise rejections. These changes improve the reliability and robustness of the unit tests for the ClaudeUsageService.
Summary by CodeRabbit
New Features
Refactor
Style
Tests
✏️ Tip: You can customize this high-level summary in your review settings.