fix(codex-bridge): audit findings: visible permanent errors, stricter model command, unbuffered stream
From ten independent read-only audits (11 Oct 2026), verified against the code: - a permanent gateway error (no tools, 401/402/403, bare upstream 400) ends the turn with a visible assistant message instead of a silent retry and an empty turn; - "modeli ... yapma", "X modeli için test yap" and general "hangi model ..." questions are no longer commands; a name whose version does not fit, or that several models share, is asked back; - the stream is forwarded as it arrives (read1) and an upstream drop is no longer logged as a client stop nor saved as an interrupted answer; - a lone "." joining a running turn is removed without the hook messages after it; - the interrupted-answer note finds the user message behind hook messages and detects completion by event type; a per-minute rate limit is not learned as a context window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1e2b8e2b9c
commit
e2793fa38f
7 files changed
+129
-32
No files matched your search
@@ -17,7 +17,7 @@ for node in tree.body:
|
||||
if isinstance(node, ast.Assign) and any(isinstance(t, ast.Name) and t.id in
|
||||
{"ID_PREFIX", "FOREIGN_ID_MARK", "REFERENCE_TYPES", "INLINE_TYPES", "ARAC_OGELERI"} for t in node.targets):
|
||||
nodes.insert(0, node)
|
||||
env = {"json": json, "re": __import__("re"), "log": lambda message: None, "pencere": pencere}
|
||||
env = {"json": json, "re": __import__("re"), "time": __import__("time"), "log": lambda message: None, "pencere": pencere}
|
||||
exec(compile(ast.Module(body=nodes, type_ignores=[]), "bridge.py", "exec"), env)
|
||||
|
||||
NANO = pencere.nano_sadelestir({"data": [
|
||||
@@ -196,9 +196,13 @@ class GatewayErrors(unittest.TestCase):
|
||||
adapter = env["SseRewriter"](set())
|
||||
raw = sse({"type": "error", "error": {"type": "upstream_error", "message": "upstream 402"}})
|
||||
out = parse(adapter.feed(raw) + adapter.flush())
|
||||
self.assertEqual(out[0]["type"], "response.failed")
|
||||
self.assertEqual(out[0]["response"]["error"]["code"], "insufficient_quota")
|
||||
self.assertIn("upstream 402", out[0]["response"]["error"]["message"])
|
||||
self.assertEqual(out[-1]["type"], "response.completed") # visible answer, turn ends normally
|
||||
self.assertIn("kredi ya da kota", out[1]["delta"])
|
||||
self.assertIn("upstream 402", out[1]["delta"])
|
||||
raw = sse({"type": "error", "error": {"type": "upstream_error", "message": "upstream 400"}})
|
||||
out = parse(env["SseRewriter"](set()).feed(raw))
|
||||
self.assertIn("nedenini bildirmedi", out[1]["delta"])
|
||||
self.assertEqual(out[-1]["type"], "response.completed")
|
||||
# A transient error is left alone so that Codex retries it.
|
||||
raw = sse({"type": "error", "error": {"type": "upstream_error", "message": "upstream 503"}})
|
||||
self.assertEqual(parse(env["SseRewriter"](set()).feed(raw))[0]["type"], "error")
|
||||
@@ -238,6 +242,11 @@ class ClaudeOrani(unittest.TestCase):
|
||||
self.assertEqual((trimmed, fits), (1, True))
|
||||
self.assertLess(estimate, 194_000)
|
||||
self.assertTrue(p.kapali_hata_mi("upstream 400"))
|
||||
# A per-minute rate limit is neither an overflow nor a window size to learn.
|
||||
rate = "Rate limit reached: limit of 32768 tokens per minute, context window ok"
|
||||
self.assertFalse(p.tasma_mi(rate))
|
||||
self.assertIsNone(p.sinir_oku(rate))
|
||||
self.assertTrue(p.tasma_mi("maximum context length is 65536 tokens"))
|
||||
self.assertFalse(p.kapali_hata_mi("upstream 400: invalid tool schema"))
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user