-
Notifications
You must be signed in to change notification settings - Fork 614
chore: fix DataImporter bug and some ux optimises #818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Improve the web content length limit setting in CommonSettings with: - Replace simple input with interactive counter design - Add -/+ buttons for quick adjustments (±100 step) - Enable click-to-edit number for direct input - Update range to 0-10000 characters - Maintain single-row compact layout - Add visual feedback and hover states 🤖 Generated with [Claude Code](https://claude.ai/code)
…t and clearSystemPrompt
…orter - Add missing fields (enabled_mcp_tools, thinking_budget, reasoning_effort, verbosity) to SELECT query - Add compatibility handling for different database schema versions - Use try-catch to fall back to basic fields when new fields are not available - Ensure INSERT and SELECT statements have matching field structure Fixes data import error: Failed to import data
… import - Fix 'no such column: metadata' error in message_attachments table - Add schema compatibility handling for both source and target databases - Use try-catch pattern to fall back to basic schema when metadata column is not available - Fix TypeScript errors by properly handling unknown error types - Ensure both SELECT and INSERT operations are compatible with different schema versions Resolves the core issue causing data import failures: SqliteError: no such column: metadata
- Remove verbose console.log statements used for debugging - Remove unnecessary try-catch wrappers that only rethrow errors - Keep essential error handling and schema compatibility features - Fix TypeScript errors related to unused catch parameters Code is now production-ready after successful debugging phase.
WalkthroughAdds default system-prompt management (reset/clear) with migration to 0.3.4, introduces model-type awareness for image-generation flows across presenter and UI, enhances SQLite importer with multi-version schema fallbacks and richer errors, updates CommonSettings web content limit control, bumps package version, and adds i18n strings for new prompt actions. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant TitleView as TitleView.vue
participant NewThread as NewThread.vue
participant ChatConfig as ChatConfig.vue
participant ThreadP as threadPresenter
participant Model as Model API
User->>TitleView: Select model
TitleView->>ChatConfig: :model-type = config.type
User->>NewThread: Start new thread
NewThread->>ChatConfig: :model-type = activeModel.type
User->>ChatConfig: Send message
ChatConfig->>ThreadP: preparePromptContent(..., modelType)
alt modelType == ImageGeneration
ThreadP-->>ThreadP: Suppress systemPrompt/search/enrichment/MCP tooling
ThreadP->>Model: formatMessagesForCompletion(with empty systemPrompt)
else
ThreadP-->>ThreadP: Include systemPrompt/search/enrichment/MCP tooling
ThreadP->>Model: formatMessagesForCompletion(with systemPrompt)
end
Model-->>ThreadP: Response
ThreadP-->>User: Rendered result
sequenceDiagram
autonumber
participant Importer as importData.ts
participant SrcDB as Source SQLite
participant DstDB as Target SQLite
Importer->>DstDB: BEGIN TRANSACTION
Importer->>SrcDB: SELECT conversations (try new fields)
alt New-schema available
SrcDB-->>Importer: Rows (new fields)
else Fallback
Importer->>SrcDB: SELECT conversations (legacy fields)
SrcDB-->>Importer: Rows (legacy)
Importer-->>Importer: Normalize missing fields with defaults
end
loop each conversation
Importer->>DstDB: INSERT conversation (try new-fields insert)
alt Insert fails
Importer->>DstDB: INSERT conversation (legacy insert)
end
Importer->>SrcDB: SELECT messages
loop each message
Importer->>DstDB: INSERT message (try/catch)
opt attachments
Importer->>SrcDB: SELECT message_attachments (try with metadata)
alt metadata missing
Importer->>SrcDB: SELECT message_attachments (legacy)
Importer-->>Importer: Normalize metadata=null
end
Importer->>DstDB: INSERT attachments (try with metadata, fallback)
end
end
end
Importer->>DstDB: COMMIT
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
✨ 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 (
|
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: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/shared/presenter.d.ts (1)
1040-1040: Type typo breaks type-checking: useunknown
unknowis invalid TS type and will cause declaration errors.- env: Record<string, unknow> + env: Record<string, unknown>src/main/presenter/sqlitePresenter/importData.ts (1)
37-39: Password quoting in PRAGMA is unsafe; escape or use hex key.Direct string interpolation into
PRAGMA keycan break on quotes and is injection-prone. Escape single quotes or use the recommended hex key format.- this.sourceDb.pragma(`cipher='sqlcipher'`) - this.sourceDb.pragma(`key='${sourcePassword}'`) + this.sourceDb.pragma(`cipher='sqlcipher'`) + this.sourceDb.pragma(`key='${String(sourcePassword).replace(/'/g, "''")}'`) @@ - this.targetDb.pragma(`cipher='sqlcipher'`) - this.targetDb.pragma(`key='${targetPassword}'`) + this.targetDb.pragma(`cipher='sqlcipher'`) + this.targetDb.pragma(`key='${String(targetPassword).replace(/'/g, "''")}'`)Optional:
this.sourceDb.pragma("key = \"x'" + Buffer.from(sourcePassword).toString('hex') + "'\"")to avoid quoting entirely.Also applies to: 49-51
🧹 Nitpick comments (12)
src/shared/presenter.d.ts (1)
461-463: Document new API and align semanticsAdd brief JSDoc to clarify behavior (reset uses built‑in default; clear sets to empty/no system prompt). Consider renaming for clarity to resetSystemPromptToDefault/clearSystemPrompt if feasible (optional).
// 默认系统提示词设置 getDefaultSystemPrompt(): Promise<string> setDefaultSystemPrompt(prompt: string): Promise<void> + /** + * Reset the system prompt to the built-in default value (removes any user override). + */ resetToDefaultPrompt(): Promise<void> + /** + * Clear the system prompt (sets to empty / no system prompt). + */ clearSystemPrompt(): Promise<void>src/renderer/src/i18n/en-US/settings.json (1)
797-800: Tighten English copy“Clear prompt words” is awkward; use “Clear prompt” for brevity/consistency.
"promptSetting": { "resetToDefault": "Reset to default prompt", - "clear": "Clear prompt words" + "clear": "Clear prompt" }src/renderer/src/components/ChatConfig.vue (2)
38-41: Use English for comments.Project guideline requires English for logs/comments. Please translate these inline comments.
-// 判断是否为图片生成模型 +// Whether the selected model is an image-generation model
141-163: Reduce v-if chain with a computed icon name.Minor readability win: compute the icon once and render a single Icon.
- <Icon - v-if="props.modelType === 'chat'" - icon="lucide:message-circle" - class="w-3 h-3 text-muted-foreground" - /> - <Icon - v-else-if="props.modelType === 'imageGeneration'" - icon="lucide:image" - class="w-3 h-3 text-muted-foreground" - /> - <Icon - v-else-if="props.modelType === 'embedding'" - icon="lucide:layers" - class="w-3 h-3 text-muted-foreground" - /> - <Icon - v-else-if="props.modelType === 'rerank'" - icon="lucide:arrow-up-down" - class="w-3 h-3 text-muted-foreground" - /> + <Icon :icon="{ + chat: 'lucide:message-circle', + imageGeneration: 'lucide:image', + embedding: 'lucide:layers', + rerank: 'lucide:arrow-up-down' + }[props.modelType || 'chat']" class="w-3 h-3 text-muted-foreground" />src/renderer/src/components/TitleView.vue (1)
126-127: Ensure config includes ‘type’; add defensive default.If
getModelDefaultConfigever omitstype,modelTypebecomes undefined. Default toModelType.Chatto avoid UI regressions.-const modelType = ref(ModelType.Chat) +const modelType = ref(ModelType.Chat) ... - modelType.value = config.type + modelType.value = (config as any)?.type ?? ModelType.ChatAlso applies to: 135-135
src/renderer/src/components/NewThread.vue (1)
216-217: Prefer carrying through model tags when available.You’re setting
tags: []repeatedly even whenmodel.tagsmay exist. Minor, but loses UI info.- tags: [], + tags: model.tags ?? [], @@ - tags: [], + tags: model.tags ?? [], @@ - tags: [], + tags: model.tags ?? [], @@ - tags: [], + tags: model.tags ?? [],Also applies to: 243-244, 269-269, 301-301
src/main/presenter/sqlitePresenter/importData.ts (2)
1-63: Enable foreign keys and use English comments.
- Turn on FK enforcement to catch integrity issues early.
- Comments are in Chinese; project guideline requires English.
constructor( @@ - // 初始化源数据库连接 + // Initialize source database connection this.sourceDb = new Database(sourcePath) + this.sourceDb.pragma('foreign_keys = ON') @@ - this.targetDb = new Database(targetDbOrPath) + this.targetDb = new Database(targetDbOrPath) this.targetDb.pragma('journal_mode = WAL') + this.targetDb.pragma('foreign_keys = ON')
237-296: Prepare statements once per method to improve performance.Inside tight loops you repeatedly call
prepare. Hoistpreparecalls outside loops and reuse statements.src/main/presenter/configPresenter/index.ts (1)
33-38: Minor copy nit in DEFAULT_SYSTEM_PROMPT.Missing space: “languages.Always”. Consider tightening wording.
-Adhere to this in all languages.Always respond in the same language as the user's query.` +Adhere to this in all languages. Always respond in the same language as the user's query.`src/renderer/src/components/settings/CommonSettings.vue (3)
448-450: limitInputRef unused; optionally focus after entering edit mode.Call focus to justify the new ref.
const startEditingLimit = () => { isEditingLimit.value = true + setTimeout(() => limitInputRef.value?.focus(), 0) }Also applies to: 751-759
724-736: Logs must be English and avoid hardcoded CN text.Update log string; keep behavior unchanged.
- if (numValue >= 0 && numValue <= 10000 && !isNaN(numValue)) { + if (numValue >= 0 && numValue <= 10000 && !isNaN(numValue)) { try { - const displayText = numValue === 0 ? '无限制' : `${numValue}字符` - console.log('设置网页内容长度限制:', displayText) + const displayText = numValue === 0 ? 'Unlimited' : `${numValue} characters` + console.log('Set web content length limit:', displayText) // 直接调用presenter设置,不依赖store await configPresenter.setSetting('webContentLengthLimit', numValue) // 更新响应式变量 webContentLengthLimit.value = numValue } catch (error) { - console.error('设置网页内容长度限制失败:', error) + console.error('Failed to set web content length limit:', error) } }
739-748: Clamp WebContentLengthLimit max to 10,000
- Change upper bound from 20,000 to 10,000 to match the input’s max and disabled state.
- Verify that
settings.common.unlimitedandsettings.common.charactersi18n keys exist.-const increaseWebContentLimit = () => { - const newValue = Math.min(webContentLengthLimit.value + 100, 20000) +const increaseWebContentLimit = () => { + const newValue = Math.min(webContentLengthLimit.value + 100, 10000) handleWebContentLengthLimitChange(newValue) }
📜 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 (20)
package.json(1 hunks)src/main/presenter/configPresenter/index.ts(5 hunks)src/main/presenter/sqlitePresenter/importData.ts(5 hunks)src/main/presenter/threadPresenter/index.ts(3 hunks)src/renderer/src/components/ChatConfig.vue(4 hunks)src/renderer/src/components/NewThread.vue(6 hunks)src/renderer/src/components/TitleView.vue(3 hunks)src/renderer/src/components/settings/CommonSettings.vue(4 hunks)src/renderer/src/components/settings/PromptSetting.vue(2 hunks)src/renderer/src/i18n/en-US/settings.json(1 hunks)src/renderer/src/i18n/fa-IR/settings.json(1 hunks)src/renderer/src/i18n/fr-FR/settings.json(1 hunks)src/renderer/src/i18n/ja-JP/settings.json(1 hunks)src/renderer/src/i18n/ko-KR/settings.json(1 hunks)src/renderer/src/i18n/ru-RU/settings.json(1 hunks)src/renderer/src/i18n/zh-CN/settings.json(1 hunks)src/renderer/src/i18n/zh-HK/settings.json(1 hunks)src/renderer/src/i18n/zh-TW/settings.json(1 hunks)src/renderer/src/stores/settings.ts(2 hunks)src/shared/presenter.d.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (21)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写
Files:
src/shared/presenter.d.tssrc/renderer/src/stores/settings.tssrc/main/presenter/sqlitePresenter/importData.tssrc/main/presenter/configPresenter/index.tssrc/main/presenter/threadPresenter/index.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
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/error-logging.mdc)
**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别Enable and adhere to strict TypeScript type checking
Files:
src/shared/presenter.d.tssrc/renderer/src/stores/settings.tssrc/main/presenter/sqlitePresenter/importData.tssrc/main/presenter/configPresenter/index.tssrc/main/presenter/threadPresenter/index.ts
src/shared/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
共享类型定义放在
shared目录
Files:
src/shared/presenter.d.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for all logs and comments
Files:
src/shared/presenter.d.tssrc/renderer/src/components/ChatConfig.vuesrc/renderer/src/stores/settings.tssrc/renderer/src/components/settings/PromptSetting.vuesrc/main/presenter/sqlitePresenter/importData.tssrc/renderer/src/components/TitleView.vuesrc/main/presenter/configPresenter/index.tssrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.vuesrc/main/presenter/threadPresenter/index.ts
src/shared/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Put shared types and IPC contracts in src/shared/
Files:
src/shared/presenter.d.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-CN/settings.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/components/ChatConfig.vuesrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/stores/settings.tssrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.vue
src/renderer/src/**
📄 CodeRabbit inference engine (CLAUDE.md)
Organize UI components by feature under src/renderer/src/
Files:
src/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/components/ChatConfig.vuesrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/stores/settings.tssrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
渲染进程代码放在
src/renderer
Files:
src/renderer/src/components/ChatConfig.vuesrc/renderer/src/stores/settings.tssrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.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/ChatConfig.vuesrc/renderer/src/stores/settings.tssrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.vue
src/renderer/src/**/*.vue
📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
Use scoped styles to prevent CSS conflicts between components
src/renderer/src/**/*.vue: Follow existing component patterns when creating new UI components
Ensure responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states to UI components
Files:
src/renderer/src/components/ChatConfig.vuesrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.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/ChatConfig.vuesrc/renderer/src/stores/settings.tssrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.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/ChatConfig.vuesrc/renderer/src/stores/settings.tssrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.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.
src/renderer/**/*.{ts,vue}: Use Pinia for frontend state management
From renderer to main, call presenters via the usePresenter.ts composable
Files:
src/renderer/src/components/ChatConfig.vuesrc/renderer/src/stores/settings.tssrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.vue
src/renderer/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
src/renderer/**/*.vue: Use Vue 3 Composition API for all components
Use Tailwind CSS with scoped styles for component styling
Files:
src/renderer/src/components/ChatConfig.vuesrc/renderer/src/components/settings/PromptSetting.vuesrc/renderer/src/components/TitleView.vuesrc/renderer/src/components/settings/CommonSettings.vuesrc/renderer/src/components/NewThread.vue
src/{main,renderer}/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
src/{main,renderer}/**/*.ts: Use context isolation for improved security
Implement proper inter-process communication (IPC) patterns
Optimize application startup time with lazy loading
Implement proper error handling and logging for debugging
Files:
src/renderer/src/stores/settings.tssrc/main/presenter/sqlitePresenter/importData.tssrc/main/presenter/configPresenter/index.tssrc/main/presenter/threadPresenter/index.ts
src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/pinia-best-practices.mdc)
src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx}: Use modules to organize related state and actions
Implement proper state persistence for maintaining data across sessions
Use getters for computed state properties
Utilize actions for side effects and asynchronous operations
Keep the store focused on global state, not component-specific data
Files:
src/renderer/src/stores/settings.ts
src/main/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Use Electron's built-in APIs for file system and native dialogs
From main to renderer, broadcast events via EventBus using mainWindow.webContents.send()
Files:
src/main/presenter/sqlitePresenter/importData.tssrc/main/presenter/configPresenter/index.tssrc/main/presenter/threadPresenter/index.ts
src/main/**/*.{ts,js,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
主进程代码放在
src/main
Files:
src/main/presenter/sqlitePresenter/importData.tssrc/main/presenter/configPresenter/index.tssrc/main/presenter/threadPresenter/index.ts
src/main/presenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain one presenter per functional domain in src/main/presenter/
Files:
src/main/presenter/sqlitePresenter/importData.tssrc/main/presenter/configPresenter/index.tssrc/main/presenter/threadPresenter/index.ts
src/main/presenter/configPresenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Centralize configuration logic under configPresenter/
Files:
src/main/presenter/configPresenter/index.ts
🧠 Learnings (7)
📚 Learning: 2025-08-26T14:13:46.601Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-26T14:13:46.601Z
Learning: Applies to src/main/presenter/configPresenter/**/*.ts : Centralize configuration logic under configPresenter/
Applied to files:
src/shared/presenter.d.tssrc/main/presenter/configPresenter/index.ts
📚 Learning: 2025-08-26T14:13:46.601Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-26T14:13:46.601Z
Learning: Applies to src/main/presenter/configPresenter/providers.ts : Add new provider configuration entries in configPresenter/providers.ts
Applied to files:
src/shared/presenter.d.tssrc/renderer/src/components/TitleView.vuesrc/main/presenter/configPresenter/index.ts
📚 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/ru-RU/settings.json
📚 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 <script setup> syntax for concise component definitions.
Applied to files:
src/renderer/src/components/ChatConfig.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/**/* : Use the 'vue-i18n' framework for all internationalization in the renderer
Applied to files:
src/renderer/src/components/ChatConfig.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Import Icon component from Iconify/Vue.
Applied to files:
src/renderer/src/components/ChatConfig.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/{composables,utils}/**/*.ts : Use VueUse for common composables and utility functions.
Applied to files:
src/renderer/src/components/ChatConfig.vue
🧬 Code graph analysis (2)
src/renderer/src/stores/settings.ts (1)
src/main/presenter/configPresenter/index.ts (2)
resetToDefaultPrompt(1208-1210)clearSystemPrompt(1213-1215)
src/main/presenter/threadPresenter/index.ts (4)
src/shared/presenter.d.ts (1)
ChatMessage(1318-1330)src/main/presenter/threadPresenter/searchManager.ts (1)
generateSearchPrompt(231-247)src/main/presenter/threadPresenter/contentEnricher.ts (1)
ContentEnricher(12-383)src/main/presenter/index.ts (1)
presenter(223-223)
⏰ 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 (16)
package.json (1)
3-3: Version bump looks good.0.3.4 aligns with the new config migration and prompt actions. No further changes needed here.
src/renderer/src/i18n/zh-HK/settings.json (2)
797-800: LGTM (terms consistent and natural).“重置為默認提示詞 / 清空提示詞” reads well and matches existing terminology.
797-800: All locales include promptSetting.resetToDefault and promptSetting.clear
Verified that every settings.json under src/renderer/src/i18n contains both keys.src/renderer/src/i18n/zh-CN/settings.json (1)
797-800: LGTM (terminology and tone are consistent).“清空提示词 / 重置为默认提示词” matches existing “系统提示词” usage.
src/shared/presenter.d.ts (1)
461-463: Presenter methods implemented and wired
ConfigPresenter definesresetToDefaultPromptandclearSystemPrompt(index.ts 1208–1214) and the renderer store calls both in src/renderer/src/stores/settings.ts (1633–1639).src/renderer/src/components/TitleView.vue (1)
77-78: Passing modelType to ChatConfig: LGTM.Propagating the model type ensures UI aligns with model capabilities (e.g., hiding system prompt). No issues spotted.
src/renderer/src/components/NewThread.vue (1)
149-157: Initialize and type model ‘type’: LGTM.Defaulting to
ModelType.Chatand typing the shape avoids undefined state; additions are consistent with the rest of this PR.src/main/presenter/sqlitePresenter/importData.ts (3)
69-121: Schema fallback on conversations: LGTM.Good multi-version compatibility with a clear fallback and sane defaults for missing fields.
123-149: Transaction wrapping with detailed error propagation: LGTM.The transaction scope and propagated errors are appropriate; rollback semantics are preserved.
360-391: Robust fallback for message_attachments: LGTM.Gracefully handles presence/absence of
metadataacross versions and normalizes results.src/main/presenter/threadPresenter/index.ts (2)
33-33: ModelType import: OKNo issues with the new import.
2123-2126: MCP tools gating: LGTMMCP tool definitions are skipped for image-generation; token accounting updated accordingly.
src/main/presenter/configPresenter/index.ts (2)
193-193: Migration rename: OKmigrateConfigData is invoked correctly in the version bump flow.
1207-1215: Reset/Clear APIs: OKMethods align with new UI actions and eventing via setSetting().
src/renderer/src/stores/settings.ts (1)
1633-1640: Approve: store passthroughs and UI handlers verified
Store methodsresetToDefaultPromptandclearSystemPromptare properly exported in settings.ts and invoked via click handlers in PromptSetting.vue; ready to merge.src/renderer/src/components/settings/PromptSetting.vue (1)
28-76: Header + actions wiring: OKButtons are properly bound; status indicator logic is clear.
| if (oldVersion && compare(oldVersion, '0.3.4', '<')) { | ||
| const currentPrompt = this.getSetting<string>('default_system_prompt') | ||
| if (!currentPrompt || currentPrompt.trim() === '') { | ||
| this.setSetting('default_system_prompt', DEFAULT_SYSTEM_PROMPT) | ||
| } | ||
| } |
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.
Default prompt set only on upgrade; fresh installs still get empty default.
New users won’t receive DEFAULT_SYSTEM_PROMPT because defaults set default_system_prompt to ''. Either set the default in ElectronStore defaults or ensure migrate runs for first-run.
Apply this change to store defaults (shown as plain TS since it’s outside the changed hunk):
// in constructor defaults:
default_system_prompt: DEFAULT_SYSTEM_PROMPT,🤖 Prompt for AI Agents
In src/main/presenter/configPresenter/index.ts around lines 278 to 283, the
migration only sets DEFAULT_SYSTEM_PROMPT for users upgrading from <0.3.4,
leaving fresh installs with an empty default; update the ElectronStore
constructor defaults to include default_system_prompt: DEFAULT_SYSTEM_PROMPT (or
alternatively ensure the migration runs on first-run by invoking it when no
prior version exists) so new installs receive the proper default prompt.
| try { | ||
| // 首先尝试使用包含所有新字段的INSERT语句 | ||
| this.targetDb | ||
| .prepare( | ||
| `INSERT INTO conversations ( | ||
| conv_id, title, created_at, updated_at, system_prompt, | ||
| temperature, context_length, max_tokens, provider_id, | ||
| model_id, is_pinned, is_new, artifacts, enabled_mcp_tools, | ||
| thinking_budget, reasoning_effort, verbosity | ||
| ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` | ||
| ) | ||
| .run( | ||
| conv.conv_id, | ||
| conv.title, | ||
| conv.created_at, | ||
| conv.updated_at, | ||
| conv.system_prompt, | ||
| conv.temperature, | ||
| conv.context_length, | ||
| conv.max_tokens, | ||
| conv.provider_id, | ||
| conv.model_id, | ||
| conv.is_pinned || 0, | ||
| conv.is_new || 0, | ||
| conv.artifacts || 0, | ||
| conv.enabled_mcp_tools || null, | ||
| conv.thinking_budget || null, | ||
| conv.reasoning_effort || null, | ||
| conv.verbosity || null | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use nullish coalescing (??) instead of || to preserve valid zero values.
thinking_budget can legitimately be 0 (used to disable reasoning). foo || null would turn 0 into null, corrupting data on import.
- conv.is_pinned || 0,
- conv.is_new || 0,
- conv.artifacts || 0,
- conv.enabled_mcp_tools || null,
- conv.thinking_budget || null,
- conv.reasoning_effort || null,
- conv.verbosity || null
+ conv.is_pinned ?? 0,
+ conv.is_new ?? 0,
+ conv.artifacts ?? 0,
+ conv.enabled_mcp_tools ?? null,
+ conv.thinking_budget ?? null,
+ conv.reasoning_effort ?? null,
+ conv.verbosity ?? nullApply the same ?? change to the legacy INSERT block, and consider token_count, is_context_edge, is_variant, vectorized, and file_size sites similarly where 0 is valid.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try { | |
| // 首先尝试使用包含所有新字段的INSERT语句 | |
| this.targetDb | |
| .prepare( | |
| `INSERT INTO conversations ( | |
| conv_id, title, created_at, updated_at, system_prompt, | |
| temperature, context_length, max_tokens, provider_id, | |
| model_id, is_pinned, is_new, artifacts, enabled_mcp_tools, | |
| thinking_budget, reasoning_effort, verbosity | |
| ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` | |
| ) | |
| .run( | |
| conv.conv_id, | |
| conv.title, | |
| conv.created_at, | |
| conv.updated_at, | |
| conv.system_prompt, | |
| conv.temperature, | |
| conv.context_length, | |
| conv.max_tokens, | |
| conv.provider_id, | |
| conv.model_id, | |
| conv.is_pinned || 0, | |
| conv.is_new || 0, | |
| conv.artifacts || 0, | |
| conv.enabled_mcp_tools || null, | |
| conv.thinking_budget || null, | |
| conv.reasoning_effort || null, | |
| conv.verbosity || null | |
| ) | |
| try { | |
| // 首先尝试使用包含所有新字段的INSERT语句 | |
| this.targetDb | |
| .prepare( | |
| `INSERT INTO conversations ( | |
| conv_id, title, created_at, updated_at, system_prompt, | |
| temperature, context_length, max_tokens, provider_id, | |
| model_id, is_pinned, is_new, artifacts, enabled_mcp_tools, | |
| thinking_budget, reasoning_effort, verbosity | |
| ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` | |
| ) | |
| .run( | |
| conv.conv_id, | |
| conv.title, | |
| conv.created_at, | |
| conv.updated_at, | |
| conv.system_prompt, | |
| conv.temperature, | |
| conv.context_length, | |
| conv.max_tokens, | |
| conv.provider_id, | |
| conv.model_id, | |
| conv.is_pinned ?? 0, | |
| conv.is_new ?? 0, | |
| conv.artifacts ?? 0, | |
| conv.enabled_mcp_tools ?? null, | |
| conv.thinking_budget ?? null, | |
| conv.reasoning_effort ?? null, | |
| conv.verbosity ?? null | |
| ) |
🤖 Prompt for AI Agents
In src/main/presenter/sqlitePresenter/importData.ts around lines 160 to 189, the
INSERT uses || to coalesce fields which converts valid zeroes to null (e.g.,
thinking_budget); replace uses of || with the nullish coalescing operator (??)
for the listed fields so that 0 is preserved. Update this INSERT block and the
legacy INSERT block similarly, and also apply ?? instead of || for other
numeric/boolean fields where 0 or false are valid (token_count, is_context_edge,
is_variant, vectorized, file_size, and any similar sites) so only null/undefined
become null while 0/false remain intact.
| supportsFunctionCall: boolean, | ||
| modelType?: ModelType | ||
| ): Promise<{ |
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.
💡 Verification agent
🧩 Analysis chain
Image-generation gating is never activated (modelType not passed to preparePromptContent).
preparePromptContent checks modelType === ModelType.ImageGeneration, but callers don’t pass modelType, so isImageGeneration is always false. Search suppression, URL enrichment suppression, system prompt suppression, and MCP tool omission won’t apply to image models.
Please pass modelConfig.type as the last argument at both call sites:
// startStreamCompletion(...)
const { finalContent, promptTokens } = await this.preparePromptContent(
conversation,
userContent,
contextMessages,
searchResults,
urlResults,
userMessage,
vision,
vision ? imageFiles : [],
modelConfig.functionCall,
modelConfig?.type // <- add this
)
// continueStreamCompletion(...)
const { finalContent, promptTokens } = await this.preparePromptContent(
conversation,
'continue',
contextMessages,
null,
[],
userMessage,
false,
[],
modelConfig.functionCall,
modelConfig?.type // <- add this
)Run to locate all call sites:
Also applies to: 2106-2126, 2145-2145
🏁 Script executed:
#!/bin/bash
rg -nP -C2 '\bpreparePromptContent\s*\(' --type=tsLength of output: 1246
Pass modelConfig.type to preparePromptContent
src/main/presenter/threadPresenter/index.ts lines 1733 and 1887 invoke preparePromptContent without the final modelType argument, so image‐generation gating never runs. Update both calls to:
…,
modelConfig.functionCall,
modelConfig.type
)🤖 Prompt for AI Agents
In src/main/presenter/threadPresenter/index.ts (call sites at ~lines 1733 and
1887; function signature around 2098-2100), preparePromptContent is currently
invoked without the final modelType parameter so image-generation gating never
runs; update both invocation sites to pass modelConfig.type as the last argument
alongside the existing modelConfig.functionCall (i.e., add modelConfig.type as
the final parameter) so preparePromptContent receives supportsFunctionCall and
the modelType.
| watch( | ||
| () => props.modelType, | ||
| (newType) => { | ||
| if (newType === 'imageGeneration' && systemPrompt.value) { | ||
| systemPrompt.value = '' | ||
| } | ||
| } | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
System prompt may still be sent for image models if this component isn’t mounted.
Clearing happens only when ChatConfig is mounted (it’s inside a Popover and may lazy-mount). If the user selects an image-generation model and sends immediately without opening settings, systemPrompt won’t be cleared. Gate at the send/path-building layer as well.
Follow-up: In NewThread.vue’s handleSend (and any other send path), force systemPrompt = '' when model.type === ImageGeneration. I’ve proposed a concrete patch in the NewThread.vue comment.
🤖 Prompt for AI Agents
In src/renderer/src/components/ChatConfig.vue around lines 44-51, clearing
systemPrompt in the component only runs when that component is mounted, so
image-generation models can still receive systemPrompt if the user sends
immediately; to fix, update the send/path-building layer (e.g., NewThread.vue
handleSend and any other send handlers) to explicitly set systemPrompt = '' (or
clear the request payload's system prompt field) whenever model.type ===
'imageGeneration' before building/sending the message; ensure you handle both
local state and the constructed API payload so no system prompt is sent for
image-generation models.
| :model-type="activeModel?.type" | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Image models still send systemPrompt on first message (Popover not opened).
Because ChatConfig’s clearing runs only when mounted, handleSend can still pass the default system prompt for image-generation models. Gate it here to enforce PR objective “Remove system prompt … from image generation model”.
Apply this patch to handleSend:
@@
-const handleSend = async (content: UserMessageContent) => {
+const handleSend = async (content: UserMessageContent) => {
+ const isImageGen = activeModel.value.type === ModelType.ImageGeneration
@@
- const threadId = await chatStore.createThread(content.text, {
+ const threadId = await chatStore.createThread(content.text, {
providerId: activeModel.value.providerId,
modelId: activeModel.value.id,
- systemPrompt: systemPrompt.value,
+ systemPrompt: isImageGen ? '' : systemPrompt.value,
@@
verbosity: verbosity.value,
enabledMcpTools: chatStore.chatConfig.enabledMcpTools
} as any)Optional: also strip tools here for image models if applicable in your domain object.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| :model-type="activeModel?.type" | |
| /> | |
| const handleSend = async (content: UserMessageContent) => { | |
| const isImageGen = activeModel.value.type === ModelType.ImageGeneration | |
| const threadId = await chatStore.createThread(content.text, { | |
| providerId: activeModel.value.providerId, | |
| modelId: activeModel.value.id, | |
| systemPrompt: isImageGen ? '' : systemPrompt.value, | |
| verbosity: verbosity.value, | |
| enabledMcpTools: chatStore.chatConfig.enabledMcpTools | |
| } as any) | |
| // …rest of handleSend | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/components/NewThread.vue around lines 100-101, handleSend
still includes the default systemPrompt when the Popover hasn't been opened
because ChatConfig clearing runs on mount; update handleSend to detect when
activeModel?.type is an image-generation model and, in that case, prevent
attaching the systemPrompt to the first message (and optionally remove any tools
from the message payload). Concretely: add a conditional in handleSend that
checks the model type (e.g., startsWith('image') or matches your image-model
enum) and if true, omit systemPrompt and strip tools before constructing/sending
the message; otherwise keep the existing behavior. Ensure this change only
affects image models and preserves existing behavior for text models.
| "promptSetting": { | ||
| "resetToDefault": "Réinitialiser avec un mot rapide par défaut", | ||
| "clear": "Effacer les mots rapides" | ||
| } |
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.
Correct unnatural French phrasing.
Avoid literal “mot rapide”. Use “prompt” consistently with “Prompt système”.
Apply this diff:
"promptSetting": {
- "resetToDefault": "Réinitialiser avec un mot rapide par défaut",
- "clear": "Effacer les mots rapides"
+ "resetToDefault": "Réinitialiser au prompt système par défaut",
+ "clear": "Effacer le prompt"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "promptSetting": { | |
| "resetToDefault": "Réinitialiser avec un mot rapide par défaut", | |
| "clear": "Effacer les mots rapides" | |
| } | |
| "promptSetting": { | |
| "resetToDefault": "Réinitialiser au prompt système par défaut", | |
| "clear": "Effacer le prompt" | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/i18n/fr-FR/settings.json around lines 797 to 800, the French
uses the literal "mot rapide" which is unnatural; replace those values to use
"prompt" consistently (matching "Prompt système"). Change "resetToDefault" to
"Réinitialiser le prompt par défaut" and "clear" to "Effacer les prompts".
| "promptSetting": { | ||
| "resetToDefault": "デフォルトのプロンプトワードにリセットします", | ||
| "clear": "迅速な単語を明確にします" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix unnatural/mistranslated Japanese labels for prompt actions
- “プロンプトワード/迅速な単語” are incorrect/unnatural. Prefer concise, consistent terms used elsewhere (e.g., “クリア”).
Apply:
- "promptSetting": {
- "resetToDefault": "デフォルトのプロンプトワードにリセットします",
- "clear": "迅速な単語を明確にします"
- }
+ "promptSetting": {
+ "resetToDefault": "デフォルトのプロンプトにリセットします",
+ "clear": "プロンプトをクリア"
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "promptSetting": { | |
| "resetToDefault": "デフォルトのプロンプトワードにリセットします", | |
| "clear": "迅速な単語を明確にします" | |
| } | |
| "promptSetting": { | |
| "resetToDefault": "デフォルトのプロンプトにリセットします", | |
| "clear": "プロンプトをクリア" | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/i18n/ja-JP/settings.json around lines 797 to 800, the
Japanese strings use unnatural/mistranslated terms (“プロンプトワード” and “迅速な単語”);
replace them with concise, natural labels consistent with the app (e.g., change
reset text to "プロンプトをデフォルトにリセットする" or "デフォルトにリセット" and change clear text to
"クリア" or "クリアする") so both entries use standard, consistent phrasing.
| "promptSetting": { | ||
| "resetToDefault": "기본 프롬프트 단어로 재설정하십시오", | ||
| "clear": "명확한 신속한 단어" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix awkward/mistranslated labels.
Current strings read like MT (“프롬프트 단어”, “신속한 단어”). Use consistent terminology with existing “시스템 프롬프트”.
Apply this diff:
"promptSetting": {
- "resetToDefault": "기본 프롬프트 단어로 재설정하십시오",
- "clear": "명확한 신속한 단어"
+ "resetToDefault": "기본 시스템 프롬프트로 재설정",
+ "clear": "시스템 프롬프트 지우기"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "promptSetting": { | |
| "resetToDefault": "기본 프롬프트 단어로 재설정하십시오", | |
| "clear": "명확한 신속한 단어" | |
| } | |
| "promptSetting": { | |
| "resetToDefault": "기본 시스템 프롬프트로 재설정", | |
| "clear": "시스템 프롬프트 지우기" | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/i18n/ko-KR/settings.json around lines 797 to 800, the labels
use awkward/mistranslated phrases ("프롬프트 단어", "신속한 단어"); change them to use the
existing consistent term "시스템 프롬프트" and clearer verbs: set "resetToDefault" to
"기본 시스템 프롬프트로 재설정" and set "clear" to "시스템 프롬프트 지우기" (replace the current values
accordingly).
| }, | ||
| "promptSetting": { | ||
| "resetToDefault": "Сбросить в приглашение по умолчанию слово", | ||
| "clear": "Чистые быстрые слова" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix Russian localization phrasing for prompt actions.
Current strings are unnatural/misleading. Suggest clearer RU translations aligned with other locales.
- "promptSetting": {
- "resetToDefault": "Сбросить в приглашение по умолчанию слово",
- "clear": "Чистые быстрые слова"
- }
+ "promptSetting": {
+ "resetToDefault": "Сбросить к системному запросу по умолчанию",
+ "clear": "Очистить системный запрос"
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| }, | |
| "promptSetting": { | |
| "resetToDefault": "Сбросить в приглашение по умолчанию слово", | |
| "clear": "Чистые быстрые слова" | |
| } | |
| }, | |
| "promptSetting": { | |
| "resetToDefault": "Сбросить к системному запросу по умолчанию", | |
| "clear": "Очистить системный запрос" | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/i18n/ru-RU/settings.json around lines 796-800, the Russian
strings for prompt actions are unnatural; replace the current values with
clearer phrasing: change "resetToDefault" to "Сбросить подсказку по умолчанию"
and change "clear" to "Очистить подсказку" so they align with other locales and
correctly convey "reset to default prompt" and "clear prompt".
| "promptSetting": { | ||
| "resetToDefault": "重置為默認提示詞", | ||
| "clear": "清空提示詞" | ||
| } |
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.
Use Traditional Chinese term “預設” instead of Simplified “默認”
Align with zh‑TW conventions.
"promptSetting": {
- "resetToDefault": "重置為默認提示詞",
+ "resetToDefault": "重置為預設提示詞",
"clear": "清空提示詞"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "promptSetting": { | |
| "resetToDefault": "重置為默認提示詞", | |
| "clear": "清空提示詞" | |
| } | |
| "promptSetting": { | |
| "resetToDefault": "重置為預設提示詞", | |
| "clear": "清空提示詞" | |
| } |
🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-TW/settings.json around lines 797 to 800, the
Traditional Chinese translation uses the Simplified Chinese term "默認"; replace
"重置為默認提示詞" with the zh‑TW preferred phrasing "重置為預設提示詞" (or "重置為預設的提示詞" if that
fits project style) so the file uses the correct local term; update only the
string value and keep the JSON key and formatting intact.
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: 1
🧹 Nitpick comments (1)
src/main/presenter/windowPresenter/index.ts (1)
1198-1218: Make position validation multi-display aware and clamp instead of always centering (optional)validateWindowPosition is only ever called after app.whenReady(), so using Electron’s screen API here is safe. You can apply the following diff to improve multi-monitor support:
private validateWindowPosition( x: number, width: number, y: number, height: number ): { x: number; y: number } { - const primaryDisplay = screen.getPrimaryDisplay() - const { workArea } = primaryDisplay - const isXValid = x >= workArea.x && x + width <= workArea.x + workArea.width - const isYValid = y >= workArea.y && y + height <= workArea.y + workArea.height - if (!isXValid || !isYValid) { - console.log( - `Window position out of bounds (x: ${x}, y: ${y}, width: ${width}, height: ${height}), centering window` - ) - return { - x: workArea.x + Math.max(0, (workArea.width - width) / 2), - y: workArea.y + Math.max(0, (workArea.height - height) / 2) - } - } - return { x, y } + // Choose the display that best matches the proposed rect; fall back to primary. + const targetDisplay = + screen.getDisplayMatching({ x, y, width, height }) ?? screen.getPrimaryDisplay() + const wa = targetDisplay.workArea + + const rectIntersects = + x < wa.x + wa.width && x + width > wa.x && y < wa.y + wa.height && y + height > wa.y + + // If entirely off-screen (e.g., prior monitor missing), center on nearest display. + if (!rectIntersects) { + console.log( + `Window position out of bounds (x: ${x}, y: ${y}, w: ${width}, h: ${height}), centering on nearest display` + ) + const centeredWidth = Math.min(width, wa.width) + const centeredHeight = Math.min(height, wa.height) + return { + x: wa.x + Math.max(0, Math.floor((wa.width - centeredWidth) / 2)), + y: wa.y + Math.max(0, Math.floor((wa.height - centeredHeight) / 2)) + } + } + + // Clamp within workArea so the window is fully visible. + const maxX = wa.x + wa.width - Math.min(width, wa.width) + const maxY = wa.y + wa.height - Math.min(height, wa.height) + return { + x: Math.min(Math.max(x, wa.x), maxX), + y: Math.min(Math.max(y, wa.y), maxY) + } }
📜 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/main/presenter/windowPresenter/index.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写
Files:
src/main/presenter/windowPresenter/index.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/windowPresenter/index.ts
src/main/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Use Electron's built-in APIs for file system and native dialogs
From main to renderer, broadcast events via EventBus using mainWindow.webContents.send()
Files:
src/main/presenter/windowPresenter/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/error-logging.mdc)
**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别Enable and adhere to strict TypeScript type checking
Files:
src/main/presenter/windowPresenter/index.ts
src/main/**/*.{ts,js,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
主进程代码放在
src/main
Files:
src/main/presenter/windowPresenter/index.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for all logs and comments
Files:
src/main/presenter/windowPresenter/index.ts
src/main/presenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain one presenter per functional domain in src/main/presenter/
Files:
src/main/presenter/windowPresenter/index.ts
🧠 Learnings (3)
📚 Learning: 2025-07-21T01:45:54.229Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:45:54.229Z
Learning: Applies to src/main/**/*.ts : Use Electron's built-in APIs for file system and native dialogs
Applied to files:
src/main/presenter/windowPresenter/index.ts
📚 Learning: 2025-07-21T01:45:54.229Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:45:54.229Z
Learning: Applies to src/renderer/src/composables/usePresenter.ts : The IPC in the renderer process is implemented in usePresenter.ts, allowing direct calls to the presenter-related interfaces exposed by the main process
Applied to files:
src/main/presenter/windowPresenter/index.ts
📚 Learning: 2025-07-21T01:45:54.229Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:45:54.229Z
Learning: Applies to src/main/presenter/index.ts : 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
Applied to files:
src/main/presenter/windowPresenter/index.ts
⏰ 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 (1)
src/main/presenter/windowPresenter/index.ts (1)
2-2: LGTM: import of screen is appropriate for position validation.
| // 计算初始位置,确保窗口完全在屏幕范围内 | ||
| const initialX = | ||
| options?.x !== undefined | ||
| ? options.x | ||
| : this.validateWindowPosition( | ||
| shellWindowState.x, | ||
| shellWindowState.width, | ||
| shellWindowState.y, | ||
| shellWindowState.height | ||
| ).x | ||
| let initialY = | ||
| options?.y !== undefined | ||
| ? options?.y | ||
| : this.validateWindowPosition( | ||
| shellWindowState.x, | ||
| shellWindowState.width, | ||
| shellWindowState.y, | ||
| shellWindowState.height | ||
| ).y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Validate once and include option overrides before validation.
Calling validateWindowPosition twice and not validating user-provided x/y independently can place windows off-screen when only one axis is overridden. Compute candidateX/Y first, then validate once.
Apply this diff:
- // 计算初始位置,确保窗口完全在屏幕范围内
- const initialX =
- options?.x !== undefined
- ? options.x
- : this.validateWindowPosition(
- shellWindowState.x,
- shellWindowState.width,
- shellWindowState.y,
- shellWindowState.height
- ).x
- let initialY =
- options?.y !== undefined
- ? options?.y
- : this.validateWindowPosition(
- shellWindowState.x,
- shellWindowState.width,
- shellWindowState.y,
- shellWindowState.height
- ).y
+ // 计算初始位置,确保窗口完全在屏幕范围内(一次校验即可)
+ const candidateX = options?.x ?? shellWindowState.x
+ const candidateY = options?.y ?? shellWindowState.y
+ const { x: initialX, y: initialY } = this.validateWindowPosition(
+ candidateX,
+ shellWindowState.width,
+ candidateY,
+ shellWindowState.height
+ )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // 计算初始位置,确保窗口完全在屏幕范围内 | |
| const initialX = | |
| options?.x !== undefined | |
| ? options.x | |
| : this.validateWindowPosition( | |
| shellWindowState.x, | |
| shellWindowState.width, | |
| shellWindowState.y, | |
| shellWindowState.height | |
| ).x | |
| let initialY = | |
| options?.y !== undefined | |
| ? options?.y | |
| : this.validateWindowPosition( | |
| shellWindowState.x, | |
| shellWindowState.width, | |
| shellWindowState.y, | |
| shellWindowState.height | |
| ).y | |
| // 计算初始位置,确保窗口完全在屏幕范围内(一次校验即可) | |
| const candidateX = options?.x ?? shellWindowState.x | |
| const candidateY = options?.y ?? shellWindowState.y | |
| const { x: initialX, y: initialY } = this.validateWindowPosition( | |
| candidateX, | |
| shellWindowState.width, | |
| candidateY, | |
| shellWindowState.height | |
| ) |
🤖 Prompt for AI Agents
In src/main/presenter/windowPresenter/index.ts around lines 578 to 596, the code
calls validateWindowPosition twice and fails to validate user-provided x/y
independently; compute candidateX and candidateY first using options.x !==
undefined ? options.x : shellWindowState.x and options.y !== undefined ?
options.y : shellWindowState.y, then call this.validateWindowPosition once with
candidateX, shellWindowState.width, candidateY, shellWindowState.height and use
the returned .x and .y as initialX and initialY so single-axis overrides are
validated correctly.
Summary by CodeRabbit
New Features
UI
Reliability
Localization
Chores