Back to Cherry Studio

PromptMigrator

src/main/data/migration/v2/migrators/README-PromptMigrator.md

2.0.04.3 KB
Original Source

PromptMigrator

PromptMigrator migrates both v1 quick-phrase stores into the single v2 prompt table. Assistant ownership is intentionally discarded because v2 exposes one global prompt list.

Data Sources

DataSourceNotes
Global quick phrasesDexie quick_phrasesOptional table in the v1 CherryStudio IndexedDB database
Assistant quick phrasesRedux state.assistants.assistants[].regularPhrasesStored inline on each assistant
Preset quick phrasesRedux state.assistants.presets[].regularPhrasesPresets share the v1 Assistant shape
Default assistant quick phrasesRedux state.assistants.defaultAssistant.regularPhrasesSeparate slot that may duplicate or diverge from assistants[0]

The absence of the Dexie table does not stop migration. Redux assistant phrases are still prepared and inserted.

Field Mapping

v1 QuickPhrasev2 prompt
idid; valid unique UUIDs are preserved, while missing, invalid, or conflicting IDs are regenerated
titletitle; trimmed, empty or invalid titles become Untitled, and titles above the v2 limit are truncated without splitting a Unicode surrogate pair
contentcontent; variable syntax is preserved
orderUsed to restore the global quick-phrase sequence before assigning orderKey
createdAtcreatedAt; preserve valid date values, otherwise use updatedAt or the migration timestamp
updatedAtupdatedAt; preserve valid date values, otherwise use the normalized createdAt

No assistant identifier is written to the target table.

Ordering

The target table has one whole-table fractional order:

  1. Dexie global phrases come first, sorted by descending legacy order to reproduce v1's canonical old-to-new sequence.
  2. Redux phrases follow in source order: assistants[], presets[], then defaultAssistant.
  3. Each regularPhrases array keeps its stored order.
  4. assignOrderKeysInSequence() stamps the combined sequence once.

This keeps the existing global migration order stable and deterministically appends the newly preserved assistant data.

Duplicate IDs

The v1 Redux state can contain the same assistant data in multiple slots, especially the default assistant.

  • Same ID, title, and content: keep the first row and count later rows as skipped duplicates. Timestamp-only differences do not create another prompt.
  • Same ID but different title or content: preserve both rows. The first row keeps the v1 ID; each later conflicting row receives a new UUID.
  • Missing or non-UUID ID: preserve the phrase under a generated UUID. Repeated non-empty legacy IDs still participate in duplicate detection before regeneration.
  • Different IDs: preserve both rows even when their title and content match. The migrator does not infer that separately-created user records are duplicates.

Source precedence is global Dexie phrases, assistants[], presets[], then defaultAssistant.

Validation

A candidate is rejected as invalid when its content cannot satisfy the v2 prompt contract (for example, it is missing, empty, or exceeds the v2 limit), or when an existing regularPhrases container is malformed. Missing IDs, invalid IDs, titles, and timestamps are normalized instead of dropping otherwise usable content.

Identical rows that reuse an ID are skipped separately as duplicates. A non-array regularPhrases value counts as one invalid source container, so it contributes to both sourceCount and skippedCount instead of disappearing from the migration report.

Before insertion and again after migration, every row is checked against the shared v2 prompt field schemas. Validation reports:

  • sourceCount: all global and assistant candidates;
  • skippedCount: invalid candidates plus identical duplicate IDs;
  • targetCount: rows present in prompt after execution.

The target count must exactly equal the number of prepared rows. The migration engine clears the target table before a run, so extra or missing rows indicate a migration error.

Execution

The combined prompt list is inserted in batches of 100 inside one SQLite transaction. This keeps the migration atomic while staying below SQLite's bound-variable limit for arbitrarily large imported assistant or preset lists.