mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-25 03:00:23 +00:00
fix: keep cross-surface session continuations visible
This commit is contained in:
committed by
nesquena-hermes
parent
f77b8aad5b
commit
7d5704c3bc
@@ -527,6 +527,10 @@ def read_session_lineage_metadata(db_path: Path, session_ids: list[str] | set[st
|
||||
entry['relationship_type'] = 'child_session'
|
||||
entry['parent_title'] = parent_row.get('title')
|
||||
entry['parent_source'] = parent_row.get('source')
|
||||
parent_source = str(parent_row.get('source') or '').strip().lower()
|
||||
child_source = str(row.get('source') or '').strip().lower()
|
||||
if parent_source and child_source and parent_source != child_source:
|
||||
entry['_cross_surface_child_session'] = True
|
||||
parent_root = _continuation_root_id(rows, parent_id)
|
||||
if parent_root:
|
||||
entry['_parent_lineage_root_id'] = parent_root
|
||||
|
||||
@@ -1870,6 +1870,10 @@ function _attachChildSessionsToSidebarRows(collapsedRows, rawSessions){
|
||||
const orphans=[];
|
||||
for(const child of rawSessions||[]){
|
||||
if(!_isChildSession(child)) continue;
|
||||
if(child._cross_surface_child_session){
|
||||
orphans.push({...child,_orphan_child_session:true});
|
||||
continue;
|
||||
}
|
||||
const parentSid=child.parent_session_id;
|
||||
let parentRow=visibleBySid.get(parentSid);
|
||||
let parentSegment=null;
|
||||
|
||||
@@ -126,6 +126,8 @@ console.log(JSON.stringify({{sid: collapsed[0].session_id, containsRoot: _sessio
|
||||
assert '"containsRoot":true' in result
|
||||
|
||||
|
||||
|
||||
|
||||
def test_sidebar_attaches_child_sessions_to_collapsed_hidden_parent_lineage():
|
||||
js = SESSIONS_JS_PATH.read_text(encoding="utf-8")
|
||||
source = f"""
|
||||
@@ -162,3 +164,47 @@ console.log(JSON.stringify(attached));
|
||||
assert [row["session_id"] for row in rows] == ["tip"]
|
||||
assert rows[0]["_child_session_count"] == 1
|
||||
assert rows[0]["_child_sessions"][0]["session_id"] == "child"
|
||||
|
||||
|
||||
def test_cross_surface_webui_child_session_remains_top_level_when_parent_is_messaging():
|
||||
js = SESSIONS_JS_PATH.read_text(encoding="utf-8")
|
||||
source = f"""
|
||||
const src = {js!r};
|
||||
function extractFunc(name) {{
|
||||
const re = new RegExp('function\\\\s+' + name + '\\\\s*\\\\(');
|
||||
const start = src.search(re);
|
||||
if (start < 0) throw new Error(name + ' not found');
|
||||
let i = src.indexOf('{{', start);
|
||||
let depth = 1; i++;
|
||||
while (depth > 0 && i < src.length) {{
|
||||
if (src[i] === '{{') depth++;
|
||||
else if (src[i] === '}}') depth--;
|
||||
i++;
|
||||
}}
|
||||
return src.slice(start, i);
|
||||
}}
|
||||
eval(extractFunc('_isChildSession'));
|
||||
eval(extractFunc('_sidebarLineageKeyForRow'));
|
||||
eval(extractFunc('_attachChildSessionsToSidebarRows'));
|
||||
const collapsed = [{{session_id:'telegram_parent', title:'Telegram parent', source_label:'Telegram'}}];
|
||||
const raw = [
|
||||
collapsed[0],
|
||||
{{
|
||||
session_id:'webui_tip',
|
||||
title:'Current WebUI continuation',
|
||||
parent_session_id:'telegram_parent',
|
||||
relationship_type:'child_session',
|
||||
parent_source:'telegram',
|
||||
source_label:'Telegram',
|
||||
session_source:'messaging',
|
||||
raw_source:'telegram',
|
||||
_cross_surface_child_session:true,
|
||||
}},
|
||||
];
|
||||
const rows = _attachChildSessionsToSidebarRows(collapsed, raw);
|
||||
console.log(JSON.stringify(rows));
|
||||
"""
|
||||
rows = json.loads(_run_node(source))
|
||||
assert [row["session_id"] for row in rows] == ["telegram_parent", "webui_tip"]
|
||||
assert rows[1].get("_orphan_child_session") is True
|
||||
assert "_child_sessions" not in rows[0]
|
||||
|
||||
@@ -45,14 +45,14 @@ def _ensure_state_db(path):
|
||||
return conn
|
||||
|
||||
|
||||
def _insert_state_row(conn, sid, *, parent=None, ended_at=None, end_reason=None, started_at=None):
|
||||
def _insert_state_row(conn, sid, *, parent=None, ended_at=None, end_reason=None, started_at=None, source='webui'):
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO sessions
|
||||
(id, source, title, model, started_at, message_count, parent_session_id, ended_at, end_reason)
|
||||
VALUES (?, 'webui', ?, 'openai/gpt-5', ?, 2, ?, ?, ?)
|
||||
VALUES (?, ?, ?, 'openai/gpt-5', ?, 2, ?, ?, ?)
|
||||
""",
|
||||
(sid, sid, started_at or time.time(), parent, ended_at, end_reason),
|
||||
(sid, source, sid, started_at or time.time(), parent, ended_at, end_reason),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
@@ -202,3 +202,35 @@ def test_cli_close_parent_preserves_cross_surface_continuation_lineage(_isolate)
|
||||
assert rows["lineage_api_webui_child"].get("_lineage_root_id") == "lineage_api_cli_parent"
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def test_cross_surface_child_session_metadata_marks_orphan_top_level_candidate(_isolate):
|
||||
conn = _ensure_state_db(_isolate)
|
||||
t0 = time.time() - 100
|
||||
try:
|
||||
_save_webui_session("lineage_api_telegram_parent", title="Telegram parent", updated_at=t0)
|
||||
_save_webui_session("lineage_api_webui_tip", title="WebUI tip", updated_at=t0 + 10)
|
||||
_insert_state_row(
|
||||
conn,
|
||||
"lineage_api_telegram_parent",
|
||||
source="telegram",
|
||||
started_at=t0,
|
||||
ended_at=t0 + 5,
|
||||
end_reason="compression",
|
||||
)
|
||||
_insert_state_row(
|
||||
conn,
|
||||
"lineage_api_webui_tip",
|
||||
source="webui",
|
||||
parent="lineage_api_telegram_parent",
|
||||
started_at=t0 + 6,
|
||||
)
|
||||
|
||||
rows = {row["session_id"]: row for row in all_sessions()}
|
||||
tip = rows["lineage_api_webui_tip"]
|
||||
|
||||
assert tip.get("relationship_type") == "child_session"
|
||||
assert tip.get("parent_source") == "telegram"
|
||||
assert tip.get("_cross_surface_child_session") is True
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
Reference in New Issue
Block a user