Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions run_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -1733,11 +1733,29 @@ def _check_compression_model_feasibility(self) -> None:

aux_base_url = str(getattr(client, "base_url", ""))
aux_api_key = str(getattr(client, "api_key", ""))
aux_context = get_model_context_length(
aux_model,
base_url=aux_base_url,
api_key=aux_api_key,
)

def _normalize_model_name(model_name: str) -> str:
model_name = (model_name or "").strip().lower()
if "/" in model_name:
model_name = model_name.rsplit("/", 1)[-1]
return model_name

same_model = _normalize_model_name(aux_model) == _normalize_model_name(self.model)
same_endpoint = aux_base_url.rstrip("/") == str(getattr(self, "base_url", "")).rstrip("/")

if same_model and same_endpoint:
# Compression defaults to the active model. Reuse the already
# resolved main-model context so explicit config overrides
# (for example model.context_length on custom endpoints) are
# honored instead of re-querying metadata and falling back to
# generic family defaults like GPT-5 = 128K.
aux_context = self.context_compressor.context_length
else:
aux_context = get_model_context_length(
aux_model,
base_url=aux_base_url,
api_key=aux_api_key,
)

threshold = self.context_compressor.threshold_tokens
if aux_context < threshold:
Expand Down
52 changes: 52 additions & 0 deletions tests/run_agent/test_compression_feasibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,58 @@ def test_just_below_threshold_warns(mock_get_client, mock_ctx_len):
assert "small-model" in messages[0]


@patch("agent.model_metadata.get_model_context_length", return_value=128_000)
@patch("agent.auxiliary_client.get_text_auxiliary_client")
def test_reuses_main_context_when_compression_model_matches_active_model(
mock_get_client, mock_ctx_len
):
"""If compression resolves to the active model on the same endpoint,
reuse the already-resolved main context instead of re-querying metadata.
"""
agent = _make_agent(main_context=1_000_000, threshold_percent=0.80)
agent.model = "gpt-5.4"
agent.base_url = "https://sub2api.tizi.lifestyle/v1"

mock_client = MagicMock()
mock_client.base_url = "https://sub2api.tizi.lifestyle/v1/"
mock_client.api_key = "sk-aux"
mock_get_client.return_value = (mock_client, "gpt-5.4")

messages = []
agent._emit_status = lambda msg: messages.append(msg)

agent._check_compression_model_feasibility()

assert len(messages) == 0
assert agent._compression_warning is None
mock_ctx_len.assert_not_called()


@patch("agent.model_metadata.get_model_context_length", return_value=32_768)
@patch("agent.auxiliary_client.get_text_auxiliary_client")
def test_explicit_different_compression_model_uses_its_own_context(
mock_get_client, mock_ctx_len
):
"""A distinct compression model should still be checked independently."""
agent = _make_agent(main_context=1_000_000, threshold_percent=0.80)
agent.model = "gpt-5.4"
agent.base_url = "https://sub2api.tizi.lifestyle/v1"

mock_client = MagicMock()
mock_client.base_url = "https://openrouter.ai/api/v1"
mock_client.api_key = "sk-aux"
mock_get_client.return_value = (mock_client, "google/gemini-3-flash-preview")

messages = []
agent._emit_status = lambda msg: messages.append(msg)

agent._check_compression_model_feasibility()

assert len(messages) == 1
assert "google/gemini-3-flash-preview" in messages[0]
mock_ctx_len.assert_called_once()


# ── Two-phase: __init__ + run_conversation replay ───────────────────


Expand Down