fix(codex-bridge): estimate Claude requests more strictly; report an unexplained 400 on a near-full request

A 607 KB Codex request was estimated at 189776 tokens (window 200000), sent untrimmed and rejected by
Claude; the gateway only said "upstream 400", so Codex saw a dropped stream. Claude targets now use
2.6 bytes/token, and that bare 400 on a request filling most of the window becomes context_length_exceeded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yilsemandClaude Opus 5.5 committed 2026-10-11 00:45:58 +03:00
1 parent 959f5f1459
commit d9a7661281
3 files changed
+46 -7

No files matched your search

+12 -2
View File
@@ -444,7 +444,8 @@ class SseRewriter:
Ayrica dis modelin asistan mesajlarina phase damgasi koyar: mesajin "bitti" olayi, arkasindan ne
geldigi belli olana kadar bekletilir (arac cagrisi ya da baska oge -> commentary; yanit bitti ->
final_answer). Metin parcalari (delta) bekletilmez, canli akar."""
def __init__(self, custom, hedef=None, tasma=None, aracsiz=None):
def __init__(self, custom, hedef=None, tasma=None, aracsiz=None, dolu=False):
self.dolu = dolu # istek hedef pencerenin buyuk kismini dolduruyor
self.custom = custom
self.buf = b""
self.custom_ids = set()
@@ -477,6 +478,13 @@ class SseRewriter:
"id": "resp_astrabridge_hata", "object": "response", "status": "failed", "output": [],
"error": {"code": "invalid_request_error", "message":
"Bu model araç çağrısını desteklemiyor; Codex'te çalışamaz. Başka bir model seçin."}}}]
if self.dolu and pencere.kapali_hata_mi(metin):
# Pencereye yakin istekte gecidin nedensiz 400'u: buyuk olasilikla sigmadi. Codex'e sessiz kopma
# yerine anlasilir hata gider (ogrenme yapilmaz; neden kesin degil).
return [{"type": "response.failed", "response": {
"id": "resp_astrabridge_hata", "object": "response", "status": "failed", "output": [],
"error": {"code": "context_length_exceeded", "message":
"Sohbet seçili modelin bağlam penceresine sığmadı. Sohbeti sıkıştırın ya da daha büyük pencereli bir model seçin."}}}]
if pencere.tasma_mi(metin):
if self.tasma is not None:
self.tasma(self.hedef, metin)
@@ -1244,7 +1252,9 @@ class H(http.server.BaseHTTPRequestHandler):
# Penceresi bilinmeyen (varsayilan degerli) modelde bekci calismaz: tahmine dayanarak gecmis kirpilmaz.
pencere_biliniyor = "varsayilan" not in ((IDE_BILGI.get(slug) or {}).get("kaynak") or "varsayilan")
if hedef_pencere and pencere_biliniyor and CFG.get("tasma_bekcisi", True) and not ozet_tetik:
kirpilan, sigdi, tahmin = pencere.sigdir(req, hedef_pencere)
kirpilan, sigdi, tahmin = pencere.sigdir(req, hedef_pencere, pencere.oran_sec(target))
if rewriter is not None:
rewriter.dolu = tahmin >= hedef_pencere * 0.7
if kirpilan:
log(f"{tag} tasma bekcisi: {kirpilan} buyuk eski parca kisaltildi (tahmini {tahmin} token, pencere {hedef_pencere})")
if not sigdi: