feat: remove legacy chat provider tables (#25416)

This commit is contained in:
Michael Suchacz
2026-05-22 09:50:01 +02:00
committed by GitHub
parent ddec110b0e
commit ca1f6b19a2
46 changed files with 1270 additions and 3505 deletions
+66 -48
View File
@@ -350,13 +350,8 @@ func (p *Server) resolveAdvisorModelOverride(
return fallbackModel, fallbackCallConfig
}
// GetEnabledChatModelConfigByID checks the model config and referenced
// provider enabled state, so it returns sql.ErrNoRows the moment an
// admin disables either one. Using the cached ModelConfigByID here
// would keep resolving an override whose provider was just disabled,
// and an available fallback key would let ModelFromConfig succeed,
// silently routing advisor prompts to a provider the admin expects to
// be off.
// Re-read the override instead of using the cache so disabled models
// or providers stop routing advisor prompts immediately.
overrideConfig, err := p.db.GetEnabledChatModelConfigByID(
ctx,
advisorCfg.ModelConfigID,
@@ -7102,9 +7097,8 @@ func (p *Server) runChat(
// Fire title generation asynchronously so it doesn't block the
// chat response. It uses a detached context so it can finish
// even after the chat processing context is canceled.
// Snapshot model, provider keys, logger, and ctx before launch; all four get
// reassigned below (model = cuModel, providerKeys = computerUseProviderKeys,
// logger = logger.With(...), ctx = runCtx) and the goroutine captures by reference.
// Snapshot values captured by the goroutine because model, providerKeys,
// logger, and ctx are reassigned below.
titleModel := model
titleProviderKeys := providerKeys
titleLogger := logger
@@ -8502,13 +8496,17 @@ func (p *Server) resolveChatModel(
}
func (p *Server) aiProviderConfig(ctx context.Context, provider database.AIProvider) (chatprovider.ConfiguredProvider, error) {
if !provider.Enabled {
return chatprovider.ConfiguredProvider{}, xerrors.Errorf("AI provider %s is disabled", provider.ID)
}
keys, err := p.db.GetAIProviderKeysByProviderID(ctx, provider.ID)
if err != nil {
return chatprovider.ConfiguredProvider{}, xerrors.Errorf("get AI provider keys: %w", err)
}
return p.aiProviderConfigFromKeys(provider, keys)
}
func (p *Server) aiProviderConfigFromKeys(provider database.AIProvider, keys []database.AIProviderKey) (chatprovider.ConfiguredProvider, error) {
if !provider.Enabled {
return chatprovider.ConfiguredProvider{}, xerrors.Errorf("AI provider %s is disabled", provider.ID)
}
apiKey := ""
// GetAIProviderKeysByProviderID orders keys oldest first. chatd consumes
// one provider-scoped key because runtime provider config has one API key slot.
@@ -8529,6 +8527,48 @@ func (p *Server) aiProviderConfig(ctx context.Context, provider database.AIProvi
}, nil
}
func (p *Server) aiProviderConfigs(ctx context.Context, providers []database.AIProvider) ([]chatprovider.ConfiguredProvider, error) {
if len(providers) == 0 {
return nil, nil
}
providerIDs := make([]uuid.UUID, 0, len(providers))
for _, provider := range providers {
providerIDs = append(providerIDs, provider.ID)
}
keys, err := p.db.GetAIProviderKeysByProviderIDs(ctx, providerIDs)
if err != nil {
return nil, xerrors.Errorf("get AI provider keys: %w", err)
}
keysByProviderID := make(map[uuid.UUID][]database.AIProviderKey, len(providers))
for _, key := range keys {
keysByProviderID[key.ProviderID] = append(keysByProviderID[key.ProviderID], key)
}
configuredProviders := make([]chatprovider.ConfiguredProvider, 0, len(providers))
for _, provider := range providers {
configuredProvider, err := p.aiProviderConfigFromKeys(provider, keysByProviderID[provider.ID])
if err != nil {
return nil, err
}
configuredProviders = append(configuredProviders, configuredProvider)
}
return configuredProviders, nil
}
func ensureUniqueConfiguredProviderTypes(providers []chatprovider.ConfiguredProvider) error {
seen := make(map[string]uuid.UUID, len(providers))
for _, provider := range providers {
normalizedProvider := chatprovider.NormalizeProvider(provider.Provider)
if normalizedProvider == "" {
continue
}
if existingProviderID, ok := seen[normalizedProvider]; ok && existingProviderID != provider.ProviderID {
return xerrors.Errorf("multiple enabled AI providers use provider type %q; select an AI provider by ID", normalizedProvider)
}
seen[normalizedProvider] = provider.ProviderID
}
return nil
}
func (p *Server) resolveUserProviderAPIKeysForProvider(
ctx context.Context,
ownerID uuid.UUID,
@@ -8559,12 +8599,6 @@ func (p *Server) resolveUserProviderAPIKeysForProvider(
[]chatprovider.ConfiguredProvider{configuredProvider},
userKeys,
)
enabledProviders := map[string]struct{}{}
normalizedProvider := chatprovider.NormalizeProvider(configuredProvider.Provider)
if normalizedProvider != "" {
enabledProviders[normalizedProvider] = struct{}{}
}
chatprovider.PruneDisabledProviderKeys(&keys, enabledProviders)
return keys, nil
}
@@ -8598,9 +8632,6 @@ func (p *Server) resolveUserProviderAPIKeys(
ownerID uuid.UUID,
selectedAIProviderID uuid.UUID,
) (chatprovider.ProviderAPIKeys, error) {
var configuredProviders []chatprovider.ConfiguredProvider
userKeys := []chatprovider.UserProviderKey{}
if selectedAIProviderID != uuid.Nil {
provider, err := p.db.GetAIProviderByID(ctx, selectedAIProviderID)
if err != nil {
@@ -8608,48 +8639,35 @@ func (p *Server) resolveUserProviderAPIKeys(
}
return p.resolveUserProviderAPIKeysForProvider(ctx, ownerID, provider)
}
providers, err := p.configCache.EnabledProviders(ctx)
if err != nil {
return chatprovider.ProviderAPIKeys{}, xerrors.Errorf(
"get enabled chat providers: %w",
"get enabled AI providers: %w",
err,
)
}
configuredProviders = make(
[]chatprovider.ConfiguredProvider, 0, len(providers),
)
for _, provider := range providers {
configuredProviders = append(
configuredProviders, chatprovider.ConfiguredProvider{
ProviderID: provider.ID,
Provider: provider.Provider,
APIKey: provider.APIKey,
BaseURL: provider.BaseUrl,
CentralAPIKeyEnabled: provider.CentralApiKeyEnabled,
AllowUserAPIKey: provider.AllowUserApiKey,
AllowCentralAPIKeyFallback: provider.AllowCentralApiKeyFallback,
},
)
configuredProviders, err := p.aiProviderConfigs(ctx, providers)
if err != nil {
return chatprovider.ProviderAPIKeys{}, err
}
allowAnyUserAPIKey := false
for _, provider := range configuredProviders {
if provider.AllowUserAPIKey {
allowAnyUserAPIKey = true
break
}
if err := ensureUniqueConfiguredProviderTypes(configuredProviders); err != nil {
return chatprovider.ProviderAPIKeys{}, err
}
if allowAnyUserAPIKey {
userKeyRows, err := p.db.GetUserChatProviderKeys(ctx, ownerID)
userKeys := []chatprovider.UserProviderKey{}
if p.allowBYOK {
userKeyRows, err := p.db.GetUserAIProviderKeysByUserID(ctx, ownerID)
if err != nil {
return chatprovider.ProviderAPIKeys{}, xerrors.Errorf(
"get user chat provider keys: %w",
"get user AI provider keys: %w",
err,
)
}
userKeys = make([]chatprovider.UserProviderKey, 0, len(userKeyRows))
for _, userKey := range userKeyRows {
userKeys = append(userKeys, chatprovider.UserProviderKey{
ChatProviderID: userKey.ChatProviderID,
ChatProviderID: userKey.AIProviderID,
APIKey: userKey.APIKey,
})
}