diff --git a/api/routes.py b/api/routes.py index cdf9e12a382..ca3e2d9c0e4 100644 --- a/api/routes.py +++ b/api/routes.py @@ -4232,6 +4232,7 @@ def handle_post(handler, parsed) -> bool: title=branch_title, messages=forked_messages, parent_session_id=source.session_id, + session_source="fork", ) with LOCK: SESSIONS[branch.session_id] = branch diff --git a/static/sessions.js b/static/sessions.js index 6e7a8f8c178..a1271219fe1 100644 --- a/static/sessions.js +++ b/static/sessions.js @@ -1978,6 +1978,7 @@ function _isChildSession(s){ function _sessionLineageKey(s, sessionIdsInList){ if(!s||!s.session_id) return null; if(_isChildSession(s)) return null; + if(s.session_source==='fork') return null; const lineageKey=s._lineage_root_id||s.lineage_root_id||null; if(lineageKey) return lineageKey; // If parent_session_id points to another session in the current list, diff --git a/tests/test_465_session_branching.py b/tests/test_465_session_branching.py index 7a09ac61873..2a3722f8e2d 100644 --- a/tests/test_465_session_branching.py +++ b/tests/test_465_session_branching.py @@ -68,6 +68,32 @@ def test_branch_creates_session_with_parent(): "Branch handler should set parent_session_id to source session" +def test_branch_marks_explicit_forks_as_fork_sessions(): + """Explicit branches must not be mistaken for compression lineage rows.""" + with open('api/routes.py') as f: + src = f.read() + branch_match = re.search( + r'parsed\.path == "/api/session/branch"(.*?)(?=\n if parsed\.path|$)', + src, re.DOTALL + ) + assert branch_match + block = branch_match.group(1) + assert 'session_source="fork"' in block, \ + "Branch handler should mark explicit forks with session_source='fork'" + + +def test_branch_fork_sessions_do_not_collapse_into_parent_lineage(): + """Forks remain selectable rows even if their parent is not in the current list.""" + with open('static/sessions.js') as f: + src = f.read() + fn = re.search(r'function _sessionLineageKey\(.*?\n\}', src, re.DOTALL) + assert fn, "Could not find _sessionLineageKey" + block = fn.group(0) + assert "if(s.session_source==='fork') return null;" in block, \ + "Explicit fork sessions should not collapse via parent_session_id" + assert block.index("if(s.session_source==='fork') return null;") < block.index('return s.parent_session_id || null') + + def test_branch_keep_count_support(): """Verify the branch endpoint supports keep_count parameter.""" with open('api/routes.py') as f: