fix(chat): bootstrap TUI bridge on demand for chat.send + detach on profile switch#73
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two related fixes for the WebSocket chat path, both surfaced by the same
test sequence.
Bug A —
chat.sendsilently drops when the WS connection hasn't seenchat.startyetRepro:
node server.js(cold WS connection,socket.tuiBridge === null)Expected: message routes to the gateway, response streams back.
Actual: nothing happens. User bubble + blinking cursor, but no response, ever. Stop button is also dead.
Cause: PR #68 (1419564) introduced
chat.sendas a lightweight follow-up tochat.start. The handler is gated onsocket.tuiBridge. The frontend (sendViaWebSocket) useswsClient.chatSendwheneversession_idis set — including the first message of a session opened directly from the sidebar. With no priorchat.start,socket.tuiBridge === null, the guard short-circuits, and the message is dropped server-side with no acknowledgement.Fix: drop the
&& socket.tuiBridgegate, bootstrap the bridge in-place (same retry loopchat.startuses), and whenmsg.session_id !== socket.tuiSessionIdroute throughbridge.chatStartso the gateway runssession.resume+prompt.submit(the lightweightbridge.chatSendcan only target sessions already mapped in_sidMap).Frontend changes (
ws-client.js,chat/websocket.js) passprofileonchat.sendso the server knows which gateway port to bootstrap.Bug B — switching profile mid-session spawns a new thread in the wrong profile
Repro (with Bug A fix applied, otherwise can't get this far):
default, start a chattomek)Expected: response streams in the clicked session.
Actual: response arrives, but a new entry appears in the
defaultprofile's session list. Subsequent messages keep spawning fresh threads indefault.Server log shows the smoking gun:
Cause:
chat.startbinds the socket to profile A's bridge subprocess. Switching the dropdown to B and clicking a B-session sendschat.sendwithmsg.profile = "B", butsocket.tuiBridgeis still A. The session_id lookup happens in A's DB, fails, and the bridge's auto-resume fallback inchatStartsilently spawns a new session viasession.create→ new thread in A.Fix: on both
chat.startandchat.send, whensocket.tuiBridge.profile !== msg.profile,removeClientand null out the binding so the nextgetBridge/ bootstrap routes through the right subprocess.Commits
fix(chat): bootstrap TUI bridge on demand for chat.send— Bug Afix(chat): detach prior bridge when WS sees a profile switch— Bug BVerified
Tested locally on top of
main(204e0e5, v3.6.0): both repros eliminated, normal chat flow unaffected. Two separate commits so each fix can be reviewed in isolation.