feat(codex-link): choose which models fill the Codex model menu and beta.41
Server CI and Windows package / verify (push) Successful in 2m54s
Server CI and Windows package / windows-package (push) Successful in 4m50s

The Codex desktop app's model picker asks the app server for one page of
at most 100 models and never asks for the next page (a fixed limit in the
app). AITURK sent 262, so everything after the first 100 in alphabetical
provider order was out of reach from the menu (Gemini, most NanoGPT
uncensored models, Grok, ModelArk...).

- Bridge: bridge.json codex_liste {medya_gizle, efor_gizle, one_al, gizli},
  re-read when the file changes. Image/audio/video models and "-low/-high"
  copies whose base model is listed are left out by default; pinned models
  follow Codex's own models in the given order; hidden ones are removed.
  The candidate list with each model's place is written to
  log/son-liste/codex-adaylar.json for the settings screen.
- Settings > Codex Bağlama: "Models shown in Codex" with a live count of the
  100 slots, search, filter, pin/move up/hide per model and the two switches.
- The IDE keeps codex_liste when it rewrites bridge.json.
- Bridge version 21, IDE 1.0.0-beta.41.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yilsemandClaude Opus 5.5 committed 2026-10-15 05:16:40 +03:00
1 parent 81ee2ca646
commit 5c76c24c9c
17 files changed
+696 -8

No files matched your search

@@ -192,7 +192,41 @@ def sec(data, tanimli=(), kapsam="ide", turler=None):
return [{"id": s["id"], "ad": s["ad"], "kind": s["kind"], "yol": s["yol"]} for s in secilen[:EN_COK_MODEL]]
def sirala_codex(modeller, ekler, ozgun_kimlikler=()):
# ---- Codex secicisinde gorunen liste (15 Ekim 2026) ----
# Codex masaustu uygulamasinin model secicisi listeyi tek sayfada, en cok 100 modelle ister (uygulamanin kendi kodunda
# sabit; sonraki sayfayi istemez). Kullanici o 100'e hangi modellerin girecegini secer (bridge.json "codex_liste"):
# "one_al" ozgun modellerin hemen arkasina verdigi sirayla alinir, "gizli" cikarilir; resim/ses/video modelleri ve
# ana modeli listede olan dusuk-orta-yuksek kopyalari istege bagli gizlenir (varsayilan: gizli).
CODEX_SECICI_SINIRI = 100
_MEDYA = re.compile(r"(?:^|[-_/. ])(?:tts|image|imagen|veo|video|lyria|embedding|transcribe|whisper|flux|kokoro|orpheus|"
r"chatterbox|seedance|seedream|nano-banana|aqa|robotics|computer-use|realtime|music|audio|speech)"
r"(?=$|[-_/. ])", re.I)
_EFOR = re.compile(r"-(?:none|minimal|low|medium|high|xhigh|max)$", re.I)
def liste_ayari(ham):
"""bridge.json "codex_liste" -> {medya_gizle, efor_gizle, one_al, gizli}; eksik ya da bozuk alan varsayilandir."""
a = ham if isinstance(ham, dict) else {}
def liste(anahtar):
deger = a.get(anahtar)
return [str(s) for s in deger if isinstance(s, str) and s.strip()][:2000] if isinstance(deger, list) else []
return {"medya_gizle": a.get("medya_gizle") is not False, "efor_gizle": a.get("efor_gizle") is not False,
"one_al": list(dict.fromkeys(liste("one_al"))), "gizli": liste("gizli")}
def medya_mi(slug, ad=""):
"""Codex sohbetinde calismayan resim, ses, video, gomme modeli mi (kimlikten ya da adindan)."""
return bool(_MEDYA.search(slug or "") or _MEDYA.search(ad or ""))
def efor_kopyasi_mi(slug, kimlikler):
""""...-high" gibi bir kopya ve ana modeli de listede mi; Codex'in kendi dusunme seviyesi secimi ana modelde var."""
taban = _EFOR.sub("", slug or "")
return taban != slug and taban in kimlikler
def sirala_codex(modeller, ekler, ozgun_kimlikler=(), ayar=None):
"""Ozgun abonelik modelleri oldugu gibi kalir: sirasi, priority degeri ve adi degismez,
listenin basinda durur. Ek modeller onlarin ARKASINA eklenir: combo A-Z, sonra
saglayici A-Z / model A-Z. Ozgun bir modelle ayni adi tasiyan ek model " (AITURK)"
@@ -227,6 +261,26 @@ def sirala_codex(modeller, ekler, ozgun_kimlikler=()):
return (1, saglayici.casefold(), model.casefold(), slug)
ek_modeller.sort(key=anahtar)
adaylar = None
if ayar is not None:
# Kullanicinin secimi: once kimin gizlenecegi, sonra one alinanlar (verdigi sirayla); gerisi yukaridaki sirada.
ayar = liste_ayari(ayar)
kimlikler = {m.get("slug", "") for m in ek_modeller}
one_sira = {s: i for i, s in enumerate(s for s in ayar["one_al"] if s in kimlikler)}
gizli = set(ayar["gizli"])
adaylar, kalan = [], []
for m in ek_modeller:
slug = m.get("slug", "")
medya, efor = medya_mi(slug, m.get("display_name")), efor_kopyasi_mi(slug, kimlikler)
one = slug in one_sira
neden = ("gizli" if slug in gizli else "medya" if medya and ayar["medya_gizle"] and not one
else "efor" if efor and ayar["efor_gizle"] and not one else "")
adaylar.append({"slug": slug, "ad": m.get("display_name") or slug, "kind": bilgiler.get(slug, {}).get("kind") or "model",
"medya": medya, "efor": efor, "neden": neden})
if not neden:
kalan.append(m)
kalan.sort(key=lambda m: (0, one_sira[m.get("slug", "")]) if m.get("slug", "") in one_sira else (1, 0))
ek_modeller = kalan
taban = max([m.get("priority") or 0 for m in ozgunler], default=-1) + 1
for n, model in enumerate(ek_modeller):
model["priority"] = taban + n
@@ -234,6 +288,14 @@ def sirala_codex(modeller, ekler, ozgun_kimlikler=()):
if yalin(ad) in ozgun_adlar:
model["display_name"] = f"{ad}{AITURK_EKI}"
modeller[:] = (ozgunler + ek_modeller)[:EN_COK_MODEL]
if adaylar is None:
return None
# Secicide gorunecek yer: ozgun modeller once sayilir; Codex ilk 100 girdiyi gosterir.
yer = {m.get("slug", ""): i for i, m in enumerate(modeller)}
for a in adaylar:
a["sira"] = yer.get(a["slug"]) if not a["neden"] else None
a["menude"] = a["sira"] is not None and a["sira"] < CODEX_SECICI_SINIRI
return {"sinir": CODEX_SECICI_SINIRI, "ozgun_sayisi": len(ozgunler), "adaylar": adaylar}
# ---- Secicide model adinin altindaki satir ----