#21955: fix(line): remove redundant group:/room: prefix from buildPeerId (#21907)
docs
size: S
experienced-contributor
Cluster:
Feishu Messaging Fixes
## Summary
- **Bug**: LINE `buildPeerId` adds redundant `group:`/`room:` prefix to peer IDs, breaking binding route matching.
- **Root cause**: `buildPeerId()` in `src/line/bot-message-context.ts` prepends `group:` to `source.groupId` and `room:` to `source.roomId`, but `matchesBindingScope()` compares peer IDs as raw strings — the binding's `peer.id` never matches the prefixed runtime value.
- **Fix**: Return raw `source.groupId`/`source.roomId` from `buildPeerId()` without prefix.
Fixes #21907
## Problem
`buildPeerId()` returns `group:${source.groupId}` for group messages. This value is passed as `peer.id` to `resolveAgentRoute()`. The binding system does strict string comparison in `matchesBindingScope()`:
```
scope.peer.id !== match.peer.id
```
- Runtime peer.id: `group:cc7e3bece...` (with prefix)
- Binding peer.id: `cc7e3bece...` (raw, as configured by user)
- Result: no match → falls through to default agent
**Before fix:**
```
Input: source.groupId = "Cc7e3bece1234567890abcdef"
Output: peer.id = "group:Cc7e3bece1234567890abcdef"
Route: agentId = "main" (default, binding not matched)
Session key: agent:main:line:group:group:cc7e3bece... (double prefix)
```
## Changes
- `src/line/bot-message-context.ts` — Remove `group:`/`room:` prefix from `buildPeerId()`, return raw IDs
**After fix:**
```
Input: source.groupId = "Cc7e3bece1234567890abcdef"
Output: peer.id = "Cc7e3bece1234567890abcdef"
Route: agentId = "line-group-agent" (binding matched)
Session key: agent:line-group-agent:line:group:cc7e3bece... (correct)
```
## Test plan
- [x] New test: group peer binding matches raw groupId without prefix
- [x] New test: room peer binding matches raw roomId without prefix
- [x] All 4 existing `bot-message-context` tests pass
- [x] Format and lint pass
## Effect on User Experience
**Before:** LINE group/room messages always route to the default agent, ignoring peer-based bindings.
**After:** LINE group/room messages correctly route to the agent specified in peer-based bindings.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a bug where LINE group and room messages always routed to the default agent because `buildPeerId()` was prepending `group:` and `room:` prefixes that didn't match user-configured binding peer IDs.
**Key changes:**
- Removed `group:` and `room:` prefixes from `buildPeerId()` return values in `src/line/bot-message-context.ts:52-57`
- Added comprehensive test coverage for both group and room peer binding scenarios
- Updated CHANGELOG.md with clear description of the fix
**How it works:**
The binding system in `matchesBindingScope()` (`src/routing/resolve-route.ts:274`) performs strict string comparison between `scope.peer.id` and `match.peer.id`. Previously, `buildPeerId()` returned prefixed values like `group:Cc7e3bece...` while user bindings contained raw IDs like `Cc7e3bece...`, causing mismatches. The fix returns raw IDs directly.
**Impact verification:**
- The `line:group:` and `line:room:` prefixes are still correctly added in `resolveLineAddresses()` (`src/line/bot-message-context.ts:201-203`) for message addresses
- The `send.ts` normalizer already strips these prefixes when processing targets (`src/line/send.ts:43-44`)
- Existing tests for group routing still pass, verifying addresses remain correct
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge - it's a focused bug fix with comprehensive test coverage
- The fix is surgical and well-tested: removes only the problematic prefixes from `buildPeerId()` (2 lines changed), adds 2 new tests covering both group and room scenarios, and all existing tests pass. The addresses/session keys in other parts of the codebase correctly retain their `line:group:` and `line:room:` prefixes, so no side effects are expected
- No files require special attention
<sub>Last reviewed commit: b14538c</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#10309: fix: use group ID for peer.id in Feishu group messages
by ParsifalC · 2026-02-06
82.0%
#14888: fix(routing): normalize peer.kind in matchesPeer for symmetric comp...
by omair445 · 2026-02-12
77.0%
#23656: fix(routing): trust binding agentId even when not in agents.list
by SleuthCo · 2026-02-22
75.1%
#22757: fix(routing): normalize input peer.kind in resolveAgentRoute
by miloudbelarebia · 2026-02-21
75.1%
#7224: feat(telegram): inherit forum topic bindings from parent group
by Buywatermelon · 2026-02-02
74.6%
#15982: fix: pass agentId to resolveSessionFilePath in reply flow (NX-003)
by automagik-genie · 2026-02-14
74.5%
#18664: fix(imessage): honor groupConfig regardless of allowlistEnabled
by brandonwise · 2026-02-16
73.8%
#9437: fix: normalize accountId in binding matching for consistent routing
by dbottme · 2026-02-05
73.6%
#13580: fix(telegram): skip updateLastRoute when dmScope isolates DM sessions
by lailoo · 2026-02-10
73.2%
#16249: fix(sessions): allow cross-agent session paths in multi-agent bindings
by 0xbrak · 2026-02-14
73.2%