feat(codex-bridge): web search for added models, forgiving spoken model names

Added models had no web search: Codex's built-in one runs on OpenAI's side and
the bridge drops it from their tool list. Measured in a voice session on
11 Oct 2026: a model looked for a search tool ten times and ended the turn
with no answer. The bridge now tells added models two ready commands (ara.py:
search and read a page, standard library only, no key). Codex's own models
never see the note: their requests do not reach the bridge.

Spoken model names: a half-spoken word matches the start of a name part
("think" -> thinking, "obli" -> obliterated), and when one candidate is the
others minus extra words, the one without the unsaid suffix is picked
("Qwen 3.8 Obliterated" -> not the ":thinking" one).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yilsemandClaude Opus 5.5 committed 2026-10-11 07:25:30 +03:00
1 parent 23e8aa8191
commit c8993d58cc
6 files changed
+265 -2

No files matched your search

@@ -15,6 +15,7 @@ Ad bulunamazsa mesaj komut sayilmaz, modele oldugu gibi gider. Birden cok aday v
"""
import json
import os
import collections
import re
import threading
import time
@@ -177,7 +178,11 @@ def _uyar(sorgu, parca):
"""Turkce ek almis soz ("geminiye", "opusa") model parcasiyla baslar."""
if sorgu == parca:
return True
return len(parca) >= 3 and sorgu.startswith(parca) and len(sorgu) - len(parca) <= 4 and not sorgu.isdigit()
if len(parca) >= 3 and sorgu.startswith(parca) and len(sorgu) - len(parca) <= 4 and not sorgu.isdigit():
return True
# Yarim soylenen ya da yarim yaziya dokulen soz adin basidir: "think" -> thinking, "obli" -> obliterated
# (olcum 11 Ekim 2026: "qwen 3.8 27b obli think" uc kez bulunamadi).
return len(sorgu) >= 4 and sorgu.isalpha() and parca.startswith(sorgu)
def eslestir(ad, modeller):
@@ -222,6 +227,14 @@ def eslestir(ad, modeller):
if len(tam) == 1 or oncelik(tam[0]) != oncelik(tam[1]):
return {"slug": tam[0][2], "ad": tam[0][3]}
return {"adaylar": [p[3] for p in tam[:4]]}
# Adaylardan biri digerlerinin "fazladan sozcuklu" hali degilse sorulur. Biri digerlerinin govdesiyse
# ("...-obliterated" ile "...-obliterated:thinking") soylenmeyen eki tasimayan secilir: kullanici "thinking"
# demediyse dusunmeyeni istiyordur (olcum 11 Ekim 2026). Fark surum rakamiysa tahmin edilmez, sorulur.
sayim = [(collections.Counter(parcala(p[3]) or parcala(p[2])), p) for p in iyi]
sayim.sort(key=lambda c: sum(c[0].values()))
govde, secilen = sayim[0]
if all(not (govde - c) and (c - govde) and not any(k.isdigit() for k in (c - govde)) for c, _ in sayim[1:]):
return {"slug": secilen[2], "ad": secilen[3]}
return {"adaylar": [p[3] for p in iyi[:4]]}