feat(codex-bridge): decision-model stages, Dify rules and beta.39
Owner request, 14 October 2026: use the decision model (Jev / Celeris) at several stages, let Dify supply the rules, code it without new bugs. Every new stage is switched on in Settings > Kademeli Gecis and starts disabled, so the upgrade changes no behaviour by itself. - Settings schema 2 (Python and TypeScript validate the same rules); a schema 1 file is filled from the defaults. Default chain is now Katman-1 -> Katman-2 -> Katman-3 with Katman-3, Chat-Model and bekci-sesli-bekci always passing (owner decision of the same day). - watchModels: the Bekci correction channel follows a settings list instead of the hard-coded Sesli-Hizli-Zeki. - prefilter: a predicted refusal starts the step at the chosen layer. - autoRoute: virtual "Otomatik" model; one decision per user turn picks the combo, tool steps of the same turn keep it. - finishCheck: an answer that stops early goes back to the same model once. - A layer whose window cannot hold the request is skipped. - policy: stage rules from a Dify workflow (karar_politikasi.py), fetched in the background, validated, last good copy kept; turns never wait. - karar_sor.py: verifierCheck for the dynamic-workflow acceptance step. - Bridge version 19, IDE 1.0.0-beta.39. Tests: 299 bridge tests, 36 electron tests; live run on a side bridge (port 8797) with Celeris and the AITURK gateway for every stage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8f53b090f7
commit
7c4ef18df0
18 files changed
+1672
-119
No files matched your search
@@ -1,5 +1,7 @@
|
||||
"""Layer check (11 Oct 2026): Jev passes or blocks each step of Katman-1..3; a blocked step is redone by the next
|
||||
layer. Katman-4 is never asked. No exceptions."""
|
||||
layer. The last layer is never asked. No exceptions.
|
||||
|
||||
14 Oct 2026 defaults: Katman-1 -> Katman-2 -> Katman-3; Katman-3, Chat-Model and bekci-sesli-bekci always pass."""
|
||||
import ast
|
||||
import io
|
||||
import json
|
||||
@@ -60,18 +62,19 @@ class Karar(unittest.TestCase):
|
||||
|
||||
class Katman(unittest.TestCase):
|
||||
def test_a_non_layer_model_falls_through_every_layer_from_the_top(self):
|
||||
self.assertEqual(jev_denetim.sonrakiler("Uncensored-Uygulama"),
|
||||
["Katman-1", "Katman-2", "Katman-3", "Katman-4"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("ide/some-model"),
|
||||
["Katman-1", "Katman-2", "Katman-3", "Katman-4"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("Uncensored-Uygulama"), ["Katman-1", "Katman-2", "Katman-3"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("ide/some-model"), ["Katman-1", "Katman-2", "Katman-3"])
|
||||
|
||||
def test_a_selected_layer_only_tries_the_ones_after_it(self):
|
||||
self.assertEqual(jev_denetim.sonrakiler("Katman-1"), ["Katman-2", "Katman-3", "Katman-4"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("Katman-2"), ["Katman-3", "Katman-4"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("Katman-3"), ["Katman-4"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("Katman-1"), ["Katman-2", "Katman-3"])
|
||||
self.assertEqual(jev_denetim.sonrakiler("Katman-2"), ["Katman-3"])
|
||||
# The always-pass last layer only uses the general fallback on transport failure; no revisits.
|
||||
self.assertEqual(jev_denetim.sonrakiler("Katman-3"), ["Katman-1", "Katman-2"])
|
||||
|
||||
def test_last_layer_is_never_asked(self):
|
||||
self.assertTrue(jev_denetim.muaf_mi("Katman-4"))
|
||||
self.assertTrue(jev_denetim.muaf_mi("Katman-3"))
|
||||
self.assertTrue(jev_denetim.muaf_mi("Chat-Model"))
|
||||
self.assertFalse(jev_denetim.muaf_mi("Katman-4"))
|
||||
self.assertEqual(jev_denetim.sonrakiler(None), [])
|
||||
|
||||
|
||||
@@ -139,7 +142,7 @@ class Akis(unittest.TestCase):
|
||||
self.h.send_response = Mock()
|
||||
self.h.send_header = Mock()
|
||||
self.h.end_headers = Mock()
|
||||
self.cevap = {"Katman-1": sse("bir"), "Katman-2": sse("iki"), "Katman-3": sse("uc"), "Katman-4": sse("dort")}
|
||||
self.cevap = {"Katman-1": sse("bir"), "Katman-2": sse("iki"), "Katman-3": sse("uc")}
|
||||
|
||||
def sor(self, istek, metin, key):
|
||||
self.asked.append(metin)
|
||||
@@ -162,7 +165,7 @@ class Akis(unittest.TestCase):
|
||||
raw = rest[n + 2:]
|
||||
return out
|
||||
|
||||
def calistir(self, body, sira=("Katman-2", "Katman-3", "Katman-4")):
|
||||
def calistir(self, body, sira=("Katman-2", "Katman-3")):
|
||||
self.h._denetimli_akis(Yanit(body), "[1]", None, None, "yap", list(sira), self.ac)
|
||||
|
||||
def test_a_passed_step_is_delivered_unchanged(self):
|
||||
@@ -176,7 +179,7 @@ class Akis(unittest.TestCase):
|
||||
body = sse("Bunu yapamam.")
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}]
|
||||
self.h._denetimli_akis(Yanit(body), "[1]", None, None, "yap",
|
||||
list(jev_denetim.KATMAN), self.ac, hedef="Sesli-Hizli-Zeki")
|
||||
list(jev_denetim.KATMAN), self.ac, hedef="Chat-Model")
|
||||
self.assertEqual(self.sent(), body)
|
||||
self.assertEqual(self.asked, [])
|
||||
self.assertEqual(self.opened, [])
|
||||
@@ -184,14 +187,13 @@ class Akis(unittest.TestCase):
|
||||
def test_voice_transport_failure_still_checks_the_fallback_model(self):
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}]
|
||||
self.h._denetimli_akis(None, "[1]", None, None, "yap",
|
||||
list(jev_denetim.KATMAN), self.ac, hedef="Sesli-Hizli-Zeki")
|
||||
list(jev_denetim.KATMAN), self.ac, hedef="Chat-Model")
|
||||
self.assertEqual(self.opened, ["Katman-1", "Katman-2"])
|
||||
self.assertEqual(self.asked, ["bir", "iki"])
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-2"])
|
||||
|
||||
def test_voice_lookalikes_are_still_checked(self):
|
||||
for target in ("sesli-hizli-zeki", "Sesli-Hizli-Zeki-v2", "ide/Sesli-Hizli-Zeki",
|
||||
"Sesli-Hizli-Zeki ", "Other-Combo"):
|
||||
for target in ("chat-model", "Chat-Model-v2", "ide/Chat-Model", "Chat-Model ", "Other-Combo"):
|
||||
with self.subTest(target=target):
|
||||
self.setUp()
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}]
|
||||
@@ -202,7 +204,7 @@ class Akis(unittest.TestCase):
|
||||
|
||||
def test_a_blocked_non_layer_model_goes_to_layer_1_first(self):
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}] # the selected (non-layer) model is blocked
|
||||
self.calistir(sse("Bunu yapamam."), sira=("Katman-1", "Katman-2", "Katman-3", "Katman-4"))
|
||||
self.calistir(sse("Bunu yapamam."), sira=("Katman-1", "Katman-2", "Katman-3"))
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-1"])
|
||||
self.assertEqual(self.opened, ["Katman-1"])
|
||||
self.assertEqual(self.asked, ["Bunu yapamam.", "bir"])
|
||||
@@ -216,17 +218,17 @@ class Akis(unittest.TestCase):
|
||||
self.assertEqual(self.asked, ["Bunu yapamam.", "iki"])
|
||||
self.h.send_response.assert_called_once()
|
||||
|
||||
def test_every_layer_blocked_ends_at_layer_4_unasked(self):
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}] * 3
|
||||
def test_every_layer_blocked_ends_at_layer_3_unasked(self):
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}] * 2
|
||||
self.calistir(sse("hayir"))
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-4"])
|
||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3", "Katman-4"])
|
||||
self.assertEqual(self.asked, ["hayir", "iki", "uc"]) # layer 4 is never asked
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-3"])
|
||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3"])
|
||||
self.assertEqual(self.asked, ["hayir", "iki"]) # the always-pass last layer is never asked
|
||||
|
||||
def test_blocked_layer_3_goes_straight_to_layer_4(self):
|
||||
def test_blocked_layer_2_goes_straight_to_layer_3(self):
|
||||
self.puanlar = [{"ret": 0.0, "sart": 0.8}]
|
||||
self.calistir(sse("kendi sartimla"), sira=("Katman-4",))
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-4"])
|
||||
self.calistir(sse("kendi sartimla"), sira=("Katman-3",))
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-3"])
|
||||
self.assertEqual(self.asked, ["kendi sartimla"])
|
||||
|
||||
def test_a_layer_that_cannot_be_opened_is_skipped(self):
|
||||
@@ -329,9 +331,9 @@ class Akis(unittest.TestCase):
|
||||
|
||||
def test_when_no_layer_opens_the_blocked_answer_is_not_delivered(self):
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}]
|
||||
self.cevap.update({"Katman-2": None, "Katman-3": None, "Katman-4": None})
|
||||
self.cevap.update({"Katman-2": None, "Katman-3": None})
|
||||
self.calistir(sse("Bunu yapamam."))
|
||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3", "Katman-4"])
|
||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3"])
|
||||
self.assertNotIn(b"yapamam", self.h.wfile.getvalue())
|
||||
self.assertIn(b'response.failed', self.sent())
|
||||
|
||||
|
||||
Reference in new issue
Block a user