|
|
@@ -229,6 +229,121 @@ describe("ProviderSettingsManager", () => {
|
|
|
expect(storedConfig.migrations.todoListEnabledMigrated).toEqual(true)
|
|
|
})
|
|
|
|
|
|
+ it("should apply model migrations for all providers", async () => {
|
|
|
+ mockSecrets.get.mockResolvedValue(
|
|
|
+ JSON.stringify({
|
|
|
+ currentApiConfigName: "default",
|
|
|
+ apiConfigs: {
|
|
|
+ default: {
|
|
|
+ config: {},
|
|
|
+ id: "default",
|
|
|
+ apiProvider: "roo",
|
|
|
+ apiModelId: "roo/code-supernova", // Old model ID
|
|
|
+ },
|
|
|
+ test: {
|
|
|
+ apiProvider: "roo",
|
|
|
+ apiModelId: "roo/code-supernova", // Old model ID
|
|
|
+ },
|
|
|
+ existing: {
|
|
|
+ apiProvider: "roo",
|
|
|
+ apiModelId: "roo/code-supernova-1-million", // Already migrated
|
|
|
+ },
|
|
|
+ otherProvider: {
|
|
|
+ apiProvider: "anthropic",
|
|
|
+ apiModelId: "roo/code-supernova", // Should not be migrated (different provider)
|
|
|
+ },
|
|
|
+ noProvider: {
|
|
|
+ id: "no-provider",
|
|
|
+ apiModelId: "roo/code-supernova", // Should not be migrated (no provider)
|
|
|
+ },
|
|
|
+ },
|
|
|
+ migrations: {
|
|
|
+ rateLimitSecondsMigrated: true,
|
|
|
+ diffSettingsMigrated: true,
|
|
|
+ openAiHeadersMigrated: true,
|
|
|
+ consecutiveMistakeLimitMigrated: true,
|
|
|
+ todoListEnabledMigrated: true,
|
|
|
+ },
|
|
|
+ }),
|
|
|
+ )
|
|
|
+
|
|
|
+ await providerSettingsManager.initialize()
|
|
|
+
|
|
|
+ // Get the last call to store, which should contain the migrated config
|
|
|
+ const calls = mockSecrets.store.mock.calls
|
|
|
+ const storedConfig = JSON.parse(calls[calls.length - 1][1])
|
|
|
+
|
|
|
+ // Roo provider configs should be migrated
|
|
|
+ expect(storedConfig.apiConfigs.default.apiModelId).toEqual("roo/code-supernova-1-million")
|
|
|
+ expect(storedConfig.apiConfigs.test.apiModelId).toEqual("roo/code-supernova-1-million")
|
|
|
+ expect(storedConfig.apiConfigs.existing.apiModelId).toEqual("roo/code-supernova-1-million")
|
|
|
+
|
|
|
+ // Non-roo provider configs should not be migrated
|
|
|
+ expect(storedConfig.apiConfigs.otherProvider.apiModelId).toEqual("roo/code-supernova")
|
|
|
+ expect(storedConfig.apiConfigs.noProvider.apiModelId).toEqual("roo/code-supernova")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should apply model migrations every time, not just once", async () => {
|
|
|
+ // First load with old model
|
|
|
+ mockSecrets.get.mockResolvedValue(
|
|
|
+ JSON.stringify({
|
|
|
+ currentApiConfigName: "default",
|
|
|
+ apiConfigs: {
|
|
|
+ default: {
|
|
|
+ apiProvider: "roo",
|
|
|
+ apiModelId: "roo/code-supernova",
|
|
|
+ id: "default",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ migrations: {
|
|
|
+ rateLimitSecondsMigrated: true,
|
|
|
+ diffSettingsMigrated: true,
|
|
|
+ openAiHeadersMigrated: true,
|
|
|
+ consecutiveMistakeLimitMigrated: true,
|
|
|
+ todoListEnabledMigrated: true,
|
|
|
+ },
|
|
|
+ }),
|
|
|
+ )
|
|
|
+
|
|
|
+ await providerSettingsManager.initialize()
|
|
|
+
|
|
|
+ // Verify migration happened
|
|
|
+ let calls = mockSecrets.store.mock.calls
|
|
|
+ let storedConfig = JSON.parse(calls[calls.length - 1][1])
|
|
|
+ expect(storedConfig.apiConfigs.default.apiModelId).toEqual("roo/code-supernova-1-million")
|
|
|
+
|
|
|
+ // Create a new instance to simulate another load
|
|
|
+ const newManager = new ProviderSettingsManager(mockContext)
|
|
|
+
|
|
|
+ // Somehow the model got reverted (e.g., manual edit, sync issue)
|
|
|
+ mockSecrets.get.mockResolvedValue(
|
|
|
+ JSON.stringify({
|
|
|
+ currentApiConfigName: "default",
|
|
|
+ apiConfigs: {
|
|
|
+ default: {
|
|
|
+ apiProvider: "roo",
|
|
|
+ apiModelId: "roo/code-supernova", // Old model again
|
|
|
+ id: "default",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ migrations: {
|
|
|
+ rateLimitSecondsMigrated: true,
|
|
|
+ diffSettingsMigrated: true,
|
|
|
+ openAiHeadersMigrated: true,
|
|
|
+ consecutiveMistakeLimitMigrated: true,
|
|
|
+ todoListEnabledMigrated: true,
|
|
|
+ },
|
|
|
+ }),
|
|
|
+ )
|
|
|
+
|
|
|
+ await newManager.initialize()
|
|
|
+
|
|
|
+ // Verify migration happened again
|
|
|
+ calls = mockSecrets.store.mock.calls
|
|
|
+ storedConfig = JSON.parse(calls[calls.length - 1][1])
|
|
|
+ expect(storedConfig.apiConfigs.default.apiModelId).toEqual("roo/code-supernova-1-million")
|
|
|
+ })
|
|
|
+
|
|
|
it("should throw error if secrets storage fails", async () => {
|
|
|
mockSecrets.get.mockRejectedValue(new Error("Storage failed"))
|
|
|
|