Skip to content

Conversation

@yyhhyyyyyy
Copy link
Collaborator

@yyhhyyyyyy yyhhyyyyyy commented Dec 18, 2025

close #1182

Summary by CodeRabbit

  • New Features

    • Data imports now complete seamlessly without requiring an application restart—changes are automatically reflected immediately upon completion.
  • Improvements

    • Enhanced database resilience with improved error handling and automatic recovery capabilities.
    • Streamlined import workflow with cleaner success messaging across all languages.

✏️ Tip: You can customize this high-level summary in your review settings.

@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

Walkthrough

This 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

Cohort / File(s) Summary
Database Presenter Core
src/main/presenter/sqlitePresenter/index.ts
Adds optional password field for SQLCipher encryption; implements reopen() method to gracefully reload database with password re-application and WAL/encryption re-initialization; enhances constructor error path with backup and recovery flow.
Sync Presenter Integration
src/main/presenter/syncPresenter/index.ts
Introduces sqliteClosed flag to track import state; adds private helpers broadcastThreadListUpdateAfterImport(), resetShellWindowsToSingleNewChatTab(), and cleanupDatabaseSidecarFiles(); conditionally reopens SQLite and broadcasts updates after import completion or on failure; cleans up database sidecar files (.wal/.shm) after overwrite import.
Type Definitions
src/shared/types/presenters/legacy.presenters.d.ts
Adds public reopen(): void method declaration to ISQLitePresenter interface.
UI and State Management
src/renderer/settings/components/DataSettings.vue, src/renderer/src/stores/sync.ts
Removes restart logic from import dialogs and toast notifications; migrates toast keys to provider scope; clears importResult on successful import; handles error dialogs only on failure.
Internationalization
src/renderer/src/i18n/{da-DK,en-US,fa-IR,fr-FR,he-IL,ja-JP,ko-KR,pt-BR,ru-RU,zh-CN,zh-HK,zh-TW}/settings.json, src/renderer/src/i18n/{da-DK,en-US,fa-IR,fr-FR,he-IL,ja-JP,ko-KR,pt-BR,ru-RU,zh-CN,zh-HK,zh-TW}/sync.json
Updates all language variants to replace "restart required" messaging with "data will refresh automatically"; removes post-import restart instructions from success messages.
Tests
test/main/presenter/SyncPresenter.test.ts
Adds assertions verifying sqlitePresenter.reopen() is called after close() in both incremental and overwrite import test paths.

Sequence Diagram

sequenceDiagram
    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)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~45 minutes

  • SQLitePresenter.reopen() logic: Verify password re-application, WAL mode, encryption key re-initialization, and error recovery flow during database lifecycle transitions.
  • sqliteClosed flag state management: Ensure flag is properly set when database closes and that reopen logic correctly handles both success and failure paths.
  • Sidecar file cleanup: Confirm .wal/.shm cleanup occurs at the correct point in the overwrite import flow without corrupting the database.
  • Integration across sync and UI layers: Validate that broadcastThreadListUpdateAfterImport() and resetShellWindowsToSingleNewChatTab() properly coordinate post-import state synchronization.

Possibly related PRs

Suggested labels

database, import-export, bug-fix, lifecycle-management

Poem

🐰 The database dances without restart!
Close and reopen, a graceful art,
Import your data, swift and clean,
No more stalling in between!
Passwords safe, transactions flow,
Watch the connections rise and grow.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(sync): reopen sqlite after import' clearly and concisely summarizes the main change: reopening the SQLite database after data import to resolve connection issues.
Linked Issues check ✅ Passed The PR successfully addresses issue #1182 by implementing automatic database connection reinitialization through SQLitePresenter.reopen() method, graceful close/reopen logic, and conditional reopening in SyncPresenter after import—enabling users to continue without restart.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing database connection handling after import and updating related UI messaging; no unrelated code modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/db-reopen-after-import

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

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 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 broadcastThreadListUpdateAfterImport and resetShellWindowsToSingleNewChatTab use 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

📥 Commits

Reviewing files that changed from the base of the PR and between afd4e84 and 52fb563.

📒 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.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/he-IL/sync.json
  • src/renderer/src/i18n/zh-TW/sync.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/zh-CN/sync.json
  • src/renderer/src/i18n/pt-BR/sync.json
  • src/renderer/src/i18n/fa-IR/sync.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/ja-JP/sync.json
  • src/renderer/src/i18n/zh-HK/sync.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/da-DK/sync.json
  • src/renderer/src/i18n/ru-RU/sync.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ko-KR/sync.json
  • src/renderer/src/i18n/fr-FR/sync.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/en-US/sync.json
src/**/*

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

New features should be developed in the src directory

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/he-IL/sync.json
  • src/renderer/src/i18n/zh-TW/sync.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/zh-CN/sync.json
  • src/renderer/src/i18n/pt-BR/sync.json
  • src/renderer/src/i18n/fa-IR/sync.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/stores/sync.ts
  • src/renderer/src/i18n/ja-JP/sync.json
  • src/renderer/src/i18n/zh-HK/sync.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/src/i18n/da-DK/sync.json
  • src/renderer/src/i18n/ru-RU/sync.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/main/presenter/sqlitePresenter/index.ts
  • src/renderer/src/i18n/ko-KR/sync.json
  • src/main/presenter/syncPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/i18n/fr-FR/sync.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/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.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/he-IL/sync.json
  • src/renderer/src/i18n/zh-TW/sync.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/zh-CN/sync.json
  • src/renderer/src/i18n/pt-BR/sync.json
  • src/renderer/src/i18n/fa-IR/sync.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/stores/sync.ts
  • src/renderer/src/i18n/ja-JP/sync.json
  • src/renderer/src/i18n/zh-HK/sync.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/src/i18n/da-DK/sync.json
  • src/renderer/src/i18n/ru-RU/sync.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ko-KR/sync.json
  • src/renderer/src/i18n/fr-FR/sync.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/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.ts
  • src/renderer/settings/components/DataSettings.vue
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • test/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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • test/main/presenter/SyncPresenter.test.ts
src/renderer/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use the usePresenter.ts composable 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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • test/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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • test/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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/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.ts
  • src/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 statements

Vue 3 app code in src/renderer/src should be organized into components/, stores/, views/, i18n/, lib/ directories with shell UI in src/renderer/shell/

Files:

  • src/renderer/src/stores/sync.ts
  • src/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.ts
  • src/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 in src/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.ts
  • src/renderer/settings/components/DataSettings.vue
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/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.ts
  • src/main/presenter/sqlitePresenter/index.ts
  • src/main/presenter/syncPresenter/index.ts
  • src/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.ts
  • src/main/presenter/syncPresenter/index.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.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 in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/sqlitePresenter/index.ts
  • src/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.ts
  • src/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 under test/main and test/renderer directories
Use Vitest and Vue Test Utils for testing with jsdom configuration
Test files must be named with .test.ts or .spec.ts extension

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.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/he-IL/sync.json
  • src/renderer/src/i18n/zh-TW/sync.json
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/zh-CN/sync.json
  • src/renderer/src/i18n/pt-BR/sync.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/ja-JP/sync.json
  • src/renderer/src/i18n/zh-HK/sync.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/da-DK/sync.json
  • src/renderer/src/i18n/ru-RU/sync.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ko-KR/sync.json
  • src/renderer/src/i18n/fr-FR/sync.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/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.json
  • src/renderer/src/i18n/zh-TW/sync.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/settings/components/DataSettings.vue
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ko-KR/sync.json
  • src/renderer/src/i18n/fr-FR/sync.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/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.json
  • src/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.ts
  • test/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.ts
  • 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/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.ts
  • 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/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.importConfirmDescription key 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.importComplete key 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 importComplete message. 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.importComplete without 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?.success ensures 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 behavior

The 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 consistently

The 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 with reopen()

Exposing reopen(): void on ISQLitePresenter aligns the shared types with the new SQLite reopen flow used by SyncPresenter and tests, without impacting existing callers.

src/renderer/src/i18n/zh-HK/sync.json (1)

2-4: Sync success toast matches restart-free flow

The 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 refresh

The 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 appropriately

The success toast now just reports the number of imported conversations, removing restart guidance while keeping the same success.importComplete key.

src/renderer/src/i18n/fa-IR/settings.json (1)

82-84: Farsi import confirmation aligned with auto-refresh semantics

The 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 flow

The 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 close and reopen methods, enabling verification of the new database recovery flow.


120-125: LGTM!

The test properly verifies that sqlitePresenter.reopen() is called after close() 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 handleAlertAction function 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.* to settings.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:

  1. Closes the existing connection
  2. Ensures the directory exists
  3. Reopens with WAL mode
  4. Reapplies encryption if a password was configured
  5. Validates the connection with a simple query
  6. Reinitializes tables, version info, and migrations
  7. Logs and rethrows errors appropriately

One consideration: if close() fails silently (due to the try-catch), the subsequent new 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 sqliteClosed flag correctly tracks whether the SQLite connection was closed, ensuring reopen() 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:

  1. Reopens SQLite when it was closed
  2. Broadcasts thread list update to refresh UI
  3. 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 cleanupDatabaseSidecarFiles helper properly removes WAL and SHM files with appropriate error handling. The use of continue for non-existent files and warning logs for deletion failures is appropriate.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Database connection reentry exceptions after data import require application restart

3 participants