()
| 1529 | * @returns {Promise<UserConfig>} |
| 1530 | */ |
| 1531 | export async function getUserConfig() { |
| 1532 | // Also fetch old keys for migration |
| 1533 | const options = await Browser.storage.local.get([ |
| 1534 | ...Object.keys(defaultConfig), |
| 1535 | 'claudeApiKey', |
| 1536 | 'customClaudeApiUrl', |
| 1537 | ]) |
| 1538 | |
| 1539 | // Migrate legacy Claude-named keys to Anthropic-named keys. |
| 1540 | // If both old/new keys coexist (for example after a partial migration), |
| 1541 | // keep the Anthropic-named keys and clean up the legacy Claude-named keys. |
| 1542 | if (options.claudeApiKey !== undefined) { |
| 1543 | if (options.anthropicApiKey === undefined) { |
| 1544 | options.anthropicApiKey = options.claudeApiKey |
| 1545 | try { |
| 1546 | await Browser.storage.local.set({ anthropicApiKey: options.claudeApiKey }) |
| 1547 | await Browser.storage.local.remove('claudeApiKey') |
| 1548 | } catch { |
| 1549 | // Retry the legacy-key cleanup on the next config read. |
| 1550 | } |
| 1551 | } else { |
| 1552 | await Browser.storage.local.remove('claudeApiKey').catch(() => {}) |
| 1553 | } |
| 1554 | } |
| 1555 | if (options.customClaudeApiUrl !== undefined) { |
| 1556 | if (options.customAnthropicApiUrl === undefined) { |
| 1557 | options.customAnthropicApiUrl = options.customClaudeApiUrl |
| 1558 | try { |
| 1559 | await Browser.storage.local.set({ customAnthropicApiUrl: options.customClaudeApiUrl }) |
| 1560 | await Browser.storage.local.remove('customClaudeApiUrl') |
| 1561 | } catch { |
| 1562 | // Retry the legacy-key cleanup on the next config read. |
| 1563 | } |
| 1564 | } else { |
| 1565 | await Browser.storage.local.remove('customClaudeApiUrl').catch(() => {}) |
| 1566 | } |
| 1567 | } |
| 1568 | |
| 1569 | const { migrated, dirty } = migrateUserConfig(options) |
| 1570 | if (dirty) { |
| 1571 | const payload = {} |
| 1572 | if (JSON.stringify(options.customApiModes) !== JSON.stringify(migrated.customApiModes)) { |
| 1573 | payload.customApiModes = migrated.customApiModes |
| 1574 | } |
| 1575 | if (options.modelName !== migrated.modelName) { |
| 1576 | payload.modelName = migrated.modelName |
| 1577 | } |
| 1578 | if (JSON.stringify(options.activeApiModes) !== JSON.stringify(migrated.activeApiModes)) { |
| 1579 | payload.activeApiModes = migrated.activeApiModes |
| 1580 | } |
| 1581 | if ( |
| 1582 | JSON.stringify(options.customOpenAIProviders) !== |
| 1583 | JSON.stringify(migrated.customOpenAIProviders) |
| 1584 | ) { |
| 1585 | payload.customOpenAIProviders = migrated.customOpenAIProviders |
| 1586 | } |
| 1587 | if (!areStringRecordValuesEqual(options.providerSecrets, migrated.providerSecrets)) { |
| 1588 | payload.providerSecrets = migrated.providerSecrets |
no test coverage detected