-
Notifications
You must be signed in to change notification settings - Fork 614
fix(sync): reopen sqlite after import #1190
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
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
WalkthroughThis PR resolves automatic database reinitialization after data import by adding database close/reopen logic around imports and removing manual restart requirements. The SQLite presenter now supports optional password encryption and provides a reopen() method for connection recovery. The sync presenter coordinates database closure, reopening, and post-import UI updates, while eliminating restart directives from user-facing messages across all supported languages. Changes
Sequence DiagramsequenceDiagram
actor User
participant UI as DataSettings UI
participant SyncPresenter as SyncPresenter
participant SQLitePresenter as SQLitePresenter
participant Store as Sync Store
User->>UI: Initiates import
UI->>SyncPresenter: importData()
SyncPresenter->>SQLitePresenter: close()
activate SQLitePresenter
SQLitePresenter->>SQLitePresenter: save password state
SQLitePresenter-->>SyncPresenter: closed (with error handling)
deactivate SQLitePresenter
Note over SyncPresenter: Mark sqliteClosed=true
SyncPresenter->>SyncPresenter: perform import operation
alt Import Success
SyncPresenter->>SyncPresenter: cleanupDatabaseSidecarFiles()
SyncPresenter->>SQLitePresenter: reopen()
activate SQLitePresenter
SQLitePresenter->>SQLitePresenter: ensure directory exists
SQLitePresenter->>SQLitePresenter: reopen with saved password
SQLitePresenter->>SQLitePresenter: re-apply WAL/encryption
SQLitePresenter->>SQLitePresenter: re-init tables & migrations
SQLitePresenter-->>SyncPresenter: reopened
deactivate SQLitePresenter
SyncPresenter->>SyncPresenter: broadcastThreadListUpdateAfterImport()
SyncPresenter->>Store: clear importResult (null)
else Import Failure
SyncPresenter->>SQLitePresenter: reopen()
SyncPresenter->>Store: set importResult (error)
end
SyncPresenter-->>UI: import flow complete
UI->>UI: show toast (success) or alert (error)
UI->>User: display result message (no restart)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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
🧹 Nitpick comments (2)
test/main/presenter/SyncPresenter.test.ts (1)
212-216: Consider adding a test for the import failure path.The test covers the successful overwrite import scenario. However, the sync presenter also calls
reopen()in the catch block when import fails (lines 280-287 in syncPresenter). Consider adding a test case to verify the database is reopened even when import fails to ensure the application remains functional.🔎 Example test case for failure path:
it('reopens sqlite when import fails', async () => { // Create a backup with invalid/corrupted data that will cause import to fail const backupFile = createBackupArchive(syncDir, Date.now(), { conversations: [{ id: 'conv-1', title: 'Test' }], // ... other required data }) // Make the import fail by corrupting the extracted DB or similar // Then verify: // expect(sqlitePresenter.close).toHaveBeenCalled() // expect(sqlitePresenter.reopen).toHaveBeenCalled() })src/main/presenter/syncPresenter/index.ts (1)
566-605: Consider extracting presenter access to reduce duplication.Both
broadcastThreadListUpdateAfterImportandresetShellWindowsToSingleNewChatTabuse the same dynamic import pattern. Consider extracting presenter access to a helper method or making the presenter available through dependency injection to reduce duplication and improve testability.🔎 Optional refactor to reduce duplication:
+ private async getPresenter(): Promise<typeof import('../index').presenter | null> { + try { + const { presenter } = await import('../index') + return presenter + } catch { + return null + } + } + private async broadcastThreadListUpdateAfterImport(): Promise<void> { try { - const { presenter } = await import('../index') - await (presenter?.threadPresenter as any)?.broadcastThreadListUpdate?.() + const presenter = await this.getPresenter() + await (presenter?.threadPresenter as any)?.broadcastThreadListUpdate?.() } catch (error) { console.warn('Failed to broadcast thread list update after import:', error) } }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (30)
src/main/presenter/sqlitePresenter/index.ts(2 hunks)src/main/presenter/syncPresenter/index.ts(6 hunks)src/renderer/settings/components/DataSettings.vue(3 hunks)src/renderer/src/i18n/da-DK/settings.json(1 hunks)src/renderer/src/i18n/da-DK/sync.json(1 hunks)src/renderer/src/i18n/en-US/settings.json(1 hunks)src/renderer/src/i18n/en-US/sync.json(1 hunks)src/renderer/src/i18n/fa-IR/settings.json(1 hunks)src/renderer/src/i18n/fa-IR/sync.json(1 hunks)src/renderer/src/i18n/fr-FR/settings.json(1 hunks)src/renderer/src/i18n/fr-FR/sync.json(1 hunks)src/renderer/src/i18n/he-IL/settings.json(1 hunks)src/renderer/src/i18n/he-IL/sync.json(1 hunks)src/renderer/src/i18n/ja-JP/settings.json(1 hunks)src/renderer/src/i18n/ja-JP/sync.json(1 hunks)src/renderer/src/i18n/ko-KR/settings.json(1 hunks)src/renderer/src/i18n/ko-KR/sync.json(1 hunks)src/renderer/src/i18n/pt-BR/settings.json(1 hunks)src/renderer/src/i18n/pt-BR/sync.json(1 hunks)src/renderer/src/i18n/ru-RU/settings.json(1 hunks)src/renderer/src/i18n/ru-RU/sync.json(1 hunks)src/renderer/src/i18n/zh-CN/settings.json(1 hunks)src/renderer/src/i18n/zh-CN/sync.json(1 hunks)src/renderer/src/i18n/zh-HK/settings.json(1 hunks)src/renderer/src/i18n/zh-HK/sync.json(1 hunks)src/renderer/src/i18n/zh-TW/settings.json(1 hunks)src/renderer/src/i18n/zh-TW/sync.json(1 hunks)src/renderer/src/stores/sync.ts(1 hunks)src/shared/types/presenters/legacy.presenters.d.ts(1 hunks)test/main/presenter/SyncPresenter.test.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (33)
src/renderer/src/i18n/**/*.json
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)
Files:
src/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/he-IL/sync.jsonsrc/renderer/src/i18n/zh-TW/sync.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-CN/sync.jsonsrc/renderer/src/i18n/pt-BR/sync.jsonsrc/renderer/src/i18n/fa-IR/sync.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/ja-JP/sync.jsonsrc/renderer/src/i18n/zh-HK/sync.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/da-DK/sync.jsonsrc/renderer/src/i18n/ru-RU/sync.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ko-KR/sync.jsonsrc/renderer/src/i18n/fr-FR/sync.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/en-US/sync.json
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/he-IL/sync.jsonsrc/renderer/src/i18n/zh-TW/sync.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-CN/sync.jsonsrc/renderer/src/i18n/pt-BR/sync.jsonsrc/renderer/src/i18n/fa-IR/sync.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/stores/sync.tssrc/renderer/src/i18n/ja-JP/sync.jsonsrc/renderer/src/i18n/zh-HK/sync.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/settings/components/DataSettings.vuesrc/renderer/src/i18n/da-DK/sync.jsonsrc/renderer/src/i18n/ru-RU/sync.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/main/presenter/sqlitePresenter/index.tssrc/renderer/src/i18n/ko-KR/sync.jsonsrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/i18n/fr-FR/sync.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/en-US/sync.json
src/renderer/**
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use lowercase with dashes for directories (e.g., components/auth-wizard)
Files:
src/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/he-IL/sync.jsonsrc/renderer/src/i18n/zh-TW/sync.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-CN/sync.jsonsrc/renderer/src/i18n/pt-BR/sync.jsonsrc/renderer/src/i18n/fa-IR/sync.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/stores/sync.tssrc/renderer/src/i18n/ja-JP/sync.jsonsrc/renderer/src/i18n/zh-HK/sync.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/settings/components/DataSettings.vuesrc/renderer/src/i18n/da-DK/sync.jsonsrc/renderer/src/i18n/ru-RU/sync.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ko-KR/sync.jsonsrc/renderer/src/i18n/fr-FR/sync.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/en-US/sync.json
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)
Files:
src/renderer/src/stores/sync.tssrc/renderer/settings/components/DataSettings.vuesrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/SyncPresenter.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enable and maintain strict TypeScript type checking for all files
**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/SyncPresenter.test.ts
src/renderer/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use the
usePresenter.tscomposable for renderer-to-main IPC communication to call presenter methods directly
Files:
src/renderer/src/stores/sync.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/SyncPresenter.test.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
Write logs and comments in English
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/SyncPresenter.test.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.ts
src/renderer/src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/**/*.{vue,ts,tsx}: All user-facing strings must use i18n keys with vue-i18n framework in the renderer
Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Use the dynamic locale.value property to switch languages at runtime
Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Files:
src/renderer/src/stores/sync.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 in Pinia stores
Implement proper state persistence for maintaining data across sessions in Pinia stores
Use getters for computed state properties in Pinia stores
Utilize actions for side effects and asynchronous operations in Pinia stores
Keep Pinia stores focused on global state, not component-specific data
Files:
src/renderer/src/stores/sync.ts
src/renderer/**/*.{vue,js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Renderer process code should be placed in
src/renderer(Vue 3 application)
Files:
src/renderer/src/stores/sync.tssrc/renderer/settings/components/DataSettings.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 in Vue.js applications
Implement proper state management with Pinia in Vue.js applications
Utilize Vue Router for navigation and route management in Vue.js applications
Leverage Vue's built-in reactivity system for efficient data handling
Files:
src/renderer/src/stores/sync.ts
src/renderer/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,tsx,vue}: Write concise, technical TypeScript code with accurate examples
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
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 statementsVue 3 app code in
src/renderer/srcshould be organized intocomponents/,stores/,views/,i18n/,lib/directories with shell UI insrc/renderer/shell/
Files:
src/renderer/src/stores/sync.tssrc/renderer/settings/components/DataSettings.vue
src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use TypeScript for all code; prefer types over interfaces
Files:
src/renderer/src/stores/sync.ts
src/renderer/**/stores/*.ts
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use Pinia for state management
Files:
src/renderer/src/stores/sync.ts
src/renderer/**/*.{ts,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching
Leverage ref, reactive, and computed for reactive state management
Use provide/inject for dependency injection when appropriate
Use Iconify/Vue for icon implementation
Files:
src/renderer/src/stores/sync.tssrc/renderer/settings/components/DataSettings.vue
src/renderer/src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/renderer/src/**/*.{ts,tsx,vue}: Use TypeScript with Vue 3 Composition API for the renderer application
All user-facing strings must use vue-i18n keys insrc/renderer/src/i18n
Files:
src/renderer/src/stores/sync.ts
src/renderer/src/stores/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use Pinia for state management
Files:
src/renderer/src/stores/sync.ts
src/**/*.{ts,tsx,vue,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Prettier with single quotes, no semicolons, and 100 character width
Files:
src/renderer/src/stores/sync.tssrc/renderer/settings/components/DataSettings.vuesrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use OxLint for linting JavaScript and TypeScript files
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.ts
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use EventBus for inter-process communication events
Files:
src/renderer/src/stores/sync.tssrc/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.ts
**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.vue: Use Vue 3 Composition API for all components instead of Options API
Use Tailwind CSS with scoped styles for component styling
Files:
src/renderer/settings/components/DataSettings.vue
src/renderer/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
src/renderer/**/*.vue: All user-facing strings must use i18n keys via vue-i18n for internationalization
Ensure proper error handling and loading states in all UI components
Implement responsive design using Tailwind CSS utilities for all UI components
src/renderer/**/*.vue: Use composition API and declarative programming patterns; avoid options API
Structure files: exported component, composables, helpers, static content, types
Use PascalCase for component names (e.g., AuthWizard.vue)
Use Vue 3 with TypeScript, leveraging defineComponent and PropType
Use template syntax for declarative rendering
Use Shadcn Vue, Radix Vue, and Tailwind for components and styling
Implement responsive design with Tailwind CSS; use a mobile-first approach
Use Suspense for asynchronous components
Use <script setup> syntax for concise component definitions
Prefer 'lucide:' icon family as the primary choice for Iconify icons
Import Icon component from '@iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'
Files:
src/renderer/settings/components/DataSettings.vue
src/main/presenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Organize core business logic into dedicated Presenter classes, with one presenter per functional domain
Files:
src/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.ts
src/main/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use EventBus from
src/main/eventbus.tsfor main-to-renderer communication, broadcasting events viamainWindow.webContents.send()
src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations
src/main/**/*.ts: Electron main process code belongs insrc/main/with presenters inpresenter/(Window/Tab/Thread/Mcp/Config/LLMProvider) andeventbus.tsfor app events
Use the Presenter pattern in the main process for UI coordination
Files:
src/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.ts
src/main/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Main process code for Electron should be placed in
src/main
Files:
src/main/presenter/sqlitePresenter/index.tssrc/main/presenter/syncPresenter/index.ts
src/shared/**/*.d.ts
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Define type definitions in shared/*.d.ts files for objects exposed by the main process to the renderer process
Files:
src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Shared type definitions and utilities between main and renderer processes should be placed in
src/shared
Files:
src/shared/types/presenters/legacy.presenters.d.ts
src/shared/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Shared types and utilities should be placed in
src/shared/
Files:
src/shared/types/presenters/legacy.presenters.d.ts
test/**/*.{test,spec}.{ts,tsx,js}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Vitest framework for unit and integration tests
Files:
test/main/presenter/SyncPresenter.test.ts
test/**/*.{test,spec}.ts
📄 CodeRabbit inference engine (AGENTS.md)
test/**/*.{test,spec}.ts: Test files should follow the same directory structure as source code undertest/mainandtest/rendererdirectories
Use Vitest and Vue Test Utils for testing with jsdom configuration
Test files must be named with.test.tsor.spec.tsextension
Files:
test/main/presenter/SyncPresenter.test.ts
🧠 Learnings (9)
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)
Applied to files:
src/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/he-IL/sync.jsonsrc/renderer/src/i18n/zh-TW/sync.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-CN/sync.jsonsrc/renderer/src/i18n/pt-BR/sync.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/ja-JP/sync.jsonsrc/renderer/src/i18n/zh-HK/sync.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/da-DK/sync.jsonsrc/renderer/src/i18n/ru-RU/sync.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ko-KR/sync.jsonsrc/renderer/src/i18n/fr-FR/sync.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/en-US/sync.json
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Applied to files:
src/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/zh-TW/sync.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/settings/components/DataSettings.vuesrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ko-KR/sync.jsonsrc/renderer/src/i18n/fr-FR/sync.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/settings.json
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to **/*.{ts,tsx,js,jsx,vue} : Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)
Applied to files:
src/renderer/src/i18n/zh-TW/sync.jsonsrc/renderer/src/i18n/zh-TW/settings.json
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/main/**/*.ts : Use the Presenter pattern in the main process for UI coordination
Applied to files:
src/main/presenter/syncPresenter/index.tstest/main/presenter/SyncPresenter.test.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms
Applied to files:
src/main/presenter/syncPresenter/index.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Applied to files:
src/main/presenter/syncPresenter/index.tstest/main/presenter/SyncPresenter.test.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/renderer/**/*.ts : Use the `usePresenter.ts` composable for renderer-to-main IPC communication to call presenter methods directly
Applied to files:
src/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/SyncPresenter.test.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/mcpPresenter/**/*.ts : Register new MCP tools in `mcpPresenter/index.ts` after implementing them in `inMemoryServers/`
Applied to files:
test/main/presenter/SyncPresenter.test.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/**/*.ts : Organize core business logic into dedicated Presenter classes, with one presenter per functional domain
Applied to files:
test/main/presenter/SyncPresenter.test.ts
🧬 Code graph analysis (1)
src/main/presenter/syncPresenter/index.ts (1)
src/main/presenter/index.ts (1)
presenter(229-229)
⏰ 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 (40)
src/renderer/src/i18n/zh-HK/settings.json (1)
83-83: Translation is consistent across all supported language files.The
data.importConfirmDescriptionkey has been updated consistently across all 12 language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR, da-DK, he-IL, ja-JP, pt-BR, zh-TW), with each translation conveying the same meaning: automatic data refresh after import completion.src/renderer/src/i18n/he-IL/sync.json (1)
3-3: Localization changes are consistent across all locales.The removal of restart messaging is properly applied across all 12 locale files (he-IL, zh-HK, ru-RU, zh-TW, pt-BR, ko-KR, ja-JP, zh-CN, fr-FR, da-DK, fa-IR, and en-US). Each file correctly maintains the
success.importCompletekey with the {count} placeholder and appropriate translation, reflecting the PR's database reconnection fix that eliminates the manual restart requirement.src/renderer/src/i18n/da-DK/sync.json (1)
3-3: Consistency verified across all required language files.The translation change correctly removes the restart instruction from the
importCompletemessage. Verification confirms that all required language files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR) have been updated consistently, with the restart-related text completely removed. The change is properly implemented across all locales as required by the coding guidelines.src/renderer/src/i18n/ko-KR/settings.json (1)
83-83: Korean translation and consistency verified across all language files.The Korean translation correctly reflects the automatic data refresh behavior. Verification confirms that all 12 supported language files (da-DK, en-US, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) have been consistently updated with matching automatic refresh messaging, maintaining the required key-value structure across all translations.
src/renderer/src/i18n/he-IL/settings.json (1)
83-83: The Hebrew locale (he-IL) is an officially supported locale in the repository and is already included in the i18n structure alongside 12 other languages. All locale settings.json files, including he-IL, have received the importConfirmDescription update consistently. The change is correct and complete—no action required.The coding guidelines document appears to list only a subset of supported locales (7 of 13 currently active); this is a documentation maintenance issue separate from this PR.
Likely an incorrect or invalid review comment.
src/renderer/src/i18n/fa-IR/sync.json (1)
3-3: LGTM! Change is consistent across all locale files.The removal of the restart instruction from the import success message correctly aligns with the PR objective of automatically reopening the database after import. The placeholder
{count}is properly preserved, JSON structure is valid, and this change has been consistently applied across all available locale files (including zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR, and additional locales).src/renderer/src/i18n/zh-CN/sync.json (1)
3-3: Translation change is consistent across all language files.The removal of the restart notification has been correctly applied to all 12 supported locales (zh-CN, zh-TW, zh-HK, en-US, ko-KR, ru-RU, fa-IR, fr-FR, ja-JP, pt-BR, he-IL, da-DK). All translations now use the structured format under
success.importCompletewithout any restart messaging, aligning with the PR objective and maintaining consistency per the coding guidelines.src/renderer/src/i18n/ko-KR/sync.json (1)
3-3: LGTM! Translation correctly updated to reflect automatic data refresh.The removal of the restart instruction aligns with the new database reopen functionality. Users no longer need to manually restart the application after import since the SQLite connection is automatically refreshed.
src/renderer/src/i18n/zh-CN/settings.json (1)
83-83: LGTM! Import confirmation message correctly updated.The change from "需要重启应用" (requires restart) to "将自动刷新数据" (data will be automatically refreshed) accurately communicates the new behavior where the database connection is automatically reopened after import.
src/renderer/src/i18n/da-DK/settings.json (1)
83-83: LGTM! Danish translation correctly reflects the new automatic refresh behavior.The message now properly indicates that data will be automatically updated after import, eliminating the need for a manual restart.
src/renderer/src/i18n/pt-BR/sync.json (1)
3-3: LGTM! Portuguese (Brazil) translation correctly updated.The removal of the restart instruction is consistent with the automatic database reopen functionality introduced in this PR.
src/renderer/src/i18n/en-US/sync.json (1)
3-3: LGTM! English translation correctly updated to reflect automatic refresh behavior.The simplified message focuses on the import count without requiring user action to restart, which aligns perfectly with the new database reopen implementation.
src/renderer/src/i18n/fr-FR/sync.json (1)
3-3: LGTM! French translation correctly updated.The removal of the restart instruction is consistent with the automatic database connection refresh implemented in the backend.
src/renderer/src/i18n/pt-BR/settings.json (1)
83-83: LGTM! Portuguese (Brazil) translation correctly updated for settings.The import confirmation description now accurately reflects that data will be automatically updated after import, removing the manual restart requirement.
src/renderer/src/stores/sync.ts (1)
88-88: UI components correctly handle null values for successful imports.The component uses proper type narrowing:
!!syncStore.importResult && !syncStore.importResult?.successensures the error dialog only displays when importResult is neither null nor successful. When the import succeeds and importResult is set to null, the dialog condition evaluates to false and doesn't render. Inside the dialog, optional chaining (syncStore.importResult?.message) safely accesses properties without risk of null-reference errors.src/renderer/src/i18n/zh-TW/settings.json (1)
82-84: Import confirmation text aligns with new auto-refresh behaviorThe updated description correctly warns about full overwrite, reminds users to back up, and reflects that data will refresh automatically after import, without altering the key structure.
src/renderer/src/i18n/fr-FR/settings.json (1)
82-84: French import confirmation updated consistentlyThe message now emphasizes overwrite risk and automatic data refresh post-import, dropping the restart requirement while keeping the translation key structure intact.
src/shared/types/presenters/legacy.presenters.d.ts (1)
282-355: ISQLitePresenter extended cleanly withreopen()Exposing
reopen(): voidonISQLitePresenteraligns the shared types with the new SQLite reopen flow used bySyncPresenterand tests, without impacting existing callers.src/renderer/src/i18n/zh-HK/sync.json (1)
2-4: Sync success toast matches restart-free flowThe shortened success message correctly focuses on the imported conversation count and no longer suggests restarting, while preserving the existing key structure.
src/renderer/src/i18n/ru-RU/settings.json (1)
82-84: Russian import confirmation correctly reflects automatic refreshThe updated description keeps the overwrite warning, adds that data will be automatically updated after import, and does so without changing keys or structure.
src/renderer/src/i18n/zh-TW/sync.json (1)
2-4: Taiwanese sync success message simplified appropriatelyThe success toast now just reports the number of imported conversations, removing restart guidance while keeping the same
success.importCompletekey.src/renderer/src/i18n/fa-IR/settings.json (1)
82-84: Farsi import confirmation aligned with auto-refresh semanticsThe updated description clearly warns about overwriting data and notes automatic refresh after import, with no changes to the i18n key structure.
src/renderer/src/i18n/ru-RU/sync.json (1)
2-4: Russian sync success toast updated to match new flowThe message now only reports how many dialogs were imported, removing the restart hint and preserving the existing key and structure.
src/renderer/src/i18n/ja-JP/settings.json (1)
83-83: LGTM!The Japanese translation correctly reflects the new automatic data refresh behavior after import, aligning with the PR's objective to eliminate the restart requirement. The key structure remains consistent with other locale files.
test/main/presenter/SyncPresenter.test.ts (2)
50-53: LGTM!The mock correctly includes both
closeandreopenmethods, enabling verification of the new database recovery flow.
120-125: LGTM!The test properly verifies that
sqlitePresenter.reopen()is called afterclose()during incremental import, ensuring the database connection is restored without requiring an application restart.src/renderer/src/i18n/ja-JP/sync.json (1)
3-3: LGTM!The simplified success message removes the restart instruction, correctly reflecting the automatic data refresh behavior introduced by this PR.
src/renderer/src/i18n/en-US/settings.json (1)
83-83: LGTM!The English translation clearly communicates the automatic data refresh behavior, maintaining consistency with the Japanese locale and the PR's objective.
src/renderer/settings/components/DataSettings.vue (3)
245-263: LGTM!The alert dialog now correctly shows only for import errors (
!syncStore.importResult?.success). The success path relies solely on toast notifications, which aligns with the new UX that doesn't require user acknowledgment for successful imports.
433-435: LGTM!The
handleAlertActionfunction now simply clears the import result without triggering an application restart, correctly reflecting the new behavior where the database connection is automatically restored.
395-402: Verify toast i18n keys exist in all locale files.The toast keys have been migrated from
settings.data.toast.*tosettings.provider.toast.*. All keys (backupSuccessTitle,backupSuccessMessage,importSuccessTitle,importSuccessMessage) exist across all 12 supported locales (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR, ja-JP, da-DK, he-IL, pt-BR, zh-TW) with correct parameter placeholders.src/main/presenter/sqlitePresenter/index.ts (3)
35-39: Storing password in memory is acceptable for this use case.The password is stored in a private field to enable the
reopen()functionality. While storing secrets in memory has inherent risks, this is a reasonable trade-off for a desktop application where the password needs to persist for database reconnection. Ensure this field is not exposed via any public API or logging.
219-225: LGTM on fault-tolerant close.Wrapping
close()in try-catch with a warning log is appropriate. This prevents errors during close from crashing the application while still providing visibility into issues.
227-253: Well-structured reopen implementation.The
reopen()method correctly:
- Closes the existing connection
- Ensures the directory exists
- Reopens with WAL mode
- Reapplies encryption if a password was configured
- Validates the connection with a simple query
- Reinitializes tables, version info, and migrations
- Logs and rethrows errors appropriately
One consideration: if
close()fails silently (due to the try-catch), the subsequentnew Database()call might fail if the old connection holds a lock. This is acceptable since the error will be caught and rethrown.src/main/presenter/syncPresenter/index.ts (6)
185-186: LGTM!The
sqliteClosedflag correctly tracks whether the SQLite connection was closed, ensuringreopen()is only called when necessary. This prevents unnecessary reopen attempts when import fails before the close operation.Also applies to: 200-201
232-232: Important: Sidecar cleanup prevents database corruption.Cleaning up WAL and SHM files after copying the backup database is essential. These sidecar files from the previous database state could cause corruption or unexpected behavior if left alongside the newly imported database.
264-270: LGTM!The success path correctly:
- Reopens SQLite when it was closed
- Broadcasts thread list update to refresh UI
- Resets shell windows for overwrite imports (clearing stale conversation references)
280-287: Good error recovery pattern.The failure path appropriately attempts to reopen SQLite and broadcast updates, wrapped in its own try-catch to prevent recovery errors from masking the original import error. This ensures the application remains functional even when import fails.
557-564: Defensive coding with optional chaining.The dynamic import and optional chaining (
?.) provide resilience against missing dependencies during the broadcast. The warning log provides visibility without crashing the application.
607-619: LGTM!The
cleanupDatabaseSidecarFileshelper properly removes WAL and SHM files with appropriate error handling. The use ofcontinuefor non-existent files and warning logs for deletion failures is appropriate.
close #1182
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.