Skip to content

Commit e33b9ac

Browse files
committed
fix(api): Prevent deleted providers from reappearing
reloadProviderConfigurations() was recreating ALL providers including deleted ones because it used '?? createDefaultConfiguration()' which created a default config when no saved config existed. Fix: Only create remote providers if there's a saved configuration. Local models (localLlama, localMLX) are still auto-created since they're discovered from disk.
1 parent 64452f7 commit e33b9ac

1 file changed

Lines changed: 35 additions & 19 deletions

File tree

Sources/APIFramework/EndpointManager.swift

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,19 +1229,35 @@ public class EndpointManager: ObservableObject {
12291229
for providerType in ProviderType.allCases {
12301230
let providerId = providerType.defaultIdentifier
12311231

1232-
/// Load saved configuration or create default.
1233-
var config = loadProviderConfiguration(for: providerId) ?? createDefaultConfiguration(for: providerType)
1232+
/// For local models, always create providers if models exist on disk.
1233+
/// Local models don't require saved configurations since they're auto-discovered.
1234+
let isLocalModel = providerType == .localLlama || providerType == .localMLX
1235+
1236+
/// Remote providers only: require saved configuration to be created.
1237+
/// If a user deleted a remote provider, we should NOT recreate it with a default config.
1238+
var config: ProviderConfiguration?
1239+
if isLocalModel {
1240+
config = loadProviderConfiguration(for: providerId) ?? createDefaultConfiguration(for: providerType)
1241+
} else {
1242+
config = loadProviderConfiguration(for: providerId)
1243+
}
1244+
1245+
/// If no config found, skip this provider entirely.
1246+
guard var finalConfig = config else {
1247+
logger.debug("Skipping provider \(providerId) - no saved configuration found")
1248+
continue
1249+
}
12341250

12351251
/// For local llama, populate models from LocalModelManager.
12361252
if providerType == .localLlama, let modelManager = localModelManager {
1237-
config.models = modelManager.getAvailableModels()
1238-
logger.debug("Found \(config.models.count) local GGUF models")
1253+
finalConfig.models = modelManager.getAvailableModels()
1254+
logger.debug("Found \(finalConfig.models.count) local GGUF models")
12391255
}
12401256

12411257
/// Only create provider if it has API key or doesn't require one.
12421258
/// GitHub Copilot also accepts device flow tokens from CopilotTokenStore.
12431259
let requiresKey = providerType.requiresApiKey
1244-
let hasAuth = config.apiKey != nil ||
1260+
let hasAuth = finalConfig.apiKey != nil ||
12451261
(providerType == .githubCopilot && CopilotTokenStore.shared.isSignedIn)
12461262
if !requiresKey || hasAuth {
12471263
/// For local llama, create one provider per model using registry identifiers.
@@ -1257,14 +1273,14 @@ public class EndpointManager: ObservableObject {
12571273
let providerSpecificConfig = ProviderConfiguration(
12581274
providerId: providerIdentifier,
12591275
providerType: .localLlama,
1260-
isEnabled: config.isEnabled,
1276+
isEnabled: finalConfig.isEnabled,
12611277
baseURL: nil,
12621278
models: [providerIdentifier],
1263-
maxTokens: config.maxTokens,
1264-
temperature: config.temperature,
1265-
customHeaders: config.customHeaders,
1266-
timeoutSeconds: config.timeoutSeconds,
1267-
retryCount: config.retryCount
1279+
maxTokens: finalConfig.maxTokens,
1280+
temperature: finalConfig.temperature,
1281+
customHeaders: finalConfig.customHeaders,
1282+
timeoutSeconds: finalConfig.timeoutSeconds,
1283+
retryCount: finalConfig.retryCount
12681284
)
12691285
let provider = LlamaProvider(
12701286
config: providerSpecificConfig,
@@ -1296,14 +1312,14 @@ public class EndpointManager: ObservableObject {
12961312
let providerSpecificConfig = ProviderConfiguration(
12971313
providerId: providerIdentifier,
12981314
providerType: .localMLX,
1299-
isEnabled: config.isEnabled,
1315+
isEnabled: finalConfig.isEnabled,
13001316
baseURL: nil,
13011317
models: [providerIdentifier],
1302-
maxTokens: config.maxTokens,
1303-
temperature: config.temperature,
1304-
customHeaders: config.customHeaders,
1305-
timeoutSeconds: config.timeoutSeconds,
1306-
retryCount: config.retryCount
1318+
maxTokens: finalConfig.maxTokens,
1319+
temperature: finalConfig.temperature,
1320+
customHeaders: finalConfig.customHeaders,
1321+
timeoutSeconds: finalConfig.timeoutSeconds,
1322+
retryCount: finalConfig.retryCount
13071323
)
13081324
/// For MLX models: Use parent directory (not individual file path)
13091325
/// For diffusers models: Path is already the directory
@@ -1331,8 +1347,8 @@ public class EndpointManager: ObservableObject {
13311347
}
13321348
}
13331349
} else {
1334-
providers[providerId] = createProvider(type: providerType, config: config)
1335-
providerConfigs[providerId] = config
1350+
providers[providerId] = createProvider(type: providerType, config: finalConfig)
1351+
providerConfigs[providerId] = finalConfig
13361352
logger.debug("Recreated provider \(providerId) with updated configuration")
13371353
}
13381354
}

0 commit comments

Comments
 (0)