Skip to content

Conversation

@deepinfect
Copy link
Collaborator

@deepinfect deepinfect commented Oct 14, 2025

Summary by CodeRabbit

  • New Features

    • Click-to-toggle headers for multiple knowledge panels; Dify auto-opens via route.
    • Data settings: buttons for backup/import/reset with clearer disabled states and updated dialogs.
    • MCP: unified enable card, collapsible advanced settings, and streamlined custom registry dialog.
    • Prompt settings: selectable default prompt and dedicated editor.
  • Refactor

    • Simplified Shortcut settings layout and recording UI.
    • Streamlined Knowledge Base header and removed add-knowledge flow.
  • Style

    • Consistent padding/heights, updated textarea and card visuals, denser servers grid.
  • Chores

    • Fixed JSON formatting.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 14, 2025

Note

Other AI code review bot(s) detected

CodeRabbit 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.

Walkthrough

Refactors multiple settings UI components: header click-to-toggle behavior, padding/layout shifts, dialog and button conversions, MCP settings and marketplace rework, prompt and shortcut UI redesigns, shared Textarea tweak, and a trailing JSON syntax fix in resources/model-db/providers.json. (≤50 words)

Changes

Cohort / File(s) Summary
JSON syntax fix
resources/model-db/providers.json
Removed an extraneous trailing comma/brace to correct JSON termination; no data changes.
Knowledge headers: click-to-toggle + layout
src/renderer/settings/components/BuiltinKnowledgeSettings.vue, src/renderer/settings/components/DifyKnowledgeSettings.vue, src/renderer/settings/components/FastGptKnowledgeSettings.vue, src/renderer/settings/components/RagflowKnowledgeSettings.vue, src/renderer/settings/components/KnowledgeBaseSettings.vue
Converted header areas to clickable containers that toggle panels; replaced chevron Buttons with inline Icons; added hover states; Dify auto-opens via route watcher; KnowledgeBase header simplified and add-dialog flow removed.
General settings padding/layout
src/renderer/settings/components/CommonSettings.vue, src/renderer/settings/components/DisplaySettings.vue
Moved ScrollArea padding inward to inner containers; standardized row heights and control sizes; removed legacy dialog state and some horizontal padding classes.
Data settings: buttons & dialogs
src/renderer/settings/components/DataSettings.vue
Reworked actions to Button-driven triggers (backup/import/reset), adjusted dialog triggers and controls, refined heights and disabled states, preserved import/reset logic.
MCP settings overhaul
src/renderer/settings/components/McpSettings.vue
Reorganized into a unified MCP card with Collapsible advanced registry settings, new custom-source Dialog flow, new state vars (npmSourceExpanded, customSourceDialogOpen), and refreshed handlers/UI layout.
MCP marketplace & cards
src/renderer/settings/components/McpBuiltinMarket.vue, src/renderer/src/components/mcp-config/components/McpServerCard.vue, src/renderer/src/components/mcp-config/components/McpServers.vue
Header/layout simplifications, added Separator, button variant tweak for install, card visual simplification (badges removed, footer border), and grid column count increased (sm:3, lg:4).
Prompt settings redesign
src/renderer/settings/components/PromptSetting.vue
Replaced header and system prompts panel with separators, default Select, new Textarea editor area, preserved reset/delete via dialogs, added window-drag utility classes, updated imports (Textarea, Separator).
Shortcut settings layout
src/renderer/settings/components/ShortcutSettings.vue
Simplified header, swapped ScrollArea for flex layout, reorganized recording UI with KbdGroup and formattedTempShortcut, moved action/status controls to a separate area.
Shared Textarea tweak
src/shadcn/components/ui/textarea/Textarea.vue
Reordered SFC blocks (script → template) and removed a focus-visible class token in class list; styling adjusted slightly, behavior unchanged.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant H as Knowledge Header
  participant P as Panel (Collapsible)
  participant R as Router

  U->>H: Click header container
  H->>P: toggle isOpen

  Note over R,H: Dify only
  R-->>H: route subtab == "dify"
  H->>P: open
Loading
sequenceDiagram
  participant U as User
  participant M as MCP Settings
  participant A as Advanced Collapsible
  participant D as Custom Source Dialog
  participant N as Registry Service

  U->>M: Toggle MCP enable
  U->>A: Expand advanced
  U->>M: Refresh registry
  M->>N: fetch registry
  N-->>M: registry info

  U->>D: Open custom source
  U->>D: Save / Clear / Redetect
  D->>N: apply/clear/detect
  N-->>D: result
  D->>M: Close and update UI
Loading
sequenceDiagram
  participant U as User
  participant DS as Data Settings
  participant ID as Import Dialog
  participant S as Store/Importer

  U->>DS: Click "导入数据"
  DS->>ID: open import dialog
  U->>ID: choose mode + confirm
  ID->>S: trigger import(mode)
  S-->>DS: import result
  DS->>U: show status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • zerob13

Poem

A rabbit taps the headers — click, unfold, delight,
Panels spring like clover in the soft interface light.
MCPs and prompts now tidy, paddings snug and neat,
A JSON brace found home — the file ends clean and sweet.
Hoppity, hop — the UI hops to a brighter beat! 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat(settings): ui optimize” accurately reflects the primary purpose of the pull request, which is to optimize the user interface across various settings components. It is concise and clearly indicates the scope as settings UI improvements without extraneous detail. Even though it uses a commit-style prefix, it succinctly conveys the key change for anyone scanning the history.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/settings-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@zerob13
Copy link
Collaborator

zerob13 commented Oct 14, 2025

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ 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

Comment on lines +70 to +76
<!-- 导入数据 -->
<Dialog v-model:open="isImportDialogOpen">
<DialogTrigger as-child>
<Button
variant="outline"
@click="syncStore.startBackup"
:disabled="!syncStore.syncEnabled"

Choose a reason for hiding this comment

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

P1 Badge Import dialog button triggers backup instead of only opening dialog

The new import button calls syncStore.startBackup even though it is already wrapped in a DialogTrigger. Clicking “Import Data” now launches a backup immediately before the user confirms the import, which is unrelated and can block the import flow (e.g. the button is disabled while a backup runs). The handler should only open the dialog and let the user choose how to import.

Useful? React with 👍 / 👎.

Comment on lines 124 to 128
<Button
variant="destructive"
class="w-48"
@click="syncStore.startBackup"
:disabled="!syncStore.syncEnabled || syncStore.isBackingUp"

Choose a reason for hiding this comment

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

P1 Badge Reset data trigger erroneously launches backup

The trigger button that opens the reset confirmation dialog now calls syncStore.startBackup. As a result, clicking “Reset Data” starts a backup and may disable the reset controls (isBackingUp), preventing the user from proceeding with the intended reset. The trigger should not perform backup operations; it should simply open the confirmation dialog.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (11)
src/renderer/settings/components/RagflowKnowledgeSettings.vue (1)

21-25: Consider click event propagation on the Switch.

The Switch is inside a clickable header area. Clicking the switch will both toggle the switch AND trigger the header's panel toggle, which may not be the intended behavior.

Add @click.stop to the Switch's wrapper to prevent event bubbling:

-              <Switch
+              <Switch
+                @click.stop
                 :model-value="isRagflowMcpEnabled"
                 :disabled="!mcpStore.mcpEnabled"
                 @update:model-value="toggleRagflowMcpServer"
               />

Alternatively, wrap the Switch in a div with @click.stop:

+              <div @click.stop>
                 <Switch
                   :model-value="isRagflowMcpEnabled"
                   :disabled="!mcpStore.mcpEnabled"
                   @update:model-value="toggleRagflowMcpServer"
                 />
+              </div>
src/renderer/settings/components/FastGptKnowledgeSettings.vue (2)

52-54: Inconsistent Switch API usage.

This Switch uses :checked with @update:checked, while the Switch at lines 21-25 uses :model-value with @update:model-value. Use consistent API across the component.

Apply this diff to standardize on model-value:

                 <Switch
-                  :checked="config.enabled === true"
+                  :model-value="config.enabled === true"
                   size="sm"
-                  @update:checked="toggleConfigEnabled(index, $event)"
+                  @update:model-value="toggleConfigEnabled(index, $event)"
                 />

21-25: Consider click event propagation on the Switch.

The Switch is inside a clickable header. Clicking it will trigger both the switch toggle AND the header's panel toggle.

Wrap the Switch or its TooltipProvider in a div with @click.stop to prevent event bubbling:

+              <div @click.stop>
               <TooltipProvider>
                 <Tooltip :delay-duration="200">
                   <TooltipTrigger>
                     <Switch
                       :model-value="isFastGptMcpEnabled"
                       :disabled="!mcpStore.mcpEnabled"
                       @update:model-value="toggleFastGptMcpServer"
                     />
                   </TooltipTrigger>
                   <TooltipContent v-if="!mcpStore.mcpEnabled">
                     <p>{{ t('settings.mcp.enableToAccess') }}</p>
                   </TooltipContent>
                 </Tooltip>
               </TooltipProvider>
+              </div>
src/renderer/settings/components/DifyKnowledgeSettings.vue (2)

237-239: Move import to the top of the script section.

The useRoute import is placed after other imports and code, violating typical import organization conventions. All imports should be at the top of the script section.

Move the import to line 208 (after other imports):

 import {
   Tooltip,
   TooltipContent,
   TooltipProvider,
   TooltipTrigger
 } from '@shadcn/components/ui/tooltip'
+import { useRoute } from 'vue-router'

 // 对话框状态
 const isDifyConfigDialogOpen = ref(false)
 
 // ... rest of code ...
 
 const { t } = useI18n()
 const mcpStore = useMcpStore()
 const { toast } = useToast()
+const route = useRoute()

 // 对话框状态
 const isDifyConfigPanelOpen = ref(false)
 const isEditing = ref(false)
-import { useRoute } from 'vue-router'
-
-const route = useRoute()

21-25: Consider click event propagation on the Switch.

The Switch inside the clickable header may trigger both the switch toggle and the header's panel toggle when clicked.

Wrap the TooltipProvider in a div with @click.stop to prevent event bubbling:

+              <div @click.stop>
               <TooltipProvider>
                 <Tooltip :delay-duration="200">
                   <TooltipTrigger>
                     <Switch
                       :model-value="isDifyMcpEnabled"
                       :disabled="!mcpStore.mcpEnabled"
                       @update:model-value="toggleDifyMcpServer"
                     />
                   </TooltipTrigger>
                   <TooltipContent v-if="!mcpStore.mcpEnabled">
                     <p>{{ t('settings.mcp.enableToAccess') }}</p>
                   </TooltipContent>
                 </Tooltip>
               </TooltipProvider>
+              </div>
src/renderer/settings/components/BuiltinKnowledgeSettings.vue (1)

23-27: Consider click event propagation on the Switch.

The Switch inside the clickable header may trigger both the switch toggle and the header's panel toggle when clicked.

Wrap the TooltipProvider in a div with @click.stop:

+              <div @click.stop>
               <TooltipProvider>
                 <Tooltip :delay-duration="200">
                   <TooltipTrigger>
                     <Switch
                       :model-value="isBuiltinMcpEnabled"
                       :disabled="!mcpStore.mcpEnabled"
                       @update:model-value="toggleBuiltinMcpServer"
                     />
                   </TooltipTrigger>
                   <TooltipContent v-if="!mcpStore.mcpEnabled">
                     <p>{{ t('settings.mcp.enableToAccess') }}</p>
                   </TooltipContent>
                 </Tooltip>
               </TooltipProvider>
+              </div>
src/renderer/settings/components/PromptSetting.vue (1)

286-314: Fix template parse error: unexpected (breaks CI)

CI reports an unexpected closing tag at Line 312. To unblock, replace the inner ScrollArea with a simple container (keeps scrolling via overflow-y) or ensure proper pairing. This minimal patch removes the offending closing tag.

Apply this diff:

-        <ScrollArea class="flex-1 overflow-hidden">
+        <div class="flex-1 overflow-y-auto">
           <div class="px-6 py-4 space-y-4">
             <!-- 名称 -->
             <div class="space-y-2">
               <Label for="system-prompt-name" class="text-sm font-medium">{{
                 t('promptSetting.name')
               }}</Label>
               <Input
                 id="system-prompt-name"
                 v-model="systemPromptForm.name"
                 :placeholder="t('promptSetting.namePlaceholder')"
               />
             </div>

           <!-- 内容 -->
           <div class="space-y-2">
             <Label for="system-prompt-content" class="text-sm font-medium">{{
               t('promptSetting.promptContent')
             }}</Label>
             <Textarea
               id="system-prompt-content"
               v-model="systemPromptForm.content"
               class="w-full h-64"
               :placeholder="t('promptSetting.contentPlaceholder')"
             ></Textarea>
           </div>
-        </ScrollArea>
+        </div>

If you prefer to keep ScrollArea styling, reintroduce it after fixing the tag pairing locally and re-run formatting to verify the parser accepts it.

src/renderer/settings/components/DisplaySettings.vue (1)

408-411: Type the computed setter parameter (strict TS).

Avoid implicit any on value.

-const fontSizeLevel = computed({
-  get: () => settingsStore.fontSizeLevel,
-  set: (value) => settingsStore.updateFontSizeLevel(value)
-})
+const fontSizeLevel = computed<number>({
+  get: () => settingsStore.fontSizeLevel,
+  set: (value: number) => settingsStore.updateFontSizeLevel(value)
+})
src/renderer/settings/components/CommonSettings.vue (3)

16-18: Invalid height utility: h-8! should be !h-8 or h-8.

Current class won’t take effect.

-              <SelectTrigger class="px-3 h-8! text-sm border-border hover:bg-accent">
+              <SelectTrigger class="px-3 !h-8 text-sm border-border hover:bg-accent">

165-167: Invalid height utility here as well.

Fix the height utility for consistency.

-            <SelectTrigger class="h-8! text-sm border-border hover:bg-accent">
+            <SelectTrigger class="!h-8 text-sm border-border hover:bg-accent">

176-198: UI clipping risk: multi-line content constrained by h-10.

The custom proxy block contains an input and an error row; h-10 will clip or overlap content. Remove fixed height on multi-line containers.

-      <div v-if="selectedProxyMode === 'custom'" class="flex flex-col gap-2 h-10">
+      <div v-if="selectedProxyMode === 'custom'" class="flex flex-col gap-2">
🧹 Nitpick comments (10)
src/renderer/settings/components/PromptSetting.vue (2)

410-416: Use the shared Textarea component for consistency

Replace the native <textarea> with the shadcn Textarea (already imported) to keep styles/behaviors consistent across the app.

Apply this diff:

-              <div>
-                <textarea
-                  v-model="form.content"
-                  class="w-full min-h-48 rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 font-mono resize-y"
-                  :placeholder="t('promptSetting.contentPlaceholder')"
-                ></textarea>
+              <div>
+                <Textarea
+                  v-model="form.content"
+                  class="w-full min-h-48 font-mono resize-y"
+                  :placeholder="t('promptSetting.contentPlaceholder')"
+                />
                 <p class="text-xs text-muted-foreground mt-2">
                   {{ t('promptSetting.contentTip', { openBrace: '{', closeBrace: '}' }) }}
                 </p>
               </div>

22-27: Use English for comments in TS/Vue files

Several template comments are Chinese. Please switch comments to English to match repo guidelines.

As per coding guidelines

Also applies to: 48-50, 300-304

src/renderer/settings/components/DisplaySettings.vue (1)

425-429: Logs should be in English.

Guideline: use English for logs/comments. Replace the Chinese log.
[coding_guidelines]

-  console.log('准备切换投屏保护状态:', value)
+  console.log('Preparing to toggle content protection:', value)
src/renderer/settings/components/CommonSettings.vue (2)

70-113: Minor UI consistency: control heights differ.

Minus button is h-8, plus button is h-7. Align for consistent tap targets.

-          <Button
+          <Button
             variant="outline"
             size="icon"
-            class="h-8 w-8"
+            class="h-8 w-8"
             @click="decreaseWebContentLimit"
             :disabled="webContentLengthLimit <= 0"
           >
             <Icon icon="lucide:minus" class="h-3 w-3" />
           </Button>
...
-          <Button
+          <Button
             variant="outline"
             size="icon"
-            class="h-7 w-7"
+            class="h-8 w-8"
             @click="increaseWebContentLimit"
             :disabled="webContentLengthLimit >= 10000"
           >

428-864: Use English for logs and comments.

Several logs and comments are in Chinese (e.g., Lines 538, 608, 678, 710, 749, 771). Convert to English to follow project guidelines.
[coding_guidelines]

src/renderer/settings/components/McpSettings.vue (4)

217-236: Registry refresh UX: disable trigger and show progress.

You already guard with refreshing; good. Consider also adding aria-busy and a toast only on change to reduce noise.


258-304: Registry validation via HEAD may be unreliable; test endpoint/package choice.

  • Many registries don’t support HEAD on package metadata; GET with small response is more robust.
  • Using a niche package (tiny-runtime-injector) risks 404s on mirrors. Prefer ubiquitous packages (e.g., react, lodash) or a ping endpoint (/-/ping) if supported.
-    const testPackage = 'tiny-runtime-injector'
-    const testUrl = `${normalizedRegistry}${testPackage}`
+    const testPackage = 'react' // ubiquitous package
+    const testUrl = `${normalizedRegistry}${testPackage}`
-    const response = await fetch(testUrl, {
-      method: 'HEAD',
+    const response = await fetch(testUrl, {
+      method: 'GET',
+      headers: { accept: 'application/json' },
       signal: AbortSignal.timeout(10000)
     })

Also confirm your runtime supports AbortSignal.timeout; if not, polyfill with AbortController and manual timeout.


318-327: Normalize and persist normalized registry value.

After setCustomNpmRegistry, ensure the stored value has trailing slash to avoid duplicates.

-    await mcpStore.setCustomNpmRegistry(registry)
+    await mcpStore.setCustomNpmRegistry(normalizeNpmRegistryUrl(registry))

354-364: Dialog close duplication.

customSourceDialogOpen.value = false appears in both try and catch; move after the try/catch to DRY.

-      customSourceDialogOpen.value = false
     } catch (detectError) {
...
-      customSourceDialogOpen.value = false
     }
+    customSourceDialogOpen.value = false
src/renderer/settings/components/DataSettings.vue (1)

240-344: Use English for logs.

E.g., console.error('重置数据失败:', error) should be English.
[coding_guidelines]

-    console.error('重置数据失败:', error)
+    console.error('Failed to reset data:', error)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84d1a35 and 715f9c0.

📒 Files selected for processing (16)
  • resources/model-db/providers.json (1 hunks)
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/CommonSettings.vue (9 hunks)
  • src/renderer/settings/components/DataSettings.vue (3 hunks)
  • src/renderer/settings/components/DifyKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/DisplaySettings.vue (2 hunks)
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/KnowledgeBaseSettings.vue (1 hunks)
  • src/renderer/settings/components/McpBuiltinMarket.vue (5 hunks)
  • src/renderer/settings/components/McpSettings.vue (5 hunks)
  • src/renderer/settings/components/PromptSetting.vue (8 hunks)
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/ShortcutSettings.vue (2 hunks)
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue (3 hunks)
  • src/renderer/src/components/mcp-config/components/McpServers.vue (2 hunks)
  • src/shadcn/components/ui/textarea/Textarea.vue (1 hunks)
🧰 Additional context used
📓 Path-based instructions (17)
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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.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/src/components/mcp-config/components/McpServers.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.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/src/components/mcp-config/components/McpServers.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for all logs and comments

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)

Use PascalCase for TypeScript types and classes

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/src/components/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Organize UI components by feature within src/renderer/src/

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/src/**

📄 CodeRabbit inference engine (AGENTS.md)

Place Vue 3 app source under src/renderer/src (components, stores, views, i18n, lib)

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/src/**/*.{vue,ts}

📄 CodeRabbit inference engine (AGENTS.md)

