Skip to content

Conversation

@hllshiro
Copy link
Collaborator

@hllshiro hllshiro commented Aug 20, 2025

Pull Request Description

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is.
Implement custom text segmentation separator.

Describe the solution you'd like
Added block separator options and the ability to directly apply system presets.

UI/UX changes for Desktop Application
If this PR introduces UI/UX changes, please describe them in detail.

  • Include screenshots or GIFs if applicable to visually demonstrate the changes.
  • Explain the reasoning behind the UI/UX decisions and how they improve the user experience of the desktop application.
    see below

Platform Compatibility Notes
If this PR has specific platform compatibility considerations (Windows, macOS, Linux), please describe them here.

  • Are there any platform-specific behaviors or code adjustments? no
  • Have you tested on all relevant platforms? only windows

Additional context
The local knowledge base is a means for users to use it offline, and it only provides a simple and easy-to-use knowledge base implementation. For complex and professional RAG requirements, we recommend using more professional knowledge base services such as RAG Flow.


Pull Request Description (中文)

你的功能请求是否与某个问题有关?请描述一下。
请对问题进行清晰扼要的描述。
实现自定义文本切分分隔符。

请描述你希望的解决方案
请对你希望实现的效果进行清晰扼要的描述。
增加了块分隔符的选项,并可直接应用系统预设。

桌面应用程序的 UI/UX 更改
如果此 PR 引入了 UI/UX 更改,请详细描述它们。

  • 如果适用,请包含屏幕截图或 GIF 以直观地演示更改。
  • 解释 UI/UX 决策背后的原因,以及它们如何改善桌面应用程序的用户体验。
image image

平台兼容性注意事项
如果此 PR 具有特定的平台兼容性考虑因素(Windows、macOS、Linux),请在此处描述。

  • 是否有任何平台特定的行为或代码调整?无
  • 你是否已在所有相关平台上进行过测试?仅windows

附加背景
本地知识库作为用户离线使用的手段,它仅提供了一种简单易用的知识库实现。对于复杂和专业的RAG需求,更推荐使用 RAG Flow 等更专业的知识库服务。

Summary by CodeRabbit

  • New Features

    • Backend-powered file validation with clear errors and suggested formats.
    • Configurable chunk separators with language presets in settings.
    • Dynamic, backend-driven supported file extensions shown in the upload UI.
    • Language presets and separator presets available for knowledge processing.
  • Improvements

    • Consolidated upload flow, better logging and error handling.
    • Faster startup by loading files and extensions concurrently.
    • Text normalization now preserves line breaks for improved chunking.
  • i18n

    • Updated translations for dynamic file support text and separators UI.
  • Tests

    • Added comprehensive tests for file validation and presenter behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 20, 2025

Walkthrough

Adds a MIME-based FileValidationService, wires file validation APIs into FilePresenter and KnowledgePresenter, exposes language/separator utilities, updates chunking and renderer UIs (separators + backend-driven file validation), adjusts string normalization, extends shared presenter types, and adds Vitest tests for new behavior.

Changes

Cohort / File(s) Summary of changes
Package metadata
package.json
Added @types/mime-types dependency; reordered a devDependency entry.
File validation service
src/main/presenter/filePresenter/FileValidationService.ts
New service that detects MIME types, maps to adapters, and returns FileValidationResult; exposes validateFile, getSupportedExtensions, getSupportedMimeTypes; defines IFileValidationService and FileValidationResult.
File presenter integration & tests
src/main/presenter/filePresenter/FilePresenter.ts, test/main/presenter/FilePresenter.test.ts
FilePresenter now accepts/injects an IFileValidationService (defaults to FileValidationService); stronger temp-dir init; adds validateFileForKnowledgeBase and getSupportedExtensions; tests verify delegation, error handling, and fallbacks.
Presenter wiring & knowledge tests
src/main/presenter/index.ts, src/main/presenter/knowledgePresenter/index.ts, test/main/presenter/KnowledgePresenter.test.ts
Injects FilePresenter into KnowledgePresenter; KnowledgePresenter gains separators property and methods: getSupportedLanguages, getSeparatorsForLanguage, validateFile, getSupportedFileExtensions with logging and fallbacks; tests cover validation and extension fallbacks.
Knowledge store updates
src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
Use filePresenter.getMimeType(...) and path.basename for fileMessage.name/mimeType; pass fileMessage.mimeType to prepare; add separators to RecursiveCharacterTextSplitter; chunk IDs now fileMessage.id + '_' + index.
Utilities
src/main/utils/strings.ts
Normalize CR/CRLF → LF, preserve LF line breaks while collapsing spaces/tabs; moved to chained replacements.
Renderer settings (separators)
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
New separators editor UI with language presets; integrates with knowledgePresenter for languages/separators; parsing/serialization helpers; persists separators in MCP config.
Renderer knowledge file UI
src/renderer/src/components/settings/KnowledgeFile.vue
Load supported extensions from backend; centralized async upload handler using backend validation; drag/drop wrapper; parallel init for file list + extensions; updated toasts and logging; acceptExts becomes reactive.
i18n updates
src/renderer/src/i18n/*/settings.json
Rename knowledgeBase.onlySupportknowledgeBase.fileSupport (placeholders) and add separators-related keys across locales (en-US, fa-IR, fr-FR, ja-JP, ko-KR, ru-RU, zh-CN, zh-HK, zh-TW).
Shared presenter types
src/shared/presenter.d.ts
Add FileValidationResult; extend IFilePresenter with validateFileForKnowledgeBase and getSupportedExtensions; extend IKnowledgePresenter with getSupportedLanguages, getSeparatorsForLanguage, validateFile, getSupportedFileExtensions; add separators?: string[] to BuiltinKnowledgeConfig.
FileValidationService tests
test/main/presenter/FileValidationService.test.ts
New Vitest suite covering MIME detection, adapter mapping, supported/unsupported flows, wildcard handling, error paths, and supported lists.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as User
  participant UI as Renderer (KnowledgeFile.vue)
  participant KP as KnowledgePresenter
  participant FP as FilePresenter
  participant FVS as FileValidationService
  participant MIME as detectMimeType

  User->>UI: Drop/Select file(s)
  UI->>KP: validateFile(path)
  KP->>FP: validateFileForKnowledgeBase(path)
  FP->>FVS: validateFile(path)
  FVS->>MIME: detect(file content)
  MIME-->>FVS: mimeType
  FVS-->>FP: FileValidationResult
  FP-->>KP: FileValidationResult
  KP-->>UI: FileValidationResult
  alt isSupported
    UI->>KP: addFile(path)
    KP-->>UI: addFile result
  else not supported
    UI-->>User: Show error + suggested extensions
  end
Loading
sequenceDiagram
  autonumber
  actor User as User
  participant Settings as BuiltinKnowledgeSettings.vue
  participant KP as KnowledgePresenter
  participant Split as RecursiveCharacterTextSplitter

  User->>Settings: Open Advanced separators
  Settings->>KP: getSupportedLanguages()
  KP-->>Settings: [languages]
  User->>Settings: Choose language
  Settings->>KP: getSeparatorsForLanguage(lang)
  KP-->>Settings: [separators]
  Settings->>Settings: Parse/serialize separators
  User->>Settings: Save config
  Settings->>KP: persist config (includes separators)
  KP->>Split: Initialize splitter with separators
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • feat: builtin knowledge #597 — Overlapping changes to built-in knowledge/file handling and presenter surface; likely direct code-level overlap.
  • Feature/builtin knowledge #630 — Related presenter interface extensions, renderer changes, and tests touching the same knowledge-base APIs.
  • Release 0.2.7 #645 — Overlaps around FilePresenter / KnowledgePresenter wiring and file validation features.

Suggested reviewers

  • zerob13
  • deepinfect

Poem

I thump my paw and sniff the file,
MIME and separators stacked in style.
Files vetted, chunks well sown,
Carrots crunched, the rabbit's shown.
Hop — validation done, joy all the while! 🥕

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

…ettings; add tooltip for accepted file extensions in KnowledgeFile
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: 11

Caution

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

⚠️ Outside diff range comments (6)
src/renderer/src/i18n/ru-RU/settings.json (1)

535-541: Placeholder name mismatch: use {fileName} (camelCase) consistently

Other locales use {fileName}. These two entries use {filename}, which will break runtime interpolation.

-      "content": "Вы уверены, что повторно загрузите файл \"{filename}\"?"
+      "content": "Вы уверены, что повторно загрузите файл \"{fileName}\"?"
...
-      "content": "Вы обязательно удалите файл \"{filename}\"? Эта операция не восстановлена."
+      "content": "Вы обязательно удалите файл \"{fileName}\"? Эта операция не восстановлена."
src/shared/presenter.d.ts (1)

1001-1001: Typo in type: “unknow” → “unknown”

This will break type checking in d.ts.

Apply this diff:

-  env: Record<string, unknow>
+  env: Record<string, unknown>
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (1)

451-458: Incorrect dynamic prop name: use :placeholder (lowercase)

Input expects placeholder; the uppercase variant won’t map to the prop.

Apply this diff:

-                        :Placeholder="t('settings.knowledgeBase.chunkSizePlaceholder')"
+                        :placeholder="t('settings.knowledgeBase.chunkSizePlaceholder')"
src/renderer/src/components/settings/KnowledgeFile.vue (3)

56-56: Fix invalid className attribute (Vue uses class).

Using className prevents styles from applying; Vue templates require class. This breaks layout/styling on the upload box and the search bar container.

Apply:

-      <div className="flex flex-col gap-2 text-balance">
+      <div class="flex flex-col gap-2 text-balance">
-          <div className="flex w-full items-center gap-1 relative">
+          <div class="flex w-full items-center gap-1 relative">

Also applies to: 108-108


161-163: Remove stray “<” in tooltip content.

There’s a spurious “<” rendered to users in the success tooltip.

-                        {{ t('settings.knowledgeBase.copySuccess') }} <
+                        {{ t('settings.knowledgeBase.copySuccess') }}

146-147: Internationalize the score label

Replace the hard-coded label:

score: {{ (item.distance * 100).toFixed(2) + '%' }}

with a call to your i18n helper:

{{ t('settings.knowledgeBase.scorePercent', { percent: (item.distance * 100).toFixed(2) }) }}

And add the new key to each locale’s message bundle. For example, in your English and Chinese files:

• src/renderer/src/i18n/en-US.json

{
  "settings": {
    "knowledgeBase": {
      "scorePercent": "score: {percent}%"
    }
  }
}

• src/renderer/src/i18n/zh-CN.json

{
  "settings": {
    "knowledgeBase": {
      "scorePercent": "相似度:{percent}%"
    }
  }
}

• Double-check that these files are loaded by your i18n setup (e.g. via createI18n/messages) and that no occurrences of scorePercent exist yet.
• Run your app and verify the label changes correctly in all locales.

🧹 Nitpick comments (26)
src/main/utils/strings.ts (4)

7-9: Doc nit: mention tabs are collapsed too.

The implementation collapses runs of spaces and tabs, not just spaces. Align the comment to avoid confusion.

- * - Collapses multiple consecutive spaces (but preserves single line breaks)
+ * - Collapses multiple consecutive spaces and tabs (preserves line breaks)

26-26: Regex simplification for CR/CRLF normalization.

Slightly simpler and equivalent pattern.

-    .replace(/(\r\n|\r)/g, '\n')
+    .replace(/\r\n?/g, '\n')

27-27: Collapse non‑breaking spaces too (NBSP).

Restricting to [ \t]+ preserves LFs as intended, but it will leave NBSPs (0xA0) intact (common from HTML/Word copy). That can degrade tokenization and chunking. Consider including NBSP while still excluding \n.

-    .replace(/[ \t]+/g, ' ')
+    .replace(/[ \t\u00A0]+/g, ' ')

If you prefer a broader “horizontal whitespace except newline” approach, an alternative is:

.replace(/[^\S\n]+/g, ' ')

Recommend adding unit tests covering:

  • CRLF/CR normalization (Windows files)
  • NBSP collapsing
  • Preservation of single LFs

23-23: Confirm intent: stripping all backslashes may mangle content.

Removing all backslashes can alter Windows paths (C:\dir\file.txtC:dirfile.txt) and code blocks/escape sequences. If this sanitizer processes arbitrary user documents (not just plain prose), consider scoping or making this configurable.

I can draft an optioned version, e.g., sanitizeText(text, { stripBackslashes: boolean }), defaulting to current behavior, or restrict removal to known escape artifacts. Want me to open a follow-up?

src/renderer/src/i18n/ja-JP/settings.json (1)

544-547: Tweak phrasing for natural Japanese and clarity

  • “ワンクリックの一時停止” is slightly awkward. “ワンクリック一時停止” is more natural in UI labels.
  • “無効な分離器” is uncommon; “区切り文字” or “セパレーター” is standard.

Apply:

-    "pauseAllRunningTasks": "ワンクリックの一時停止",
+    "pauseAllRunningTasks": "ワンクリック一時停止",
-    "invalidSeparators": "無効な分離器",
+    "invalidSeparators": "無効な区切り文字",
src/renderer/src/i18n/en-US/settings.json (2)

505-505: Grammar: use “Supports …” (singular) for button/label text

Small UX polish.

-    "fileSupport": "Support {accept} and {count} other formats",
+    "fileSupport": "Supports {accept} and {count} other formats",

545-549: Use imperative “Load presets” for separatorsPreset

All locale files already include the separatorsPreset key—update the en-US entry and coordinate with localization to use the imperative form:

In src/renderer/src/i18n/en-US/settings.json:

-    "separatorsPreset": "Loading presets"
+    "separatorsPreset": "Load presets"

Consider propagating this change to other locales’ translations to maintain consistency.

src/renderer/src/i18n/fr-FR/settings.json (2)

545-545: Prefer “Séparateurs de blocs” (plural) for label naturalness

-    "separators": "Séparateur de blocage",
+    "separators": "Séparateurs de blocs",

548-548: Use imperative for action label

Keep consistent with other locales (action vs. status).

-    "separatorsPreset": "Chargement des préréglages"
+    "separatorsPreset": "Charger les préréglages"
src/renderer/src/i18n/ru-RU/settings.json (1)

543-549: Improve action label tone and preset wording

  • “Пауза с одним щелчком” is awkward; prefer “Поставить на паузу одним кликом”.
  • Use imperative “Загрузить пресеты” for the button label.
-    "pauseAllRunningTasks": "Пауза с одним щелчком",
+    "pauseAllRunningTasks": "Поставить на паузу одним кликом",
-    "separatorsPreset": "Загрузка пресетов"
+    "separatorsPreset": "Загрузить пресеты"
src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts (3)

63-70: Compute MIME once and persist on file record.

Getting MIME via presenter.filePresenter.getMimeType(filePath) and persisting it into fileMessage.mimeType/name improves downstream processing determinism.

You could guard against empty-string MIME results to fall back to later detection:

-const mimeType = await presenter.filePresenter.getMimeType(filePath)
+const detected = await presenter.filePresenter.getMimeType(filePath)
+const mimeType = detected && detected.trim().length > 0 ? detected : undefined

120-124: Respect configurable separators; add a safe fallback when empty.

Using this.config.separators enables custom chunking. If users configure an empty array, the splitter will effectively have no separators; consider falling back to defaults when the list is empty.

-const chunker = new RecursiveCharacterTextSplitter({
-  chunkSize: this.config.chunkSize,
-  chunkOverlap: this.config.chunkOverlap,
-  separators: this.config.separators
-})
+const separators =
+  Array.isArray(this.config.separators) && this.config.separators.length > 0
+    ? this.config.separators
+    : undefined
+const chunker = new RecursiveCharacterTextSplitter({
+  chunkSize: this.config.chunkSize,
+  chunkOverlap: this.config.chunkOverlap,
+  separators
+})

63-63: Reduce global coupling on presenter (optional).

Accessing presenter.filePresenter from inside the store presenter creates a cyclic dependency path. Consider injecting an IFilePresenter (or MIME detector) directly into KnowledgeStorePresenter to remove the global import and tighten boundaries.

src/main/presenter/filePresenter/FilePresenter.ts (2)

28-41: Temp dir init is async; simplify and make intent explicit.

Wrapping a Promise in try/catch doesn’t catch async rejections. Prefer a one-liner with explicit discard, and keep the contextual error message.

Apply:

-    try {
-      const mkdirResult = fs.mkdir(this.tempDir, { recursive: true })
-      if (mkdirResult && typeof mkdirResult.catch === 'function') {
-        mkdirResult.catch(console.error)
-      }
-    } catch (error) {
-      console.error('Failed to create temp directory:', error)
-    }
+    void fs
+      .mkdir(this.tempDir, { recursive: true })
+      .catch((err) => console.error('Failed to create temp directory:', err))

276-306: Supported extensions surface with sensible fallback.

Returning a sorted fallback set is good resilience. Note: the same fallback set appears in KnowledgePresenter; consider centralizing to avoid drift.

You could export a shared constant (e.g., DEFAULT_KB_EXTENSIONS) from the service module and reuse it in both places.

test/main/presenter/KnowledgePresenter.test.ts (1)

87-89: Mock vector utils on the alias used by SUT.

SUT imports getMetric from @/utils/vector. Update the mock to ensure it applies if used.

-vi.mock('../../../src/main/utils/vector', () => ({
+vi.mock('@/utils/vector', () => ({
   getMetric: vi.fn().mockReturnValue('cosine')
 }))
src/main/presenter/knowledgePresenter/index.ts (1)

422-460: Extension discovery: OK, but de-duplicate fallback lists.

You have a very similar fallback list in FilePresenter. Prefer a shared constant to avoid drift.

As a follow-up, export DEFAULT_KB_EXTENSIONS from the validation service module and use it here and in FilePresenter.

src/main/presenter/filePresenter/FileValidationService.ts (1)

50-61: Unreachable branch: AdapterConstructor is never undefined

findAdapterForMimeType always returns a constructor (falls back to UnsupportFileAdapter), so if (!AdapterConstructor) cannot be hit. Consider simplifying by checking explicitly for UnsupportFileAdapter and handling it consistently in a single path.

Example refactor (optional):

-      const AdapterConstructor = this.findAdapterForMimeType(mimeType, adapterMap)
-
-      if (!AdapterConstructor) {
-        return {
-          isSupported: false,
-          mimeType,
-          error: 'No adapter found for this file type',
-          suggestedExtensions: this.getSupportedExtensions()
-        }
-      }
+      const AdapterConstructor = this.findAdapterForMimeType(mimeType, adapterMap)
src/shared/presenter.d.ts (1)

1546-1553: Consolidate FileValidationResult into a single shared definition

The FileValidationResult interface is declared in both:

  • src/shared/presenter.d.ts (lines 1546–1553)
  • src/main/presenter/filePresenter/FileValidationService.ts (lines 6–13)

Maintaining two separate definitions risks them diverging over time. To avoid duplication:

• Remove the duplicate interface in FileValidationService.ts.
• Import and re-export the shared definition instead. For example, in FileValidationService.ts:

// before
export interface FileValidationResult {
  isSupported: boolean
  mimeType?: string
  adapterType?: string
  error?: string
  suggestedExtensions?: string[]
}

// after
import { FileValidationResult } from '../../../shared/presenter';
export { FileValidationResult };

This keeps a single source of truth and prevents future drift.

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

347-348: ⚠️ Prefix in tooltip is user-facing; consider moving into i18n

To keep all user-visible strings behind i18n, include the warning emoji inside the translation value rather than the template literal.


794-806: Consider explicit clearing behavior when separators input is empty

Currently, if the input is cleared, existing separators on the config remain unchanged. If the intended UX is “clearing the input removes custom separators,” delete the field when blank.

Apply this diff:

   // 转换separators格式
   if (separators.value && separators.value.trim() !== '') {
     const separatorsArray = separatorString2Array(separators.value)
     if (separatorsArray.length === 0) {
       toast({
         title: t('settings.knowledgeBase.invalidSeparators'),
         variant: 'destructive',
         duration: 3000
       })
       submitLoading.value = false
       return
     }
     editingBuiltinConfig.value.separators = separatorsArray
   }
+  else {
+    delete editingBuiltinConfig.value.separators
+  }
src/renderer/src/components/settings/KnowledgeFile.vue (5)

73-78: Locale-aware list formatting for supported extensions; avoid hardcoded Chinese comma.

Joining with ',' hardcodes punctuation and isn’t locale-aware. Prefer a locale-aware list or at least a neutral join.

Minimal change:

-                      accept: acceptExts.slice(0, 5).join(','),
+                      accept: acceptExts.slice(0, 5).join(', '),

Optional: Use Intl.ListFormat with the current i18n locale for better UX:

-                      accept: acceptExts.slice(0, 5).join(','),
+                      accept: new Intl.ListFormat($i18n.locale, { style: 'short', type: 'conjunction' })
+                        .format(acceptExts.slice(0, 5)),

231-233: Use English for code comments per guidelines.

Comments should be in English in .vue files.

-// 允许的文件扩展名 - 动态加载
+// Allowed file extensions - dynamically loaded

290-307: Normalize and de-duplicate extensions; handle leading dots and casing.

Backends may return extensions with leading dots or mixed case, causing issues like “..md” in the file input accept attribute and duplicate entries in the preview. Normalize and de-duplicate before merging with defaults.

-// 加载支持的文件扩展名
+// Load supported file extensions
 const loadSupportedExtensions = async () => {
   try {
     console.log('[KnowledgeFile] Loading supported extensions from backend')
-    const extensions = await knowledgePresenter.getSupportedFileExtensions()
-    // 保证 defaultSupported 排在最前,且不重复
-    const uniqueExts = extensions.filter((ext) => !defaultSupported.includes(ext))
-    acceptExts.value = [...defaultSupported, ...uniqueExts]
-    console.log(`[KnowledgeFile] Loaded ${extensions.length} supported extensions:`, extensions)
+    const extensions = await knowledgePresenter.getSupportedFileExtensions()
+    // Normalize: trim, remove leading dot, lower-case
+    const normalize = (ext: string) => ext.trim().replace(/^\./, '').toLowerCase()
+    const normalized = Array.from(new Set(extensions.map(normalize)))
+    // Keep defaults at the front and avoid duplicates
+    const uniqueExts = normalized.filter((ext) => !defaultSupported.includes(ext))
+    acceptExts.value = [...defaultSupported, ...uniqueExts]
+    console.log(
+      `[KnowledgeFile] Loaded ${normalized.length} supported extensions:`,
+      acceptExts.value
+    )
   } catch (error) {
     console.error('[KnowledgeFile] Failed to load supported extensions:', error)
-    // 使用回退扩展名列表
+    // Fallback to default extensions
     acceptExts.value = [...defaultSupported]
   }
 }

309-314: Reset file input after upload to allow re-selecting the same file.

Without clearing the input, selecting the same file again won’t trigger change in many browsers.

-const handleChange = async (event: Event) => {
-  const files = (event.target as HTMLInputElement).files
+const handleChange = async (event: Event) => {
+  const input = event.target as HTMLInputElement
+  const files = input.files
   if (files && files.length > 0) {
     await handleFileUpload(Array.from(files))
   }
+  // Clear input value to enable selecting the same file again
+  input.value = ''
 }

424-428: Guard parallel initialization with try/catch to avoid unhandled rejections.

If loadList rejects, onMounted will throw. Wrap in try/catch to toast/log gracefully.

-onMounted(async () => {
-  // 并行加载文件列表和支持的扩展名
-  await Promise.all([loadList(), loadSupportedExtensions()])
+onMounted(async () => {
+  // Load file list and supported extensions in parallel
+  try {
+    await Promise.all([loadList(), loadSupportedExtensions()])
+  } catch (error) {
+    console.error('[KnowledgeFile] Initialization failed:', error)
+    toast({
+      title: t('common.error'),
+      description: t('settings.knowledgeBase.initFailed'),
+      variant: 'destructive',
+      duration: 3000
+    })
+  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5284000 and 19b7d57.

📒 Files selected for processing (22)
  • package.json (2 hunks)
  • src/main/presenter/filePresenter/FilePresenter.ts (2 hunks)
  • src/main/presenter/filePresenter/FileValidationService.ts (1 hunks)
  • src/main/presenter/index.ts (1 hunks)
  • src/main/presenter/knowledgePresenter/index.ts (4 hunks)
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts (5 hunks)
  • src/main/utils/strings.ts (2 hunks)
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (9 hunks)
  • src/renderer/src/components/settings/KnowledgeFile.vue (5 hunks)
  • src/renderer/src/i18n/en-US/settings.json (2 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (2 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (2 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (2 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (2 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (2 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (2 hunks)
  • src/shared/presenter.d.ts (4 hunks)
  • test/main/presenter/FilePresenter.test.ts (1 hunks)
  • test/main/presenter/FileValidationService.test.ts (1 hunks)
  • test/main/presenter/KnowledgePresenter.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (21)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • test/main/presenter/KnowledgePresenter.test.ts
  • test/main/presenter/FilePresenter.test.ts
  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
  • test/main/presenter/FileValidationService.test.ts
  • src/renderer/src/components/settings/KnowledgeFile.vue
  • src/main/utils/strings.ts
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Strict type checking enabled for TypeScript

**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别

Files:

  • test/main/presenter/KnowledgePresenter.test.ts
  • test/main/presenter/FilePresenter.test.ts
  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
  • test/main/presenter/FileValidationService.test.ts
  • src/main/utils/strings.ts
test/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use Vitest for unit and integration tests

Files:

  • test/main/presenter/KnowledgePresenter.test.ts
  • test/main/presenter/FilePresenter.test.ts
  • test/main/presenter/FileValidationService.test.ts
test/**/*

📄 CodeRabbit Inference Engine (CLAUDE.md)

Place test files in test/ directory with corresponding structure

Files:

  • test/main/presenter/KnowledgePresenter.test.ts
  • test/main/presenter/FilePresenter.test.ts
  • test/main/presenter/FileValidationService.test.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/development-setup.mdc)

**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写

Files:

  • test/main/presenter/KnowledgePresenter.test.ts
  • test/main/presenter/FilePresenter.test.ts
  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
  • test/main/presenter/FileValidationService.test.ts
  • src/main/utils/strings.ts
src/main/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Main to Renderer: Use EventBus to broadcast events via mainWindow.webContents.send()

Use Electron's built-in APIs for file system and native dialogs

Files:

  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
  • src/main/utils/strings.ts
src/main/presenter/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

One presenter per functional domain

Files:

  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
src/{main,renderer}/**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

src/{main,renderer}/**/*.ts: Use context isolation for improved security
Implement proper inter-process communication (IPC) patterns
Optimize application startup time with lazy loading
Implement proper error handling and logging for debugging

Files:

  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
  • src/main/utils/strings.ts
src/main/presenter/index.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

The IPC messages from the main process to notify the view mainly rely on the EventBus index.ts to listen for events that need to be notified and then send them to the renderer through the mainWindow

Files:

  • src/main/presenter/index.ts
src/main/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

主进程代码放在 src/main

Files:

  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/main/presenter/filePresenter/FilePresenter.ts
  • src/main/presenter/filePresenter/FileValidationService.ts
  • src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts
  • src/main/utils/strings.ts
src/renderer/src/**/*

📄 CodeRabbit Inference Engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/components/settings/KnowledgeFile.vue
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
src/shared/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared types in src/shared/

Files:

  • src/shared/presenter.d.ts
src/shared/*.d.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

The shared/*.d.ts files are used to define the types of objects exposed by the main process to the renderer process

Files:

  • src/shared/presenter.d.ts
src/shared/**/*.{ts,tsx,d.ts}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

共享类型定义放在 shared 目录

Files:

  • src/shared/presenter.d.ts
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

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

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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/settings/KnowledgeFile.vue
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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/settings/KnowledgeFile.vue
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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/settings/KnowledgeFile.vue
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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.

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
🧠 Learnings (10)
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to test/**/*.{ts,tsx,js,jsx} : Use Vitest for unit and integration tests

Applied to files:

  • test/main/presenter/FilePresenter.test.ts
  • test/main/presenter/FileValidationService.test.ts
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use Shadcn Vue, Radix Vue, and Tailwind for components and styling.

Applied to files:

  • package.json
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/**/*.ts : Centralize configuration in configPresenter/

Applied to files:

  • src/main/presenter/index.ts
  • src/main/presenter/knowledgePresenter/index.ts
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/**/*.ts : One presenter per functional domain

Applied to files:

  • src/main/presenter/index.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : `src/main/presenter/llmProviderPresenter/index.ts` should manage the overall Agent loop, conversation history, tool execution via `McpPresenter`, and frontend communication via `eventBus`.

Applied to files:

  • src/main/presenter/knowledgePresenter/index.ts
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/common.json : Shared translation keys must be placed in 'src/renderer/src/i18n/common.json'

Applied to files:

  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/*.json : Maintain consistent structure across all translation files

Applied to files:

  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/*.json : When adding new translations, add shared keys to 'common.json' and language-specific keys to the respective language file; keep all language files' keys consistent

Applied to files:

  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/*.json : Each language must have a separate JSON file in 'src/renderer/src/i18n/'

Applied to files:

  • src/renderer/src/i18n/zh-CN/settings.json
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/renderer/src/**/*.{ts,tsx,vue} : Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
🧬 Code Graph Analysis (8)
test/main/presenter/KnowledgePresenter.test.ts (2)
src/shared/presenter.d.ts (3)
  • IConfigPresenter (343-465)
  • IFilePresenter (936-954)
  • FileValidationResult (1546-1552)
src/main/presenter/knowledgePresenter/index.ts (1)
  • KnowledgePresenter (29-461)
test/main/presenter/FilePresenter.test.ts (2)
src/main/presenter/filePresenter/FilePresenter.ts (1)
  • FilePresenter (22-307)
src/main/presenter/filePresenter/FileValidationService.ts (1)
  • IFileValidationService (14-18)
src/main/presenter/index.ts (1)
src/main/presenter/knowledgePresenter/index.ts (1)
  • KnowledgePresenter (29-461)
src/main/presenter/knowledgePresenter/index.ts (2)
src/shared/presenter.d.ts (2)
  • IFilePresenter (936-954)
  • FileValidationResult (1546-1552)
src/main/lib/textsplitters/text_splitter.ts (3)
  • SupportedTextSplitterLanguages (223-240)
  • RecursiveCharacterTextSplitter (244-671)
  • SupportedTextSplitterLanguage (242-242)
src/main/presenter/filePresenter/FilePresenter.ts (2)
src/shared/presenter.d.ts (2)
  • IFilePresenter (936-954)
  • FileValidationResult (1546-1552)
src/main/presenter/filePresenter/FileValidationService.ts (2)
  • IFileValidationService (14-18)
  • FileValidationService (20-227)
src/main/presenter/filePresenter/FileValidationService.ts (2)
src/main/presenter/filePresenter/mime.ts (2)
  • detectMimeType (111-167)
  • getMimeTypeAdapterMap (17-109)
src/main/presenter/filePresenter/UnsupportFileAdapter.ts (1)
  • UnsupportFileAdapter (3-29)
src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts (1)
src/main/presenter/index.ts (1)
  • presenter (188-188)
test/main/presenter/FileValidationService.test.ts (2)
src/main/presenter/filePresenter/FileValidationService.ts (1)
  • FileValidationService (20-227)
src/main/presenter/filePresenter/mime.ts (2)
  • getMimeTypeAdapterMap (17-109)
  • detectMimeType (111-167)
🔇 Additional comments (45)
src/main/utils/strings.ts (2)

22-28: Good move: preserve LF line breaks; safer for downstream chunking.

Switching from “flatten all newlines to space” to “normalize CR/CRLF to LF and keep LFs” is a solid change for text-splitting accuracy. The fluent chain also reads cleanly.


22-28: No callers depend on single-line output—safe to merge

Ran a search for sanitizeText(…) and common newline-flattening patterns; all uses preserve the intended behavior:

• Definitions and calls:
– src/main/utils/strings.ts (sanitizeText)
– src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts:
chunker.splitText(sanitizeText(fileInfo.content))
[sanitizeText(key)] passed to embeddings API

• No instances of .replace(/\n/g, ' '), split(/\s+/) or .join(' ') immediately following sanitizeText.

No callers assume a single-line result—no changes required.

package.json (2)

161-161: Reordering devDependencies is a no-op.

No action needed.


123-123: Confirm @types/mime-types compatibility with mime-types@2.1.35

File: package.json
Lines: 123-123

    "@types/mime-types": "^3.0.1",

Add @types/mime-types: good placement; compatibility confirmed with mime-types@2.1.35.

Keeping typings in devDependencies is correct. @types/mime-types@^3.0.1 (latest 3.0.1) supports both mime-types 2.x and 3.x—including 2.1.35—using the same stable API surface. No DTS mismatch risk.

src/renderer/src/i18n/ko-KR/settings.json (2)

505-505: fileSupport key looks good and uses placeholders correctly.

Placeholders {accept} and {count} align with other locales.


544-549: Cross-locale coverage confirmed; verify renderer usage

I ran a scan across src/renderer/src/i18n/*/settings.json and confirmed that the following keys are defined in every locale:

  • separators
  • separatorsHelper
  • invalidSeparators
  • selectLanguage
  • separatorsPreset

Next, please ensure these keys are actually consumed by the renderer (no hardcoded labels):

  • Search your UI components for calls like
    t('settings.separators'), t('settings.separatorsHelper'), etc., or their equivalent.
  • Verify there are no remaining string literals for these labels in the settings UI (e.g. separators input, presets dropdown).
src/renderer/src/i18n/zh-TW/settings.json (2)

505-505: fileSupport key updated with placeholders: LGTM.

Consistent with other locales and follows i18n placeholder style.


544-549: Separators-related keys added: LGTM; keep punctuation escaping as-is.

The explanatory string correctly escapes double quotes inside JSON.

src/renderer/src/i18n/zh-CN/settings.json (2)

507-507: fileSupport message aligns with the new dynamic format list: LGTM.

Placeholders are consistent with other locales.


543-549: Manual i18n and UI reference verification required

  • The sandbox couldn’t run i18n-check (i18n: types succeeded, but i18n failed due to missing packages).
    Please run locally:
    pnpm install
    pnpm i18n:types
    pnpm i18n -s zh-CN -f i18next --locales src/renderer/src/i18n
    
    and confirm there are no missing-key or placeholder-mismatch warnings for knowledgeBase.separators* and knowledgeBase.fileSupport.
  • Also verify that any UI code which previously referenced the onlySupport key now uses fileSupport.
src/renderer/src/i18n/fa-IR/settings.json (1)

505-505: fileSupport with placeholders: LGTM.

Interpolation variables are correct and consistent.

src/renderer/src/i18n/zh-HK/settings.json (2)

505-505: Rename to fileSupport with placeholders looks good

The dynamic placeholders are correct and consistent with other locales.


543-549: Separators/preset keys added correctly

Key set and helper text read well in zh-HK. No issues.

src/renderer/src/i18n/fr-FR/settings.json (1)

505-505: LGTM on fileSupport

Placeholder usage looks correct.

src/renderer/src/i18n/ru-RU/settings.json (1)

505-505: LGTM on fileSupport

Text and placeholders look correct.

src/main/presenter/index.ts (1)

90-94: Verified: All KnowledgePresenter calls use the new 3-arg constructor

  • src/main/presenter/index.ts (lines 90–94)
  • test/main/presenter/KnowledgePresenter.test.ts (line 109)

No remaining 2-argument instantiations found.

src/main/presenter/knowledgePresenter/knowledgeStorePresenter.ts (3)

2-2: Use of node:path is correct.

Switching to node:path is consistent with modern Node ESM imports.


98-100: Pass-through MIME to adapter creation is correct.

Forwarding fileMessage.mimeType to prepareFileCompletely lets adapters short-circuit MIME detection for performance.


136-136: Deterministic chunk IDs.

Using ${fileMessage.id}_${index} is stable and reproducible across re-index runs. Ensure your DB uniqueness constraints are by chunkId (or by [fileId, chunkIndex]) to prevent collisions.

Do your chunk tables use chunkId as the unique key or a composite key including fileId? If it’s only chunkId, re-adding the same file (with the same fileId) after a partial failure must delete existing chunks first (you already do this in reAddFile, which is good).

src/main/presenter/filePresenter/FilePresenter.ts (2)

16-20: Nice: Introduced FileValidationService via DI.

Constructor DI enables testing and future extension without hard-coding service internals.


259-270: Validation API looks solid and defensive.

validateFileForKnowledgeBase delegates to the service, normalizes errors, and returns suggestions on failure.

test/main/presenter/KnowledgePresenter.test.ts (3)

103-111: Constructor wiring with DI is correct in tests.

Passing a mocked IFilePresenter into KnowledgePresenter matches the new constructor and keeps tests focused.


183-192: Positive test coverage for happy path.

The test asserts both delegation and returned shape for supported files.


194-226: Fallback behavior test is solid – please verify mocks locally

Once you’ve updated the mock specifiers to match your alias imports, this test will remain isolated and valid. Since the sandbox couldn’t locate the Vitest binary, please manually confirm that mocks apply and no real FS/path calls occur:

• Run the specific spec locally, for example:
npx vitest -t "KnowledgePresenter Validation Methods"
• Or run the full suite:
npm test

Ensure mockFilePresenter.getSupportedExtensions is called and the fallback array is returned.

src/main/presenter/knowledgePresenter/index.ts (3)

52-56: Constructor now accepts IFilePresenter: good separation of concerns.

Storing the dependency for validation tasks avoids coupling validation logic to the store layer.


371-385: Language-specific separators with safe fallback.

Using RecursiveCharacterTextSplitter.getSeparatorsForLanguage with a conservative fallback makes the feature resilient.


392-416: Validation API is well-designed; returns actionable suggestions.

Good logging, sanitized error messages, and suggestedExtensions on failure. This matches intended UX for pre-validation in the UI.

test/main/presenter/FilePresenter.test.ts (4)

65-81: Constructor DI tests look solid

You validate both injected and default service paths without overreaching into implementation details. This is sufficient for guarding the new DI surface.


83-138: Happy path and error-path coverage for validation is adequate

The tests exercise supported/unsupported results and error fallbacks with suggested extensions, including unknown (string) errors. These align with FilePresenter’s catch behavior.


140-176: Fallback/sorting assertions for getSupportedExtensions are appropriate

Verifying contents and sortedness of the fallback list provides good guardrails around the presenter’s resilience.


178-205: Error logging assertions are precise

Asserting the exact console.error prefix strings helps prevent regression in observable logs.

src/main/presenter/filePresenter/FileValidationService.ts (2)

133-184: Supported extensions derivation is reasonable; fallback list is comprehensive

Deriving extensions via MIME map + supplementing common text formats, with a sorted fallback, is pragmatic and robust. The console.error on failure is helpful.


190-226: MIME types listing is correct and excludes wildcards

Excluding wildcard entries and audio/image types is consistent with the knowledge-base scope. Fallback list looks sensible and sorted.

src/shared/presenter.d.ts (3)

952-954: Expose new FilePresenter API on shared surface

Adding validateFileForKnowledgeBase and getSupportedExtensions to IFilePresenter aligns with the presenter implementation and tests.


1664-1666: Config surface change looks good

Adding separators?: string[] to BuiltinKnowledgeConfig matches the UI and new knowledge splitting feature.


1625-1647: Verified IKnowledgePresenter implementations
All new methods—getSupportedLanguages(), getSeparatorsForLanguage(language), validateFile(filePath), and getSupportedFileExtensions()—are implemented in src/main/presenter/knowledgePresenter/index.ts. No further action required.

src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (3)

972-986: Separator serializer looks correct

Escaping backslash, quotes, and control characters before quoting the tokens is the right approach for a user-editable representation.


992-1022: Robust parser for quoted tokens

Regex correctly handles escaped characters; de-duplication with Set is a nice touch. Consider trimming whitespace around the list string before parsing (you already call trim()).


365-427: New separators UI is well integrated

Label, tooltip, input, and language preset popover form a cohesive UX and align with the new API surface.

test/main/presenter/FileValidationService.test.ts (5)

98-121: Expected error string must match service change

These assertions expect “File type not supported for knowledge base processing”. Ensure the service change (error message update) lands, otherwise these will fail.

After applying the service diff, re-run the tests.


134-143: Wildcard matching scenario is valid

The test isolates wildcard behavior by not adding an exact 'text/csv' entry. This is a good check for the fallback matching path.


176-216: Supported extensions assertions capture both inclusion and exclusion well

You’re checking presence of common text/code formats and absence of excluded media extensions, including sortedness. This gives high confidence in the API.


218-254: MIME types list checks are comprehensive

Excluding wildcards and media types while asserting presence of typical text/pdf/code types is appropriate.


343-365: Real adapter map integration sanity check is helpful

Rebinding to the real map and ensuring arrays are returned provides minimal but effective integration coverage without coupling to the full map contents.

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

392-398: Drag-and-drop handler looks good.

Uses the centralized upload path and respects the template’s @drop.prevent. No issues.

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: 2

Caution

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

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

56-56: Fix Vue attribute typo: use class, not className

Vue templates don’t support React’s className. This breaks styling of those containers.

-      <div className="flex flex-col gap-2 text-balance">
+      <div class="flex flex-col gap-2 text-balance">
-          <div className="flex w-full items-center gap-1 relative">
+          <div class="flex w-full items-center gap-1 relative">

Also applies to: 108-108

♻️ Duplicate comments (1)
src/renderer/src/components/settings/KnowledgeFile.vue (1)

346-350: Use i18n placeholder key for toasts (avoid mixing free text with translations)

Use a dedicated i18n key with a filename placeholder for better localization. This mirrors the prior review.

-        toast({
-          title: `"${file.name}" ${t('settings.knowledgeBase.uploadError')}`,
-          description: validationResult.error,
-          variant: 'destructive',
-          duration: 3000
-        })
+        toast({
+          title: t('settings.knowledgeBase.uploadErrorWithFilename', { filename: file.name }),
+          description: validationResult.error,
+          variant: 'destructive',
+          duration: 3000
+        })
-        toast({
-          title: `${file.name} ${t('settings.knowledgeBase.uploadError')}`,
-          description: result.error,
-          variant: 'destructive',
-          duration: 3000
-        })
+        toast({
+          title: t('settings.knowledgeBase.uploadErrorWithFilename', { filename: file.name }),
+          description: result.error,
+          variant: 'destructive',
+          duration: 3000
+        })
-      toast({
-        title: `${file.name} ${t('settings.knowledgeBase.uploadError')}`,
-        description: (error as Error).message,
-        variant: 'destructive',
-        duration: 3000
-      })
+      toast({
+        title: t('settings.knowledgeBase.uploadErrorWithFilename', { filename: file.name }),
+        description: (error as Error).message,
+        variant: 'destructive',
+        duration: 3000
+      })

Follow-up: ensure the settings.knowledgeBase.uploadErrorWithFilename key exists in every locale.

#!/bin/bash
# Verify the new i18n key exists across all locales
fd settings.json src/renderer/src/i18n -x rg -nP '"uploadErrorWithFilename"\s*:' {}

Also applies to: 361-366, 383-387

🧹 Nitpick comments (3)
src/renderer/src/components/settings/KnowledgeFile.vue (3)

330-390: Optional: limited-concurrency uploads for large drops

Current loop is serial. For large drops this slows UX. Consider a lightweight limiter (no new deps) to process N files concurrently while relying on backend validation.

Example (outside the selected lines, for reference):

// simple limiter
const withLimit = (limit: number) => {
  let running = 0
  const queue: (() => Promise<void>)[] = []
  const runNext = () => {
    if (running >= limit || queue.length === 0) return
    running++
    const task = queue.shift()!
    task().finally(() => {
      running--
      runNext()
    })
  }
  return <T>(fn: () => Promise<T>) =>
    new Promise<T>((resolve, reject) => {
      queue.push(() => fn().then(resolve, reject) as unknown as Promise<void>)
      runNext()
    })
}

// usage
const limit = withLimit(3)
await Promise.all(files.map((f) => limit(() => processOneFile(f))))

Where processOneFile is the current per-file body inside handleFileUpload.


---

`162-162`: **Remove stray character in tooltip content**

There is an extra `<` rendered in the UI.

```diff
-                        {{ t('settings.knowledgeBase.copySuccess') }} <
+                        {{ t('settings.knowledgeBase.copySuccess') }}

231-231: Use English for code comments per project guidelines

Several newly added/edited comments are in Chinese. Please convert them to English to comply with repo standards.

Example changes:

-// 允许的文件扩展名 - 动态加载
+// Allowed file extensions - dynamically loaded

-// 加载支持的文件扩展名
+// Load supported file extensions

-// 处理文件上传的通用方法
+// Shared handler for file uploads (input and drag-and-drop)

-// 上传文件到内置知识库 - 拖拽处理
+// Upload files to built-in knowledge base - drag-and-drop handler

-// 初始化文件列表和支持的扩展名
+// Initialize file list and supported extensions

Also applies to: 292-293, 330-331, 392-393, 424-425

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 19b7d57 and aea2881.

📒 Files selected for processing (2)
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (9 hunks)
  • src/renderer/src/components/settings/KnowledgeFile.vue (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
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/settings/KnowledgeFile.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/settings/KnowledgeFile.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/settings/KnowledgeFile.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/settings/KnowledgeFile.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/settings/KnowledgeFile.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.

Files:

  • src/renderer/src/components/settings/KnowledgeFile.vue
🔇 Additional comments (5)
src/renderer/src/components/settings/KnowledgeFile.vue (5)

231-233: LGTM: Reactive accept list

Moving acceptExts to a ref is the right call for dynamically fetched extensions.


392-398: LGTM: Drag-and-drop funnels through the same validation path

Reusing handleFileUpload keeps logic DRY. Accept filtering is correctly deferred to backend validation for dropped files.


424-428: LGTM: Parallel initialization

Using Promise.all for file list + supported extensions is clean and efficient.


72-79: All locales include the settings.knowledgeBase.fileSupport key

Confirmed that fileSupport is defined in every settings.json under src/renderer/src/i18n. No missing translations found—no further action needed.


337-339: Backend file validation API and types verified

The knowledgePresenter.validateFile and getSupportedFileExtensions methods are implemented, exported, and match the expected signatures:

• FileValidationResult interface (includes isSupported: boolean, optional error?: string, plus mimeType?, adapterType?, suggestedExtensions?)
– src/main/presenter/filePresenter/FileValidationService.ts: lines 6–12

• knowledgePresenter.validateFile returns Promise
– src/main/presenter/knowledgePresenter/index.ts: lines 392–399

• getSupportedFileExtensions returns Promise<string[]>
– src/main/presenter/knowledgePresenter/index.ts: lines 422–427

No further changes required.

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

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

949-955: Make logs English and add error handling and loading state for supportedLanguages (duplicate of earlier feedback)

Attach a catch to avoid unhandled rejections and log in English. Track loading state for better UX.

-const separators = ref('')
-const supportedLanguages = ref<string[]>([])
-knowledgeP.getSupportedLanguages().then((res) => {
-  supportedLanguages.value = res
-  console.log('支持的语言:', supportedLanguages.value)
-})
+const separators = ref('')
+const supportedLanguages = ref<string[]>([])
+const isLoadingLanguages = ref(false)
+isLoadingLanguages.value = true
+knowledgeP
+  .getSupportedLanguages()
+  .then((res) => {
+    supportedLanguages.value = res
+    console.log('[INFO][BuiltinKnowledgeSettings] Supported languages:', supportedLanguages.value)
+  })
+  .catch((error) => {
+    console.error('[ERROR][BuiltinKnowledgeSettings] Failed to load supported languages:', error)
+    toast({
+      title: t('common.error.operationFailed'),
+      description: String(error),
+      variant: 'destructive',
+      duration: 3000
+    })
+  })
+  .finally(() => {
+    isLoadingLanguages.value = false
+  })

956-961: Harden language preset loading with try/catch and always close the popover (duplicate of earlier feedback)

Avoid unhandled rejections and ensure UI closes regardless of outcome. Use English for the comment.

-// 处理语言选择
-const handleLanguageSelect = async (language: string) => {
-  separators.value = separatorsArray2String(await getSeparatorsForLanguage(language))
-  separatorsPopoverOpen.value = false
-}
+// Handle language preset selection
+const handleLanguageSelect = async (language: string) => {
+  try {
+    const arr = await getSeparatorsForLanguage(language)
+    separators.value = separatorsArray2String(arr)
+  } catch (error) {
+    console.error('[ERROR][BuiltinKnowledgeSettings] Failed to load separators for language:', language, error)
+    toast({
+      title: t('common.error.operationFailed'),
+      description: String(error),
+      variant: 'destructive',
+      duration: 3000
+    })
+  } finally {
+    separatorsPopoverOpen.value = false
+  }
+}
🧹 Nitpick comments (6)
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (6)

395-404: Add aria-label to the “presets” icon-only button for accessibility

Icon-only controls should expose an accessible name.

-                            <Button
+                            <Button
                               size="xs"
                               variant="ghost"
                               class="whitespace-nowrap"
                               :title="t('settings.knowledgeBase.separatorsPreset')"
+                              :aria-label="t('settings.knowledgeBase.separatorsPreset')"
                             >

405-423: Show loading/empty state for language presets list

Provide feedback while loading and when no languages are available.

-                          <PopoverContent class="w-40 p-2">
+                          <PopoverContent class="w-40 p-2">
                             <div class="space-y-2">
                               <div class="text-sm text-secoudary">
                                 {{ t('settings.knowledgeBase.selectLanguage') }}
                               </div>
-                              <div class="max-h-48 overflow-y-auto space-y-1">
-                                <Button
-                                  v-for="language in supportedLanguages"
-                                  :key="language"
-                                  variant="ghost"
-                                  size="sm"
-                                  class="w-full justify-start text-left"
-                                  @click="handleLanguageSelect(language)"
-                                >
-                                  {{ language }}
-                                </Button>
-                              </div>
+                              <div v-if="isLoadingLanguages" class="text-xs text-muted-foreground py-1">
+                                {{ t('common.loading') }}
+                              </div>
+                              <div v-else-if="supportedLanguages.length === 0" class="text-xs text-muted-foreground py-1">
+                                {{ t('common.empty') }}
+                              </div>
+                              <div v-else class="max-h-48 overflow-y-auto space-y-1">
+                                <Button
+                                  v-for="language in supportedLanguages"
+                                  :key="language"
+                                  variant="ghost"
+                                  size="sm"
+                                  class="w-full justify-start text-left"
+                                  @click="handleLanguageSelect(language)"
+                                >
+                                  {{ language }}
+                                </Button>
+                              </div>
                             </div>
                           </PopoverContent>

614-615: Use English for comments

Align with repo guidelines for TS/Vue files.

-// 分隔符弹窗
+// Separators popover
 const separatorsPopoverOpen = ref(false)

962-965: Nit: no need for async/await in a simple forwarder

Return the promise directly; it keeps the type and avoids an extra microtask.

-const getSeparatorsForLanguage = async (language: string) => {
-  return await knowledgeP.getSeparatorsForLanguage(language)
-}
+const getSeparatorsForLanguage = (language: string) => knowledgeP.getSeparatorsForLanguage(language)

971-985: Use English comments and guard non-array inputs

Minor robustness: handle unexpected inputs gracefully; also translate comments.

-/**
- * separator array to string
- * @example separatorsArray2String(['\n\n', '\n', ' ', '']) // '"\n\n", "\n", " ", ""'
- * @param arr
- */
+/**
+ * Convert separator array to a quoted, escaped string list.
+ * @example separatorsArray2String(['\n\n', '\n', ' ', '']) // '"\n\n", "\n", " ", ""'
+ * @param arr string[]
+ */
 const separatorsArray2String = (arr: string[]): string => {
-  // 对特殊字符进行转义处理
-  return arr
+  // Escape special characters for safe inline display
+  if (!Array.isArray(arr)) return ''
+  return arr
     .map((s) => {
-      // 转义双引号、反斜杠、换行、回车、制表符等特殊字符
+      // Escape quotes, backslashes, newlines, carriage returns, tabs, etc.
       const escaped = s
         .replace(/\\/g, '\\\\')
         .replace(/"/g, '\\"')
         .replace(/\n/g, '\\n')
         .replace(/\r/g, '\\r')
         .replace(/\t/g, '\\t')
       return `"${escaped}"`
     })
     .join(', ')
 }

991-1021: Prefer English comments and minor defensive tweaks

Keep comments consistent with repo guidelines; optionally short-circuit early for empty input.

-/**
- * separator string to array, remove quotes and duplicates
- * @example separatorString2Array('"\n\n", "\n", " ", ""') // ['\n\n', '\n', ' ', '']
- * @param str
- */
+/**
+ * Parse quoted separators into an array, unescaping and de-duplicating.
+ * @example separatorString2Array('"\n\n", "\n", " ", ""') // ['\n\n', '\n', ' ', '']
+ * @param str string
+ */
 const separatorString2Array = (str: string): string[] => {
-  // 正则匹配所有被双引号包裹的内容(支持转义字符)
+  // Match all double-quoted segments (supports escapes)
   const regex = /"((?:\\.|[^"\\])*)"/g
   const matches: string[] = []
   let match
 
-  // 提取所有匹配项
+  // Extract every match
   while ((match = regex.exec(str.trim())) !== null) {
-    // 处理转义字符(将 \n、\t 等还原为实际字符)
+    // Unescape sequences (\n, \t, \r, \", \\)
     const unescaped = match[1].replace(/\\([nrt"\\])/g, (_, char) => {
       switch (char) {
         case 'n':
           return '\n'
         case 'r':
           return '\r'
         case 't':
           return '\t'
         case '"':
           return '"'
         case '\\':
           return '\\'
         default:
           return char
       }
     })
     matches.push(unescaped)
   }
 
-  // 去重并返回
+  // De-duplicate and return
   return Array.from(new Set(matches))
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between aea2881 and 8295006.

📒 Files selected for processing (2)
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (10 hunks)
  • src/renderer/src/components/settings/KnowledgeFile.vue (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/components/settings/KnowledgeFile.vue
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
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/settings/BuiltinKnowledgeSettings.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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/settings/BuiltinKnowledgeSettings.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/settings/BuiltinKnowledgeSettings.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/settings/BuiltinKnowledgeSettings.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.

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
🧠 Learnings (4)
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to **/*.{ts,tsx,js,jsx,vue} : Use English for logs and comments

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : `src/main/presenter/llmProviderPresenter/index.ts` should manage the overall Agent loop, conversation history, tool execution via `McpPresenter`, and frontend communication via `eventBus`.

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/**/*.ts : Centralize configuration in configPresenter/

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/renderer/src/**/*.{ts,tsx,vue} : Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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 (5)
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (5)

347-348: LGTM: clear “normalized” helper hint

Using the emoji prefix is consistent with the other warnings and the copy is i18n-driven.


455-456: LGTM: chunk size placeholder is correctly i18n-bound

Thanks for switching to a translation key and the proper prop casing.


605-606: LGTM: presenter injection for knowledgePresenter

Correctly uses usePresenter composable; aligns with architecture guidance.


669-669: LGTM: reset separators on “Add config”

Prevents carrying over stale state into new configs.


776-776: LGTM: clear separators on dialog close

Good cleanup to avoid leaking state between sessions.

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: 0

♻️ Duplicate comments (4)
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (4)

388-394: Localize the separators placeholder (avoid hardcoded user-visible text)

Replace the hardcoded placeholder with an i18n key.

-                        <Input
+                        <Input
                           id="edit-builtin-config-separators"
                           v-model="separators"
-                          placeholder='"\n\n", "\n", " ", ""'
+                          :placeholder="t('settings.knowledgeBase.separatorsPlaceholder')"
                           class="flex-1"
                         ></Input>

794-797: Translate comment to English (logic is good, comment needs localization)

You already implemented the removal logic; just convert the comment to English.

-  // 转换separators格式
+  // Convert separators string input into an array and persist/remove accordingly

953-959: English logs and add error handling for getSupportedLanguages()

Logs must be in English, and the IPC call should be guarded with a catch to avoid unhandled rejections and to notify users.

-const separators = ref('')
-const supportedLanguages = ref<string[]>([])
-knowledgeP.getSupportedLanguages().then((res) => {
-  supportedLanguages.value = res
-  console.log('支持的语言:', supportedLanguages.value)
-})
+const separators = ref('')
+const supportedLanguages = ref<string[]>([])
+knowledgeP
+  .getSupportedLanguages()
+  .then((res) => {
+    supportedLanguages.value = res
+    console.log('[INFO][BuiltinKnowledgeSettings] Supported languages:', supportedLanguages.value)
+  })
+  .catch((error) => {
+    console.error('[ERROR][BuiltinKnowledgeSettings] Failed to load supported languages:', error)
+    toast({
+      title: t('common.error.operationFailed'),
+      description: String(error),
+      variant: 'destructive',
+      duration: 3000
+    })
+  })

961-964: Harden language preset loading with try/catch and always close the popover

Prevents unhandled rejections and ensures UI closes even on errors, with user feedback.

-const handleLanguageSelect = async (language: string) => {
-  separators.value = separatorsArray2String(await getSeparatorsForLanguage(language))
-  separatorsPopoverOpen.value = false
-}
+const handleLanguageSelect = async (language: string) => {
+  try {
+    const arr = await getSeparatorsForLanguage(language)
+    separators.value = separatorsArray2String(arr)
+  } catch (error) {
+    console.error('[ERROR][BuiltinKnowledgeSettings] Failed to load separators for language:', language, error)
+    toast({
+      title: t('common.error.operationFailed'),
+      description: String(error),
+      variant: 'destructive',
+      duration: 3000
+    })
+  } finally {
+    separatorsPopoverOpen.value = false
+  }
+}
🧹 Nitpick comments (4)
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (4)

347-347: Move the warning icon into i18n (avoid mixing literal UI text with translations)

Keep all user-visible content in translations. Put the "⚠️" inside the i18n string instead of hardcoding it in the template.

-                          <p>⚠️ {{ t('settings.knowledgeBase.normalizedHelper') }}</p>
+                          <p>{{ t('settings.knowledgeBase.normalizedHelper') }}</p>

Follow-up: update the translation value for settings.knowledgeBase.normalizedHelper to include the "⚠️" prefix. Do you want me to open a PR for the locale files?


614-616: Use English comments per guidelines

Convert this comment to English.

-// 分隔符弹窗
+// Separators popover

966-969: Nit: Remove unnecessary await and add return type

The additional await is unnecessary, and returning an explicit Promise<string[]> clarifies intent.

-const getSeparatorsForLanguage = async (language: string) => {
-  return await knowledgeP.getSeparatorsForLanguage(language)
-}
+const getSeparatorsForLanguage = (language: string): Promise<string[]> => {
+  return knowledgeP.getSeparatorsForLanguage(language)
+}

995-1025: Type safety and minor perf nit in separatorString2Array

Avoid implicit any for the regex exec result and avoid re-trimming on every iteration.

-const separatorString2Array = (str: string): string[] => {
-  // 正则匹配所有被双引号包裹的内容(支持转义字符)
-  const regex = /"((?:\\.|[^"\\])*)"/g
-  const matches: string[] = []
-  let match
-
-  // 提取所有匹配项
-  while ((match = regex.exec(str.trim())) !== null) {
-    // 处理转义字符(将 \n、\t 等还原为实际字符)
-    const unescaped = match[1].replace(/\\([nrt"\\])/g, (_, char) => {
+const separatorString2Array = (str: string): string[] => {
+  // Match quoted segments (supports escape sequences)
+  const regex = /"((?:\\.|[^"\\])*)"/g
+  const matches: string[] = []
+  const input = str.trim()
+  let exec: RegExpExecArray | null
+
+  // Extract all matches
+  while ((exec = regex.exec(input)) !== null) {
+    // Unescape \n, \r, \t, quotes and backslashes
+    const unescaped = exec[1].replace(/\\([nrt"\\])/g, (_, char) => {
       switch (char) {
         case 'n':
           return '\n'
         case 'r':
           return '\r'
         case 't':
           return '\t'
         case '"':
           return '"'
         case '\\':
           return '\\'
         default:
           return char
       }
     })
     matches.push(unescaped)
   }
 
   // 去重并返回
   return Array.from(new Set(matches))
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8295006 and 192c91e.

📒 Files selected for processing (1)
  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (10 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
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/settings/BuiltinKnowledgeSettings.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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/settings/BuiltinKnowledgeSettings.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/settings/BuiltinKnowledgeSettings.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/settings/BuiltinKnowledgeSettings.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.

Files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
🧠 Learnings (4)
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to **/*.{ts,tsx,js,jsx,vue} : Use English for logs and comments

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : `src/main/presenter/llmProviderPresenter/index.ts` should manage the overall Agent loop, conversation history, tool execution via `McpPresenter`, and frontend communication via `eventBus`.

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/**/*.ts : Centralize configuration in configPresenter/

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/renderer/src/**/*.{ts,tsx,vue} : Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Applied to files:

  • src/renderer/src/components/settings/BuiltinKnowledgeSettings.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 (9)
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (9)

365-386: LGTM: Solid separators UI structure with labeling and helper tooltip

Clear labeling, helper tooltip, and Composition API usage align with guidelines.


395-426: LGTM: Language preset popover and selection flow make sense

The popover and language list are straightforward and discoverable. Good use of v-model to control open state.


455-455: LGTM: Chunk size placeholder correctly uses i18n

This aligns with the renderer i18n requirement.


605-605: LGTM: Presenter wiring for KnowledgePresenter

Correctly uses usePresenter('knowledgePresenter') for renderer→main calls.


669-669: LGTM: Reset separators on “Add config”

Prevents stale values when starting a new config.


746-751: LGTM: Clear separators when editing a config without separators

Prevents stale UI values when the target config lacks separators.


778-779: LGTM: Reset separators on dialog close

Avoids leaking state across sessions.


795-809: LGTM: Robust separators handling on save (validate, persist, and allow removal)

  • Parses string → array
  • Validates empty result with toast
  • Deletes the field when blank to allow removal

Matches earlier feedback.


975-989: LGTM: Safe escaping for separatorsArray2String

Properly escapes backslashes, quotes, and control characters before quoting and joining.

@zerob13 zerob13 merged commit dc20e13 into ThinkInAIXYZ:dev Aug 20, 2025
2 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2025
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.

2 participants