fix(pool): strip stale member names from settings on save

When a pool member provider is deleted/disabled, its name persists in
the owner's extra_provider_names config. Validation already skips stale
refs, but the names accumulated as garbage in the DB.

Now stripStalePoolMembers() runs after validation passes, removing
member names that don't exist in the active provider set before the
settings are written to the database.
This commit is contained in:
viettranx committed 2026-04-05 08:47:10 +07:00
1 parent e9733e08c4
commit b65b23b212
1 file changed
+60 -1
+60 -1
View File
@@ -128,7 +128,66 @@ func validateChatGPTOAuthProviderCandidate(
finalProviders = append(finalProviders, *candidate)
}
return validateChatGPTOAuthPoolGraph(finalProviders)
if err := validateChatGPTOAuthPoolGraph(finalProviders); err != nil {
return err
}
// Strip stale member references from the candidate's settings so they
// don't accumulate as garbage in the DB after deleted/disabled providers.
stripStalePoolMembers(candidate, finalProviders)
return nil
}
// stripStalePoolMembers removes pool member names from the candidate's
// settings that no longer exist in the active provider set. This prevents
// deleted/disabled provider names from accumulating as garbage in the DB.
func stripStalePoolMembers(candidate *store.LLMProviderData, activeProviders []store.LLMProviderData) {
if candidate == nil || len(candidate.Settings) == 0 {
return
}
// Parse full settings as generic map to preserve non-pool fields.
var raw map[string]any
if json.Unmarshal(candidate.Settings, &raw) != nil {
return
}
cpRaw, ok := raw["codex_pool"]
if !ok {
return
}
cpMap, ok := cpRaw.(map[string]any)
if !ok {
return
}
namesRaw, ok := cpMap["extra_provider_names"]
if !ok {
return
}
namesSlice, ok := namesRaw.([]any)
if !ok || len(namesSlice) == 0 {
return
}
known := make(map[string]bool, len(activeProviders))
for _, p := range activeProviders {
known[p.Name] = true
}
filtered := make([]any, 0, len(namesSlice))
for _, n := range namesSlice {
if name, ok := n.(string); ok && known[name] {
filtered = append(filtered, name)
}
}
if len(filtered) == len(namesSlice) {
return // nothing changed
}
cpMap["extra_provider_names"] = filtered
if updated, err := json.Marshal(raw); err == nil {
candidate.Settings = updated
}
}
func validateChatGPTOAuthAgentRouting(