fix(codex-bridge): close the gaps an independent review found
Server CI and Windows package / verify (push) Successful in 3m23s
Server CI and Windows package / windows-package (push) Successful in 7m9s

- One decision per real turn: a turn starts with a user message after the
  previous final answer; tool steps, messages typed mid-turn, a lone "."
  and compaction keep the combo. Works without prompt_cache_key too.
- The virtual Otomatik name never reaches the gateway (stage off or error
  -> last choice or targets.zor); prefilter.target may not be it.
- finishCheck: at most once per turn; a broken, empty or refused retry
  delivers the already approved first answer.
- Layer window filter: only trusted windows, never the last layer.
- Correction channel only on always-pass targets while checks are on;
  Sesli-Hizli-Zeki stays always-pass by default; a >256 KB SSE frame
  passes unfiltered instead of breaking the stream.
- Turn-start questions wait in the local queue no longer than their
  timeout; decision-turn memory under a lock with refreshed order.
- Dify fetch refuses redirects (the app key never moves host); the
  rules file write retries a Windows sharing violation.
- An unreadable settings file no longer breaks every request.
- TypeScript accepts only https:// URLs the bridge accepts;
  finishCheck.timeoutSeconds (unused) removed.

Tests: 310 bridge tests, 36 electron tests; side-bridge live run for the
turn, prefilter (incl. decision timeout) and finish-check paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yilsemandClaude Opus 5.5 committed 2026-10-14 08:14:38 +03:00
1 parent 7c4ef18df0
commit a7ba300448
10 files changed
+353 -91

No files matched your search

+20 -12
View File
@@ -38,11 +38,14 @@ SORU = {
_ANAHTAR = {"okundu": False, "deger": ""}
def izleme_mi(hedef):
"""Bekci izleme kanali (cevaptan sonra duzeltme) bu hedefin mi? Ayar: watchModels, tam ad eslesmesi."""
"""Bekci izleme kanali (cevaptan sonra duzeltme) bu hedefin mi? Ayar: watchModels, tam ad eslesmesi.
Jev acikken yalniz muaf hedefte: denetlenen cevap baska katmana gecebilir, makbuz kullanicinin gormedigi
cevaba baglanmasin."""
try:
return hedef in jev_settings.read()[0]['watchModels']
s = jev_settings.read()[0]
return hedef in s['watchModels'] and (not s['enabled'] or hedef in s['exemptModels'])
except Exception:
return hedef == "Sesli-Hizli-Zeki"
return False
def muaf_mi(hedef):
@@ -125,18 +128,23 @@ def son_istek(req):
return son_istek_sirasi(req)[0]
def istek_metni(oge):
"""Bir kullanici mesajindaki istek: sesli aktarimda <input> icindeki soz; sarmalli sistem mesaji ise ""."""
if not (isinstance(oge, dict) and oge.get("type", "message") == "message" and oge.get("role") == "user"):
return ""
metin = _metin(oge).strip()
m = re.search(r"<realtime_delegation>.*?<input>(.*?)</input>", metin, re.S)
if m:
return m.group(1).strip()
return metin if metin and not metin.startswith("<") else ""
def son_istek_sirasi(req):
"""(istek, girdideki sirasi). Turun arac adimlarinda da ayni sira doner; yoksa ("", -1)."""
girdi = req.get("input") or []
for sira in range(len(girdi) - 1, -1, -1):
oge = girdi[sira]
if not (isinstance(oge, dict) and oge.get("type", "message") == "message" and oge.get("role") == "user"):
continue
metin = _metin(oge).strip()
m = re.search(r"<realtime_delegation>.*?<input>(.*?)</input>", metin, re.S)
if m:
return m.group(1).strip(), sira
if metin and not metin.startswith("<"):
metin = istek_metni(girdi[sira])
if metin:
return metin, sira
return "", -1
@@ -202,7 +210,7 @@ def sorular(durum, soru, key, timeout, gonder=_gonder, settings=None):
return None
govde = {"model": settings['model'], "state": durum,
"questions": {k: {"type": "noul", "instructions": v} for k, v in soru.items()}}
if not jev_settings.acquire(settings):
if not jev_settings.acquire(settings, wait=timeout):
return None
try:
response = gonder(govde, key, settings, timeout) if gonder is _gonder else gonder(govde, key)