mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-05-18 20:08:19 +00:00
feat: WhatsApp AI assistant — provider-agnostic messaging with Gupshup
Provider-agnostic WhatsApp integration for AI-driven appointment booking: - MessagingProvider interface (sendText, sendButtons, sendList, parseInbound) - GupshupProvider implementation (Gupshup WhatsApp API) - MessagingService — AI orchestration with tools (department/doctor/slot lists via interactive WhatsApp messages, appointment booking, caller resolution + context injection) - Redis conversation history (24h TTL, matches WhatsApp session window) - Webhook controller at POST /api/messaging/webhook Swappable to Ozonetel or Meta Cloud API by implementing MessagingProvider and switching MESSAGING_PROVIDER env var. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
41
src/messaging/messaging-conversation.service.ts
Normal file
41
src/messaging/messaging-conversation.service.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import Redis from 'ioredis';
|
||||
import { ConversationEntry } from './types';
|
||||
|
||||
@Injectable()
|
||||
export class MessagingConversationService {
|
||||
private readonly logger = new Logger(MessagingConversationService.name);
|
||||
private readonly redis: Redis;
|
||||
private readonly ttlSec = 24 * 60 * 60; // 24h — matches WhatsApp session window
|
||||
private readonly maxHistory = 20;
|
||||
|
||||
constructor(config: ConfigService) {
|
||||
const redisUrl = config.get<string>('redis.url') ?? 'redis://localhost:6379';
|
||||
this.redis = new Redis(redisUrl);
|
||||
}
|
||||
|
||||
private key(phone: string): string {
|
||||
return `wa:conv:${phone}`;
|
||||
}
|
||||
|
||||
async getHistory(phone: string): Promise<ConversationEntry[]> {
|
||||
const raw = await this.redis.get(this.key(phone));
|
||||
if (!raw) return [];
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async addMessages(phone: string, entries: ConversationEntry[]): Promise<void> {
|
||||
const existing = await this.getHistory(phone);
|
||||
const updated = [...existing, ...entries].slice(-this.maxHistory);
|
||||
await this.redis.setex(this.key(phone), this.ttlSec, JSON.stringify(updated));
|
||||
}
|
||||
|
||||
async clear(phone: string): Promise<void> {
|
||||
await this.redis.del(this.key(phone));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user