All user-facing strings must use vue-i18n ($t/keys) rather than hardcoded literals

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
**/*.{ts,tsx,js,jsx,vue,css,scss,md,json,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

Prettier style: single quotes, no semicolons, print width 100; run pnpm run format

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • resources/model-db/providers.json
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx,vue}: Use OxLint for JS/TS code; keep lint clean
Use camelCase for variables and functions
Use SCREAMING_SNAKE_CASE for constants

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue component files in PascalCase (e.g., ChatInput.vue)

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
{build,resources,out,dist}/**

📄 CodeRabbit inference engine (AGENTS.md)

Treat build outputs and assets (build/, resources/, out/, dist/) as generated artifacts; do not hand-edit

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/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/McpSettings.vue
🪛 GitHub Actions: PR Check
src/renderer/settings/components/PromptSetting.vue

[error] 312-312: Vue template syntax error: Unexpected closing tag "ScrollArea" in PromptSetting.vue.


[error] 310-314: HTML / Vue template parse error reported during Prettier check: Unexpected closing tag may indicate a mismatched or missing opening tag.

🔇 Additional comments (9)
resources/model-db/providers.json (1)

39874-39877: Valid JSON fix applied correctly.

Trailing comma removal restores proper JSON syntax; no further action needed.

src/renderer/src/components/mcp-config/components/McpServers.vue (1)

262-279: Verify 3-up layout at the sm breakpoint

Jumping from 1→3 columns as soon as we hit the sm breakpoint (~640 px) shrinks each McpServerCard to ~200 px width. Please double-check on real content (buttons, tags, tool counts) that nothing overflows or wraps awkwardly—if it does, consider keeping sm:grid-cols-2 and moving the 3rd column to md.

Also applies to: 294-313

src/renderer/settings/components/McpBuiltinMarket.vue (4)

3-13: LGTM! Clean header restructure.

The refactored header with sticky positioning and stacked layout for the title and "powered by" link creates a clearer visual hierarchy. The sticky positioning at the top improves usability when scrolling through market items.


29-41: LGTM! Cleaner styling with proper separation.

The simplified styling and addition of the Separator component creates a cleaner, more modern appearance while maintaining clear visual distinction between sections.


72-72: LGTM! Verify the visual appearance.

The button variant change to 'outline' for non-installed servers is a reasonable UI optimization. The logic is correct and clear.

Consider verifying the visual appearance of the outline variant to ensure it provides appropriate emphasis for the install action in the context of the market cards.


127-127: LGTM! Proper component import.

The Separator import is correctly added and consistent with other shadcn component imports in the file.

src/renderer/src/components/mcp-config/components/McpServerCard.vue (1)

142-142: LGTM: Card layout improvements.

The switch to a vertical flex layout with card background and simplified hover effects improves visual hierarchy and aligns with the design system.

src/renderer/settings/components/KnowledgeBaseSettings.vue (1)

2-23: LGTM: Simplified layout and explicit component rendering.

The refactor improves code clarity by:

  • Removing the complex dialog flow for adding knowledge bases
  • Explicitly rendering each knowledge settings component
  • Conditionally showing BuiltinKnowledgeSettings based on system support
  • Simplifying the header and spacing for better visual hierarchy

These changes make the component more maintainable and easier to understand.

src/shadcn/components/ui/textarea/Textarea.vue (1)

22-27: Textarea component usage looks correct

v-model wiring via useVModel and class composition with cn are consistent; no behavior risk spotted.

Comment on lines +3 to +6
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleBuiltinConfigPanel"
>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix cursor and add accessibility attributes to clickable header.

The header div has cursor-default but is clickable. Add proper cursor style and accessibility attributes.

Apply this diff:

     <div
-      class="flex items-center p-4 hover:bg-accent cursor-default"
+      class="flex items-center p-4 hover:bg-accent cursor-pointer"
+      role="button"
+      tabindex="0"
       @click="toggleBuiltinConfigPanel"
+      @keydown.enter="toggleBuiltinConfigPanel"
+      @keydown.space.prevent="toggleBuiltinConfigPanel"
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleBuiltinConfigPanel"
>
<div
class="flex items-center p-4 hover:bg-accent cursor-pointer"
role="button"
tabindex="0"
@click="toggleBuiltinConfigPanel"
@keydown.enter="toggleBuiltinConfigPanel"
@keydown.space.prevent="toggleBuiltinConfigPanel"
>
🤖 Prompt for AI Agents
In src/renderer/settings/components/BuiltinKnowledgeSettings.vue around lines 3
to 6, the header div is clickable but uses cursor-default and lacks
accessibility attributes; change the cursor to cursor-pointer, add
role="button", tabindex="0", and aria-expanded (bound to the panel open state)
and aria-controls (pointing to the panel ID), and wire a keyboard handler
(keydown for Enter/Space) that invokes the same toggleBuiltinConfigPanel method
so keyboard users can activate the header.

Comment on lines +25 to +31
<Input
v-model="syncFolderPath"
:disabled="!syncStore.syncEnabled"
class="cursor-pointer h-8!"
@click="syncStore.selectSyncFolder"
/>
<Button
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Invalid height utility: h-8! on Input.

Use !h-8 or h-8.

-          <Input
+          <Input
             v-model="syncFolderPath"
             :disabled="!syncStore.syncEnabled"
-            class="cursor-pointer h-8!"
+            class="cursor-pointer !h-8"
             @click="syncStore.selectSyncFolder"
           />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Input
v-model="syncFolderPath"
:disabled="!syncStore.syncEnabled"
class="cursor-pointer h-8!"
@click="syncStore.selectSyncFolder"
/>
<Button
<Input
v-model="syncFolderPath"
:disabled="!syncStore.syncEnabled"
class="cursor-pointer !h-8"
@click="syncStore.selectSyncFolder"
/>
<Button
🤖 Prompt for AI Agents
In src/renderer/settings/components/DataSettings.vue around lines 25 to 31, the
Input component uses an invalid Tailwind utility class "h-8!"; replace it with a
valid class like "!h-8" (to force-important) or just "h-8" depending on whether
you need to override other styles, i.e. update the class attribute to use one of
those valid utilities.

Comment on lines +3 to +6
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleDifyConfigPanel"
>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix cursor and add accessibility attributes to clickable header.

The header div has cursor-default but is clickable. Add proper cursor style and accessibility attributes.

Apply this diff:

     <div
-      class="flex items-center p-4 hover:bg-accent cursor-default"
+      class="flex items-center p-4 hover:bg-accent cursor-pointer"
+      role="button"
+      tabindex="0"
       @click="toggleDifyConfigPanel"
+      @keydown.enter="toggleDifyConfigPanel"
+      @keydown.space.prevent="toggleDifyConfigPanel"
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleDifyConfigPanel"
>
<div
class="flex items-center p-4 hover:bg-accent cursor-pointer"
role="button"
tabindex="0"
@click="toggleDifyConfigPanel"
@keydown.enter="toggleDifyConfigPanel"
@keydown.space.prevent="toggleDifyConfigPanel"
>
🤖 Prompt for AI Agents
In src/renderer/settings/components/DifyKnowledgeSettings.vue around lines 3 to
6, the header div is clickable but uses cursor-default and lacks accessibility
attributes; change the class to use cursor-pointer instead of cursor-default,
add role="button" and tabindex="0", wire keyboard activation by adding
@keydown.enter.prevent="toggleDifyConfigPanel" and
@keydown.space.prevent="toggleDifyConfigPanel", and expose the panel state via
aria-expanded (e.g. :aria-expanded="isDifyConfigPanelOpen" or the component's
equivalent boolean) so screen readers can detect the toggle state.

Comment on lines +15 to 16
<SelectTrigger class="h-8!">
<SelectValue :placeholder="t('settings.common.languageSelect')" />
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Invalid height utility: use !h-8 or h-8 instead of h-8!.

h-8! won’t be parsed by Tailwind (important modifier is prefixed as !h-8). Height won’t apply.

Apply:

-            <SelectTrigger class="h-8!">
+            <SelectTrigger class="!h-8">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<SelectTrigger class="h-8!">
<SelectValue :placeholder="t('settings.common.languageSelect')" />
<SelectTrigger class="!h-8">
<SelectValue :placeholder="t('settings.common.languageSelect')" />
🤖 Prompt for AI Agents
In src/renderer/settings/components/DisplaySettings.vue around lines 15 to 16,
the class "h-8!" is an invalid Tailwind utility (the important modifier must be
prefixed), so replace it with either "!h-8" if you need to force the height or
"h-8" if not; update the SelectTrigger class attribute accordingly to use the
correct utility.

Comment on lines +3 to +6
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleFastGptConfigPanel"
>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix cursor and add accessibility attributes to clickable header.

The header div has cursor-default but is clickable. This provides poor UX and lacks proper accessibility attributes for keyboard navigation.

Apply this diff:

     <div
-      class="flex items-center p-4 hover:bg-accent cursor-default"
+      class="flex items-center p-4 hover:bg-accent cursor-pointer"
+      role="button"
+      tabindex="0"
       @click="toggleFastGptConfigPanel"
+      @keydown.enter="toggleFastGptConfigPanel"
+      @keydown.space.prevent="toggleFastGptConfigPanel"
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleFastGptConfigPanel"
>
<div
class="flex items-center p-4 hover:bg-accent cursor-pointer"
role="button"
tabindex="0"
@click="toggleFastGptConfigPanel"
@keydown.enter="toggleFastGptConfigPanel"
@keydown.space.prevent="toggleFastGptConfigPanel"
>
🤖 Prompt for AI Agents
In src/renderer/settings/components/FastGptKnowledgeSettings.vue around lines 3
to 6, the header div is clickable but uses cursor-default and lacks
keyboard/accessibility attributes; change cursor-default to cursor-pointer, add
role="button" and tabindex="0", add key handlers for Enter and Space (e.g.,
@keydown.enter="toggleFastGptConfigPanel" and
@keydown.space.prevent="toggleFastGptConfigPanel"), and add an aria-expanded
attribute bound to the boolean state that controls the panel (use the existing
panel-open/computed ref or create one) so screen readers and keyboard users can
discover and operate the toggle.

Comment on lines +3 to +6
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleRagflowConfigPanel"
>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix cursor and add accessibility attributes to clickable header.

The header div has cursor-default but is clickable via @click. This provides poor UX as users won't see a pointer cursor. Additionally, the clickable div lacks proper accessibility attributes.

Apply this diff to fix the cursor style and add accessibility:

     <div
-      class="flex items-center p-4 hover:bg-accent cursor-default"
+      class="flex items-center p-4 hover:bg-accent cursor-pointer"
+      role="button"
+      tabindex="0"
       @click="toggleRagflowConfigPanel"
+      @keydown.enter="toggleRagflowConfigPanel"
+      @keydown.space.prevent="toggleRagflowConfigPanel"
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
class="flex items-center p-4 hover:bg-accent cursor-default"
@click="toggleRagflowConfigPanel"
>
<div
class="flex items-center p-4 hover:bg-accent cursor-pointer"
role="button"
tabindex="0"
@click="toggleRagflowConfigPanel"
@keydown.enter="toggleRagflowConfigPanel"
@keydown.space.prevent="toggleRagflowConfigPanel"
>
🤖 Prompt for AI Agents
In src/renderer/settings/components/RagflowKnowledgeSettings.vue around lines 3
to 6, the header div is clickable but uses cursor-default and has no
accessibility attributes; change the class to use cursor-pointer, add
tabindex="0" and role="button", wire keyboard activation by handling Enter and
Space keydown to call the same toggleRagflowConfigPanel handler, and add ARIA
attributes such as :aria-expanded="isRagflowConfigOpen" and
aria-controls="<id-of-panel>" (replace with the panel's id) so screen readers
and keyboard users can recognize and interact with the control.

Comment on lines 57 to 60
<div
v-if="recordingShortcutId === shortcut.id"
class="mt-1 text-xs"
:class="shortcutError ? 'text-destructive' : 'text-muted-foreground'"
class="ml-auto flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100"
:class="{ 'opacity-100': recordingShortcutId === shortcut.id }"
>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Restore keyboard-visible controls for edit/clear buttons.

Hiding the action group with opacity-0 and only revealing it on group-hover makes the buttons stay invisible when focused via keyboard, so users tabbing into the control never see what they’re on. Please add group-focus-within:opacity-100 (or equivalent) so focus also reveals the actions.

-              <div
-                class="ml-auto flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100"
+              <div
+                class="ml-auto flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
v-if="recordingShortcutId === shortcut.id"
class="mt-1 text-xs"
:class="shortcutError ? 'text-destructive' : 'text-muted-foreground'"
class="ml-auto flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100"
:class="{ 'opacity-100': recordingShortcutId === shortcut.id }"
>
<div
class="ml-auto flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100"
:class="{ 'opacity-100': recordingShortcutId === shortcut.id }"
>
🤖 Prompt for AI Agents
In src/renderer/settings/components/ShortcutSettings.vue around lines 57 to 60,
the action button group is hidden with opacity-0 and only shown on hover, which
prevents keyboard-focused users from seeing the controls; update the class list
to also reveal the group when focused by keyboard (e.g., add
group-focus-within:opacity-100 or the equivalent focus-related Tailwind class)
so that tabbing into the control toggles opacity to 100 and keyboard users can
access the edit/clear buttons.

Comment on lines +198 to +209
<p
ref="descriptionRef"
class="text-xs text-secondary-foreground cursor-pointer overflow-hidden leading-5 break-all mb-2"
:class="[
!isDescriptionExpanded ? 'line-clamp-1' : '',
needsExpansion ? 'hover:text-foreground transition-colors' : ''
]"
style="min-height: 1rem"
@click="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
>
{{ fullDescription }}
</p>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add accessibility attributes to clickable description.

The description paragraph is clickable when needsExpansion is true, but it lacks proper accessibility attributes for keyboard navigation and screen readers.

Apply this diff:

       <p
         ref="descriptionRef"
         class="text-xs text-secondary-foreground cursor-pointer overflow-hidden leading-5 break-all mb-2"
         :class="[
           !isDescriptionExpanded ? 'line-clamp-1' : '',
           needsExpansion ? 'hover:text-foreground transition-colors' : ''
         ]"
         style="min-height: 1rem"
+        :role="needsExpansion ? 'button' : undefined"
+        :tabindex="needsExpansion ? 0 : undefined"
+        :aria-expanded="needsExpansion ? isDescriptionExpanded : undefined"
         @click="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
+        @keydown.enter="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
+        @keydown.space.prevent="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
       >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p
ref="descriptionRef"
class="text-xs text-secondary-foreground cursor-pointer overflow-hidden leading-5 break-all mb-2"
:class="[
!isDescriptionExpanded ? 'line-clamp-1' : '',
needsExpansion ? 'hover:text-foreground transition-colors' : ''
]"
style="min-height: 1rem"
@click="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
>
{{ fullDescription }}
</p>
<p
ref="descriptionRef"
class="text-xs text-secondary-foreground cursor-pointer overflow-hidden leading-5 break-all mb-2"
:class="[
!isDescriptionExpanded ? 'line-clamp-1' : '',
needsExpansion ? 'hover:text-foreground transition-colors' : ''
]"
style="min-height: 1rem"
:role="needsExpansion ? 'button' : undefined"
:tabindex="needsExpansion ? 0 : undefined"
:aria-expanded="needsExpansion ? isDescriptionExpanded : undefined"
@click="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
@keydown.enter="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
@keydown.space.prevent="needsExpansion && (isDescriptionExpanded = !isDescriptionExpanded)"
>
{{ fullDescription }}
</p>
🤖 Prompt for AI Agents
In src/renderer/src/components/mcp-config/components/McpServerCard.vue around
lines 198 to 209, the description <p> is clickable when needsExpansion is true
but lacks accessibility attributes and keyboard handlers; add role="button" and
tabindex="0" when needsExpansion is true, set aria-expanded to the boolean
isDescriptionExpanded, add an @keydown handler (or specific @keydown.enter and
@keydown.space) that toggles isDescriptionExpanded when needsExpansion is true
(and preventDefault for Space), and include a concise aria-label or
aria-labelledby so screen readers know this control expands/collapses the
description.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (5)
src/renderer/settings/components/DifyKnowledgeSettings.vue (1)

237-237: Move import to the top of the script section.

The useRoute import is placed after other code (line 237). According to coding guidelines and best practices, all imports should be grouped at the top of the script section for better readability and consistency.

Apply this diff to move the import:

 import { useToast } from '@/components/use-toast'
 import {
   Tooltip,
   TooltipContent,
   TooltipProvider,
   TooltipTrigger
 } from '@shadcn/components/ui/tooltip'
+import { useRoute } from 'vue-router'

 // 对话框状态
 const isDifyConfigDialogOpen = ref(false)
 
 ...
 
 const { t } = useI18n()
 const mcpStore = useMcpStore()
 const { toast } = useToast()
+const route = useRoute()

 // 对话框状态
 const isDifyConfigPanelOpen = ref(false)
 const isEditing = ref(false)
-import { useRoute } from 'vue-router'
-
-const route = useRoute()
src/renderer/settings/components/FastGptKnowledgeSettings.vue (1)

3-36: Stop propagation on the FastGPT switch.
In src/renderer/settings/components/FastGptKnowledgeSettings.vue, add @click.stop to the <Switch> so toggling the MCP server won’t also trigger toggleFastGptConfigPanel.

src/renderer/settings/components/CommonSettings.vue (1)

16-18: Replace h-8! with a valid Tailwind class.

h-8! never matches Tailwind output, so both SelectTriggers render at default height. Swap to !h-8 (or h-8) to restore sizing.

Also applies to: 165-169

src/renderer/settings/components/PromptSetting.vue (2)

1222-1237: Localizable text: replace hardcoded strings with i18n keys

Toast descriptions contain hardcoded text ('错误:', '文件读取失败'). All user-facing strings must use vue-i18n.

Apply this diff (adjust keys to match your i18n schema):

-          toast({
-            title: t('promptSetting.importFailed'),
-            description: `错误: ${errorMessage}`,
-            variant: 'destructive'
-          })
+          toast({
+            title: t('promptSetting.importFailed'),
+            description: t('promptSetting.importErrorWithMessage', { message: errorMessage }),
+            variant: 'destructive'
+          })
-        toast({
-          title: t('promptSetting.importFailed'),
-          description: '文件读取失败',
-          variant: 'destructive'
-        })
+        toast({
+          title: t('promptSetting.importFailed'),
+          description: t('promptSetting.fileReadFailed'),
+          variant: 'destructive'
+        })

As per coding guidelines


976-982: Fix non-reactive Set mutations (expand/collapse not updating UI reliably)

Mutating a Set inside a ref doesn’t trigger reactivity. Reassign a new Set after mutation.

Apply this diff:

-const toggleShowMore = (promptId: string) => {
-  if (expandedPrompts.value.has(promptId)) {
-    expandedPrompts.value.delete(promptId)
-  } else {
-    expandedPrompts.value.add(promptId)
-  }
-}
+const toggleShowMore = (promptId: string) => {
+  const next = new Set(expandedPrompts.value)
+  next.has(promptId) ? next.delete(promptId) : next.add(promptId)
+  expandedPrompts.value = next
+}
♻️ Duplicate comments (5)
src/renderer/settings/components/BuiltinKnowledgeSettings.vue (1)

3-38: Same event propagation concern as FastGptKnowledgeSettings.vue.

This component has the same pattern where interactive children (Switch on lines 23-27) are inside a clickable header container. The review comment on FastGptKnowledgeSettings.vue applies here as well.

src/renderer/settings/components/DifyKnowledgeSettings.vue (1)

3-36: Same event propagation concern as FastGptKnowledgeSettings.vue.

This component has the same pattern where interactive children (Switch on lines 21-25) are inside a clickable header container. The review comment on FastGptKnowledgeSettings.vue applies here as well.

src/renderer/settings/components/RagflowKnowledgeSettings.vue (1)

3-36: Same event propagation concern as FastGptKnowledgeSettings.vue.

This component has the same pattern where interactive children (Switch on lines 21-25) are inside a clickable header container. The review comment on FastGptKnowledgeSettings.vue applies here as well.

src/renderer/settings/components/DataSettings.vue (2)

73-81: Remove backup side effect from import trigger.

Clicking the import trigger still fires syncStore.startBackup, so the user is forced into a backup before the dialog even opens—exactly the regression called out earlier. Drop that handler; let the dialog drive backup/import flow.


125-133: Don’t launch backup when opening the reset dialog.

The reset trigger again invokes syncStore.startBackup, which blocks the confirmation flow (isBackingUp) and repeats the previously flagged bug. The trigger must only open the dialog.

🧹 Nitpick comments (4)
src/renderer/settings/components/McpBuiltinMarket.vue (1)

40-40: LGTM! Proper Separator usage enhances visual hierarchy.

The Separator component is correctly imported and used to provide clear visual separation between the help text and content sections.

Optional: Consider grouping UI component imports together for better organization:

 import { Button } from '@shadcn/components/ui/button'
 import { Input } from '@shadcn/components/ui/input'
+import { Separator } from '@shadcn/components/ui/separator'
 import { usePresenter } from '@/composables/usePresenter'
 import { useToast } from '@/components/use-toast'
-import { Separator } from '@shadcn/components/ui/separator'

Also applies to: 127-127

src/renderer/settings/components/PromptSetting.vue (2)

411-417: Unify editors: replace raw textarea with shared Textarea component

For consistency and styling parity, use the shared Textarea here as elsewhere in this file.

Apply this diff:

-              <div>
-                <textarea
-                  v-model="form.content"
-                  class="w-full min-h-48 rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 font-mono resize-y"
-                  :placeholder="t('promptSetting.contentPlaceholder')"
-                ></textarea>
+              <div>
+                <Textarea
+                  v-model="form.content"
+                  class="w-full min-h-48 font-mono resize-y"
+                  :placeholder="t('promptSetting.contentPlaceholder')"
+                ></Textarea>

As per coding guidelines


4-4: Comments language consistency

Inline comments are in Chinese. The repo guidelines require English for all logs and comments in Vue/TS files. Consider updating comments in this component for consistency.

As per coding guidelines

Also applies to: 48-49, 422-423, 508-510, 594-599

src/renderer/settings/components/McpSettings.vue (1)

267-304: Improve custom registry validation robustness (HEAD→GET fallback + clearer errors)

Some registries/CORS proxies reject HEAD. Fall back to GET if HEAD fails or returns a non-OK status.

Apply this diff:

-    const response = await fetch(testUrl, {
-      method: 'HEAD',
-      signal: AbortSignal.timeout(10000)
-    })
-    if (!response.ok) {
-      throw new Error(`HTTP ${response.status}`)
-    }
-    return true
+    const controller = new AbortController()
+    const signal = AbortSignal.timeout(10000)
+    let response: Response | null = null
+    try {
+      response = await fetch(testUrl, { method: 'HEAD', signal })
+    } catch {}
+    if (!response || !response.ok) {
+      // Fallback to GET (some registries do not support HEAD or block it via CORS)
+      response = await fetch(testUrl, {
+        method: 'GET',
+        headers: { accept: 'application/json' },
+        signal
+      })
+      if (!response.ok) throw new Error(`HTTP ${response.status}`)
+    }
+    return true
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84d1a35 and 900cdee.

📒 Files selected for processing (16)
  • resources/model-db/providers.json (1 hunks)
  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/CommonSettings.vue (9 hunks)
  • src/renderer/settings/components/DataSettings.vue (3 hunks)
  • src/renderer/settings/components/DifyKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/DisplaySettings.vue (2 hunks)
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/KnowledgeBaseSettings.vue (1 hunks)
  • src/renderer/settings/components/McpBuiltinMarket.vue (5 hunks)
  • src/renderer/settings/components/McpSettings.vue (5 hunks)
  • src/renderer/settings/components/PromptSetting.vue (8 hunks)
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue (2 hunks)
  • src/renderer/settings/components/ShortcutSettings.vue (2 hunks)
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue (3 hunks)
  • src/renderer/src/components/mcp-config/components/McpServers.vue (2 hunks)
  • src/shadcn/components/ui/textarea/Textarea.vue (1 hunks)
🧰 Additional context used
📓 Path-based instructions (17)
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.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/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.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/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.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/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for all logs and comments

Files:

  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and adhere to strict TypeScript typing (avoid implicit any, prefer precise types)

Use PascalCase for TypeScript types and classes

Files:

  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
**/*.{ts,tsx,js,jsx,vue,css,scss,md,json,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

Prettier style: single quotes, no semicolons, print width 100; run pnpm run format

Files:

  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • resources/model-db/providers.json
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx,vue}: Use OxLint for JS/TS code; keep lint clean
Use camelCase for variables and functions
Use SCREAMING_SNAKE_CASE for constants

