-
Notifications
You must be signed in to change notification settings - Fork 614
feat(window): add settings window #996
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
Conversation
|
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. WalkthroughIntroduces a standalone Settings renderer and singleton Settings window in the main process. Router removes in-app Settings routes. Build config adds a new HTML entry for settings. Shortcuts and events route to the new window. Adds settings UI files, icons, and styling tweaks. Expands provider DB with a new “cherryin” provider. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Renderer (Main App)
participant Main (WindowPresenter)
participant Settings Window
User->>Renderer (Main App): Click "Settings" / trigger GO_SETTINGS
Renderer (Main App)->>Main (WindowPresenter): GO_SETTINGS (IPC/EventBus)
alt Settings window not open
Main (WindowPresenter)->>Main (WindowPresenter): createSettingsWindow()
Main (WindowPresenter)->>Settings Window: instantiate + load URL
else Already open
Main (WindowPresenter)->>Settings Window: focus/show
end
Settings Window-->>User: Settings UI displayed
sequenceDiagram
participant User
participant OS
participant Main (ShortcutPresenter)
participant Main (WindowPresenter)
participant Settings Window
OS->>Main (ShortcutPresenter): CloseTab shortcut
Main (ShortcutPresenter)->>Main (WindowPresenter): getSettingsWindowId()
alt Focused is Settings
Main (ShortcutPresenter)->>Main (WindowPresenter): closeSettingsWindow()
Main (WindowPresenter)->>Settings Window: close
else Focused is regular window
Main (ShortcutPresenter)->>Focused Renderer: CLOSE_CURRENT_TAB (with id)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used📓 Path-based instructions (15)src/renderer/src/**/*📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
Files:
src/renderer/**/*.{vue,ts,js,tsx,jsx}📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Files:
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
Files:
src/renderer/src/**/*.vue📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
Files:
src/renderer/**/*.{ts,tsx,vue}📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Files:
src/renderer/**/*.{vue,ts}📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Files:
src/renderer/**/*.{ts,vue}📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Files:
**/*.{ts,tsx,js,vue}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx,vue}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/renderer/{src,shell,floating}/**/*.vue📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/renderer/src/components/**/*📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/renderer/src/**📄 CodeRabbit inference engine (AGENTS.md)
Files:
src/renderer/src/**/*.{vue,ts}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{js,jsx,ts,tsx,vue}📄 CodeRabbit inference engine (AGENTS.md)
Files:
src/renderer/**/*.vue📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (2)📚 Learning: 2025-07-23T00:45:57.322ZApplied to files:
📚 Learning: 2025-07-21T01:47:28.817ZApplied to files:
⏰ 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)
🔇 Additional comments (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@codex review |
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.
💡 Codex Review
deepchat/src/renderer/src/views/WelcomeView.vue
Lines 53 to 55 in 48ad538
| const ModelConfigItem = defineAsyncComponent( | |
| () => import('@/components/settings/ModelConfigItem.vue') | |
| ) |
The commit moved ModelConfigItem.vue into src/renderer/settings/components, but WelcomeView.vue still lazy‑loads it from @/components/settings/ModelConfigItem.vue. With the file no longer under src/renderer/src/components/settings, Vite/Vitest will fail to resolve the module and the renderer won’t build. Update the import path (or provide a re‑export) so the file can be bundled again.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
| } else { | ||
| configPresenter.setSetting('init_complete', true) | ||
| if (!providerModels.value || providerModels.value.length === 0) { | ||
| router.push({ name: 'settings' }) | ||
| return | ||
| } else { | ||
| router.push({ | ||
| name: 'chat', | ||
| query: { | ||
| modelId: providerModels.value[0].id, | ||
| providerId: selectedProvider.value | ||
| } | ||
| }) | ||
| } | ||
| router.push({ | ||
| name: 'chat', | ||
| query: { | ||
| modelId: providerModels.value[0].id, | ||
| providerId: selectedProvider.value | ||
| } |
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.
Guard against missing provider models on onboarding completion
The final step of the onboarding wizard now unconditionally does providerModels.value[0].id when routing to the chat view. When the user has not configured any provider models (the default state on first run), providerModels.value is empty and this expression throws, leaving the app stuck. Previously this branch redirected the user to Settings. Either keep the empty‑state check or open the new settings window so onboarding completes without a runtime error.
Useful? React with 👍 / 👎.
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: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/renderer/src/router/index.ts (1)
28-40: Remove outdated settings route name references
Update or remove references tosettings,settings-mcp, andsettings-knowledge-basein:
- src/renderer/src/stores/settings.ts (lines 208, 211, 215)
- src/renderer/src/components/mcp-config/components/McpServers.vue (line 190)
These should invoke the new Settings window API instead of router-based navigation.
🧹 Nitpick comments (6)
src/renderer/settings/components/ProviderApiConfig.vue (1)
55-55: Avoid!importantin inline styles.Using
!importantin inline styles is an anti-pattern that can make styles harder to maintain and override. Consider using proper CSS class specificity instead.Apply this diff to remove the inline style:
- style="padding-right: 2.5rem !important"Then add this CSS to your component's style section or scoped styles:
<style scoped> /* Adjust input padding for toggle button */ .relative input { padding-right: 2.5rem; } </style>Or target the specific input more precisely if needed.
src/renderer/settings/icons/MinimizeIcon.vue (1)
1-19: Prefer Iconify icon over custom SVG component.This custom SVG icon component contradicts the established pattern for icon implementation. Based on learnings and coding guidelines, icon components should use Iconify/Vue with lucide icons instead of custom SVG components.
Based on learnings.
Consider using the Iconify icon component:
-<template> - <svg width="10" height="1" viewBox="0 0 10 1" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M0.498047 1C0.429688 1 0.364583 0.986979 0.302734 0.960938C0.244141 0.934896 0.192057 0.899089 0.146484 0.853516C0.100911 0.807943 0.0651042 0.755859 0.0390625 0.697266C0.0130208 0.635417 0 0.570312 0 0.501953C0 0.433594 0.0130208 0.370117 0.0390625 0.311523C0.0651042 0.249674 0.100911 0.195964 0.146484 0.150391C0.192057 0.101562 0.244141 0.0641276 0.302734 0.0380859C0.364583 0.0120443 0.429688 -0.000976562 0.498047 -0.000976562H9.50195C9.57031 -0.000976562 9.63379 0.0120443 9.69238 0.0380859C9.75423 0.0641276 9.80794 0.101562 9.85352 0.150391C9.89909 0.195964 9.9349 0.249674 9.96094 0.311523C9.98698 0.370117 10 0.433594 10 0.501953C10 0.570312 9.98698 0.635417 9.96094 0.697266C9.9349 0.755859 9.89909 0.807943 9.85352 0.853516C9.80794 0.899089 9.75423 0.934896 9.69238 0.960938C9.63379 0.986979 9.57031 1 9.50195 1H0.498047Z" - :fill="fill" - /> - </svg> -</template> - -<script setup lang="ts"> -withDefaults( - defineProps<{ - fill?: string - }>(), - { - fill: 'currentColor' - } -) -</script> +<template> + <Icon icon="lucide:minus" :style="{ color: fill }" /> +</template> + +<script setup lang="ts"> +import { Icon } from '@iconify/vue' + +withDefaults( + defineProps<{ + fill?: string + }>(), + { + fill: 'currentColor' + } +) +</script>This applies to other custom icon components as well (CloseIcon, MaximizeIcon, RestoreIcon).
src/renderer/settings/components/McpSettings.vue (1)
222-225: Import path is valid; consider using path alias
The relative path../../src/components/mcp-config/constresolves correctly. If a@/alias is configured, switch to@/components/mcp-config/constfor consistency.src/renderer/settings/index.html (1)
2-2: Consider dynamic language attribute for i18n support.The
langattribute is hardcoded to"en". Since the application supports internationalization via vue-i18n, consider making this dynamic based on the user's language preference to improve accessibility and localization.As per coding guidelines
You could initialize the language dynamically in
main.tsor use a template variable if the build system supports it.src/renderer/settings/icons/CloseIcon.vue (1)
1-18: Stick to the Iconify-based icon patternRenderer icons should go through the shared
<Icon>wrapper (Iconify) instead of bespoke inline SVGs, so that sizing, theming, and future replacements stay consistent. Please swap this component to render the matching Iconify asset (e.g.lucide:x) and drop the custom SVG. Based on learningssrc/renderer/settings/icons/MaximizeIcon.vue (1)
1-20: Reuse the shared Iconify icon pipelineLike the close glyph, this maximize control should leverage the standard
<Icon>component (Iconify, e.g.lucide:maximize) instead of an ad-hoc SVG so we keep styling and updates centralized. Please align with the shared Iconify approach. Based on learnings
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
electron.vite.config.ts(1 hunks)src/main/presenter/shortcutPresenter.ts(1 hunks)src/main/presenter/windowPresenter/index.ts(5 hunks)src/renderer/settings/App.vue(1 hunks)src/renderer/settings/components/CommonSettings.vue(17 hunks)src/renderer/settings/components/DisplaySettings.vue(1 hunks)src/renderer/settings/components/McpSettings.vue(1 hunks)src/renderer/settings/components/ModelConfigItem.vue(2 hunks)src/renderer/settings/components/ModelProviderSettings.vue(5 hunks)src/renderer/settings/components/ModelProviderSettingsDetail.vue(5 hunks)src/renderer/settings/components/ProviderApiConfig.vue(2 hunks)src/renderer/settings/components/ProviderModelManager.vue(2 hunks)src/renderer/settings/components/ProviderRateLimitConfig.vue(1 hunks)src/renderer/settings/icons/CloseIcon.vue(1 hunks)src/renderer/settings/icons/MaximizeIcon.vue(1 hunks)src/renderer/settings/icons/MinimizeIcon.vue(1 hunks)src/renderer/settings/icons/RestoreIcon.vue(1 hunks)src/renderer/settings/index.html(1 hunks)src/renderer/settings/main.ts(1 hunks)src/renderer/shell/components/app-bar/AppBarTabItem.vue(2 hunks)src/renderer/src/composables/usePresenter.ts(1 hunks)src/renderer/src/router/index.ts(1 hunks)src/renderer/src/views/WelcomeView.vue(1 hunks)src/shadcn/components/ui/input/Input.vue(1 hunks)src/shared/types/presenters/legacy.presenters.d.ts(1 hunks)tsconfig.app.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (27)
src/renderer/**/*.{vue,ts,js,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
渲染进程代码放在
src/renderer
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vuesrc/renderer/settings/components/ModelProviderSettings.vuesrc/renderer/settings/components/ProviderApiConfig.vue
src/renderer/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vuesrc/renderer/settings/components/ModelProviderSettings.vuesrc/renderer/settings/components/ProviderApiConfig.vue
src/renderer/**/*.{vue,ts}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Implement lazy loading for routes and components.
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vuesrc/renderer/settings/components/ModelProviderSettings.vuesrc/renderer/settings/components/ProviderApiConfig.vue
src/renderer/**/*.{ts,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.Use Pinia for frontend state management (do not introduce alternative state libraries)
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vuesrc/renderer/settings/components/ModelProviderSettings.vuesrc/renderer/settings/components/ProviderApiConfig.vue
**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for all logs and comments
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/shadcn/components/ui/input/Input.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vueelectron.vite.config.tssrc/renderer/settings/components/ModelProviderSettings.vuesrc/main/presenter/shortcutPresenter.tssrc/renderer/settings/components/ProviderApiConfig.vuesrc/main/presenter/windowPresenter/index.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/shadcn/components/ui/input/Input.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vueelectron.vite.config.tssrc/renderer/settings/components/ModelProviderSettings.vuesrc/main/presenter/shortcutPresenter.tssrc/renderer/settings/components/ProviderApiConfig.vuesrc/main/presenter/windowPresenter/index.ts
**/*.{js,jsx,ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting: single quotes, no semicolons, max width 100
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/shadcn/components/ui/input/Input.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vueelectron.vite.config.tssrc/renderer/settings/components/ModelProviderSettings.vuesrc/main/presenter/shortcutPresenter.tssrc/renderer/settings/components/ProviderApiConfig.vuesrc/main/presenter/windowPresenter/index.ts
src/renderer/**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
Name Vue components in PascalCase (e.g., ChatInput.vue)
Files:
src/renderer/settings/components/DisplaySettings.vuesrc/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/src/views/WelcomeView.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/components/CommonSettings.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vuesrc/renderer/settings/components/ModelConfigItem.vuesrc/renderer/settings/App.vuesrc/renderer/settings/components/ProviderModelManager.vuesrc/renderer/settings/components/ProviderRateLimitConfig.vuesrc/renderer/settings/icons/RestoreIcon.vuesrc/renderer/settings/components/McpSettings.vuesrc/renderer/settings/components/ModelProviderSettingsDetail.vuesrc/renderer/settings/components/ModelProviderSettings.vuesrc/renderer/settings/components/ProviderApiConfig.vue
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写
**/*.{js,jsx,ts,tsx}: Use OxLint for JS/TS code; pre-commit hooks run lint-staged and typecheck
Use camelCase for variables and functions
Use PascalCase for types and classes
Use SCREAMING_SNAKE_CASE for constants
Files:
src/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/router/index.tssrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tselectron.vite.config.tssrc/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/error-logging.mdc)
**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别
Files:
src/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/router/index.tssrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tselectron.vite.config.tssrc/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
src/shared/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
共享类型定义放在
shared目录
Files:
src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Place shared types, utilities, constants, and IPC contract definitions under src/shared/
Files:
src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**
📄 CodeRabbit inference engine (AGENTS.md)
Store shared TypeScript types/utilities in src/shared/
Files:
src/shared/types/presenters/legacy.presenters.d.ts
src/{main,renderer}/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
src/{main,renderer}/**/*.ts: Use context isolation for improved security
Implement proper inter-process communication (IPC) patterns
Optimize application startup time with lazy loading
Implement proper error handling and logging for debugging
Files:
src/renderer/src/router/index.tssrc/renderer/src/composables/usePresenter.tssrc/renderer/settings/main.tssrc/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
src/renderer/src/**/*
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system
Files:
src/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/src/composables/usePresenter.ts
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling
Files:
src/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/src/composables/usePresenter.ts
src/renderer/src/router/**/*.{vue,ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/vue-router-best-practices.mdc)
src/renderer/src/router/**/*.{vue,ts,tsx,js,jsx}: Use named routes for easier navigation and maintenance
Implement route-level code splitting for better performance
Use route meta fields for attaching additional data to routes
Implement proper navigation guards for authentication and authorization
Use dynamic routing for handling variable route segments
Files:
src/renderer/src/router/index.ts
src/renderer/src/**
📄 CodeRabbit inference engine (AGENTS.md)
Put application code for the Vue app under src/renderer/src (components, stores, views, i18n, lib)
Files:
src/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/src/composables/usePresenter.ts
src/renderer/src/**/*.{vue,ts}
📄 CodeRabbit inference engine (AGENTS.md)
All user-facing strings in the renderer must use vue-i18n keys defined in src/renderer/src/i18n
Files:
src/renderer/src/router/index.tssrc/renderer/src/views/WelcomeView.vuesrc/renderer/src/composables/usePresenter.ts
src/renderer/src/**/*.vue
📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
Use scoped styles to prevent CSS conflicts between components
Files:
src/renderer/src/views/WelcomeView.vue
src/renderer/{src,shell,floating}/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
src/renderer/{src,shell,floating}/**/*.vue: Use Vue 3 Composition API for all components
All user-facing strings must use i18n keys via vue-i18n (no hard-coded UI strings)
Use Tailwind CSS utilities and ensure styles are scoped in Vue components
Files:
src/renderer/src/views/WelcomeView.vuesrc/renderer/shell/components/app-bar/AppBarTabItem.vue
src/renderer/shell/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep shell UI code in src/renderer/shell/
Files:
src/renderer/shell/components/app-bar/AppBarTabItem.vue
src/renderer/src/composables/usePresenter.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
The IPC in the renderer process is implemented in usePresenter.ts, allowing direct calls to the presenter-related interfaces exposed by the main process
Files:
src/renderer/src/composables/usePresenter.ts
src/main/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Use Electron's built-in APIs for file system and native dialogs
Files:
src/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
src/main/**/*.{ts,js,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
主进程代码放在
src/main
Files:
src/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
src/main/**
📄 CodeRabbit inference engine (AGENTS.md)
Place all Electron main-process code under src/main/
Files:
src/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
src/main/presenter/**
📄 CodeRabbit inference engine (AGENTS.md)
src/main/presenter/**: Organize main-process presenters under src/main/presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider)
Follow the Presenter pattern for main-process modules
Files:
src/main/presenter/shortcutPresenter.tssrc/main/presenter/windowPresenter/index.ts
🧠 Learnings (10)
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Iconify/Vue for icon implementation.
Applied to files:
src/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vuesrc/renderer/settings/icons/RestoreIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Import Icon component from Iconify/Vue.
Applied to files:
src/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/settings/icons/CloseIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use the Icon component with lucide icons.
Applied to files:
src/renderer/settings/icons/MaximizeIcon.vuesrc/renderer/settings/icons/MinimizeIcon.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Shadcn Vue, Radix Vue, and Tailwind for components and styling.
Applied to files:
tsconfig.app.jsonsrc/renderer/settings/App.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Vue 3 with TypeScript, leveraging defineComponent and PropType.
Applied to files:
tsconfig.app.json
📚 Learning: 2025-07-21T01:47:11.608Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-07-21T01:47:11.608Z
Learning: Applies to src/renderer/**/*.{vue,ts,js,tsx,jsx} : 渲染进程代码放在 `src/renderer`
Applied to files:
tsconfig.app.json
📚 Learning: 2025-07-21T01:47:11.608Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-07-21T01:47:11.608Z
Learning: Applies to src/shared/**/*.{ts,tsx,d.ts} : 共享类型定义放在 `shared` 目录
Applied to files:
tsconfig.app.json
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/**/* : Use the 'vue-i18n' framework for all internationalization in the renderer
Applied to files:
tsconfig.app.json
📚 Learning: 2025-07-21T01:45:54.229Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:45:54.229Z
Learning: Applies to src/renderer/src/composables/usePresenter.ts : The IPC in the renderer process is implemented in usePresenter.ts, allowing direct calls to the presenter-related interfaces exposed by the main process
Applied to files:
src/renderer/src/composables/usePresenter.ts
📚 Learning: 2025-07-21T01:47:28.817Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:47:28.817Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx,js,jsx} : Utilize Vue Router for navigation and route management
Applied to files:
src/renderer/settings/App.vue
🧬 Code graph analysis (2)
src/main/presenter/shortcutPresenter.ts (1)
src/main/presenter/index.ts (1)
presenter(223-223)
src/main/presenter/windowPresenter/index.ts (4)
test/mocks/electron.ts (3)
BrowserWindow(36-51)ipcMain(12-16)nativeImage(53-55)src/main/eventbus.ts (1)
eventBus(151-151)src/main/events.ts (1)
SHORTCUT_EVENTS(149-164)test/mocks/electron-toolkit-utils.ts (1)
is(1-3)
🪛 GitHub Actions: PR Check
src/renderer/settings/App.vue
[error] 62-62: TS6133: 'themeStore' is declared but its value is never read.
🪛 GitHub Check: build-check (x64)
src/renderer/settings/App.vue
[failure] 136-136:
'newLang' is declared but its value is never read.
[failure] 62-62:
'themeStore' is declared but its value is never read.
🔇 Additional comments (13)
src/renderer/settings/components/ProviderApiConfig.vue (1)
60-70: LGTM!The show/hide API key toggle implementation is well-structured with proper state management, conditional rendering, and user-friendly icon feedback.
Also applies to: 175-175
src/renderer/settings/components/DisplaySettings.vue (1)
2-2: LGTM!The padding adjustment improves the visual spacing of the settings area.
src/renderer/settings/components/ModelConfigItem.vue (2)
2-2: LGTM!The padding adjustment improves horizontal spacing consistency.
24-26: LGTM!The conditional rendering correctly filters out the "default" group label, reducing visual noise.
electron.vite.config.ts (1)
97-98: LGTM!The new
settingsentry point properly supports the dedicated Settings window architecture introduced in this PR.src/shadcn/components/ui/input/Input.vue (1)
20-33: LGTM!The simplified focus styling using
focus-visible:border-ringis cleaner and maintains visual consistency.src/renderer/src/composables/usePresenter.ts (1)
8-21: Remove null‐handling enforcement ongetWebContentsIdexport
No external callers of this new API exist—only the internal proxy uses it (with its own “unknown” fallback).Likely an incorrect or invalid review comment.
src/renderer/shell/components/app-bar/AppBarTabItem.vue (1)
5-5: LGTM! UI refinements improve visual consistency.The reduced padding and adjusted hover styling for the close icon align well with the new Settings window UI design introduced in this PR.
Also applies to: 16-16
src/renderer/settings/components/ModelProviderSettingsDetail.vue (1)
3-4: LGTM! Separators improve visual organization.The addition of
Separatorcomponents between configuration sections and the padding adjustments enhance the visual structure of the settings detail view.Also applies to: 17-17, 27-27, 37-37, 42-42, 94-94
src/renderer/settings/icons/RestoreIcon.vue (1)
1-18: Verify custom SVG pattern vs. Iconify for window chrome controls.This custom SVG icon component deviates from the established guideline to use Iconify/Vue for icon implementation (based on learnings). While custom SVG components may be intentional for window chrome controls (restore, minimize, maximize, close buttons) that require precise styling and behavior, please confirm this pattern is preferred over Iconify icons for these specific use cases.
Based on learnings
src/renderer/settings/components/ProviderRateLimitConfig.vue (1)
2-2: LGTM! Styling simplification aligns with Settings window design.Removing the border and background styling creates a cleaner, more integrated appearance within the dedicated Settings window.
tsconfig.app.json (1)
21-23: LGTM! TypeScript configuration updated correctly.The inclusion of the new Settings directory patterns ensures proper type checking and compilation for the dedicated Settings window code.
src/main/presenter/shortcutPresenter.ts (1)
75-79: Approve Settings window shortcut handling
Logic correctly distinguishes the Settings window and uses the existinggetSettingsWindowId()andcloseSettingsWindow()APIs.
|
|
||
| if (electronFocusedWindow) { | ||
| const windowId = electronFocusedWindow.id | ||
| console.log(this.windows) | ||
| const ourWindow = this.windows.get(windowId) | ||
|
|
||
| // 验证 Electron 报告的窗口是否在我们管理范围内且有效 | ||
| if (ourWindow && !ourWindow.isDestroyed()) { | ||
| this.focusedWindowId = windowId // 更新内部记录 | ||
| return ourWindow | ||
| } else if (this.settingsWindow) { | ||
| if (windowId === this.settingsWindow.id) { | ||
| return this.settingsWindow | ||
| } else { | ||
| return | ||
| } | ||
| } else { |
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.
Don’t treat the settings window as a regular managed window.
The new branch makes getFocusedWindow() return settingsWindow, but callers expect a shell window that lives in this.windows. For example, sendToDefaultTab now tries to fetch tabs for the settings window ID, which fails and breaks keyboard shortcuts whenever the settings window is focused. Keep returning only managed shell windows (i.e., drop the settings-window branch) so existing logic keeps working.
🤖 Prompt for AI Agents
In src/main/presenter/windowPresenter/index.ts around lines 996 to 1012, callers
expect getFocusedWindow() to return only managed shell windows from
this.windows; remove the branch that treats settingsWindow as a regular managed
window (the else if (this.settingsWindow) { ... } block), so when the focused
Electron window is not in this.windows the function returns undefined/null
instead of returning settingsWindow; also ensure focusedWindowId is not updated
to the settings window ID (keep it unchanged) so existing logic like
sendToDefaultTab continues to work.
| onMounted(() => { | ||
| const tempArray: { | ||
| title: string | ||
| name: string | ||
| icon: string | ||
| path: string | ||
| position: number | ||
| }[] = [] | ||
| routes.forEach((route) => { | ||
| // In settings window, all routes are top-level, no parent 'settings' route | ||
| if (route.path !== '/' && route.meta?.titleKey) { | ||
| console.log(`Adding settings route: ${route.path} with titleKey: ${route.meta.titleKey}`) | ||
| tempArray.push({ | ||
| title: route.meta.titleKey as string, | ||
| icon: route.meta.icon as string, | ||
| path: route.path, | ||
| name: route.name as string, | ||
| position: (route.meta.position as number) || 999 | ||
| }) | ||
| } | ||
| // Sort by position meta field, default to 999 if not present | ||
| tempArray.sort((a, b) => { | ||
| return a.position - b.position | ||
| }) | ||
| settings.value = tempArray | ||
| console.log('Final sorted settings routes:', settings.value) | ||
| }) |
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.
Window title never reflects the current section on first load.
watch(() => route.name, … { immediate: true }) runs before the routes are collected, so settings.value is empty and the title gets stuck at the fallback 'Settings'. Call updateTitle() after populating settings.value (or watch settings) so the initial window title includes the active section.
🤖 Prompt for AI Agents
In src/renderer/settings/App.vue around lines 80 to 106, the settings routes are
collected and assigned to settings.value but updateTitle() is not invoked
afterwards, so the window title watcher runs earlier and the title stays at the
fallback; after you finish populating and sorting tempArray and assign
settings.value, call updateTitle() (or alternatively change the watcher to watch
settings and run immediate) so the initial window title reflects the active
settings section.
| @blur=" | ||
| String($event.target.value) !== apiHost && | ||
| handleApiHostChange(String($event.target.value)) | ||
| " |
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.
Type safety issue with event target.
The $event.target is typed as EventTarget which doesn't have a value property, and you're converting it to String twice unnecessarily.
As per coding guidelines, TypeScript strict typing should be adhered to avoid implicit any.
Apply this diff to fix the type safety and redundancy:
- @blur="
- String($event.target.value) !== apiHost &&
- handleApiHostChange(String($event.target.value))
- "
+ @blur="
+ (e: Event) => {
+ const value = (e.target as HTMLInputElement).value
+ if (value !== apiHost) handleApiHostChange(value)
+ }
+ "🤖 Prompt for AI Agents
In src/renderer/settings/components/ProviderApiConfig.vue around lines 21 to 24,
the blur handler uses $event.target whose type is EventTarget and is converted
to String twice; change the handler to cast the event target to HTMLInputElement
once, read its .value into a local const, compare that string to apiHost, and
call handleApiHostChange with the value only when they differ (avoid redundant
String(...) wrapping and ensure proper TypeScript typing).
| :type="showApiKey ? 'text' : 'password'" | ||
| :placeholder="t('settings.provider.keyPlaceholder')" | ||
| style="padding-right: 2.5rem !important" | ||
| @blur="$event.target.value !== apiKey && handleApiKeyChange($event.target.value)" |
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.
Type safety and consistency issues.
Similar to the API host handler, $event.target lacks proper typing. Additionally, this handler is inconsistent with the API host handler (line 22) which uses String() conversion.
Apply this diff for type safety and consistency:
- @blur="$event.target.value !== apiKey && handleApiKeyChange($event.target.value)"
+ @blur="
+ (e: Event) => {
+ const value = (e.target as HTMLInputElement).value
+ if (value !== apiKey) handleApiKeyChange(value)
+ }
+ "📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @blur="$event.target.value !== apiKey && handleApiKeyChange($event.target.value)" | |
| @blur=" | |
| (e: Event) => { | |
| const value = (e.target as HTMLInputElement).value | |
| if (value !== apiKey) handleApiKeyChange(value) | |
| } | |
| " |
🤖 Prompt for AI Agents
In src/renderer/settings/components/ProviderApiConfig.vue around line 56, the
blur handler uses $event.target without typing and differs from the API host
handler; cast $event.target to an HTMLInputElement (or otherwise access the
typed .value) and use String(...) to convert the value before comparing and
passing it to handleApiKeyChange so it matches the API host handler's
type-safety and conversion behavior.
| router.push({ | ||
| name: 'chat', | ||
| query: { | ||
| modelId: providerModels.value[0].id, | ||
| providerId: selectedProvider.value | ||
| } | ||
| }) | ||
| } |
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.
Potential runtime error: Unsafe array access.
The code accesses providerModels.value[0].id without checking if the array is non-empty. If providerModels.value is empty (e.g., when model sync fails, as shown in line 379), this will cause a runtime error.
Apply this diff to add a safety check:
} else {
configPresenter.setSetting('init_complete', true)
+ if (providerModels.value.length === 0) {
+ console.error('No models available')
+ showErrorDialog.value = true
+ dialogMessage.value = t('welcome.error.noModels')
+ return
+ }
router.push({
name: 'chat',
query: {
modelId: providerModels.value[0].id,
providerId: selectedProvider.value
}
})
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| router.push({ | |
| name: 'chat', | |
| query: { | |
| modelId: providerModels.value[0].id, | |
| providerId: selectedProvider.value | |
| } | |
| }) | |
| } | |
| } else { | |
| configPresenter.setSetting('init_complete', true) | |
| if (providerModels.value.length === 0) { | |
| console.error('No models available') | |
| showErrorDialog.value = true | |
| dialogMessage.value = t('welcome.error.noModels') | |
| return | |
| } | |
| router.push({ | |
| name: 'chat', | |
| query: { | |
| modelId: providerModels.value[0].id, | |
| providerId: selectedProvider.value | |
| } | |
| }) | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/views/WelcomeView.vue around lines 166 to 173, the code
unguardedly accesses providerModels.value[0].id which can throw if
providerModels.value is empty; add a safety check to ensure providerModels.value
exists and has at least one element before using index 0, and if empty either
abort router.push or use a sensible fallback (e.g., first available model from
another source or omit modelId), and ensure selectedProvider.value is validated
similarly so router.push only runs with valid values.
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: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/renderer/settings/components/CommonSettings.vue (2)
112-112: Hardcoded Chinese text should be internationalized.The text "字符" is hardcoded instead of using the i18n translation function. This violates the coding guideline requiring English for all code.
Apply this diff to use i18n:
- <span class="text-xs text-muted-foreground ml-1">字符</span> + <span class="text-xs text-muted-foreground ml-1">{{ t('settings.common.characters') }}</span>Ensure the translation key is added to your i18n resource files.
784-784: Inconsistent maximum value for web content length limit.The
increaseWebContentLimitfunction uses20000as the maximum value, but the template (lines 93 and 108) specifies:max="10000"and:disabled="webContentLengthLimit >= 10000". This inconsistency could allow values beyond the intended maximum.Apply this diff to align with the template's maximum:
const increaseWebContentLimit = () => { - const newValue = Math.min(webContentLengthLimit.value + 100, 20000) + const newValue = Math.min(webContentLengthLimit.value + 100, 10000) handleWebContentLengthLimitChange(newValue) }
🧹 Nitpick comments (4)
src/renderer/settings/components/CommonSettings.vue (2)
562-562: Address TODO comments for error notifications.There are TODO comments indicating missing error notification functionality when adding or deleting custom search engines fails. This could leave users unaware of failures.
Do you want me to generate code for displaying error notifications using a toast/notification component, or would you prefer to open an issue to track this enhancement?
Also applies to: 711-711
652-652: Consider replacing console.log with structured logging.Multiple console.log statements are used throughout the code. For production code, consider using a structured logging solution that can be controlled via the logging settings and provides better debugging capabilities.
Example pattern to consider:
// Use a logger utility import { logger } from '@/utils/logger' // Instead of: console.log('update search model', model, providerId) // Use: logger.debug('update search model', { model, providerId })This allows centralized control of logging levels and formats.
Also applies to: 749-749, 759-759, 771-771
resources/model-db/providers.json (2)
39588-39605: Schema consistency for non-chat models (embeddings/rerankers/images).
- x-ai/grok-2-image lacks limit (Lines 39588–39605). Add a basic limit for consistency, or ensure the renderer tolerates missing.
- Embedding/reranker IDs (Lines 39286–39301, 39440–39447, 39449–39456, 39458–39465) may need modality types other than "text" output (e.g., "embedding" or "score") depending on your schema.
Recommend:
- Define explicit modalities/limit for these, aligned with your accepted modality enum.
- If the UI filters by modality, missing/incorrect values will hide these models or cause errors.
I can align all entries once you confirm the modality enum and required fields for non-chat models.
Also applies to: 39727-39734, 39286-39301, 39440-39447, 39449-39456, 39458-39465
39709-39716: Minor naming/style consistency (optional).
- Use Title Case in name/display_name for consistency (e.g., "xAI: Grok 4 Fast (Reasoning)").
- Ensure provider names are consistently capitalized (e.g., "OpenAI: GPT‑OSS 120B").
Purely cosmetic; feel free to defer.
Also applies to: 39718-39725, 38946-38953, 39640-39647
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
resources/model-db/providers.json(1 hunks)src/renderer/settings/App.vue(1 hunks)src/renderer/settings/components/CommonSettings.vue(17 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/renderer/settings/App.vue
🧰 Additional context used
📓 Path-based instructions (9)
src/renderer/**/*.{vue,ts,js,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
渲染进程代码放在
src/renderer
Files:
src/renderer/settings/components/CommonSettings.vue
src/renderer/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
Files:
src/renderer/settings/components/CommonSettings.vue
src/renderer/**/*.{vue,ts}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Implement lazy loading for routes and components.
Files:
src/renderer/settings/components/CommonSettings.vue
src/renderer/**/*.{ts,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.Use Pinia for frontend state management (do not introduce alternative state libraries)
Files:
src/renderer/settings/components/CommonSettings.vue
**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for all logs and comments
Files:
src/renderer/settings/components/CommonSettings.vue
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)
Files:
src/renderer/settings/components/CommonSettings.vue
**/*.{js,jsx,ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting: single quotes, no semicolons, max width 100
Files:
src/renderer/settings/components/CommonSettings.vue
src/renderer/**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
Name Vue components in PascalCase (e.g., ChatInput.vue)
Files:
src/renderer/settings/components/CommonSettings.vue
{build,resources,out,dist}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep build outputs and assets within build/, resources/, out/, and dist/
Files:
resources/model-db/providers.json
🧠 Learnings (1)
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Import Icon component from Iconify/Vue.
Applied to files:
src/renderer/settings/components/CommonSettings.vue
🔇 Additional comments (2)
src/renderer/settings/components/CommonSettings.vue (2)
2-3: LGTM! Layout standardization improves consistency.The layout changes successfully standardize spacing, heights, and alignment across all settings sections:
- Increased container padding (p-4) and gaps (gap-3) for better visual breathing room
- Standardized row heights (h-10) for consistent alignment
- Explicit button sizing with
icon-smand w-x/h-x classes- Consistent end-alignment for popovers and select dropdowns
These changes enhance the overall visual consistency and user experience of the settings interface.
Also applies to: 5-59, 62-114, 117-153, 155-175, 200-215, 218-233, 236-251, 254-269, 295-301, 307-312
139-142: LGTM! Icon usage follows coding guidelines.The Icon component from
@iconify/vueis correctly used with thelucide:chevron-downicon reference, which aligns with the project's coding guidelines and learnings.Based on learnings
| "attachment": true, | ||
| "open_weights": false, | ||
| "knowledge": "2024-01", | ||
| "release_date": "2025-02-19", | ||
| "last_updated": "2025-02-19", |
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.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Normalize knowledge date format (mixed YYYY-MM and YYYY-MM-DD).
Mixed formats can break parsing/sorting. Prefer ISO-8601 YYYY-MM-DD consistently.
- "2024-01" → "2024-01-01"
- "2024-10" → "2024-10-01"
Run this check to find non-YYYY-MM-DD values:
Also applies to: 38714-38718, 38837-38841
🏁 Script executed:
#!/bin/bash
# List knowledge fields not matching YYYY-MM-DD
jq -r '
paths | select(.[-1]=="knowledge") as $p
| getpath($p) as $val
| if ($val|type=="string") and ($val|test("^[0-9]{4}-[0-9]{2}-[0-9]{2}$")|not)
then ($p|@json)+" => "+$val
else empty end
' resources/model-db/providers.jsonLength of output: 98
🏁 Script executed:
#!/bin/bash
# List all 'knowledge' values not in ISO-8601 YYYY-MM-DD format
jq -r '
.. | objects | .knowledge? // empty
| select(type=="string" and (test("^[0-9]{4}-[0-9]{2}-[0-9]{2}$")|not))
' resources/model-db/providers.jsonLength of output: 3903
Normalize all knowledge fields to ISO-8601 YYYY-MM-DD.
Update every "YYYY-MM" entry (e.g. "2024-01") to "YYYY-MM-01" in resources/model-db/providers.json.
🤖 Prompt for AI Agents
In resources/model-db/providers.json around lines 38205 to 38209, the
"knowledge" field is in "YYYY-MM" form ("2024-01"); update these to full
ISO-8601 dates by appending "-01" (e.g., "2024-01" -> "2024-01-01") for all
entries that use only year-month so every "knowledge" value is "YYYY-MM-DD";
perform a targeted find-and-replace for patterns matching four digits, hyphen,
two digits without a day and ensure you only change the "knowledge" fields.
| "id": "bytedance/seed-oss-36b-instruct", | ||
| "name": "ByteDance: Seed OSS 36B Instruct", | ||
| "display_name": "ByteDance: Seed OSS 36B Instruct", | ||
| "tool_call": false, | ||
| "reasoning": { | ||
| "supported": false | ||
| } | ||
| }, |
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.
🧩 Analysis chain
Missing common fields (modalities/limit) — likely to break UI/schema consumers.
These model entries omit modalities (and/or limit), unlike most others:
- bytedance/seed-oss-36b-instruct (Lines 38358–38365)
- qwen/qwen3-coder-480b-a35b-instruct (Lines 39277–39284)
- x-ai/grok-4-fast-non-reasoning (Lines 39709–39716)
- x-ai/grok-4-fast-reasoning (Lines 39718–39725)
Add minimal fields for consistency (adjust if schema differs):
{
"id": "bytedance/seed-oss-36b-instruct",
"name": "ByteDance: Seed OSS 36B Instruct",
"display_name": "ByteDance: Seed OSS 36B Instruct",
+ "modalities": {
+ "input": ["text"],
+ "output": ["text"]
+ },
+ "limit": { "context": 131072 },
"tool_call": false,
"reasoning": {
"supported": false
}
}, {
"id": "qwen/qwen3-coder-480b-a35b-instruct",
"name": "Qwen: Qwen3 Coder 480B A35B Instruct",
"display_name": "Qwen: Qwen3 Coder 480B A35B Instruct",
+ "modalities": {
+ "input": ["text"],
+ "output": ["text"]
+ },
+ "limit": { "context": 262144 },
"tool_call": false,
"reasoning": {
"supported": false
}
}, {
"id": "x-ai/grok-4-fast-non-reasoning",
"name": "x-ai/grok-4-fast-non-reasoning",
"display_name": "x-ai/grok-4-fast-non-reasoning",
+ "modalities": {
+ "input": ["text"],
+ "output": ["text"]
+ },
+ "limit": { "context": 131072 },
"tool_call": false,
"reasoning": {
"supported": false
}
}, {
"id": "x-ai/grok-4-fast-reasoning",
"name": "x-ai/grok-4-fast-reasoning",
"display_name": "x-ai/grok-4-fast-reasoning",
+ "modalities": {
+ "input": ["text"],
+ "output": ["text"]
+ },
+ "limit": { "context": 131072 },
"tool_call": false,
"reasoning": {
"supported": false
}
},If embeddings/rerankers have special modality values in your schema, align those accordingly. Please confirm required keys in the consuming code.
Also applies to: 39277-39284, 39709-39716, 39718-39725
🏁 Script executed:
#!/bin/bash
echo "Context for bytedance/seed-oss-36b-instruct:"
rg -n '"id": "bytedance/seed-oss-36b-instruct"' -C5 resources/model-db/providers.json
echo "Context for qwen/qwen3-coder-480b-a35b-instruct:"
rg -n '"id": "qwen/qwen3-coder-480b-a35b-instruct"' -C5 resources/model-db/providers.json
echo "Sample modalities usage in file:"
rg -n '"modalities":' -C3 resources/model-db/providers.json | head -n 20
echo "Sample limit usage in file:"
rg -n '"limit":' -C3 resources/model-db/providers.json | head -n 20Length of output: 3224
🏁 Script executed:
#!/bin/bash
echo "Context for x-ai/grok-4-fast-non-reasoning:"
rg -n '"id": "x-ai/grok-4-fast-non-reasoning"' -C5 resources/model-db/providers.json
echo "Context for x-ai/grok-4-fast-reasoning:"
rg -n '"id": "x-ai/grok-4-fast-reasoning"' -C5 resources/model-db/providers.jsonLength of output: 883
Add missing modalities and limit fields to four provider entries
- bytedance/seed-oss-36b-instruct (resources/model-db/providers.json 38358–38365)
- qwen/qwen3-coder-480b-a35b-instruct (39277–39284)
- x-ai/grok-4-fast-non-reasoning (39709–39716)
- x-ai/grok-4-fast-reasoning (39718–39725)
Example addition (adjust context/output values per model):
"modalities": { "input": ["text"], "output": ["text"] },
"limit": { "context": 131072 }Include limit.output if required by your schema.
🤖 Prompt for AI Agents
In resources/model-db/providers.json around lines 38358–38365
(bytedance/seed-oss-36b-instruct), 39277–39284
(qwen/qwen3-coder-480b-a35b-instruct), 39709–39716
(x-ai/grok-4-fast-non-reasoning) and 39718–39725 (x-ai/grok-4-fast-reasoning)
the provider objects are missing the modalities and limit fields; add a
"modalities" object (e.g. "modalities": { "input": ["text"], "output": ["text"]
}) and a "limit" object (e.g. "limit": { "context": 131072 } ), adjusting the
context and output sizes per model as needed, and include "limit.output" if your
schema requires it; ensure proper JSON commas and indentation so the new fields
integrate with the existing object.
| "limit": { | ||
| "context": 163800 | ||
| }, | ||
| "temperature": false, | ||
| "tool_call": false, |
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.
Fix context limit typos (will affect token validation/UI).
The following context values look mistyped:
- 163800 → 163840
- 1047576 → 1048576 (three places)
Apply this diff:
- "limit": {
- "context": 163800
- },
+ "limit": {
+ "context": 163840
+ },- "limit": {
- "context": 1047576,
- "output": 32768
- },
+ "limit": {
+ "context": 1048576,
+ "output": 32768
+ },- "limit": {
- "context": 1047576,
- "output": 32768
- },
+ "limit": {
+ "context": 1048576,
+ "output": 32768
+ },- "limit": {
- "context": 1047576,
- "output": 32768
- },
+ "limit": {
+ "context": 1048576,
+ "output": 32768
+ },Also applies to: 38737-38741, 38770-38774, 38803-38807
🤖 Prompt for AI Agents
In resources/model-db/providers.json around lines 38434-38438 (and also at
38737-38741, 38770-38774, 38803-38807), there are typos in context limit values:
change 163800 to 163840, and change any occurrences of 1047576 to 1048576 (three
places). Edit those numeric values exactly so the JSON context limits are
corrected to 163840 and 1048576 respectively, preserving surrounding structure
and formatting.
| variant="outline" | ||
| size="icon" | ||
| class="h-8 w-8 rounded-full" | ||
| class="h-8 w-8" |
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.
Inconsistent button sizes for increase/decrease controls.
The decrease button (line 74) uses h-8 w-8 while the increase button (line 106) uses h-7 w-7. For visual consistency and better UX, both buttons should have the same size.
Apply this diff to standardize the sizes:
<Button
variant="outline"
size="icon"
- class="h-7 w-7"
+ class="h-8 w-8"
@click="increaseWebContentLimit"
:disabled="webContentLengthLimit >= 10000"
>Also applies to: 106-106
🤖 Prompt for AI Agents
In src/renderer/settings/components/CommonSettings.vue lines 74 and 106, the
decrease button uses class "h-8 w-8" while the increase button uses "h-7 w-7",
causing inconsistent sizes; update the increase button on line 106 to use "h-8
w-8" so both controls match, ensuring visual consistency.
…deepchat into feat/split-settings-window
split settings window into single window
Summary by CodeRabbit
New Features
Style
Refactor