ui: align persisted config with strict server schema and enable thinking by default (#25242)
* ui: migrate legacy string-encoded booleans in persisted config * ui: enable thinking by default Fresh users and legacy conversations without a persisted thinking preference now default to enabled. The per-conversation toggle and the persisted localStorage choice keep taking precedence. Picks up the enable_thinking default from #24876.
This commit is contained in:
@@ -551,13 +551,49 @@ const mcpDefaultEnabledMigration: Migration = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CONFIG_TYPES_MIGRATION_ID = 'config-type-normalization-v1';
|
||||||
|
|
||||||
|
const configTypesMigration: Migration = {
|
||||||
|
id: CONFIG_TYPES_MIGRATION_ID,
|
||||||
|
description: 'Coerce legacy string-encoded booleans in persisted config to real booleans',
|
||||||
|
|
||||||
|
async run(): Promise<void> {
|
||||||
|
const configRaw = localStorage.getItem(CONFIG_LOCALSTORAGE_KEY);
|
||||||
|
if (configRaw === null) return;
|
||||||
|
|
||||||
|
const config = JSON.parse(configRaw);
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
// Pre-schema configs persisted booleans as the strings "true"/"false", which the
|
||||||
|
// strict server schema now rejects. Coerce those back to real booleans. No config
|
||||||
|
// string field holds exactly "true"/"false", so the match is unambiguous.
|
||||||
|
for (const key of Object.keys(config)) {
|
||||||
|
if (config[key] === 'true') {
|
||||||
|
config[key] = true;
|
||||||
|
changed = true;
|
||||||
|
} else if (config[key] === 'false') {
|
||||||
|
config[key] = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
localStorage.setItem(CONFIG_LOCALSTORAGE_KEY, JSON.stringify(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.env.DEV && import.meta.env.VITE_DEBUG)
|
||||||
|
console.log(`[Migration] Config types: coerced string booleans (changed=${changed})`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const migrations: Migration[] = [
|
const migrations: Migration[] = [
|
||||||
localStorageMigration,
|
localStorageMigration,
|
||||||
idxdbMigration,
|
idxdbMigration,
|
||||||
legacyMessageMigration,
|
legacyMessageMigration,
|
||||||
themeMigration,
|
themeMigration,
|
||||||
customJsonKeyMigration,
|
customJsonKeyMigration,
|
||||||
mcpDefaultEnabledMigration
|
mcpDefaultEnabledMigration,
|
||||||
|
configTypesMigration
|
||||||
];
|
];
|
||||||
|
|
||||||
export const MigrationService = {
|
export const MigrationService = {
|
||||||
|
|||||||
@@ -114,14 +114,13 @@ class ConversationsStore {
|
|||||||
|
|
||||||
/** Load thinking-enabled default from localStorage */
|
/** Load thinking-enabled default from localStorage */
|
||||||
private static loadThinkingDefaults(): boolean {
|
private static loadThinkingDefaults(): boolean {
|
||||||
if (typeof globalThis.localStorage === 'undefined') return false;
|
if (typeof globalThis.localStorage === 'undefined') return true;
|
||||||
try {
|
try {
|
||||||
const raw = localStorage.getItem(THINKING_ENABLED_DEFAULT_LOCALSTORAGE_KEY);
|
const raw = localStorage.getItem(THINKING_ENABLED_DEFAULT_LOCALSTORAGE_KEY);
|
||||||
if (!raw) return false;
|
if (!raw) return true;
|
||||||
const parsed = raw === 'true';
|
return raw === 'true';
|
||||||
return typeof parsed === 'boolean' ? parsed : false;
|
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +332,7 @@ class ConversationsStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.pendingMcpServerOverrides = [];
|
this.pendingMcpServerOverrides = [];
|
||||||
this.pendingThinkingEnabled = false;
|
this.pendingThinkingEnabled = ConversationsStore.loadThinkingDefaults();
|
||||||
this.activeConversation = conversation;
|
this.activeConversation = conversation;
|
||||||
|
|
||||||
if (conversation.currNode) {
|
if (conversation.currNode) {
|
||||||
|
|||||||
Reference in New Issue
Block a user