Files:

  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/shadcn/components/ui/textarea/Textarea.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue component files in PascalCase (e.g., ChatInput.vue)

Files:

  • src/renderer/settings/components/BuiltinKnowledgeSettings.vue
  • src/renderer/settings/components/RagflowKnowledgeSettings.vue
  • src/renderer/settings/components/FastGptKnowledgeSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
  • src/renderer/settings/components/KnowledgeBaseSettings.vue
  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
  • src/renderer/settings/components/DisplaySettings.vue
  • src/renderer/settings/components/DifyKnowledgeSettings.vue
  • src/renderer/settings/components/McpBuiltinMarket.vue
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/McpSettings.vue
  • src/renderer/settings/components/PromptSetting.vue
  • src/renderer/settings/components/ShortcutSettings.vue
{build,resources,out,dist}/**

📄 CodeRabbit inference engine (AGENTS.md)

Treat build outputs and assets (build/, resources/, out/, dist/) as generated artifacts; do not hand-edit

Files:

  • resources/model-db/providers.json
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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.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/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/src/components/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Organize UI components by feature within src/renderer/src/

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/src/**

📄 CodeRabbit inference engine (AGENTS.md)

Place Vue 3 app source under src/renderer/src (components, stores, views, i18n, lib)

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
src/renderer/src/**/*.{vue,ts}

