Client or integration
Codex CLI
Area
Catalog / models
Summary
ocx sync on 2.56.0 generated opencodex-catalog.json with 507 entries but only 72 unique slugs (e.g. CC-MiniMaxAI-MiniMax-M3 repeated 14x). I expected one entry per slug. The duplicates are byte-identical, so they are safe to drop — but the sync should never emit them.
Root cause (verified against pristine 2.56.0 tarball): my config uses the official modelAliases feature (providers.command-code.modelAliases = {"MiniMaxAI/MiniMax-M3": "CC-MiniMaxAI-MiniMax-M3", ...}, 17 entries). The alias form becomes the public slug via model.alias (catalogModelSlug in src/codex/catalog/parsing.ts:843: model.alias ?? routedSlug(provider, id)). The sync ALSO emits the canonical command-code/... form via routedSlug, and the merge (mergeCatalogEntriesFromObservedState in src/codex/catalog/build-entries.ts, key slugEquivalenceKey in src/providers/slug-codec.ts) never unifies them:
slugEquivalenceKey("CC-X") → ["exact","CC-X"] (no slash = exact key)
slugEquivalenceKey("command-code/...") → ["routed","command-code",...]
Three different keys for the same model = three rows.
Reproduction
- Config with provider
command-code + modelAliases mapping Vendor/Model → CC-Vendor-Model (17 entries), plus provider alias: "CC".
ocx sync --restart-codex && ocx sync-cache --restart-codex (config validates {"ok": true}).
jq '.models|length' ~/.codex/opencodex-catalog.json → 507; jq '[.models[].slug]|unique|length' → 72.
- Note:
ocx sync-cache alone kept 72/72; the explosion came from ocx sync. A later ocx sync on the same config stayed 72/72, so it is intermittent (possibly first sync after upgrade, or cache-state dependent).
Version
2.56.0 (@bitkyc08/opencodex, npm latest 2026-09-15)
Operating system
Ubuntu 24.04 (VPS, HestiaCP)
Provider and model
command-code provider (gateway), any model with a modelAliases entry
Logs or error output
# before dedup
$ jq '.models|length' ~/.codex/opencodex-catalog.json
507
$ jq '[.models[].slug]|unique|length' ~/.codex/opencodex-catalog.json
72
$ jq -r '.models[].slug' ~/.codex/opencodex-catalog.json | sort | uniq -c | sort -rn | head -3
15 agy-gemini-3.8-flash
14 agy-claude-sonnet-4-6
14 CC-MiniMaxAI-MiniMax-M3
# entries are byte-identical per slug:
$ jq -c '[.models | group_by(.slug) | map(select(length>1)) | .[0][]] | unique | length'
1
Local validator correctly refused to publish: publish-catalog.sh: source-invalid (requires unique slugs).
Screenshots and supporting files
Sample pair for the same model (same display_name, description, context_window):
{"slug":"CC-MiniMaxAI-MiniMax-M3","display_name":"CC-MiniMaxAI-MiniMax-M3","description":"Routed via opencodex → command-code (command-code)."}
{"slug":"command-code/MiniMaxAI-MiniMax-M3","display_name":"CC-MiniMaxAI-MiniMax-M3","description":"Routed via opencodex → command-code (command-code)."}
Full 11 MB pre-dedup catalog available on request (507 entries).
Redacted configuration
{
"providers": {
"command-code": {
"alias": "CC",
"liveModels": true,
"selectedModels": ["MiniMaxAI/MiniMax-M3", "deepseek/deepseek-v4-flash"],
"modelAliases": {
"MiniMaxAI/MiniMax-M3": "CC-MiniMaxAI-MiniMax-M3",
"deepseek/deepseek-v4-flash": "CC-deepseek-deepseek-v4-flash"
}
}
}
}
Proposed fix
In syncCatalogModels/retained-sync.ts, final dedup by slug after merge — the model.alias (user personalization, e.g. CC-X) wins over the canonical form when content is identical; warn with removed count. Preserves personalization, kills duplicates, single change point. Local test proving safe discard (507→72, 0 unique slugs lost, personalized content byte-identical) available as input for the PR.
Checks
Client or integration
Codex CLI
Area
Catalog / models
Summary
ocx syncon 2.56.0 generatedopencodex-catalog.jsonwith 507 entries but only 72 unique slugs (e.g.CC-MiniMaxAI-MiniMax-M3repeated 14x). I expected one entry per slug. The duplicates are byte-identical, so they are safe to drop — but the sync should never emit them.Root cause (verified against pristine 2.56.0 tarball): my config uses the official
modelAliasesfeature (providers.command-code.modelAliases = {"MiniMaxAI/MiniMax-M3": "CC-MiniMaxAI-MiniMax-M3", ...}, 17 entries). The alias form becomes the public slug viamodel.alias(catalogModelSluginsrc/codex/catalog/parsing.ts:843:model.alias ?? routedSlug(provider, id)). The sync ALSO emits the canonicalcommand-code/...form viaroutedSlug, and the merge (mergeCatalogEntriesFromObservedStateinsrc/codex/catalog/build-entries.ts, keyslugEquivalenceKeyinsrc/providers/slug-codec.ts) never unifies them:slugEquivalenceKey("CC-X")→["exact","CC-X"](no slash = exact key)slugEquivalenceKey("command-code/...")→["routed","command-code",...]Three different keys for the same model = three rows.
Reproduction
command-code+modelAliasesmappingVendor/Model→CC-Vendor-Model(17 entries), plus provideralias: "CC".ocx sync --restart-codex && ocx sync-cache --restart-codex(config validates{"ok": true}).jq '.models|length' ~/.codex/opencodex-catalog.json→ 507;jq '[.models[].slug]|unique|length'→ 72.ocx sync-cachealone kept 72/72; the explosion came fromocx sync. A laterocx syncon the same config stayed 72/72, so it is intermittent (possibly first sync after upgrade, or cache-state dependent).Version
2.56.0 (
@bitkyc08/opencodex, npmlatest2026-09-15)Operating system
Ubuntu 24.04 (VPS, HestiaCP)
Provider and model
command-code provider (gateway), any model with a
modelAliasesentryLogs or error output
Local validator correctly refused to publish:
publish-catalog.sh: source-invalid(requires unique slugs).Screenshots and supporting files
Sample pair for the same model (same display_name, description, context_window):
{"slug":"CC-MiniMaxAI-MiniMax-M3","display_name":"CC-MiniMaxAI-MiniMax-M3","description":"Routed via opencodex → command-code (command-code)."} {"slug":"command-code/MiniMaxAI-MiniMax-M3","display_name":"CC-MiniMaxAI-MiniMax-M3","description":"Routed via opencodex → command-code (command-code)."}Full 11 MB pre-dedup catalog available on request (507 entries).
Redacted configuration
{ "providers": { "command-code": { "alias": "CC", "liveModels": true, "selectedModels": ["MiniMaxAI/MiniMax-M3", "deepseek/deepseek-v4-flash"], "modelAliases": { "MiniMaxAI/MiniMax-M3": "CC-MiniMaxAI-MiniMax-M3", "deepseek/deepseek-v4-flash": "CC-deepseek-deepseek-v4-flash" } } } }Proposed fix
In
syncCatalogModels/retained-sync.ts, final dedup by slug after merge — themodel.alias(user personalization, e.g.CC-X) wins over the canonical form when content is identical; warn with removed count. Preserves personalization, kills duplicates, single change point. Local test proving safe discard (507→72, 0 unique slugs lost, personalized content byte-identical) available as input for the PR.Checks