fix: preserve native model switches and bound project searches
Server CI and Windows package / verify (push) Failing after 1m40s
Server CI and Windows package / windows-package (push) Skipped

This commit is contained in:
yilsem committed 2026-10-13 16:32:50 +03:00
1 parent db5e876f40
commit e7d3080e0a
14 files changed
+371 -35

No files matched your search

+10 -4
View File
@@ -34,7 +34,7 @@ import urllib.request
import gecis_context
HERE = os.path.dirname(os.path.abspath(__file__))
SURUM = "16" # AITURK IDE'nin bekledigi kopru surumu (codex-link-config.ts CODEX_BRIDGE_VERSION)
SURUM = "17" # AITURK IDE'nin bekledigi kopru surumu (codex-link-config.ts CODEX_BRIDGE_VERSION)
try:
with open(os.path.abspath(__file__), "rb") as _f:
KOD = hashlib.sha256(_f.read()).hexdigest()[:8]
@@ -484,15 +484,21 @@ class H(http.server.BaseHTTPRequestHandler):
source = TRANSFERS.get(scope) if thread else None
# A completed return to the subscription ends migration. Historical
# foreign IDs must not keep later native turns in the preparer.
mixed = ek_model_mu(source or "") or (source is None and gecis_context.foreign(req))
if external or mixed:
mixed = ek_model_mu(source or "") or (source is None and gecis_context.foreign_history(req))
# Format repair is stateless: the saved transcript can still contain
# foreign wrappers after a successful native return (or a restart).
if external or mixed or gecis_context.foreign(req):
try:
normalized = gecis_context.normalize(req)
except gecis_context.TransferError as e:
self._transfer_begin()
return self._transfer_fail(str(e))
# Small returning requests need no summarizer or local worker.
if external or gecis_context.tokens(normalized) > int(32768 * 0.70):
# Native opaque state must remain on its owner route. Its byte
# size is not a semantic token budget and cannot trigger a
# foreign summarizer, including when transfer state is cold.
if external or (mixed and not gecis_context.native_opaque(normalized)
and gecis_context.tokens(normalized) > int(32768 * 0.70)):
prepared, started = self._prepare(normalized, source)
if prepared is None:
return
@@ -180,9 +180,13 @@ def prepare(handler, module, payload, checkpoints):
slug = original.get('model', '')
external = module.ek_model_mu(slug)
source_model = payload.get('source_model') or ''
if not external and gc.native_opaque(original):
# Defense in depth for direct/older splitter callers. Native encrypted
# state never enters owner decoding or cross-provider summarization.
return {'request': gc.normalize(original)}
# Defense in depth: an accidental worker call cannot alter native-only history.
if not external and not module.ek_model_mu(source_model) and not gc.foreign(original):
return {'request': copy.deepcopy(original), 'window': handler._transfer_window(slug)}
if not external and not module.ek_model_mu(source_model) and not gc.foreign_history(original):
return {'request': gc.normalize(original)}
settings = settings_store.read(module.HOME)
actual = (module.yonlendirilen(str(original.get('prompt_cache_key') or ''), slug) or slug) if external else slug
window = handler._transfer_window(actual)
@@ -54,6 +54,22 @@ def foreign(req):
return False
def native_opaque(req):
"""Native encrypted state belongs to the subscription, even in mixed history."""
return any(isinstance(item, dict) and item.get("type") == "compaction" and item.get("encrypted_content")
and not str(item["encrypted_content"]).startswith(ozet_kopru.ISARET)
for item in req.get("input") or [])
def foreign_history(req):
"""Semantic migration evidence, excluding tool ID format mismatches."""
return any(isinstance(item, dict) and (
"chatcmpl-" in str(item.get("id") or "")
or "astrabridge" in str(item.get("id") or "")
or str(item.get("encrypted_content") or "").startswith(ozet_kopru.ISARET))
for item in req.get("input") or [])
def normalize(req):
"""Repair local wrappers/IDs, retaining real OpenAI encrypted compaction.
@@ -82,6 +98,10 @@ def normalize(req):
if any(visible):
result.append(ozet_kopru._ozet_mesaji("\n".join(visible)))
continue
if ("chatcmpl-" in str(identity) or "astrabridge" in str(identity)) and (
item.get("type") == "message" or item.get("role")):
# Inline message content is portable; its foreign server ID is not.
item.pop("id", None)
prefix = PREFIXES.get(item.get("type"))
if prefix and isinstance(identity, str) and identity and not identity.startswith(prefix + "_"):
item["id"] = prefix + "_" + identity.split("_", 1)[-1]
+2 -2
View File
@@ -40,7 +40,7 @@ from bekci_watch import MetadataFilter
# Installed only by owned native launcher, never an HTTP control endpoint.
WATCH_OWNER = None
SURUM = "16"
SURUM = "17"
HERE = os.path.dirname(os.path.abspath(__file__))
try:
with open(os.path.abspath(__file__), "rb") as _f:
@@ -1287,7 +1287,7 @@ class H(http.server.BaseHTTPRequestHandler):
for model in json.loads(cached["body"]).get("models", []):
if model.get("slug") == slug and model.get("context_window"):
return int(model["context_window"])
return 32768
raise gecis_context.TransferError("Abonelik modelinin bağlam kapasitesi katalogda bulunamadı; geçmiş korundu.")
def _prepare_transfer(self, payload):
@@ -0,0 +1,83 @@
"""Native switch regressions using the real HTTP splitter and offline peers."""
import copy
import gzip
import json
import unittest
import ast
from pathlib import Path
import bridge
import gecis_context as gc
import ozet_kopru
import test_ayirici as fixtures
class NativeSwitch(unittest.TestCase):
setUp = fixtures.Ayirici.setUp
tearDown = fixtures.Ayirici.tearDown
iste = fixtures.Ayirici.iste
def test_unknown_native_capacity_is_not_invented(self):
tree = ast.parse(Path(__file__).with_name('kopru.py').read_text(encoding='utf-8'))
method = next(node for node in ast.walk(tree)
if isinstance(node, ast.FunctionDef) and node.name == '_transfer_window')
ns = {'ek_model_mu': lambda _: False, 'LAST_MODELS': {}, 'gecis_context': gc, 'json': json}
exec(compile(ast.Module(body=[method], type_ignores=[]), 'window', 'exec'), ns)
from types import SimpleNamespace
with self.assertRaises(gc.TransferError):
ns['_transfer_window'](SimpleNamespace(headers={}), 'gpt-6-astra')
def test_opaque_native_switch_with_persisted_foreign_residue(self):
self.ozgun.cevap = fixtures.duz(200, b'data: {"type":"response.completed"}\n\n', 'text/event-stream')
compact = {'type': 'compaction', 'id': 'cmp_native',
'encrypted_content': 'gAAAAABp' + 'AqZ09_-jX' * 10000}
req = {'model': 'gpt-6.1-sol', 'prompt_cache_key': 'restart', 'input': [
ozet_kopru.ozet_ogesi('DECISION-4827 must survive'), compact,
{'type': 'custom_tool_call', 'id': 'fc_123', 'call_id': 'call_123',
'name': 'apply_patch', 'input': 'patch text'},
{'type': 'custom_tool_call_output', 'id': 'fco_123',
'call_id': 'call_123', 'output': 'complete'},
{'role': 'user', 'content': 'continue'}]}
before = copy.deepcopy(req)
for cold, model in ((True, 'gpt-6.1-sol'), (False, 'gpt-6-astra'), (True, 'gpt-6-astra')):
if cold:
bridge.TRANSFERS.clear()
req['model'] = model
body = gzip.compress(json.dumps(req).encode())
self.assertEqual(self.iste('POST', '/backend-api/codex/responses', body,
{'Content-Encoding': 'gzip'})[0], 200)
sent = json.loads(self.ozgun.gelen[-1]['govde'])
self.assertEqual(sent['input'][1], compact)
self.assertEqual(sent['input'][2]['id'], 'ctc_123')
self.assertEqual(sent['input'][3]['id'], 'ctco_123')
self.assertEqual(sent['input'][3]['call_id'], 'call_123')
self.assertIn('DECISION-4827', json.dumps(sent))
self.assertEqual(self.kopru.gelen, [])
self.assertEqual(req['input'], before['input'])
def test_clean_native_body_is_byte_identical_even_after_external_source(self):
req = {'model': 'ide/test', 'prompt_cache_key': 'return', 'input': []}
self.iste('POST', '/backend-api/codex/responses', json.dumps(req).encode())
self.kopru.gelen.clear()
req.update(model='gpt-6-astra', input=[{'type': 'compaction',
'encrypted_content': 'gAAAAABp' + 'X' * 100000}])
raw = gzip.compress(json.dumps(req, indent=3).encode())
self.iste('POST', '/backend-api/codex/responses', raw, {'Content-Encoding': 'gzip'})
self.assertEqual(self.ozgun.gelen[-1]['govde'], raw)
self.assertEqual(self.kopru.gelen, [])
def test_cold_native_tool_id_repair_does_not_require_semantic_budget(self):
req = {'model': 'gpt-6-astra', 'input': [
{'type': 'custom_tool_call', 'id': 'fc_old', 'call_id': 'call_old',
'name': 'apply_patch', 'input': 'x' * 100000},
{'type': 'custom_tool_call_output', 'id': 'fco_old',
'call_id': 'call_old', 'output': 'complete'}]}
self.iste('POST', '/backend-api/codex/responses', json.dumps(req).encode())
self.assertEqual(len(self.kopru.gelen), 0)
sent = json.loads(self.ozgun.gelen[-1]['govde'])
self.assertEqual(sent, gc.normalize(req))
self.assertEqual(req['input'][0]['id'], 'fc_old')
if __name__ == '__main__':
unittest.main()