feat: enrich AI stream with replyToMessageId, sourceGroupName, organizationId + tenant/source filters
- Extract quotedPlatformMsgId from Baileys contextInfo.stanzaId in normalizer - Thread quotedPlatformMsgId through IngestJobData → ingest processor → Message record - Widen ingest processor group/tenant selects to include name and organizationId - Add replyToMessageId, sourceGroupName, organizationId to StreamMessagePayload and XADD - Update StreamRecord, parseFields, and streamMessages in AI stream service with new fields - Add optional ?tenant= and ?source= SSE filters; cursor advances for filtered entries so Last-Event-ID resume remains accurate across reconnects Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,9 @@ interface StreamRecord {
|
||||
senderJid: string;
|
||||
senderName: string | null;
|
||||
sourceGroupId: string;
|
||||
sourceGroupName: string | null;
|
||||
organizationId: string | null;
|
||||
replyToMessageId: string | null;
|
||||
tags: string[];
|
||||
effectiveAction: string | null;
|
||||
traceId: string | null;
|
||||
@@ -46,7 +49,7 @@ export class AiStreamService {
|
||||
* '0' → replay the entire retained stream (~50k messages) then follow live
|
||||
* '<id>' → resume strictly after that entry (used on reconnect)
|
||||
*/
|
||||
streamMessages(afterId: string): Observable<MessageEvent> {
|
||||
streamMessages(afterId: string, filters?: { tenantId?: string; sourceGroupId?: string }): Observable<MessageEvent> {
|
||||
return new Observable<MessageEvent>((subscriber) => {
|
||||
const redis = new Redis(this.redisUrl, { maxRetriesPerRequest: null });
|
||||
let active = true;
|
||||
@@ -70,8 +73,11 @@ export class AiStreamService {
|
||||
|
||||
for (const [, entries] of res) {
|
||||
for (const [id, fields] of entries) {
|
||||
const record = parseFields(fields);
|
||||
cursor = id;
|
||||
subscriber.next({ id, data: parseFields(fields) } as MessageEvent);
|
||||
if (filters?.tenantId && record.tenantId !== filters.tenantId) continue;
|
||||
if (filters?.sourceGroupId && record.sourceGroupId !== filters.sourceGroupId) continue;
|
||||
subscriber.next({ id, data: record } as MessageEvent);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -142,6 +148,9 @@ function parseFields(fields: string[]): StreamRecord {
|
||||
senderJid: obj.senderJid ?? '',
|
||||
senderName: obj.senderName || null,
|
||||
sourceGroupId: obj.sourceGroupId ?? '',
|
||||
sourceGroupName: obj.sourceGroupName || null,
|
||||
organizationId: obj.organizationId || null,
|
||||
replyToMessageId: obj.replyToMessageId || null,
|
||||
tags,
|
||||
effectiveAction: obj.effectiveAction || null,
|
||||
traceId: obj.traceId || null,
|
||||
|
||||
Reference in New Issue
Block a user