π File detail
migrations/migrateSonnet45ToSonnet46.ts
π§© .tsπ 68 linesπΎ 2,055 bytesπ text
β Back to All Filesπ― Use case
This file lives under βmigrations/β, which covers version migrations for settings or on-disk data. On the API surface it exposes migrateSonnet45ToSonnet46 β mainly functions, hooks, or classes. It composes internal code from services and utils (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent, } from '../services/analytics/index.js' import {
π€ Exports (heuristic)
migrateSonnet45ToSonnet46
π₯οΈ Source preview
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
} from '../services/analytics/index.js'
import {
isMaxSubscriber,
isProSubscriber,
isTeamPremiumSubscriber,
} from '../utils/auth.js'
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js'
import { getAPIProvider } from '../utils/model/providers.js'
import {
getSettingsForSource,
updateSettingsForSource,
} from '../utils/settings/settings.js'
/**
* Migrate Pro/Max/Team Premium first-party users off explicit Sonnet 4.5
* model strings to the 'sonnet' alias (which now resolves to Sonnet 4.6).
*
* Users may have been pinned to explicit Sonnet 4.5 strings by:
* - The earlier migrateSonnet1mToSonnet45 migration (sonnet[1m] β explicit 4.5[1m])
* - Manually selecting it via /model
*
* Reads userSettings specifically (not merged) so we only migrate what /model
* wrote β project/local pins are left alone.
* Idempotent: only writes if userSettings.model matches a Sonnet 4.5 string.
*/
export function migrateSonnet45ToSonnet46(): void {
if (getAPIProvider() !== 'firstParty') {
return
}
if (!isProSubscriber() && !isMaxSubscriber() && !isTeamPremiumSubscriber()) {
return
}
const model = getSettingsForSource('userSettings')?.model
if (
model !== 'claude-sonnet-4-5-20250929' &&
model !== 'claude-sonnet-4-5-20250929[1m]' &&
model !== 'sonnet-4-5-20250929' &&
model !== 'sonnet-4-5-20250929[1m]'
) {
return
}
const has1m = model.endsWith('[1m]')
updateSettingsForSource('userSettings', {
model: has1m ? 'sonnet[1m]' : 'sonnet',
})
// Skip notification for brand-new users β they never experienced the old default
const config = getGlobalConfig()
if (config.numStartups > 1) {
saveGlobalConfig(current => ({
...current,
sonnet45To46MigrationTimestamp: Date.now(),
}))
}
logEvent('tengu_sonnet45_to_46_migration', {
from_model:
model as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
has_1m: has1m,
})
}