- Frontend React (SKEEN Brand) con Vite, TypeScript, Tailwind - Frontend Homenest (versión alternativa) - Módulos Odoo 17 custom (citas, pacientes, monedero, pagos, ventas, inventario, whatsapp) - WACRM fork (Next.js 16 + Supabase) - Hermes + Bridge + Skills (Qwen3.6 via Nan Builders) - Scripts de migración y operación - Documentación extensiva en docs/
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
import type { ChatMessage } from './types'
|
|
import { aiContextMessageLimit } from './defaults'
|
|
|
|
interface DbMessage {
|
|
sender_type: 'customer' | 'agent' | 'bot'
|
|
content_text: string | null
|
|
}
|
|
|
|
/**
|
|
* Fetch the last N text messages of a conversation and map them to the
|
|
* provider-neutral chat shape. Customer messages become `user`; agent
|
|
* and bot messages become `assistant`. Non-text messages (media,
|
|
* templates, interactive) are excluded — they carry no text to model.
|
|
*
|
|
* Ordered oldest-first (chronological) so the transcript reads
|
|
* naturally and the most recent customer message lands last.
|
|
*/
|
|
export async function buildConversationContext(
|
|
db: SupabaseClient,
|
|
conversationId: string,
|
|
limit: number = aiContextMessageLimit(),
|
|
): Promise<ChatMessage[]> {
|
|
const { data, error } = await db
|
|
.from('messages')
|
|
.select('sender_type, content_text')
|
|
.eq('conversation_id', conversationId)
|
|
.eq('content_type', 'text')
|
|
.order('created_at', { ascending: false })
|
|
.limit(limit)
|
|
|
|
if (error) throw error
|
|
|
|
const rows = ((data ?? []) as DbMessage[]).reverse()
|
|
return rows
|
|
.filter((m) => m.content_text && m.content_text.trim())
|
|
.map((m) => ({
|
|
role: m.sender_type === 'customer' ? 'user' : 'assistant',
|
|
content: m.content_text!.trim(),
|
|
}))
|
|
}
|