Skip to content

fix(tui): sync ctx.sid on session.info after compression fork (#36777)#36811

Open
luyao618 wants to merge 1 commit into
NousResearch:mainfrom
luyao618:fix/tui-session-info-sid-after-compress
Open

fix(tui): sync ctx.sid on session.info after compression fork (#36777)#36811
luyao618 wants to merge 1 commit into
NousResearch:mainfrom
luyao618:fix/tui-session-info-sid-after-compress

Conversation

@luyao618

@luyao618 luyao618 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #36777. After /compress forks the TUI session (ends parent, creates continuation), the gateway emits session.info with the new session_id — but the TUI handler was dropping the update on the floor, leaving ctx.sid pointing at the closed parent session. All subsequent RPCs (message submission, /image, /model, etc.) then targeted the dead session.

Root cause

Two interlocking bugs in ui-tui/src/app/createGatewayEventHandler.ts:

  1. Guard discarded the event. The top-level guard early-returned any event whose ev.session_id differed from state.sid (except gateway.*). The post-compression session.info — which by definition carries a different sid — was silently discarded before any case ran.
  2. Handler ignored sid. Even with the event delivered, the session.info case only patched info / status / usage — never sid.

The gateway side (tui_gateway/server.py::_sync_session_key_after_compress, _emit("session.info", new_sid, ...)) is correct; the bug was purely on the TS receiver.

Fix

  • Allow session.info past the sid mismatch guard so the compression-fork event reaches the handler.
  • In the session.info case, read ev.session_id (set by the gateway _emit envelope) and update state.sid when it differs.
case 'session.info': {
  const info = ev.payload
  const incomingSid = ev.session_id
  patchUiState(state => {
    const sidChanged = Boolean(incomingSid) && incomingSid !== state.sid
    return {
      ...state,
      info,
      sid: sidChanged ? (incomingSid as string) : state.sid,
      status: state.status === 'starting agent…' ? 'ready' : state.status,
      usage: info.usage ? { ...state.usage, ...info.usage } : state.usage
    }
  })
  ...
}

Testing

  • Added two vitest cases in ui-tui/src/__tests__/createGatewayEventHandler.test.ts:
    • updates sid when ev.session_id differs (compression fork)
    • leaves sid unchanged when it matches or is absent
  • npx vitest run src/__tests__/createGatewayEventHandler.test.ts52/52 pass
  • npx tsc --noEmit → no new errors in touched files

Notes

  • Issue reporter's suggested fix read info.session_id from the payload, but the gateway puts session_id on the event envelope (_emit line params = {"type": event, "session_id": sid}), not in the payload dict — so this PR uses ev.session_id, which is the source of truth and is what the existing guard also reads.
  • Scope is intentionally minimal: only the handler + tests; no refactors.

When /compress forks the session (ends parent, creates continuation),
the gateway emits session.info with the new session_id, but the TUI
event handler dropped sid updates on the floor — leaving ctx.sid
pointing at the closed parent session and breaking subsequent RPCs.

Two interlocking bugs:

1. The top-level guard in createGatewayEventHandler dropped any event
   whose ev.session_id differed from state.sid (except gateway.*).
   That meant the post-compression session.info — which by definition
   carries a *different* sid — was silently discarded before reaching
   any case handler.

2. The session.info case patched info/status/usage but never touched
   state.sid, so even if the event arrived, the UI would not re-anchor
   onto the new continuation session.

Fix:
- Allow 'session.info' through the sid guard so the compression-fork
  event still reaches the handler.
- In the session.info handler, read ev.session_id (set by the gateway
  _emit envelope) and update state.sid when it differs.

Vitest covers both update-on-mismatch and no-op-on-match.

Fixes NousResearch#36777
@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists labels Jun 1, 2026

@mxnstrexgl mxnstrexgl left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Automated PR Review

Security Scan

  • ✓ No hardcoded secrets, injection sinks, unsafe deserialization, or dependency red flags found by this automated scan.

Code Quality

  • ✓ No blocking code-quality issues found by this automated scan.

Summary

Status: APPROVE — security findings: 0, quality suggestions: 0.

Automated review; raw diff content intentionally omitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI: session.info event does not update ctx.sid after compression fork

3 participants