📄 CodeRabbit inference engine (AGENTS.md)

All user-facing strings must use vue-i18n ($t/keys) rather than hardcoded literals

Files:

  • src/renderer/src/components/mcp-config/components/McpServers.vue
  • src/renderer/src/components/mcp-config/components/McpServerCard.vue
🧠 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/KnowledgeBaseSettings.vue
  • src/renderer/settings/components/McpSettings.vue
⏰ 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: build-check (x64)
🔇 Additional comments (7)
src/renderer/settings/components/McpBuiltinMarket.vue (3)

3-13: LGTM! Well-executed header refactor.

The sticky header with compact vertical layout improves UX during scrolling while maintaining clear visual hierarchy. The z-10 z-index and flexbox alignment are appropriate.


29-29: LGTM! Styling simplification improves visual clarity.

Removing the border and background styling streamlines the help text presentation while maintaining proper spacing.


72-72: LGTM! Improved visual feedback for installation state.

The conditional button variant (outline for available, secondary for installed) enhances UX by providing clearer visual distinction between installation states, complementing the existing disabled state.

src/renderer/settings/components/KnowledgeBaseSettings.vue (1)

2-23: LGTM! Clean UI simplification.

The layout adjustments (increased padding and gaps) and simplified header improve visual clarity and align with the broader UI optimization goals of this PR. The removal of the add-knowledge dialog flow streamlines the interface.

src/shadcn/components/ui/textarea/Textarea.vue (1)

22-27: LGTM on the Textarea refactor

Reordering and class tweak look fine; behavior remains intact.

src/renderer/src/components/mcp-config/components/McpServers.vue (1)

262-280: Grid layout update looks good

Increasing columns improves density; no logic affected.

Also applies to: 294-313

src/renderer/src/components/mcp-config/components/McpServerCard.vue (1)

142-155: Card refactor is cohesive

Header simplification, description clamp, and footer controls align with the new design; events/props preserved.

Also applies to: 198-209, 233-239, 241-277

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/renderer/settings/components/DataSettings.vue (2)

28-28: Fix invalid Tailwind utility.

The Input uses h-8! which is invalid syntax. Use !h-8 (important) or h-8 instead.

As per coding guidelines.


75-75: Import button triggers backup instead of opening dialog.

The Import button (inside DialogTrigger) calls syncStore.startBackup, which starts a backup operation before the user confirms the import. Remove the @click handler so the button only opens the import dialog.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 900cdee and b436b30.

📒 Files selected for processing (2)
  • src/renderer/settings/components/CommonSettings.vue (10 hunks)
  • src/renderer/settings/components/DataSettings.vue (3 hunks)
🧰 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/DataSettings.vue
  • 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/DataSettings.vue
  • 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/DataSettings.vue
  • 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/DataSettings.vue
  • 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/DataSettings.vue
  • 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)

Use PascalCase for TypeScript types and classes

Files:

  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
