Skip to content

Commit 6edec46

Browse files
committed
Revert "fix(catalog): prioritize model names in picker labels" (lidge-jun#763)
This reverts merge commit bf7a643, restoring the historical default picker label for routed catalog rows: the full Codex-facing `provider/model` slug. PR lidge-jun#763 replaced that default with the final segment of the native model id (`anthropic/claude-opus-5` -> `claude-opus-5`), plus a collision ladder widening the label back to the native id and then to `id (provider)` when two emitted rows would otherwise collide. The revert restores `deriveEntry` and `applyCatalogModelMetadata` to their pre-lidge-jun#763 signatures and drops `routedFallbackDisplayNames` entirely. Explicitly configured `displayName` values, combo public aliases, and native OpenAI marketing names were unaffected by lidge-jun#763 and remain unaffected here. The on-disk row preservation from lidge-jun#836 (`catalogModelsForMerge`) sits later in `syncCatalogModels` and is untouched. (cherry picked from commit d4c9eeec2da64027cdc60558af0d0e1fd3a221a7) (cherry picked from commit 7e02a86)
1 parent 3f1730b commit 6edec46

10 files changed

Lines changed: 26 additions & 170 deletions

File tree

docs-site/src/content/docs/guides/codex-integration.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,7 @@ start and on `ocx sync`, opencodex:
184184
4. **Filters** `config.disabledModels` and each provider's non-empty `selectedModels` allowlist.
185185
5. **Re-ranks** so featured models sort first (see below), then writes the merged catalog back.
186186

187-
The cloned catalog `base_instructions` identity line is rewritten to the real upstream model name
188-
as static catalog metadata. Runtime request identity is handled separately: routed adapters replace
189-
Codex's live GPT-5 identity line with a model-agnostic coding-agent introduction.
190-
When unique, their default picker label is the final segment of the native model id, so provider
191-
namespaces do not hide the model name in narrow pickers. Basename collisions retain enough native
192-
route context to distinguish the rows; if the same native id comes from multiple providers, the
193-
provider is shown too. The full catalog slug remains in the description. Configure a custom display
194-
name when the route itself matters visually (for example, `Claude Opus 5 (TeamClaude)`); custom
195-
names continue to take precedence.
187+
Routed catalog entries also get their GPT-5 identity rewritten to the real upstream model name.
196188
Reasoning controls come from provider/model metadata across Codex's `low | medium | high | xhigh |
197189
max | ultra` ladder; unsupported values are mapped or clamped before the upstream request.
198190

docs-site/src/content/docs/ja/guides/codex-integration.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,7 @@ Codex はディスクのカタログ(デフォルト `$CODEX_HOME/opencodex-cata
147147
4. `config.disabledModels` と各プロバイダーの空でない `selectedModels` 許可リストを**適用**します。
148148
5. フィーチャー済みモデルが先に並ぶよう**再整列**した後(下記参照)、マージされたカタログを書き戻します。
149149

150-
複製されたカタログの `base_instructions` にあるアイデンティティ行は、静的なカタログメタデータとして実際の
151-
上流モデル名に合わせて書き換えられます。実行時リクエストのアイデンティティは別に処理され、ルーティング
152-
アダプターが Codex のライブ GPT-5 アイデンティティ行をモデル非依存のコーディングエージェント文言に置き換えます。
153-
一意であれば、デフォルトのピッカーラベルにはネイティブモデル ID の最後のセグメントが使われるため、幅の狭い
154-
ピッカーでもプロバイダーの名前空間がモデル名を隠しません。同じ basename が衝突する場合は行を区別できるだけの
155-
ネイティブ経路を残し、同じネイティブ ID が複数のプロバイダーにある場合はプロバイダー名も表示します。完全な
156-
カタログスラッグは説明に残ります。
157-
経路自体を見分ける必要がある場合(例: `Claude Opus 5 (TeamClaude)`)はカスタム表示名を設定してください。
158-
カスタム表示名は引き続きデフォルトラベルより優先されます。推論選択肢は
150+
ルーティングされたカタログ項目の GPT-5 アイデンティティ文言も実際の上流モデル名に合わせます。推論選択肢は
159151
プロバイダーとモデルメタデータに応じて Codex の `low | medium | high | xhigh | max | ultra` 段階を使い、
160152
上流がサポートしない値はリクエスト送信前にマッピングまたはサポート範囲に下げます。
161153

docs-site/src/content/docs/ko/guides/codex-integration.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,7 @@ Codex는 디스크의 카탈로그(기본값 `$CODEX_HOME/opencodex-catalog.json
145145
4. `config.disabledModels`와 각 프로바이더의 비어 있지 않은 `selectedModels` 허용 목록을 **적용**합니다.
146146
5. featured 모델이 먼저 정렬되도록 **재정렬**한 뒤(아래 참고), 병합된 카탈로그를 다시 작성합니다.
147147

148-
복제된 카탈로그의 `base_instructions` 정체성 문구는 정적 카탈로그 메타데이터에서만 실제 업스트림 모델 이름으로
149-
바뀝니다. 런타임 요청의 정체성은 별도로 처리되며, 라우팅 어댑터가 Codex의 실시간 GPT-5 정체성 문구를 모델과 무관한
150-
코딩 에이전트 문구로 바꿉니다. 이름이 고유하면 기본 선택기
151-
레이블은 네이티브 모델 ID의 마지막 부분만 사용하므로 폭이 좁은 선택기에서도 프로바이더 네임스페이스가 모델 이름을
152-
가리지 않습니다. 같은 basename이 겹치면 행을 구분하는 데 필요한 네이티브 경로를 남기고, 같은 네이티브 ID가 여러
153-
프로바이더에 있으면 프로바이더 이름도 표시합니다. 전체 카탈로그 slug는 설명에 그대로 남습니다. 경로 자체를 눈에 띄게
154-
구분해야 한다면(예: `Claude Opus 5 (TeamClaude)`) 사용자 지정 표시 이름을 설정하세요. 사용자 지정 이름은
155-
계속 기본 레이블보다 우선합니다. reasoning 선택지는
148+
라우팅된 카탈로그 항목의 GPT-5 정체성 문구도 실제 업스트림 모델 이름에 맞게 바꿉니다. reasoning 선택지는
156149
프로바이더와 모델 메타데이터에 따라 Codex의 `low | medium | high | xhigh | max | ultra` 단계를 사용하며,
157150
업스트림이 지원하지 않는 값은 요청을 보내기 전에 매핑하거나 지원 범위로 낮춥니다.
158151

docs-site/src/content/docs/ru/guides/codex-integration.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,8 @@ Codex показывает модели из каталога на диске (
165165
5. **Переранжирует** так, чтобы избранные модели шли первыми (см. ниже), и записывает
166166
объединённый каталог обратно.
167167

168-
В клонированном `base_instructions` строка идентичности переписывается на настоящее имя вышестоящей
169-
модели только как статические метаданные каталога. Идентичность рабочего запроса обрабатывается
170-
отдельно: маршрутизируемые адаптеры заменяют живую строку Codex о GPT-5 нейтральным описанием
171-
агента программирования. Если имя уникально, по умолчанию в селекторе показывается последний сегмент
172-
нативного идентификатора модели, поэтому пространство имён провайдера не скрывает имя модели в узком
173-
селекторе. При совпадении basename сохраняется достаточная часть нативного маршрута, а если один и тот
174-
же нативный ID доступен у нескольких провайдеров, показывается и провайдер. Полный slug каталога
175-
сохраняется в описании. Если маршрут важно различать визуально
176-
(например, `Claude Opus 5 (TeamClaude)`), задайте пользовательское отображаемое имя; оно по-прежнему
177-
имеет приоритет над меткой по умолчанию. Элементы управления рассуждениями берутся из метаданных провайдера и модели
168+
У маршрутизируемых записей каталога идентичность GPT-5 также переписывается на настоящее имя
169+
вышестоящей модели. Элементы управления рассуждениями берутся из метаданных провайдера и модели
178170
по шкале Codex `low | medium | high | xhigh | max | ultra`; неподдерживаемые значения
179171
сопоставляются или ограничиваются перед запросом к вышестоящему провайдеру.
180172

docs-site/src/content/docs/zh-cn/guides/codex-integration.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,7 @@ Codex 显示的模型来自一个磁盘上的目录(默认为 `$CODEX_HOME/ope
138138
4. **应用过滤**`config.disabledModels`,以及每个提供商非空的 `selectedModels` allowlist。
139139
5. **重新排序**,使置顶模型排在最前(见下文),然后将合并后的目录写回。
140140

141-
克隆目录中的 `base_instructions` 身份行只会作为静态目录元数据改写为真实的上游模型名称。
142-
运行时请求的身份信息单独处理:路由适配器会把 Codex 实时发送的 GPT-5 身份行替换为与模型无关的编码代理说明。
143-
名称唯一时,默认的选择器标签使用原生模型 ID 的最后一段,因此在较窄的选择器中,提供商命名空间不会遮住模型名称。
144-
若 basename 冲突,则保留足以区分各行的原生路由信息;若多个提供商暴露同一个原生 ID,还会显示提供商名称。
145-
完整的目录 slug 仍保留在说明中。如果需要直观看出路由本身(例如
146-
`Claude Opus 5 (TeamClaude)`),请配置自定义显示名称;自定义名称仍然优先于默认标签。reasoning 选项会依据提供商和模型元数据,
141+
路由目录条目还会把 GPT-5 身份文案改为真实的上游模型名称。reasoning 选项会依据提供商和模型元数据,
147142
使用 Codex 的 `low | medium | high | xhigh | max | ultra` 档位;上游不支持的值会在发送请求前完成
148143
映射或下调。
149144

src/codex/catalog/effort.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,29 +109,19 @@ export function catalogEntryEfforts(entry: RawEntry): string[] {
109109

110110
export const ROUTED_REASONING_LEVELS = [...CODEX_REASONING_LEVELS];
111111

112-
export function applyCatalogModelMetadata(
113-
entry: RawEntry,
114-
model?: CatalogModel,
115-
fallbackDisplayName?: string,
116-
): void {
112+
export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel): void {
117113
if (!model) return;
118114
// This marker survives strict catalog normalization and lets sync distinguish a stale
119115
// bare combo alias from a genuine native model row.
120116
if (model.provider === COMBO_NAMESPACE) entry.owned_by = model.owned_by ?? COMBO_NAMESPACE;
121117
// displayName is DISPLAY-ONLY: it relabels the picker row but never touches the routing
122-
// slug, alias, or provider. A configured displayName wins. Otherwise physical routed rows
123-
// use the final segment of their native id, keeping provider/vendor namespaces out of the
124-
// narrow picker label. buildCatalogEntries supplies a longer fallback only when that basename
125-
// would collide with another visible row. Aliased combos keep their public alias. Natives never
126-
// reach here (no CatalogModel), so genuine upstream marketing names are preserved untouched.
118+
// slug, alias, or provider. deriveEntry already stamped the slug as display_name; a
119+
// configured displayName overrides just the label. The `/` separator is rejected at every
120+
// input boundary (CLI `ocx models add`, management API), so the catalog trusts its source.
121+
// Combos carry no displayName, and natives never reach here (no CatalogModel), so genuine
122+
// upstream marketing names and combo alias labels are preserved untouched.
127123
const displayName = typeof model.displayName === "string" ? model.displayName.trim() : "";
128124
if (displayName) entry.display_name = displayName;
129-
else if (!model.alias) {
130-
const nativeId = model.id.trim();
131-
const finalSegment = nativeId.slice(nativeId.lastIndexOf("/") + 1).trim();
132-
const fallback = fallbackDisplayName?.trim() || finalSegment;
133-
if (fallback) entry.display_name = fallback;
134-
}
135125
if (typeof model.contextWindow === "number" && model.contextWindow > 0) {
136126
entry.context_window = model.contextWindow;
137127
entry.max_context_window = model.contextWindow;

src/codex/catalog/parsing.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,7 @@ export interface CatalogModel {
9292
/**
9393
* Display-only Codex catalog `display_name` override. Relabels the picker row ONLY — it never
9494
* affects the routing slug, alias-collision order, native marketing-name precedence, or provider
95-
* behavior. When unset, routed entries use the final segment of the native model id so the
96-
* provider namespace does not crowd the picker; basename collisions retain enough route context
97-
* to stay distinguishable, and aliased combo rows keep their public alias.
95+
* behavior. When unset, the entry falls back to its Codex-facing slug (the historical behavior).
9896
* Native upstream entries (e.g. gpt-5.6-sol → "GPT-5.6-Sol") come from the pinned snapshot path
9997
* which carries no CatalogModel, so a configured displayName can never override a native name.
10098
*/

src/codex/catalog/sync.ts

Lines changed: 6 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ export function deriveEntry(
166166
priority: number,
167167
model?: CatalogModel,
168168
exactComboSlugs: ReadonlySet<string> = new Set(),
169-
fallbackDisplayName?: string,
170169
): RawEntry {
171170
const preserveExact = isExactComboCatalogModel(model, exactComboSlugs);
172171
const isRouted = model !== undefined;
@@ -203,7 +202,7 @@ export function deriveEntry(
203202
applyReasoningLevels(e, model?.reasoningEfforts, model?.defaultReasoningEffort, preserveExact);
204203
normalizeRoutedCatalogEntry(e, model?.parallelToolCalls === true);
205204
if (model) applyJawcodeCatalogMetadata(e, model.provider, model.id, model.contextCap);
206-
applyCatalogModelMetadata(e, model, fallbackDisplayName);
205+
applyCatalogModelMetadata(e, model);
207206
} else {
208207
applyNativeOpenAiContextOverride(e);
209208
if (isGpt56NativeSlug(slug)) ensureGpt56ReasoningLevels(e);
@@ -240,58 +239,14 @@ export function deriveEntry(
240239
if (isGpt56NativeSlug(slug)) ensureGpt56ReasoningLevels(entry);
241240
}
242241
if (model && isRouted) applyJawcodeCatalogMetadata(entry, model.provider, model.id, model.contextCap);
243-
applyCatalogModelMetadata(entry, model, fallbackDisplayName);
242+
applyCatalogModelMetadata(entry, model);
244243
if (!isRouted) applyNativeOpenAiContextOverride(entry);
245244
return ensureStrictCatalogFields(normalizeServiceTiers(entry), {
246245
preserveExactInputModalities: preserveExact,
247246
isRouted,
248247
});
249248
}
250249

251-
function configuredDisplayName(model: CatalogModel): string {
252-
return typeof model.displayName === "string" ? model.displayName.trim() : "";
253-
}
254-
255-
function defaultPickerLabel(model: CatalogModel): string {
256-
const nativeId = model.id.trim();
257-
return nativeId.slice(nativeId.lastIndexOf("/") + 1).trim();
258-
}
259-
260-
/**
261-
* Keep the common picker path compact, but retain only as much route context as needed when two
262-
* emitted rows would otherwise have the same label. Explicit display names and combo aliases are
263-
* author-owned and never rewritten. If distinct native ids share a basename, the native id is
264-
* enough; if the same native id is exposed by multiple providers, append the provider as well.
265-
*/
266-
function routedFallbackDisplayNames(models: readonly CatalogModel[]): Map<CatalogModel, string> {
267-
const intendedLabel = (model: CatalogModel): string =>
268-
configuredDisplayName(model) || model.alias?.trim() || defaultPickerLabel(model);
269-
const labelCounts = new Map<string, number>();
270-
const nativeIdCounts = new Map<string, number>();
271-
for (const model of models) {
272-
const label = intendedLabel(model);
273-
if (!label) continue;
274-
labelCounts.set(label, (labelCounts.get(label) ?? 0) + 1);
275-
const nativeKey = `${label}\u0000${model.id.trim()}`;
276-
nativeIdCounts.set(nativeKey, (nativeIdCounts.get(nativeKey) ?? 0) + 1);
277-
}
278-
279-
const out = new Map<CatalogModel, string>();
280-
for (const model of models) {
281-
if (configuredDisplayName(model) || model.alias) continue;
282-
const label = defaultPickerLabel(model);
283-
if (!label) continue;
284-
if ((labelCounts.get(label) ?? 0) <= 1) {
285-
out.set(model, label);
286-
continue;
287-
}
288-
const nativeId = model.id.trim();
289-
const sameNativeIdCount = nativeIdCounts.get(`${label}\u0000${nativeId}`) ?? 0;
290-
out.set(model, sameNativeIdCount > 1 ? `${nativeId} (${model.provider})` : nativeId);
291-
}
292-
return out;
293-
}
294-
295250
export function buildCatalogEntries(
296251
template: RawEntry | null,
297252
gptSlugs: string[],
@@ -316,28 +271,22 @@ export function buildCatalogEntries(
316271
if (rank.has(slug)) e.priority = rank.get(slug)!;
317272
out.push(e);
318273
}
319-
const routedModels = goModels.filter(m => {
320-
if (collisionSkipped.has(m)) return false;
274+
for (const m of goModels) {
275+
if (collisionSkipped.has(m)) continue;
321276
const slug = catalogModelSlug(m);
322277
if (m.provider !== COMBO_NAMESPACE && comboPublicSlugs.has(slug)) {
323278
warnComboMasqueradeCollisionOnce(slug);
324-
return false;
279+
continue;
325280
}
326-
return true;
327-
});
328-
const fallbackDisplayNames = routedFallbackDisplayNames(routedModels);
329-
for (const m of routedModels) {
330-
const slug = catalogModelSlug(m);
331281
// Provider rows use the one-slash slug codec; combo aliases intentionally override that
332282
// public slug and may be bare.
333283
const e = deriveEntry(
334284
template,
335285
slug,
336-
`Routed via opencodex → ${slug} (${m.owned_by ?? m.provider}).`,
286+
`Routed via opencodex → ${m.provider} (${m.owned_by ?? m.provider}).`,
337287
5,
338288
m,
339289
exactComboSlugs,
340-
fallbackDisplayNames.get(m),
341290
);
342291
// Featured picks may be stored raw (legacy) or encoded — honor both.
343292
const rankHit = rank.get(slug) ?? rank.get(`${m.provider}/${m.id}`);

0 commit comments

Comments
 (0)