fix: persist active_remote_id in state for remote session restore

Remote sessions failed to reconnect after page refresh because
restoreState() and renderSheetList() didn't pass remoteId to
openSession(). Fix:

- state.py: add active_remote_id field to empty_state()
- main.py: extend StatePatch model to accept active_session and
  active_remote_id; update PATCH /api/state to selectively update
  only fields explicitly provided (using model_fields_set)
- app.js restoreState(): read state.active_remote_id and pass it
  as remoteId option so page-refresh reconnects remote sessions
- app.js openSession(): fire-and-forget PATCH /api/state to persist
  active_session + active_remote_id after successful connect
- app.js closeSession(): fire-and-forget PATCH /api/state to clear
  both fields so refresh doesn't try to reopen a closed session
- app.js renderSheetList(): add data-remote-id to sheet items and
  pass remoteId in click handler (previously called openSession(name)
  with no remoteId, routing remote sessions to local 404 endpoint)

Fixes: POST /api/sessions/paperclip-adapter/connect 404 when clicking
a remote session from the mobile bottom sheet or after page refresh.
This commit is contained in:
Brian Krabach
2026-04-06 18:08:19 -07:00
parent 50abb4f40b
commit add9e03718
6 changed files with 212 additions and 6 deletions
+16 -3
View File
@@ -279,7 +279,9 @@ app.add_middleware(
class StatePatch(BaseModel):
session_order: list[str]
session_order: list[str] | None = None
active_session: str | None = None
active_remote_id: str | None = None
class HeartbeatPayload(BaseModel):
@@ -332,10 +334,21 @@ async def get_state() -> dict:
@app.patch("/api/state")
async def patch_state(patch: StatePatch) -> dict:
"""Update session_order in the persistent state and return the updated state."""
"""Update fields in the persistent state and return the updated state.
Only fields explicitly included in the request body are updated;
omitted fields are left unchanged. Supports: session_order,
active_session, active_remote_id.
"""
async with state_lock:
state = load_state()
state["session_order"] = patch.session_order
changed = patch.model_fields_set
if "session_order" in changed:
state["session_order"] = patch.session_order
if "active_session" in changed:
state["active_session"] = patch.active_session
if "active_remote_id" in changed:
state["active_remote_id"] = patch.active_remote_id
save_state(state)
return state