154 lines
6.6 KiB
Python
154 lines
6.6 KiB
Python
"""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
|
|
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_drops_unkept_tool_rows_after_user_boundary():
|
|
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-user-keep", "id": "tool-call-after-user-keep"},
|
|
{"role": "tool", "content": "tool-result-after-user-keep", "id": "tool-result-after-user-keep"},
|
|
{"role": "assistant", "content": "a2", "id": "a2", "timestamp": 4.0},
|
|
]
|
|
out = truncate_context_for_display_keep(ctx, msgs, 3)
|
|
contents = [m["content"] for m in out]
|
|
assert contents == ["u1", "a1", "u2"]
|
|
assert "tool-call-after-user-keep" not in contents
|
|
assert "tool-result-after-user-keep" not in contents
|
|
assert "a2" not in contents
|
|
|
|
|
|
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]
|
|
|
|
|
|
def test_truncate_context_for_display_keep_keeps_real_user_turn_when_duplicate_rows_lack_identity():
|
|
msgs = [
|
|
{"role": "user", "content": "u1"},
|
|
{"role": "assistant", "content": "a1"},
|
|
]
|
|
ctx = [
|
|
{"role": "user", "content": "u1"},
|
|
{"role": "user", "content": "u1"},
|
|
{"role": "assistant", "content": "a1"},
|
|
]
|
|
out = truncate_context_for_display_keep(ctx, msgs, 1)
|
|
assert [row["content"] for row in out] == ["u1", "u1"]
|
|
|
|
def test_truncate_context_for_display_keep_keeps_tool_tail_before_ambiguous_unkept_anchor():
|
|
msgs = [
|
|
{"role": "user", "content": "u1", "id": "u1"},
|
|
{"role": "assistant", "content": "a1", "id": "a1", "tool_calls": [{"id": "kept-tool"}]},
|
|
{"role": "user", "content": "u2"},
|
|
]
|
|
ctx = [
|
|
{"role": "user", "content": "u1", "id": "u1"},
|
|
{"role": "assistant", "content": "a1", "id": "a1", "tool_calls": [{"id": "kept-tool"}]},
|
|
{"role": "tool", "content": "kept-tool-result", "tool_call_id": "kept-tool"},
|
|
{"role": "user", "content": "u2"},
|
|
{"role": "user", "content": "u2"},
|
|
{"role": "assistant", "content": "a2", "id": "a2"},
|
|
]
|
|
out = truncate_context_for_display_keep(ctx, msgs, 2)
|
|
assert [row["content"] for row in out] == ["u1", "a1", "kept-tool-result"]
|