**/*.{ts,tsx,js,jsx,vue,css,scss,md,json,yml,yaml}

📄 CodeRabbit inference engine (AGENTS.md)

Prettier style: single quotes, no semicolons, print width 100; run pnpm run format

Files:

  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx,vue}: Use OxLint for JS/TS code; keep lint clean
Use camelCase for variables and functions
Use SCREAMING_SNAKE_CASE for constants

Files:

  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue component files in PascalCase (e.g., ChatInput.vue)

Files:

  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/settings/components/CommonSettings.vue
🔇 Additional comments (3)
src/renderer/settings/components/CommonSettings.vue (1)

2-3: LGTM: Padding reorganization aligns with component consistency.

The outer ScrollArea padding removal and inner container padding allocation matches the layout pattern applied across other settings components in this PR.

src/renderer/settings/components/DataSettings.vue (2)

2-3: LGTM: Padding reorganization is consistent.

The padding shift from ScrollArea to the inner container aligns with the unified layout approach used across settings components in this PR.


127-127: Reset button disabled state references backup operation.

The Reset button's disabled attribute checks syncStore.isBackingUp, which is semantically unrelated to reset operations. If the intent is to prevent concurrent operations, consider adding a dedicated isResetting flag in the store, or verify that isBackingUp is intentionally used to gate all data operations.

Comment on lines +272 to +302
<Dialog v-model:open="isLoggingDialogOpen" @update:open="cancelLoggingChange">
<DialogTrigger as-child>
<Button class="w-36" variant="outline" :dir="langStore.dir" @click="openLogFolder">
<Icon icon="lucide:external-link" class="w-4 h-4 text-muted-foreground" />
<span class="text-sm font-medium">{{ t('settings.common.openLogFolder') }}</span>
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{{ t('settings.common.loggingDialogTitle') }}</DialogTitle>
<DialogDescription>
<div class="space-y-2">
<p>
{{
newLoggingValue
? t('settings.common.loggingEnableDesc')
: t('settings.common.loggingDisableDesc')
}}
</p>
<p>{{ t('settings.common.loggingRestartNotice') }}</p>
</div>
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" @click="cancelLoggingChange">{{
t('common.cancel')
}}</Button>
<Button @click="confirmLoggingChange">{{ t('common.confirm') }}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

DialogTrigger wraps the wrong button.

The DialogTrigger (line 273) wraps the "Open Log Folder" button (lines 274-277), but the Dialog content (lines 279-301) contains the logging enable/disable confirmation. This means clicking "Open Log Folder" would show the logging confirmation dialog instead of opening the folder.

The logging confirmation dialog should be triggered by the logging Switch (lines 227-232) via the handleLoggingChange handler, not by the log folder button. The log folder button should directly call openLogFolder without being wrapped in a DialogTrigger.

Apply this diff to fix the structure:

-      <div class="flex flex-row gap-3">
-        <!-- 日志开关确认对话框 -->
-        <Dialog v-model:open="isLoggingDialogOpen" @update:open="cancelLoggingChange">
-          <DialogTrigger as-child>
-            <Button class="w-36" variant="outline" :dir="langStore.dir" @click="openLogFolder">
-              <Icon icon="lucide:external-link" class="w-4 h-4 text-muted-foreground" />
-              <span class="text-sm font-medium">{{ t('settings.common.openLogFolder') }}</span>
-            </Button>
-          </DialogTrigger>
-          <DialogContent>
-            <DialogHeader>
-              <DialogTitle>{{ t('settings.common.loggingDialogTitle') }}</DialogTitle>
-              <DialogDescription>
-                <div class="space-y-2">
-                  <p>
-                    {{
-                      newLoggingValue
-                        ? t('settings.common.loggingEnableDesc')
-                        : t('settings.common.loggingDisableDesc')
-                    }}
-                  </p>
-                  <p>{{ t('settings.common.loggingRestartNotice') }}</p>
-                </div>
-              </DialogDescription>
-            </DialogHeader>
-            <DialogFooter>
-              <Button variant="outline" @click="cancelLoggingChange">{{
-                t('common.cancel')
-              }}</Button>
-              <Button @click="confirmLoggingChange">{{ t('common.confirm') }}</Button>
-            </DialogFooter>
-          </DialogContent>
-        </Dialog>
-      </div>
+      <div class="flex flex-row gap-3">
+        <Button class="w-36" variant="outline" :dir="langStore.dir" @click="openLogFolder">
+          <Icon icon="lucide:external-link" class="w-4 h-4 text-muted-foreground" />
+          <span class="text-sm font-medium">{{ t('settings.common.openLogFolder') }}</span>
+        </Button>
+      </div>
+
+      <!-- 日志开关确认对话框 -->
+      <Dialog v-model:open="isLoggingDialogOpen" @update:open="cancelLoggingChange">
+        <DialogContent>
+          <DialogHeader>
+            <DialogTitle>{{ t('settings.common.loggingDialogTitle') }}</DialogTitle>
+            <DialogDescription>
+              <div class="space-y-2">
+                <p>
+                  {{
+                    newLoggingValue
+                      ? t('settings.common.loggingEnableDesc')
+                      : t('settings.common.loggingDisableDesc')
+                  }}
+                </p>
+                <p>{{ t('settings.common.loggingRestartNotice') }}</p>
+              </div>
+            </DialogDescription>
+          </DialogHeader>
+          <DialogFooter>
+            <Button variant="outline" @click="cancelLoggingChange">{{
+              t('common.cancel')
+            }}</Button>
+            <Button @click="confirmLoggingChange">{{ t('common.confirm') }}</Button>
+          </DialogFooter>
+        </DialogContent>
+      </Dialog>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Dialog v-model:open="isLoggingDialogOpen" @update:open="cancelLoggingChange">
<DialogTrigger as-child>
<Button class="w-36" variant="outline" :dir="langStore.dir" @click="openLogFolder">
<Icon icon="lucide:external-link" class="w-4 h-4 text-muted-foreground" />
<span class="text-sm font-medium">{{ t('settings.common.openLogFolder') }}</span>
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{{ t('settings.common.loggingDialogTitle') }}</DialogTitle>
<DialogDescription>
<div class="space-y-2">
<p>
{{
newLoggingValue
? t('settings.common.loggingEnableDesc')
: t('settings.common.loggingDisableDesc')
}}
</p>
<p>{{ t('settings.common.loggingRestartNotice') }}</p>
</div>
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" @click="cancelLoggingChange">{{
t('common.cancel')
}}</Button>
<Button @click="confirmLoggingChange">{{ t('common.confirm') }}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<div class="flex flex-row gap-3">
<Button class="w-36" variant="outline" :dir="langStore.dir" @click="openLogFolder">
<Icon icon="lucide:external-link" class="w-4 h-4 text-muted-foreground" />
<span class="text-sm font-medium">{{ t('settings.common.openLogFolder') }}</span>
</Button>
</div>
<!-- 日志开关确认对话框 -->
<Dialog v-model:open="isLoggingDialogOpen" @update:open="cancelLoggingChange">
<DialogContent>
<DialogHeader>
<DialogTitle>{{ t('settings.common.loggingDialogTitle') }}</DialogTitle>
<DialogDescription>
<div class="space-y-2">
<p>
{{
newLoggingValue
? t('settings.common.loggingEnableDesc')
: t('settings.common.loggingDisableDesc')
}}
</p>
<p>{{ t('settings.common.loggingRestartNotice') }}</p>
</div>
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" @click="cancelLoggingChange">{{
t('common.cancel')
}}</Button>
<Button @click="confirmLoggingChange">{{ t('common.confirm') }}</Button>
</DialogFooter>
</DialogContent>
</Dialog>

@zerob13 zerob13 merged commit 4757605 into dev Oct 14, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants