-
Notifications
You must be signed in to change notification settings - Fork 614
Optimize/builtin knowledge text splitter #757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize/builtin knowledge text splitter #757
Conversation
…wledge-text-splitter
…upported extensions
…idation and supported extensions retrieval
… file checks and extensions retrieval
…upported file types
WalkthroughAdds 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
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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
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
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
…ettings; add tooltip for accepted file extensions in KnowledgeFile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 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) consistentlyOther 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)
Inputexpectsplaceholder; 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 invalidclassNameattribute (Vue usesclass).Using
classNameprevents styles from applying; Vue templates requireclass. 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 labelReplace 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
scorePercentexist 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.txt→C: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 textSmall UX polish.
- "fileSupport": "Support {accept} and {count} other formats", + "fileSupport": "Supports {accept} and {count} other formats",
545-549: Use imperative “Load presets” for separatorsPresetAll locale files already include the
separatorsPresetkey—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 labelKeep 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 intofileMessage.mimeType/nameimproves 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.separatorsenables 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.filePresenterfrom inside the store presenter creates a cyclic dependency path. Consider injecting anIFilePresenter(or MIME detector) directly intoKnowledgeStorePresenterto 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
getMetricfrom@/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_EXTENSIONSfrom 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
findAdapterForMimeTypealways returns a constructor (falls back to UnsupportFileAdapter), soif (!AdapterConstructor)cannot be hit. Consider simplifying by checking explicitly forUnsupportFileAdapterand 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 definitionThe
FileValidationResultinterface 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, inFileValidationService.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 i18nTo 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 emptyCurrently, 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.
📒 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.tstest/main/presenter/FilePresenter.test.tssrc/main/presenter/index.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/shared/presenter.d.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/main/presenter/knowledgePresenter/knowledgeStorePresenter.tstest/main/presenter/FileValidationService.test.tssrc/renderer/src/components/settings/KnowledgeFile.vuesrc/main/utils/strings.tssrc/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.tstest/main/presenter/FilePresenter.test.tssrc/main/presenter/index.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/shared/presenter.d.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/main/presenter/knowledgePresenter/knowledgeStorePresenter.tstest/main/presenter/FileValidationService.test.tssrc/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.tstest/main/presenter/FilePresenter.test.tstest/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.tstest/main/presenter/FilePresenter.test.tstest/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.tstest/main/presenter/FilePresenter.test.tssrc/main/presenter/index.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/shared/presenter.d.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/main/presenter/knowledgePresenter/knowledgeStorePresenter.tstest/main/presenter/FileValidationService.test.tssrc/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.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/main/presenter/knowledgePresenter/knowledgeStorePresenter.tssrc/main/utils/strings.ts
src/main/presenter/**/*.ts
📄 CodeRabbit Inference Engine (CLAUDE.md)
One presenter per functional domain
Files:
src/main/presenter/index.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/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.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/main/presenter/knowledgePresenter/knowledgeStorePresenter.tssrc/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.tssrc/main/presenter/knowledgePresenter/index.tssrc/main/presenter/filePresenter/FilePresenter.tssrc/main/presenter/filePresenter/FileValidationService.tssrc/main/presenter/knowledgePresenter/knowledgeStorePresenter.tssrc/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.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/components/settings/KnowledgeFile.vuesrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/components/settings/BuiltinKnowledgeSettings.vuesrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/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 componentsUse scoped styles to prevent CSS conflicts between components
Files:
src/renderer/src/components/settings/KnowledgeFile.vuesrc/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.vuesrc/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.vuesrc/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.vuesrc/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.vuesrc/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.vuesrc/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.vuesrc/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.tstest/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.tssrc/main/presenter/knowledgePresenter/index.tssrc/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.tssrc/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.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/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.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/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.jsonsrc/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 mergeRan 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 followingsanitizeText.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.35File: 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 bothmime-types2.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 usageI ran a scan across
src/renderer/src/i18n/*/settings.jsonand 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: typessucceeded, buti18nfailed due to missing packages).
Please run locally:and confirm there are no missing-key or placeholder-mismatch warnings forpnpm install pnpm i18n:types pnpm i18n -s zh-CN -f i18next --locales src/renderer/src/i18nknowledgeBase.separators*andknowledgeBase.fileSupport.- Also verify that any UI code which previously referenced the
onlySupportkey now usesfileSupport.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 goodThe dynamic placeholders are correct and consistent with other locales.
543-549: Separators/preset keys added correctlyKey set and helper text read well in zh-HK. No issues.
src/renderer/src/i18n/fr-FR/settings.json (1)
505-505: LGTM on fileSupportPlaceholder usage looks correct.
src/renderer/src/i18n/ru-RU/settings.json (1)
505-505: LGTM on fileSupportText and placeholders look correct.
src/main/presenter/index.ts (1)
90-94: Verified: AllKnowledgePresentercalls 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:pathis consistent with modern Node ESM imports.
98-100: Pass-through MIME to adapter creation is correct.Forwarding
fileMessage.mimeTypetoprepareFileCompletelylets 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
chunkIdas the unique key or a composite key includingfileId? If it’s onlychunkId, re-adding the same file (with the samefileId) 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.
validateFileForKnowledgeBasedelegates 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
IFilePresenterintoKnowledgePresentermatches 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 locallyOnce 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 testEnsure
mockFilePresenter.getSupportedExtensionsis 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.getSeparatorsForLanguagewith a conservative fallback makes the feature resilient.
392-416: Validation API is well-designed; returns actionable suggestions.Good logging, sanitized error messages, and
suggestedExtensionson failure. This matches intended UX for pre-validation in the UI.test/main/presenter/FilePresenter.test.ts (4)
65-81: Constructor DI tests look solidYou 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 adequateThe 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 appropriateVerifying contents and sortedness of the fallback list provides good guardrails around the presenter’s resilience.
178-205: Error logging assertions are preciseAsserting 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 comprehensiveDeriving 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 wildcardsExcluding 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 surfaceAdding
validateFileForKnowledgeBaseandgetSupportedExtensionsto IFilePresenter aligns with the presenter implementation and tests.
1664-1666: Config surface change looks goodAdding
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), andgetSupportedFileExtensions()—are implemented insrc/main/presenter/knowledgePresenter/index.ts. No further action required.src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue (3)
972-986: Separator serializer looks correctEscaping backslash, quotes, and control characters before quoting the tokens is the right approach for a user-editable representation.
992-1022: Robust parser for quoted tokensRegex 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 integratedLabel, 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 changeThese 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 validThe 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 wellYou’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 comprehensiveExcluding wildcards and media types while asserting presence of typical text/pdf/code types is appropriate.
343-365: Real adapter map integration sanity check is helpfulRebinding 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.
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/renderer/src/components/settings/KnowledgeFile.vue (1)
56-56: Fix Vue attribute typo: useclass, notclassNameVue 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.uploadErrorWithFilenamekey 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 dropsCurrent 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
processOneFileis the current per-file body insidehandleFileUpload.--- `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 guidelinesSeveral 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 extensionsAlso 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.
📒 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 componentsUse 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 listMoving acceptExts to a ref is the right call for dynamically fetched extensions.
392-398: LGTM: Drag-and-drop funnels through the same validation pathReusing
handleFileUploadkeeps logic DRY. Accept filtering is correctly deferred to backend validation for dropped files.
424-428: LGTM: Parallel initializationUsing Promise.all for file list + supported extensions is clean and efficient.
72-79: All locales include thesettings.knowledgeBase.fileSupportkeyConfirmed that
fileSupportis defined in everysettings.jsonundersrc/renderer/src/i18n. No missing translations found—no further action needed.
337-339: Backend file validation API and types verifiedThe
knowledgePresenter.validateFileandgetSupportedFileExtensionsmethods are implemented, exported, and match the expected signatures:• FileValidationResult interface (includes
isSupported: boolean, optionalerror?: string, plusmimeType?,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–427No further changes required.
… and KnowledgeFile components
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 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 accessibilityIcon-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 listProvide 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 commentsAlign with repo guidelines for TS/Vue files.
-// 分隔符弹窗 +// Separators popover const separatorsPopoverOpen = ref(false)
962-965: Nit: no need for async/await in a simple forwarderReturn 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 inputsMinor 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 tweaksKeep 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.
📒 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 componentsUse 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 hintUsing the emoji prefix is consistent with the other warnings and the copy is i18n-driven.
455-456: LGTM: chunk size placeholder is correctly i18n-boundThanks for switching to a translation key and the proper prop casing.
605-606: LGTM: presenter injection for knowledgePresenterCorrectly 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 closeGood cleanup to avoid leaking state between sessions.
src/renderer/src/components/settings/BuiltinKnowledgeSettings.vue
Outdated
Show resolved
Hide resolved
…tors in BuiltinKnowledgeSettings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 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 popoverPrevents 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 guidelinesConvert this comment to English.
-// 分隔符弹窗 +// Separators popover
966-969: Nit: Remove unnecessary await and add return typeThe 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 separatorString2ArrayAvoid 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.
📒 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 componentsUse 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 tooltipClear labeling, helper tooltip, and Composition API usage align with guidelines.
395-426: LGTM: Language preset popover and selection flow make senseThe 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 i18nThis aligns with the renderer i18n requirement.
605-605: LGTM: Presenter wiring for KnowledgePresenterCorrectly 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 separatorsPrevents stale UI values when the target config lacks separators.
778-779: LGTM: Reset separators on dialog closeAvoids 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 separatorsArray2StringProperly escapes backslashes, quotes, and control characters before quoting and joining.
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.
see below
Platform Compatibility Notes
If this PR has specific platform compatibility considerations (Windows, macOS, Linux), please describe them here.
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 更改,请详细描述它们。
平台兼容性注意事项
如果此 PR 具有特定的平台兼容性考虑因素(Windows、macOS、Linux),请在此处描述。
附加背景
本地知识库作为用户离线使用的手段,它仅提供了一种简单易用的知识库实现。对于复杂和专业的RAG需求,更推荐使用
RAG Flow等更专业的知识库服务。Summary by CodeRabbit
New Features
Improvements
i18n
Tests