fix(sessions): hermes sessions adopt offers login-stamped phone chats

adoptable_sessions validated each row with no subject, so a phone chat stamped
with the dashboard login (basic:admin) was dropped although the host owner the
adoption resumes as can adopt it. Judge rows for host_owner_subject(). The test
now also registers Platform(mobile) first: a routeless row with that label still
adopts while the hermes-mobile plugin is loaded.
This commit is contained in:
Teknium committed 2026-11-01 21:30:21 -08:00
1 parent 3da1531caf
commit 7aa5200e91
2 files changed
+10 -1

No files matched your search

+4 -1
View File
@@ -24,6 +24,7 @@ def adoptable_sessions(path) -> list[dict]:
count a dry run reports is what an adoption run attempts. A row the owner already bound is not
offered again, which makes a second run a no-op."""
from hermes_state import SessionDB
from gateway.owner_identity import host_owner_subject
from hermes_state_local import POLICY_PREFIX
from hermes_state_local_migration import LEGACY_LOCAL_SOURCES, LEGACY_PREFIX, not_client_labels, validate_legacy_row
from hermes_state_runtime import RuntimeStoreError
@@ -53,7 +54,9 @@ def adoptable_sessions(path) -> list[dict]:
if tip is None or POLICY_PREFIX + key in bound or LEGACY_PREFIX + key in bound:
continue
try:
validate_legacy_row(db, tip)
# The host runs this command: judge each row for the owner the adoption resumes as, so a
# chat a phone app stored under the dashboard login (``basic:admin``) is offered too.
validate_legacy_row(db, tip, subject=host_owner_subject())
except RuntimeStoreError:
continue
found.append(tip)
@@ -45,6 +45,12 @@ async def test_a_phone_apps_own_label_resumes_writable_and_a_webui_row_stays_rea
db.create_session(sid, source=source, model='m', cwd=str(tmp_path), user_id=user_id)
db.append_message(sid, role='user', content='hi from ' + sid)
db.end_session(sid, 'ws_orphan_reap')
# hermes-mobile installed registers Platform('mobile'): a routeless row with that label still adopts.
from gateway.config import Platform
Platform._add_pseudo_member('mobile')
from hermes_cli.sessions_adopt import adoptable_sessions
offered = {row['id'] for row in adoptable_sessions(db.db_path)}
assert {'phone-mobile', 'phone-ios'} <= offered and not offered & {'webui-row', 'teams-row', 'curator-row'}
for i, sid in enumerate(('phone-mobile', 'phone-ios')):
resumed = await desktop.dispatch({'id': i, 'method': 'session.resume', 'params': {'session_id': sid}})
assert resumed.get('result', {}).get('session_id') == sid, resumed