fix(codex-bridge): leave Codex's own models alone
User decision, 11 Oct 2026: Codex's own (subscription) models are one side, the models we add are the other. A request for one of Codex's own models now goes to chatgpt.com as it is: no model command, lone-dot answer, info note, work-line instruction, half-answer note or compaction handling. Codex compacts those chats itself; the bridge making the summary on gpt-6-astra failed four times this morning and left Codex with 'Error running remote compact task'. Only the bridge's own traces are still cleaned (foreign ids and bridge-made summaries left by an added model earlier in the same chat); without any, the body is byte-identical. Voice switching stays among the added models. Asking for one of Codex's own models by voice is answered with how to do it: pick it in the model picker and send a lone dot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dd5f99c406
commit
12eeec7b0f
5 files changed
+139
-77
No files matched your search
@@ -253,7 +253,9 @@ class Zincir(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.env = build(top("nokta_mesaji_mi", "NOKTA_ISARETLERI", "is_timeout", "kopma_mi", "flatten_request",
|
||||
"claude_sonu_duzelt") + [method("_responses"), method("_model_komutu")], {
|
||||
"claude_sonu_duzelt", "ek_model_mu", "yonlendirilen")
|
||||
+ [method("_responses"), method("_model_komutu"), method("_ozgun")], {
|
||||
"gecit_modelleri": lambda: [],
|
||||
"json": json, "re": __import__("re"), "os": __import__("os"), "copy": copy, "http": __import__("http.client"),
|
||||
"time": types.SimpleNamespace(sleep=lambda s: None, time=time.time),
|
||||
"urllib": types.SimpleNamespace(request=types.SimpleNamespace(Request=urllib.request.Request, urlopen=Mock()),
|
||||
@@ -269,6 +271,7 @@ class Zincir(unittest.TestCase):
|
||||
})
|
||||
Sahte._responses = self.env["_responses"]
|
||||
Sahte._model_komutu = self.env["_model_komutu"]
|
||||
Sahte._ozgun = self.env["_ozgun"]
|
||||
|
||||
def send(self, model, items, key="sohbet-1", path="/responses"):
|
||||
fake = Sahte()
|
||||
@@ -276,40 +279,67 @@ class Zincir(unittest.TestCase):
|
||||
fake._responses(1, path, body)
|
||||
return fake, body
|
||||
|
||||
def test_mid_turn_note_reaches_the_subscription_model_behind_hook_messages(self):
|
||||
items = [user("işe başla"), CALL, OUT, user("modeli sol yap"), developer("k1"), developer("k2"), developer("k3")]
|
||||
fake, body = self.send("gpt-6-astra", items)
|
||||
fake._yerel_yanit.assert_not_called()
|
||||
def test_a_request_for_codex_own_model_is_passed_through_untouched(self):
|
||||
"""User decision, 11 Oct 2026: Codex's own models are one side, the added models the other; the bridge
|
||||
does not touch a request for Codex's own model (no command, dot, note, work line or compaction handling)."""
|
||||
self.env["CFG"].update({"nokta_karsila": True, "model_bilgi": True, "yarim_cevap": True,
|
||||
"ozet_kopru": {"enabled": True, "kapsam": "hepsi"},
|
||||
"aiturk_hat": {"enabled": True, "komut": "aiturk is"}})
|
||||
mid_turn = [user("işe başla"), CALL, OUT, user("modeli opus 5 5 yap"), developer("k1")]
|
||||
for items in ([user("modeli opus 5 5 yap")], [user(".")], [user("seçili model hangisi")], mid_turn,
|
||||
[user("uzun iş"), {"type": "compaction_trigger"}]):
|
||||
with self.subTest(items=items):
|
||||
fake = Sahte(headers={"originator": "Codex Desktop"})
|
||||
body = json.dumps({"model": "gpt-6-astra", "prompt_cache_key": "sohbet-1", "input": items}).encode()
|
||||
fake._responses(1, "/responses", body)
|
||||
fake._yerel_yanit.assert_not_called()
|
||||
args, kwargs = fake._passthrough.call_args
|
||||
self.assertEqual(args[2], body)
|
||||
self.assertFalse(kwargs["rewritten"])
|
||||
self.assertEqual(self.env["YONLENDIRME"].veri, {})
|
||||
|
||||
def test_only_the_bridges_own_traces_are_cleaned_for_codex_own_model(self):
|
||||
self.env["fix_tool_ids"] = lambda req: 2 # ids left behind by an added model earlier in the chat
|
||||
fake, body = self.send("gpt-6-astra", [user("devam")])
|
||||
args, kwargs = fake._passthrough.call_args
|
||||
self.assertTrue(kwargs["rewritten"])
|
||||
self.assertNotEqual(args[2], body)
|
||||
sent = json.loads(args[2])
|
||||
self.assertIn("ad belirsizdi", sent["input"][3]["content"][0]["text"])
|
||||
self.assertEqual(sent["model"], "gpt-6-astra")
|
||||
self.assertEqual(json.loads(args[2]), json.loads(body))
|
||||
fake._yerel_yanit.assert_not_called()
|
||||
|
||||
def test_idle_switch_says_how_to_return_and_routes_the_next_request(self):
|
||||
fake, _ = self.send("gpt-6-sol", [user("modeli gpt 6 astra yap")])
|
||||
answer = fake._yerel_yanit.call_args.args[1]
|
||||
self.assertIn("Sohbetin modeli artık GPT-6-Astra", answer)
|
||||
self.assertIn('"modeli GPT-6-Sol yap"', answer)
|
||||
final = {"type": "message", "role": "assistant", "phase": "final_answer", "content": "ok"}
|
||||
fake, _ = self.send("gpt-6-sol", [user("modeli gpt 6 astra yap"), final, user("devam")])
|
||||
sent = json.loads(fake._passthrough.call_args.args[2])
|
||||
self.assertEqual(sent["model"], "gpt-6-astra")
|
||||
self.assertIn("GPT-6-Astra olarak değiştirdi", sent["input"][0]["content"][0]["text"])
|
||||
back, _ = self.send("gpt-6-sol", [user("modeli gpt 6 astra yap"), final, user("modeli gpt 6 sol yap")])
|
||||
self.assertNotIn("dönmek için", back._yerel_yanit.call_args.args[1]) # already back on the picked model
|
||||
def test_voice_switch_stays_among_the_added_models(self):
|
||||
opus, flash = "ide/9router-cc-claude-opus-5-5", "ide/9router-ag-gemini-3.8-flash-low"
|
||||
self.env["ROUTES"]["aiturk-ide"] = {"url": "https://example.invalid/v1/responses", "key": "k"}
|
||||
fake = Sahte()
|
||||
answer = fake._model_komutu(1, {"input": [user("modeli gemini flash low yap")]}, "sohbet-1", opus)
|
||||
self.assertIn("Sohbetin modeli artık agy/gemini-3.8-flash-low", answer)
|
||||
self.assertEqual(self.env["yonlendirilen"]("sohbet-1", opus), flash)
|
||||
# Codex's own model is not a voice target, from an added model either.
|
||||
answer = fake._model_komutu(1, {"input": [user("modeli gpt 6 astra yap")]}, "sohbet-1", opus)
|
||||
self.assertIn("GPT-6-Astra Codex'in kendi modeli", answer)
|
||||
self.assertIn("sesle geçilmiyor", answer)
|
||||
self.assertIn('"."', answer)
|
||||
self.assertEqual(self.env["yonlendirilen"]("sohbet-1", opus), flash)
|
||||
# In the middle of a turn the running model is told to pass that on; the work is not cut.
|
||||
req = {"input": [user("işe başla"), CALL, OUT, user("modeli gpt 6 astra yap")]}
|
||||
self.assertIsNone(fake._model_komutu(1, req, "sohbet-1", opus))
|
||||
self.assertIn("sesle yapılamıyor", req["input"][3]["content"][0]["text"])
|
||||
# A record left from before the rule that points at Codex's own model is ignored.
|
||||
self.env["YONLENDIRME"].koy("sohbet-2", opus, "gpt-6-astra")
|
||||
self.assertIsNone(self.env["yonlendirilen"]("sohbet-2", opus))
|
||||
|
||||
def test_a_refused_switch_is_not_told_as_done_after_compaction(self):
|
||||
items = [user("modeli opus 5 5 yap"), {"type": "compaction_trigger"}] # the ide/ route is closed here
|
||||
fake, body = self.send("gpt-6-sol", items)
|
||||
self.assertEqual(fake._passthrough.call_args.args[2], body)
|
||||
|
||||
def test_lone_dot_answer_says_selected_not_ready(self):
|
||||
def test_lone_dot_is_answered_for_an_added_model_and_left_alone_for_codex_own(self):
|
||||
self.env["CFG"]["nokta_karsila"] = True
|
||||
fake, _ = self.send("gpt-6-sol", [user(".")])
|
||||
self.assertIn("GPT-6-Sol seçildi", fake._yerel_yanit.call_args.args[1])
|
||||
fake, _ = self.send("ide/9router-cc-claude-opus-5-5", [user(".")])
|
||||
self.assertIn("cc/opus-5-5 seçildi", fake._yerel_yanit.call_args.args[1])
|
||||
self.assertNotIn("hazır", fake._yerel_yanit.call_args.args[1])
|
||||
fake, body = self.send("gpt-6-sol", [user(".")])
|
||||
fake._yerel_yanit.assert_not_called()
|
||||
self.assertEqual(fake._passthrough.call_args.args[2], body)
|
||||
|
||||
def test_old_router_name_without_a_route_is_refused_locally(self):
|
||||
fake, _ = self.send("9r/cc/claude-opus-5-5", [user("selam")])
|
||||
|
||||
Reference in new issue
Block a user