#17527: fix(gateway): allow WebChat to attach to main session regardless of deliveryContext channel
size: S
experienced-contributor
Cluster:
Network Error Handling Improvements
Fixes #15189
## Problem
When WebChat connects to the main session, `recordInboundSession` updates the session's `lastChannel` and `deliveryContext` fields to `webchat`. This breaks announce, heartbeat, and cron delivery because those systems route replies through `deliveryContext` — and WebChat uses WebSocket, not deliveryContext routing.
**Example:** User chats via Telegram, opens WebChat to check something, and suddenly all cron/heartbeat announcements try to route through `webchat` (which has no external delivery path) instead of Telegram.
## Fix
Skip the `updateLastRoute` call when the inbound channel is an internal message channel (WebChat). The existing `isInternalMessageChannel()` utility already identifies these channels — we just gate the route update behind it.
### Changed files
- **`src/channels/session.ts`** — Early return before `updateLastRoute` when channel is internal (8 lines)
- **`src/channels/session.test.ts`** — New test file with 2 cases: WebChat preserves existing delivery context; external channels update normally (125 lines)
## Tests
```
✓ src/channels/session.test.ts (2 tests)
✓ skips updateLastRoute when channel is webchat (internal)
✓ updates lastRoute normally for external channels
```
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a bug where WebChat connections to the main session would overwrite the session's `deliveryContext` and `lastChannel` to "webchat", breaking announce/heartbeat/cron delivery for the external channel (e.g., Telegram) that actually owns the conversation. The fix adds an early return in `recordInboundSession` that skips the `updateLastRoute` call when the inbound channel is an internal message channel (webchat), using the existing `isInternalMessageChannel()` utility.
- **`src/channels/session.ts`**: Gates `updateLastRoute` behind `isInternalMessageChannel()` check — webchat skips route updates while still recording session metadata via `recordSessionMetaFromInbound`
- **`src/channels/session.test.ts`**: New test file with two integration tests verifying webchat preserves existing delivery context and external channels update normally
- Minor: unused `vi` import in the test file
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it's a targeted, well-scoped bug fix with proper test coverage
- The change is minimal (one guard clause using an existing utility), correctly addresses a real routing bug, and has two passing integration tests covering both the fix and the happy path. The fix is applied at the right layer — `recordSessionMetaFromInbound` (origin metadata) is still called, only `updateLastRoute` (delivery routing) is skipped for internal channels. No risk of regression for external channels.
- No files require special attention
<sub>Last reviewed commit: cb87e1e</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#17337: fix(delivery): keep route fields paired to channel during context m...
by Glucksberg · 2026-02-15
83.1%
#13580: fix(telegram): skip updateLastRoute when dmScope isolates DM sessions
by lailoo · 2026-02-10
82.7%
#18694: fix(ui): reset session key to main after /new in webchat
by Phineas1500 · 2026-02-17
81.7%
#11123: Fix webchat→external channel cross-delivery
by jingkang0822 · 2026-02-07
81.4%
#6850: fix: support direct channel:account:peer format in session key extr...
by toboto · 2026-02-02
80.7%
#22469: fix(gateway): avoid stale whatsapp labels on direct sessions
by loganprit · 2026-02-21
80.4%
#3182: fix(gateway): use canonical session key in chat.send
by chrisherold · 2026-01-28
78.7%
#5391: fix(commands): prevent webchat/tui from inheriting messaging channe...
by Glucksberg · 2026-01-31
78.6%
#18232: fix: webchat rapid messages create orphan sessions
by MisterGuy420 · 2026-02-16
78.4%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
78.1%