Compare commits
1 Commits
feat/fabri
...
fix/fabric
| Author | SHA1 | Date | |
|---|---|---|---|
| a0b280541c |
@@ -27,27 +27,31 @@ import { getChannelType } from './channel-meta.js';
|
||||
* Map a Fabric channel xType to an openclaw routing peer.kind / ChatType.
|
||||
*
|
||||
* Fabric distinguishes channels by xType ('dm' | 'triage' | 'group' |
|
||||
* 'broadcast' | 'announce' | ...). Openclaw's session router only knows
|
||||
* 'direct' | 'group' | 'channel'. We collapse:
|
||||
* - 'dm' → 'direct' (1:1 conversation; agent always speaks)
|
||||
* - rest → 'group' (multi-party; turn-engine gates speech)
|
||||
* 'broadcast' | 'announce' | ...). This maps each to:
|
||||
* - peerKind — openclaw's SESSION router key ('direct' | 'group')
|
||||
* - chatType — ctx.ChatType the agent sees (drives isDirectMessage etc.)
|
||||
*
|
||||
* Sessions are keyed by peer.kind, so inbound and outbound MUST agree —
|
||||
* otherwise the agent's outbound message lands in a different session
|
||||
* than the inbound that triggered it and conversation state splits.
|
||||
* CRITICAL: peerKind for 'dm' is 'group', NOT 'direct'. Openclaw routes
|
||||
* peer.kind==='direct' through `session.dmScope` (default "main"), which
|
||||
* collapses EVERY direct conversation into the agent's single `:main`
|
||||
* session. Fabric, however, supports many independent DM channels for the
|
||||
* same pair of users — each must get its own openclaw session, or they all
|
||||
* pile into `:main` and share context (a recruiter DM'd on channel A would
|
||||
* see channel B's history, and never opens a fresh linear journal per DM).
|
||||
* Routing 'dm' as peerKind='group' keys the session by channelId
|
||||
* (`agent:<id>:fabric:group:<chan>`) — one session per DM channel — while
|
||||
* chatType='direct' preserves 1:1 semantics (agent always speaks; the
|
||||
* inbound no-wakeup-gating exception keys off xType==='dm', not chatType).
|
||||
*
|
||||
* Outbound has no live xType (the agent target is just a channelId), so
|
||||
* it consults the channel-meta cache populated by inbound. Cache miss
|
||||
* (channel never observed) falls back to 'group' — same as the pre-fix
|
||||
* behavior, no regression on cold cache. The proactive-DM-first-message
|
||||
* edge case (agent DMs a channel before any inbound) still lands as
|
||||
* 'group' on that one outbound; the next inbound + outbound pair will
|
||||
* agree on 'direct'.
|
||||
* Sessions are keyed by peerKind, so inbound and outbound MUST agree.
|
||||
* Both now resolve 'dm' (and the cold-cache fallback) to 'group', so they
|
||||
* never split.
|
||||
*/
|
||||
export type FabricPeerRouting = { peerKind: 'direct' | 'group'; chatType: 'direct' | 'group' };
|
||||
|
||||
export function fabricPeerRoutingForXType(xType: string | null | undefined): FabricPeerRouting {
|
||||
if (xType === 'dm') return { peerKind: 'direct', chatType: 'direct' };
|
||||
// dm → group session routing (per-channel), but direct chat semantics.
|
||||
if (xType === 'dm') return { peerKind: 'group', chatType: 'direct' };
|
||||
return { peerKind: 'group', chatType: 'group' };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user