2026-06-28 17:37:27 +00:00
|
|
|
"""Branch must not inherit full parent context_messages (#5096 A)."""
|
|
|
|
|
|
|
|
|
|
import copy
|
|
|
|
|
|
|
|
|
|
from api.session_ops import truncate_context_for_display_keep
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_truncate_context_for_display_keep_drops_parent_tail():
|
|
|
|
|
msgs = [
|
|
|
|
|
{"role": "user", "content": "u1"},
|
|
|
|
|
{"role": "assistant", "content": "a1"},
|
|
|
|
|
{"role": "user", "content": "after-fork"},
|
|
|
|
|
]
|
|
|
|
|
# Same-length context as display — fork at keep=2 matches messages[:2]
|
|
|
|
|
ctx = copy.deepcopy(msgs)
|
|
|
|
|
out = truncate_context_for_display_keep(ctx, msgs, 2)
|
|
|
|
|
assert len(out) == 2
|
|
|
|
|
assert out[-1]["content"] == "a1"
|
|
|
|
|
assert "after-fork" not in [m["content"] for m in out]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_truncate_context_preserves_leading_compaction_row():
|
|
|
|
|
msgs = [
|
|
|
|
|
{"role": "user", "content": "u1"},
|
|
|
|
|
{"role": "assistant", "content": "a1"},
|
|
|
|
|
]
|
|
|
|
|
ctx = [
|
|
|
|
|
{"role": "user", "content": "compaction-ref-only"},
|
|
|
|
|
{"role": "user", "content": "u1"},
|
|
|
|
|
{"role": "assistant", "content": "a1"},
|
|
|
|
|
]
|
|
|
|
|
out = truncate_context_for_display_keep(ctx, msgs, 2)
|
|
|
|
|
assert len(out) == 3
|
2026-06-29 14:39:08 +00:00
|
|
|
assert out[0]["content"] == "compaction-ref-only"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_truncate_context_for_display_keep_drops_interleaved_tool_tail():
|
|
|
|
|
msgs = [
|
|
|
|
|
{"role": "user", "content": "u1", "id": "u1", "timestamp": 1.0},
|
|
|
|
|
{"role": "assistant", "content": "a1", "id": "a1", "timestamp": 2.0},
|
|
|
|
|
{"role": "user", "content": "u2", "id": "u2", "timestamp": 3.0},
|
|
|
|
|
{"role": "assistant", "content": "a2", "id": "a2", "timestamp": 4.0},
|
|
|
|
|
]
|
|
|
|
|
ctx = [
|
|
|
|
|
{"role": "user", "content": "u1", "id": "u1", "timestamp": 1.0},
|
|
|
|
|
{"role": "assistant", "content": "a1", "id": "a1", "timestamp": 2.0},
|
|
|
|
|
{"role": "user", "content": "u2", "id": "u2", "timestamp": 3.0},
|
|
|
|
|
{"role": "assistant", "content": "tool-call-after-cut", "id": "tool-call-after-cut"},
|
|
|
|
|
{"role": "tool", "content": "tool-result-after-cut", "id": "tool-result-after-cut"},
|
|
|
|
|
{"role": "assistant", "content": "a2", "id": "a2", "timestamp": 4.0},
|
|
|
|
|
]
|
|
|
|
|
out = truncate_context_for_display_keep(ctx, msgs, 2)
|
|
|
|
|
contents = [m["content"] for m in out]
|
|
|
|
|
assert contents == ["u1", "a1"]
|
|
|
|
|
assert "u2" not in contents
|
|
|
|
|
assert "tool-call-after-cut" not in contents
|
|
|
|
|
assert "tool-result-after-cut" not in contents
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_truncate_context_for_display_keep_keeps_tool_rows_before_next_display_anchor():
|
|
|
|
|
msgs = [
|
|
|
|
|
{"role": "user", "content": "u1", "id": "u1", "timestamp": 1.0},
|
|
|
|
|
{"role": "assistant", "content": "a1", "id": "a1", "timestamp": 2.0},
|
|
|
|
|
{"role": "user", "content": "u2", "id": "u2", "timestamp": 3.0},
|
|
|
|
|
{"role": "assistant", "content": "a2", "id": "a2", "timestamp": 4.0},
|
|
|
|
|
]
|
|
|
|
|
ctx = [
|
|
|
|
|
{"role": "user", "content": "u1", "id": "u1", "timestamp": 1.0},
|
|
|
|
|
{"role": "assistant", "content": "a1", "id": "a1", "timestamp": 2.0},
|
|
|
|
|
{"role": "assistant", "content": "assistant-think", "id": "a1-think"},
|
|
|
|
|
{"role": "assistant", "content": "assistant-tool-result", "id": "a1-tool", "timestamp": 2.5},
|
|
|
|
|
{"role": "user", "content": "u2", "id": "u2", "timestamp": 3.0},
|
|
|
|
|
{"role": "assistant", "content": "a2", "id": "a2", "timestamp": 4.0},
|
|
|
|
|
]
|
|
|
|
|
out = truncate_context_for_display_keep(ctx, msgs, 2)
|
|
|
|
|
contents = [m["content"] for m in out]
|
|
|
|
|
assert contents == [
|
|
|
|
|
"u1",
|
|
|
|
|
"a1",
|
|
|
|
|
"assistant-think",
|
|
|
|
|
"assistant-tool-result",
|
|
|
|
|
]
|
|
|
|
|
assert contents[-1] != "u2"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_truncate_context_for_display_keep_prefers_compact_summary_fallback():
|
|
|
|
|
msgs = [
|
|
|
|
|
{"role": "user", "content": "u1", "id": "u1", "timestamp": 1.0},
|
|
|
|
|
{"role": "assistant", "content": "a1", "id": "a1", "timestamp": 2.0},
|
|
|
|
|
{"role": "user", "content": "u2", "id": "u2", "timestamp": 3.0},
|
|
|
|
|
{"role": "assistant", "content": "a2", "id": "a2", "timestamp": 4.0},
|
|
|
|
|
]
|
|
|
|
|
ctx = [
|
|
|
|
|
{"role": "user", "content": "compact", "id": "summary"},
|
|
|
|
|
{"role": "user", "content": "u1", "id": "u1", "timestamp": 1.0},
|
|
|
|
|
{"role": "assistant", "content": "a1", "id": "a1", "timestamp": 2.0},
|
|
|
|
|
]
|
|
|
|
|
out = truncate_context_for_display_keep(ctx, msgs, 2)
|
|
|
|
|
assert out == ctx[:2]
|