first commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { logEvent } from 'src/services/analytics/index.js'
|
||||
import {
|
||||
getCurrentProjectConfig,
|
||||
saveCurrentProjectConfig,
|
||||
} from '../utils/config.js'
|
||||
import { logError } from '../utils/log.js'
|
||||
import {
|
||||
getSettingsForSource,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 迁移:将 MCP 服务器批准字段从项目配置移到本地设置
|
||||
* 这同时迁移 enableAllProjectMcpServers 和 enabledMcpjsonServers 到
|
||||
* 设置系统以更好地管理和保持一致。
|
||||
*/
|
||||
export function migrateEnableAllProjectMcpServersToSettings(): void {
|
||||
const projectConfig = getCurrentProjectConfig()
|
||||
|
||||
// 检查项目配置中是否存在任何字段
|
||||
const hasEnableAll = projectConfig.enableAllProjectMcpServers !== undefined
|
||||
const hasEnabledServers =
|
||||
projectConfig.enabledMcpjsonServers &&
|
||||
projectConfig.enabledMcpjsonServers.length > 0
|
||||
const hasDisabledServers =
|
||||
projectConfig.disabledMcpjsonServers &&
|
||||
projectConfig.disabledMcpjsonServers.length > 0
|
||||
|
||||
if (!hasEnableAll && !hasEnabledServers && !hasDisabledServers) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const existingSettings = getSettingsForSource('localSettings') || {}
|
||||
const updates: Partial<{
|
||||
enableAllProjectMcpServers: boolean
|
||||
enabledMcpjsonServers: string[]
|
||||
disabledMcpjsonServers: string[]
|
||||
}> = {}
|
||||
const fieldsToRemove: Array<
|
||||
| 'enableAllProjectMcpServers'
|
||||
| 'enabledMcpjsonServers'
|
||||
| 'disabledMcpjsonServers'
|
||||
> = []
|
||||
|
||||
// 如果 enableAllProjectMcpServers 存在且尚未迁移,则迁移它
|
||||
if (
|
||||
hasEnableAll &&
|
||||
existingSettings.enableAllProjectMcpServers === undefined
|
||||
) {
|
||||
updates.enableAllProjectMcpServers =
|
||||
projectConfig.enableAllProjectMcpServers
|
||||
fieldsToRemove.push('enableAllProjectMcpServers')
|
||||
} else if (hasEnableAll) {
|
||||
// 已经迁移,仅标记为移除
|
||||
fieldsToRemove.push('enableAllProjectMcpServers')
|
||||
}
|
||||
|
||||
// 如果 enabledMcpjsonServers 存在,则迁移它
|
||||
if (hasEnabledServers && projectConfig.enabledMcpjsonServers) {
|
||||
const existingEnabledServers =
|
||||
existingSettings.enabledMcpjsonServers || []
|
||||
// 合并服务器(避免重复)
|
||||
updates.enabledMcpjsonServers = [
|
||||
...new Set([
|
||||
...existingEnabledServers,
|
||||
...projectConfig.enabledMcpjsonServers,
|
||||
]),
|
||||
]
|
||||
fieldsToRemove.push('enabledMcpjsonServers')
|
||||
}
|
||||
|
||||
// 如果 disabledMcpjsonServers 存在,则迁移它
|
||||
if (hasDisabledServers && projectConfig.disabledMcpjsonServers) {
|
||||
const existingDisabledServers =
|
||||
existingSettings.disabledMcpjsonServers || []
|
||||
// 合并服务器(避免重复)
|
||||
updates.disabledMcpjsonServers = [
|
||||
...new Set([
|
||||
...existingDisabledServers,
|
||||
...projectConfig.disabledMcpjsonServers,
|
||||
]),
|
||||
]
|
||||
fieldsToRemove.push('disabledMcpjsonServers')
|
||||
}
|
||||
|
||||
// 如果有任何更新,则更新设置
|
||||
if (Object.keys(updates).length > 0) {
|
||||
updateSettingsForSource('localSettings', updates)
|
||||
}
|
||||
|
||||
// 从项目配置中移除已迁移的字段
|
||||
if (
|
||||
fieldsToRemove.includes('enableAllProjectMcpServers') ||
|
||||
fieldsToRemove.includes('enabledMcpjsonServers') ||
|
||||
fieldsToRemove.includes('disabledMcpjsonServers')
|
||||
) {
|
||||
saveCurrentProjectConfig(current => {
|
||||
const {
|
||||
enableAllProjectMcpServers: _enableAll,
|
||||
enabledMcpjsonServers: _enabledServers,
|
||||
disabledMcpjsonServers: _disabledServers,
|
||||
...configWithoutFields
|
||||
} = current
|
||||
return configWithoutFields
|
||||
})
|
||||
}
|
||||
|
||||
// 记录迁移事件
|
||||
logEvent('tengu_migrate_mcp_approval_fields_success', {
|
||||
migratedCount: fieldsToRemove.length,
|
||||
})
|
||||
} catch (e: unknown) {
|
||||
// 记录迁移失败但不要抛出以避免破坏启动
|
||||
logError(e)
|
||||
logEvent('tengu_migrate_mcp_approval_fields_error', {})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { logEvent } from 'src/services/analytics/index.js'
|
||||
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js'
|
||||
import { logError } from '../utils/log.js'
|
||||
import {
|
||||
hasSkipDangerousModePermissionPrompt,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 迁移:将 bypassPermissionsModeAccepted 从全局配置移到 settings.json
|
||||
* 作为 skipDangerousModePermissionPrompt。这是更好的归宿,
|
||||
* 因为 settings.json 是用户可配置的设置文件。
|
||||
*/
|
||||
export function migrateBypassPermissionsAcceptedToSettings(): void {
|
||||
const globalConfig = getGlobalConfig()
|
||||
|
||||
if (!globalConfig.bypassPermissionsModeAccepted) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (!hasSkipDangerousModePermissionPrompt()) {
|
||||
updateSettingsForSource('userSettings', {
|
||||
skipDangerousModePermissionPrompt: true,
|
||||
})
|
||||
}
|
||||
|
||||
logEvent('tengu_migrate_bypass_permissions_accepted', {})
|
||||
|
||||
saveGlobalConfig(current => {
|
||||
if (!('bypassPermissionsModeAccepted' in current)) return current
|
||||
const { bypassPermissionsModeAccepted: _, ...updatedConfig } = current
|
||||
return updatedConfig
|
||||
})
|
||||
} catch (error) {
|
||||
logError(
|
||||
new Error(`Failed to migrate bypass permissions accepted: ${error}`),
|
||||
)
|
||||
}
|
||||
}
|
||||
45
claude-code源码-中文注释/src/migrations/migrateFennecToOpus.ts
Normal file
45
claude-code源码-中文注释/src/migrations/migrateFennecToOpus.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
getSettingsForSource,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 将使用已删除的 fennec 模型别名的用户迁移到新的 Opus 4.6 别名。
|
||||
* - fennec-latest → opus
|
||||
* - fennec-latest[1m] → opus[1m]
|
||||
* - fennec-fast-latest → opus[1m] + fast 模式
|
||||
* - opus-4-5-fast → opus + fast 模式
|
||||
*
|
||||
* 仅触及 userSettings。读写相同源保持此操作
|
||||
* 幂等而不需要完成标志。project/local/policy
|
||||
* 设置中的 Fennec 别名保留不动 — 我们不能/不应该重写那些,
|
||||
* 在这里读取合并设置会导致无限重新运行 + 静默全局提升。
|
||||
*/
|
||||
export function migrateFennecToOpus(): void {
|
||||
if (process.env.USER_TYPE !== 'ant') {
|
||||
return
|
||||
}
|
||||
|
||||
const settings = getSettingsForSource('userSettings')
|
||||
|
||||
const model = settings?.model
|
||||
if (typeof model === 'string') {
|
||||
if (model.startsWith('fennec-latest[1m]')) {
|
||||
updateSettingsForSource('userSettings', {
|
||||
model: 'opus[1m]',
|
||||
})
|
||||
} else if (model.startsWith('fennec-latest')) {
|
||||
updateSettingsForSource('userSettings', {
|
||||
model: 'opus',
|
||||
})
|
||||
} else if (
|
||||
model.startsWith('fennec-fast-latest') ||
|
||||
model.startsWith('opus-4-5-fast')
|
||||
) {
|
||||
updateSettingsForSource('userSettings', {
|
||||
model: 'opus[1m]',
|
||||
fastMode: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
logEvent,
|
||||
} from '../services/analytics/index.js'
|
||||
import { saveGlobalConfig } from '../utils/config.js'
|
||||
import { isLegacyModelRemapEnabled } from '../utils/model/model.js'
|
||||
import { getAPIProvider } from '../utils/model/providers.js'
|
||||
import {
|
||||
getSettingsForSource,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 将第一方用户从显式 Opus 4.0/4.1 模型字符串迁移出来。
|
||||
*
|
||||
* 'opus' 别名已经为 1P 解析为 Opus 4.6,所以任何仍在
|
||||
* 使用显式 4.0/4.1 字符串的用户是在 4.5 发布之前在设置中固定它的。
|
||||
* parseUserSpecifiedModel 现在无论如何都会在运行时静默重新映射这些 —
|
||||
* 此迁移清理 settings.json 以便 /model 显示正确的内容,
|
||||
* 并设置时间戳以便 REPL 可以显示一次性通知。
|
||||
*
|
||||
* 仅触及 userSettings。项目/本地/策略设置中的旧字符串
|
||||
* 保持不变(我们不能/不应该重写那些),仍然在运行时由
|
||||
* parseUserSpecifiedModel 重新映射。读写相同源
|
||||
* 保持此操作的幂等性而不需要完成标志,并避免静默
|
||||
* 将 'opus' 提升为仅在一个项目中固定它的用户的全局默认值。
|
||||
*/
|
||||
export function migrateLegacyOpusToCurrent(): void {
|
||||
if (getAPIProvider() !== 'firstParty') {
|
||||
return
|
||||
}
|
||||
|
||||
if (!isLegacyModelRemapEnabled()) {
|
||||
return
|
||||
}
|
||||
|
||||
const model = getSettingsForSource('userSettings')?.model
|
||||
if (
|
||||
model !== 'claude-opus-4-20250514' &&
|
||||
model !== 'claude-opus-4-1-20250805' &&
|
||||
model !== 'claude-opus-4-0' &&
|
||||
model !== 'claude-opus-4-1'
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
updateSettingsForSource('userSettings', { model: 'opus' })
|
||||
saveGlobalConfig(current => ({
|
||||
...current,
|
||||
legacyOpusMigrationTimestamp: Date.now(),
|
||||
}))
|
||||
logEvent('tengu_legacy_opus_migration', {
|
||||
from_model:
|
||||
model as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
}
|
||||
43
claude-code源码-中文注释/src/migrations/migrateOpusToOpus1m.ts
Normal file
43
claude-code源码-中文注释/src/migrations/migrateOpusToOpus1m.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { logEvent } from '../services/analytics/index.js'
|
||||
import {
|
||||
getDefaultMainLoopModelSetting,
|
||||
isOpus1mMergeEnabled,
|
||||
parseUserSpecifiedModel,
|
||||
} from '../utils/model/model.js'
|
||||
import {
|
||||
getSettingsForSource,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 当用户有资格获得合并的 Opus 1M 体验(1P 上的 Max/Team Premium)时,
|
||||
* 将设置中固定了 'opus' 的用户迁移到 'opus[1m]'。
|
||||
*
|
||||
* 使用 --model opus 的 CLI 调用不受影响:该标志是运行时
|
||||
* 覆盖,不触及 userSettings,因此继续使用普通 Opus。
|
||||
*
|
||||
* Pro 订阅者被跳过 — 他们保留单独的 Opus 和 Opus 1M 选项。
|
||||
* 3P 用户被跳过 — 他们的模型字符串是完整模型 ID,不是别名。
|
||||
*
|
||||
* 幂等:仅在 userSettings.model 正好是 'opus' 时写入。
|
||||
*/
|
||||
export function migrateOpusToOpus1m(): void {
|
||||
if (!isOpus1mMergeEnabled()) {
|
||||
return
|
||||
}
|
||||
|
||||
const model = getSettingsForSource('userSettings')?.model
|
||||
if (model !== 'opus') {
|
||||
return
|
||||
}
|
||||
|
||||
const migrated = 'opus[1m]'
|
||||
const modelToSet =
|
||||
parseUserSpecifiedModel(migrated) ===
|
||||
parseUserSpecifiedModel(getDefaultMainLoopModelSetting())
|
||||
? undefined
|
||||
: migrated
|
||||
updateSettingsForSource('userSettings', { model: modelToSet })
|
||||
|
||||
logEvent('tengu_opus_to_opus1m_migration', {})
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { saveGlobalConfig } from '../utils/config.js'
|
||||
|
||||
/**
|
||||
* 将 `replBridgeEnabled` 配置键迁移到 `remoteControlAtStartup`。
|
||||
*
|
||||
* 旧键是泄漏到用户面向配置的实现细节。
|
||||
* 此迁移将值复制到新键并删除旧键。
|
||||
* 幂等 — 仅在旧键存在且新键不存在时执行。
|
||||
*/
|
||||
export function migrateReplBridgeEnabledToRemoteControlAtStartup(): void {
|
||||
saveGlobalConfig(prev => {
|
||||
// 旧键不再在 GlobalConfig 类型中,因此通过
|
||||
// 无类型转换访问它。仅在旧键存在且新键
|
||||
// 尚未设置时迁移。
|
||||
const oldValue = (prev as Record<string, unknown>)['replBridgeEnabled']
|
||||
if (oldValue === undefined) return prev
|
||||
if (prev.remoteControlAtStartup !== undefined) return prev
|
||||
const next = { ...prev, remoteControlAtStartup: Boolean(oldValue) }
|
||||
delete (next as Record<string, unknown>)['replBridgeEnabled']
|
||||
return next
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import {
|
||||
getMainLoopModelOverride,
|
||||
setMainLoopModelOverride,
|
||||
} from '../bootstrap/state.js'
|
||||
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js'
|
||||
import {
|
||||
getSettingsForSource,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 将保存了 "sonnet[1m]" 的用户迁移到显式 "sonnet-4-5-20250929[1m]"。
|
||||
*
|
||||
* "sonnet" 别名现在解析为 Sonnet 4.6,所以之前设置
|
||||
* "sonnet[1m]"(以 Sonnet 4.5 1M 为目标)的用户需要固定到
|
||||
* 显式版本以保留其intended model。
|
||||
*
|
||||
* 这是必需的,因为 Sonnet 4.6 1M 向不同组的用户提供了比
|
||||
* Sonnet 4.5 1M,所以我们需要将现有的 sonnet[1m] 用户固定到 Sonnet 4.5 1M。
|
||||
*
|
||||
* 专门从 userSettings 读取(不是合并设置)所以我们不会
|
||||
* 将项目范围的 "sonnet[1m]" 提升为全局默认值。运行一次,
|
||||
* 通过全局配置中的完成标志跟踪。
|
||||
*/
|
||||
export function migrateSonnet1mToSonnet45(): void {
|
||||
const config = getGlobalConfig()
|
||||
if (config.sonnet1m45MigrationComplete) {
|
||||
return
|
||||
}
|
||||
|
||||
const model = getSettingsForSource('userSettings')?.model
|
||||
if (model === 'sonnet[1m]') {
|
||||
updateSettingsForSource('userSettings', {
|
||||
model: 'sonnet-4-5-20250929[1m]',
|
||||
})
|
||||
}
|
||||
|
||||
// 同样迁移已设置的内存覆盖
|
||||
const override = getMainLoopModelOverride()
|
||||
if (override === 'sonnet[1m]') {
|
||||
setMainLoopModelOverride('sonnet-4-5-20250929[1m]')
|
||||
}
|
||||
|
||||
saveGlobalConfig(current => ({
|
||||
...current,
|
||||
sonnet1m45MigrationComplete: true,
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
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'
|
||||
|
||||
/**
|
||||
* 将 Pro/Max/Team Premium 第一方用户从显式 Sonnet 4.5
|
||||
* 模型字符串迁移到 'sonnet' 别名(现在解析为 Sonnet 4.6)。
|
||||
*
|
||||
* 用户可能已通过以下方式固定到显式 Sonnet 4.5 字符串:
|
||||
* - 较早的 migrateSonnet1mToSonnet45 迁移(sonnet[1m] → 显式 4.5[1m])
|
||||
* - 通过 /model 手动选择
|
||||
*
|
||||
* 专门读取 userSettings(不是合并的)所以我们只迁移 /model
|
||||
* 写入的内容 — 项目/本地固定保留不动。
|
||||
* 幂等:仅在 userSettings.model 匹配 Sonnet 4.5 字符串时写入。
|
||||
*/
|
||||
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',
|
||||
})
|
||||
|
||||
// 跳过新用户通知 — 他们从未体验过旧默认值
|
||||
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,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { feature } from 'bun:bundle'
|
||||
import { logEvent } from 'src/services/analytics/index.js'
|
||||
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js'
|
||||
import { logError } from '../utils/log.js'
|
||||
import { getAutoModeEnabledState } from '../utils/permissions/permissionSetup.js'
|
||||
import {
|
||||
getSettingsForSource,
|
||||
updateSettingsForSource,
|
||||
} from '../utils/settings/settings.js'
|
||||
|
||||
/**
|
||||
* 一次性迁移:清除已接受旧 2 选项 AutoModeOptInDialog
|
||||
* 但没有将 auto 作为默认值的用户的 skipAutoPermissionPrompt。
|
||||
* 重新显示对话框,以便他们看到新的"使其成为我的默认模式"选项。
|
||||
* 保护存在于 GlobalConfig(~/.claude.json)中,而不是 settings.json 中,
|
||||
* 因此它在设置重置后保留并且不会重新武装自己。
|
||||
*
|
||||
* 仅在 tengu_auto_mode_config.enabled === 'enabled' 时运行。对于 'opt-in'
|
||||
* 用户,清除 skipAutoPermissionPrompt 会从轮播中移除 auto
|
||||
*(permissionSetup.ts:988)— 对话框将变得不可达并且
|
||||
* 迁移会自我失败。实际上,约 40 个目标蚂蚁都是
|
||||
* 'enabled'(他们通过 bare Shift+Tab 到达旧对话框,这需要
|
||||
* 'enabled'),但保护使其无论如何都是安全的。
|
||||
*/
|
||||
export function resetAutoModeOptInForDefaultOffer(): void {
|
||||
if (feature('TRANSCRIPT_CLASSIFIER')) {
|
||||
const config = getGlobalConfig()
|
||||
if (config.hasResetAutoModeOptInForDefaultOffer) return
|
||||
if (getAutoModeEnabledState() !== 'enabled') return
|
||||
|
||||
try {
|
||||
const user = getSettingsForSource('userSettings')
|
||||
if (
|
||||
user?.skipAutoPermissionPrompt &&
|
||||
user?.permissions?.defaultMode !== 'auto'
|
||||
) {
|
||||
updateSettingsForSource('userSettings', {
|
||||
skipAutoPermissionPrompt: undefined,
|
||||
})
|
||||
logEvent('tengu_migrate_reset_auto_opt_in_for_default_offer', {})
|
||||
}
|
||||
|
||||
saveGlobalConfig(c => {
|
||||
if (c.hasResetAutoModeOptInForDefaultOffer) return c
|
||||
return { ...c, hasResetAutoModeOptInForDefaultOffer: true }
|
||||
})
|
||||
} catch (error) {
|
||||
logError(new Error(`Failed to reset auto mode opt-in: ${error}`))
|
||||
}
|
||||
}
|
||||
}
|
||||
51
claude-code源码-中文注释/src/migrations/resetProToOpusDefault.ts
Normal file
51
claude-code源码-中文注释/src/migrations/resetProToOpusDefault.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { logEvent } from 'src/services/analytics/index.js'
|
||||
import { isProSubscriber } from '../utils/auth.js'
|
||||
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js'
|
||||
import { getAPIProvider } from '../utils/model/providers.js'
|
||||
import { getSettings_DEPRECATED } from '../utils/settings/settings.js'
|
||||
|
||||
export function resetProToOpusDefault(): void {
|
||||
const config = getGlobalConfig()
|
||||
|
||||
if (config.opusProMigrationComplete) {
|
||||
return
|
||||
}
|
||||
|
||||
const apiProvider = getAPIProvider()
|
||||
|
||||
// 第一方的 Pro 用户自动迁移到 Opus 4.5 默认值
|
||||
if (apiProvider !== 'firstParty' || !isProSubscriber()) {
|
||||
saveGlobalConfig(current => ({
|
||||
...current,
|
||||
opusProMigrationComplete: true,
|
||||
}))
|
||||
logEvent('tengu_reset_pro_to_opus_default', { skipped: true })
|
||||
return
|
||||
}
|
||||
|
||||
const settings = getSettings_DEPRECATED()
|
||||
|
||||
// 仅在用户使用默认值时显示通知(没有自定义模型设置)
|
||||
if (settings?.model === undefined) {
|
||||
const opusProMigrationTimestamp = Date.now()
|
||||
saveGlobalConfig(current => ({
|
||||
...current,
|
||||
opusProMigrationComplete: true,
|
||||
opusProMigrationTimestamp,
|
||||
}))
|
||||
logEvent('tengu_reset_pro_to_opus_default', {
|
||||
skipped: false,
|
||||
had_custom_model: false,
|
||||
})
|
||||
} else {
|
||||
// 用户有自定义模型设置,仅标记迁移完成
|
||||
saveGlobalConfig(current => ({
|
||||
...current,
|
||||
opusProMigrationComplete: true,
|
||||
}))
|
||||
logEvent('tengu_reset_pro_to_opus_default', {
|
||||
skipped: false,
|
||||
had_custom_model: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user