fix(desktop): route bot-chat RPCs to the bot's own gateway via tile ownerRoute - #92956
Merged
Merged
Conversation
…wnerRoute The real fix for Bot Mode 'session not found' / endless hang: dispatch session-scoped RPCs on the OWNING profile's local gateway, using the route the chat tile already carries — the same multi-connection machinery Sessions mode uses, which has never had this problem. Root cause chain: - A bot chat is a persisted tile that records its exact owner (connectionId + profile) in tile.ownerRoute; requestForSessionProfile already dispatches on any (connectionId, profile) via the per-profile local gateway pool. - But wiring's requestGateway resolved the owner via rememberedSessionProfile, a $sessions row lookup. Canonical Bot Chats are born hidden (never listed), so the lookup missed and fell back to the ACTIVE profile -> prompt.submit hit the launch backend that never owned the session -> 4001, and the resume ladder re-resolved through the same blind spot, so it hung. - It also keyed off $selectedStoredSessionId, but a bot chat renders in a TILE whose id is $focusedStoredSessionId (selected stays the primary pane), so even the row path was reading the wrong session. Fix: - wiring requestGateway: resolve owner from the FOCUSED stored id, preferring the tile's persisted ownerRoute; fall back to the list-derived profile only when no tile route exists. One resolver, every session RPC (submit, resume, attach, interrupt, compress) inherits it. - sdk openSession: synthesize a local ownerRoute from for bot opens that carry no explicit cross-connection route, so LOCAL bot tiles carry their owner too (previously only remote routes did). Strictly routing metadata: the dial path, all-profiles view, and the route-registry retry check all still key off the EXPLICIT route, so a plain local open behaves exactly as before (no registry-secondary dial, no forced all-profiles view). Fixes already-open chats (tile route is persisted, needs no fresh open) and survives relaunch. 3 tests for sessionTileOwnerRoute. tsc 0 errors.
Contributor
૮ >ﻌ< ა ci reviewran on f701aab — fix(desktop): route bot-chat RPCs to the bot's own gateway v
|
2 tasks
This was referenced Aug 23, 2026
Merged
This was referenced Aug 27, 2026
melon-xf
added a commit
to melon-xf/hermes-agent
that referenced
this pull request
Sep 3, 2026
…wnerRoute (NousResearch#92956) The real fix for Bot Mode 'session not found' / endless hang: dispatch session-scoped RPCs on the OWNING profile's local gateway, using the route the chat tile already carries — the same multi-connection machinery Sessions mode uses, which has never had this problem. Root cause chain: - A bot chat is a persisted tile that records its exact owner (connectionId + profile) in tile.ownerRoute; requestForSessionProfile already dispatches on any (connectionId, profile) via the per-profile local gateway pool. - But wiring's requestGateway resolved the owner via rememberedSessionProfile, a $sessions row lookup. Canonical Bot Chats are born hidden (never listed), so the lookup missed and fell back to the ACTIVE profile -> prompt.submit hit the launch backend that never owned the session -> 4001, and the resume ladder re-resolved through the same blind spot, so it hung. - It also keyed off $selectedStoredSessionId, but a bot chat renders in a TILE whose id is $focusedStoredSessionId (selected stays the primary pane), so even the row path was reading the wrong session. Fix: - wiring requestGateway: resolve owner from the FOCUSED stored id, preferring the tile's persisted ownerRoute; fall back to the list-derived profile only when no tile route exists. One resolver, every session RPC (submit, resume, attach, interrupt, compress) inherits it. - sdk openSession: synthesize a local ownerRoute from for bot opens that carry no explicit cross-connection route, so LOCAL bot tiles carry their owner too (previously only remote routes did). Strictly routing metadata: the dial path, all-profiles view, and the route-registry retry check all still key off the EXPLICIT route, so a plain local open behaves exactly as before (no registry-secondary dial, no forced all-profiles view). Fixes already-open chats (tile route is persisted, needs no fresh open) and survives relaunch. 3 tests for sessionTileOwnerRoute. tsc 0 errors. Co-authored-by: Teknium <teknium1@users.noreply.github.com>
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.
The real fix
Chatting with any Bot Mode bot except the launch profile failed with "session not found" (4001), then hung endlessly on retry. This dispatches each bot chat's RPCs on that bot's own local gateway — the same per-profile connection pool Sessions mode already uses without issue. No new architecture: the multi-connection machinery exists; the bots path just wasn't using it.
Root cause (traced end-to-end in live logs + source)
connectionId+profile) intile.ownerRoute.requestForSessionProfilealready dispatches on any(connectionId, profile)via the per-profile local gateway.requestGatewayresolved the owner viarememberedSessionProfile, a$sessionsrow lookup. Canonical Bot Chats are born hidden (never listed), so the lookup missed and fell back to the active profile →prompt.submithit the launch backend that never owned the session → 4001. ThewithSessionNotFoundResumeladder re-resolved through the same blind spot, so it re-registered the wrong backend and hung.$selectedStoredSessionId, but a bot chat renders in a tile whose id is$focusedStoredSessionId(selected stays the primary pane) — so even the row path was reading the wrong session id.Log fingerprint (user's machine): the bot backend shows
ws accepted … ws closed messages=0with notui prompt accepted, while the launch backend logs the bot's session id running a turn that never finishes.Fix
wiring.tsxrequestGateway: resolve owner from the focused stored id, preferring the tile's persistedownerRoute; fall back to the list-derived profile only when no tile route exists. One resolver — submit, resume, attach, interrupt, compress all inherit it.sdk/index.tsopenSession: synthesize a localownerRoutefromprofilefor bot opens with no explicit cross-connection route, so local bot tiles carry their owner too (previously only remote routes did). Strictly routing metadata — the dial path, all-profiles view, and route-registry retry check all still key off the explicit route, so a plain local open behaves exactly as before (no registry-secondary dial, no forced all-profiles view).Why this fixes the current stuck chats
The tile
ownerRouteis persisted and needs no list membership, so it works for chats already open across a rebuild/relaunch — not just freshly opened ones. That was the gap the prior PR (#92928, in-memory owner hints) couldn't cover.Verification
tsc --noEmit: 0 errors.sessionTileOwnerRoute(bot tile route returned; no-route tile → undefined; no tile → undefined).