feat(registry): remote-refresh Codex client model catalog#4276
Conversation
Load codex_client_models.json like models.json with validation, revisioned handler reloads, CI bake, and Home-aware updater gates so list IDs still come from Home while templates can refresh on the edge.
There was a problem hiding this comment.
Code Review
This pull request introduces dynamic fetching, validation, and reloading of the Codex client model catalog (codex_client_models.json). It adds a background updater, a dedicated validation command, and updates the server and API handlers to reload templates when the catalog revision changes. The review feedback suggests two key improvements: first, avoid discarding successfully read catalog data if resp.Body.Close() returns an error; second, optimize template loading concurrency by replacing the exclusive sync.Mutex with a sync.RWMutex and implementing a double-checked locking pattern to prevent lock contention on /v1/models requests.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if errClose != nil { | ||
| log.Debugf("Codex client models response close failed for %s: %v", sourceURL, errClose) | ||
| continue | ||
| } |
There was a problem hiding this comment.
Discarding the successfully fetched and read catalog data solely because resp.Body.Close() returned an error is overly strict. Transport-level errors during connection teardown can occur even when the payload has been fully and correctly read. It is safer to log the close error and proceed with the validated data.
if errClose != nil {
log.Debugf("Codex client models response close failed for %s: %v", sourceURL, errClose)
}| codexClientModelTemplates map[string]map[string]any | ||
| codexClientDefaultTemplate map[string]any | ||
| codexClientModelTemplatesErr error | ||
| codexClientModelTemplatesMu sync.Mutex |
There was a problem hiding this comment.
Using a sync.Mutex forces an exclusive lock on every call to /v1/models (via loadCodexClientModelTemplatesSnapshot), even when the templates are already loaded and the revision has not changed. Under high concurrency, this can lead to lock contention. Consider using a sync.RWMutex to allow concurrent read access for the common case.
| codexClientModelTemplatesMu sync.Mutex | |
| codexClientModelTemplatesMu sync.RWMutex |
| func loadCodexClientModelTemplatesSnapshot(raw []byte, revision uint64) (map[string]map[string]any, map[string]any, error) { | ||
| codexClientModelTemplatesMu.Lock() | ||
| defer codexClientModelTemplatesMu.Unlock() | ||
| if codexClientModelTemplatesLoaded && codexClientModelTemplatesRevision == revision { | ||
| return codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr | ||
| } |
There was a problem hiding this comment.
With codexClientModelTemplatesMu upgraded to a sync.RWMutex, we can implement a double-checked locking pattern. This allows concurrent requests to read the cached templates using a read lock (RLock), completely avoiding exclusive lock contention when the revision has not changed.
func loadCodexClientModelTemplatesSnapshot(raw []byte, revision uint64) (map[string]map[string]any, map[string]any, error) {
codexClientModelTemplatesMu.RLock()
if codexClientModelTemplatesLoaded && codexClientModelTemplatesRevision == revision {
templates, defaultTemplate, err := codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr
codexClientModelTemplatesMu.RUnlock()
return templates, defaultTemplate, err
}
codexClientModelTemplatesMu.RUnlock()
codexClientModelTemplatesMu.Lock()
defer codexClientModelTemplatesMu.Unlock()
if codexClientModelTemplatesLoaded && codexClientModelTemplatesRevision == revision {
return codexClientModelTemplates, codexClientDefaultTemplate, codexClientModelTemplatesErr
}
Summary
codex_client_models.jsonfrom the shared models repository alongsidemodels.jsonValidation
go test ./...go test -race ./internal/registry ./sdk/api/handlers/openaigo vet ./cmd/server ./cmd/fetch_codex_models ./cmd/validate_codex_models ./internal/registry ./internal/api ./sdk/api/handlers/openaigo build -o test-output ./cmd/server && rm test-outputbash -n .github/scripts/refresh-model-catalogs.shactionlinton the changed workflowsrouter-for-me/modelsCodex client catalog