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.
|
* Map a Fabric channel xType to an openclaw routing peer.kind / ChatType.
|
||||||
*
|
*
|
||||||
* Fabric distinguishes channels by xType ('dm' | 'triage' | 'group' |
|
* Fabric distinguishes channels by xType ('dm' | 'triage' | 'group' |
|
||||||
* 'broadcast' | 'announce' | ...). Openclaw's session router only knows
|
* 'broadcast' | 'announce' | ...). This maps each to:
|
||||||
* 'direct' | 'group' | 'channel'. We collapse:
|
* - peerKind — openclaw's SESSION router key ('direct' | 'group')
|
||||||
* - 'dm' → 'direct' (1:1 conversation; agent always speaks)
|
* - chatType — ctx.ChatType the agent sees (drives isDirectMessage etc.)
|
||||||
* - rest → 'group' (multi-party; turn-engine gates speech)
|
|
||||||
*
|
*
|
||||||
* Sessions are keyed by peer.kind, so inbound and outbound MUST agree —
|
* CRITICAL: peerKind for 'dm' is 'group', NOT 'direct'. Openclaw routes
|
||||||
* otherwise the agent's outbound message lands in a different session
|
* peer.kind==='direct' through `session.dmScope` (default "main"), which
|
||||||
* than the inbound that triggered it and conversation state splits.
|
* 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
|
* Sessions are keyed by peerKind, so inbound and outbound MUST agree.
|
||||||
* it consults the channel-meta cache populated by inbound. Cache miss
|
* Both now resolve 'dm' (and the cold-cache fallback) to 'group', so they
|
||||||
* (channel never observed) falls back to 'group' — same as the pre-fix
|
* never split.
|
||||||
* 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'.
|
|
||||||
*/
|
*/
|
||||||
export type FabricPeerRouting = { peerKind: 'direct' | 'group'; chatType: 'direct' | 'group' };
|
export type FabricPeerRouting = { peerKind: 'direct' | 'group'; chatType: 'direct' | 'group' };
|
||||||
|
|
||||||
export function fabricPeerRoutingForXType(xType: string | null | undefined): FabricPeerRouting {
|
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' };
|
return { peerKind: 'group', chatType: 'group' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user