@@ -26,9 +26,10 @@ func chatKey(channel, accountID, chatID string) string {
2626
2727// processInbound consumes the message bus and routes each message to the
2828// correct user's agent. Identity resolution order:
29- // 1. msg.OwnerUserID set explicitly (cron, webhook with user_id)
30- // 2. lookup the receiving channel's row in the channels table — its
31- // (scope, scope_id) tells us which user owns this conversation
29+ // 1. msg.OwnerUserID set explicitly (cron, webhook with user_id)
30+ // 2. lookup the receiving channel's row in the channels table — its
31+ // (scope, scope_id) tells us which user owns this conversation
32+ //
3233// If neither yields a user_id the message is dropped, never silently
3334// routed to a default identity.
3435func (g * Gateway ) processInbound (ctx context.Context ) {
@@ -135,16 +136,11 @@ func (g *Gateway) resolveChannelOwner(ctx context.Context, msg bus.InboundMessag
135136// - empty UserID → "" (caller leaves the slot empty; chatterUserID will
136137// fall back to the agent owner).
137138// - already `u_`-prefixed → assume it's already canonical, leave alone.
138- // - channel owner is an app_user (has apikey_id) → lazy-mint an
139- // app_user keyed by (apikey_id, "<channel>:<msg.UserID>") so every
140- // distinct IM sender gets a stable u_xxx of their own. Channel name
141- // is prefixed so a numeric id colliding across two channel types
142- // (telegram chat 123, line user 123) can't merge into one row.
143- // - channel owner is a regular user (no apikey_id) → treat as a single-
144- // user dogfood/personal bot and pin the chatter to the owner. This
145- // preserves the simple "I registered my own wechat to my own agent"
146- // flow without forcing the owner to start over with a fresh empty
147- // USER.md every conversation.
139+ // - lazy-mint an app_user keyed by the owner namespace plus
140+ // "<channel>:<accountID>:<msg.UserID>" so every distinct IM sender gets
141+ // a stable u_xxx of their own. Channel and account are prefixed so the
142+ // same numeric id on two platforms or two bots cannot merge into one
143+ // USER.md / MEMORY.md row.
148144//
149145// Returns "" when the original msg.UserID should be kept unchanged
150146// (empty input, already canonical, or any error path) — the caller treats
@@ -165,16 +161,15 @@ func (g *Gateway) resolveChatter(ctx context.Context, ownerID string, msg bus.In
165161 "owner" , ownerID , "channel" , msg .Channel , "error" , err )
166162 return ""
167163 }
168- if owner .APIKeyID == "" {
169- // Personal / dogfood install — every IM sender is treated as the
170- // channel owner so the operator's own USER.md applies.
171- return ownerID
164+ namespace := owner .APIKeyID
165+ if namespace == "" {
166+ namespace = "owner:" + ownerID
172167 }
173- extID := msg .Channel + ":" + msg .UserID
174- acc , err := g .accounts .EnsureAppUser (ctx , owner . APIKeyID , extID , "" )
168+ extID := msg .Channel + ":" + msg .AccountID + ":" + msg . UserID
169+ acc , err := g .accounts .EnsureAppUser (ctx , namespace , extID , msg . SenderName )
175170 if err != nil {
176171 slog .Warn ("resolveChatter: EnsureAppUser failed" ,
177- "apikey " , owner . APIKeyID , "ext" , extID , "error" , err )
172+ "owner " , ownerID , "namespace" , namespace , "ext" , extID , "error" , err )
178173 return ""
179174 }
180175 return acc .ID
0 commit comments