|
@@ -13,6 +13,12 @@ import {
|
|
|
isVapiConfigured,
|
|
isVapiConfigured,
|
|
|
VapiAssistantConfig
|
|
VapiAssistantConfig
|
|
|
} from './vapi-client.ts'
|
|
} from './vapi-client.ts'
|
|
|
|
|
+import {
|
|
|
|
|
+ loadSystemPrompt,
|
|
|
|
|
+ loadStoreBusinessHours,
|
|
|
|
|
+ loadStoreSpecialHours,
|
|
|
|
|
+ buildCompleteSystemPrompt
|
|
|
|
|
+} from './prompt-utils.ts'
|
|
|
|
|
|
|
|
export interface VapiSetupResult {
|
|
export interface VapiSetupResult {
|
|
|
success: boolean
|
|
success: boolean
|
|
@@ -27,9 +33,27 @@ export interface VapiUpdateResult {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Default greeting message template
|
|
|
|
|
|
|
+ * Default language code used when integrating webshops
|
|
|
|
|
+ */
|
|
|
|
|
+const DEFAULT_LANGUAGE_CODE = 'hu'
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Load default greeting message from database
|
|
|
|
|
+ * Falls back to hardcoded message if not found
|
|
|
*/
|
|
*/
|
|
|
-function getDefaultGreetingMessage(storeName: string): string {
|
|
|
|
|
|
|
+async function loadDefaultGreetingMessage(
|
|
|
|
|
+ supabase: SupabaseClient,
|
|
|
|
|
+ storeName: string,
|
|
|
|
|
+ languageCode: string = DEFAULT_LANGUAGE_CODE
|
|
|
|
|
+): Promise<string> {
|
|
|
|
|
+ const prompts = await loadSystemPrompt(supabase, languageCode)
|
|
|
|
|
+
|
|
|
|
|
+ if (prompts?.greetingMessage) {
|
|
|
|
|
+ // Replace ${storeName} placeholder in greeting
|
|
|
|
|
+ return prompts.greetingMessage.replace(/\$\{storeName\}/g, storeName)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Fallback to hardcoded message
|
|
|
return `Üdvözlöm! A ${storeName} ügyfélszolgálata vagyok. Miben segíthetek?`
|
|
return `Üdvözlöm! A ${storeName} ügyfélszolgálata vagyok. Miben segíthetek?`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -68,8 +92,8 @@ async function pickRandomVoice(
|
|
|
* This function:
|
|
* This function:
|
|
|
* 1. Picks a random enabled voice from the database (or uses existing ai_config)
|
|
* 1. Picks a random enabled voice from the database (or uses existing ai_config)
|
|
|
* 2. Creates a default greeting message (or uses existing ai_config)
|
|
* 2. Creates a default greeting message (or uses existing ai_config)
|
|
|
- * 3. Registers the phone number with VAPI
|
|
|
|
|
- * 4. Creates a VAPI assistant
|
|
|
|
|
|
|
+ * 3. Creates a VAPI assistant
|
|
|
|
|
+ * 4. Registers the phone number with VAPI (with assistantId to link them)
|
|
|
* 5. Updates the store's alt_data with VAPI IDs and ai_config
|
|
* 5. Updates the store's alt_data with VAPI IDs and ai_config
|
|
|
*
|
|
*
|
|
|
* @param supabase - Supabase client (with service role for admin operations)
|
|
* @param supabase - Supabase client (with service role for admin operations)
|
|
@@ -92,7 +116,7 @@ export async function setupVapiForStore(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // First, check if store already has ai_config with voice_type
|
|
|
|
|
|
|
+ // First, check if store already has ai_config
|
|
|
const { data: storeData } = await supabase
|
|
const { data: storeData } = await supabase
|
|
|
.from('stores')
|
|
.from('stores')
|
|
|
.select('alt_data')
|
|
.select('alt_data')
|
|
@@ -102,14 +126,36 @@ export async function setupVapiForStore(
|
|
|
const existingAiConfig = storeData?.alt_data?.ai_config
|
|
const existingAiConfig = storeData?.alt_data?.ai_config
|
|
|
let voiceId: string
|
|
let voiceId: string
|
|
|
let greetingMessage: string
|
|
let greetingMessage: string
|
|
|
|
|
+ const languageCode = existingAiConfig?.language_code || DEFAULT_LANGUAGE_CODE
|
|
|
|
|
+
|
|
|
|
|
+ // Step 1: Load base system prompt from database
|
|
|
|
|
+ console.log(`[VAPI Setup] Loading system prompt for language: ${languageCode}`)
|
|
|
|
|
+ const promptData = await loadSystemPrompt(supabase, languageCode)
|
|
|
|
|
+ if (!promptData?.systemPrompt) {
|
|
|
|
|
+ const error = `Failed to load system prompt for language: ${languageCode}`
|
|
|
|
|
+ console.error(`[VAPI Setup] ${error}`)
|
|
|
|
|
+ await updateStoreWithError(supabase, storeId, error)
|
|
|
|
|
+ return { success: false, error }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Step 2: Use existing greeting from DB if available, otherwise use default from database
|
|
|
|
|
+ if (existingAiConfig?.greeting_message) {
|
|
|
|
|
+ greetingMessage = existingAiConfig.greeting_message
|
|
|
|
|
+ console.log(`[VAPI Setup] Using existing greeting from store config: ${storeId}`)
|
|
|
|
|
+ } else if (promptData.greetingMessage) {
|
|
|
|
|
+ // Replace ${storeName} placeholder in greeting from DB
|
|
|
|
|
+ greetingMessage = promptData.greetingMessage.replace(/\$\{storeName\}/g, storeName)
|
|
|
|
|
+ console.log(`[VAPI Setup] Using default greeting from database for store: ${storeId}`)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ greetingMessage = `Üdvözlöm! A ${storeName} ügyfélszolgálata vagyok. Miben segíthetek?`
|
|
|
|
|
+ console.log(`[VAPI Setup] Using hardcoded fallback greeting for store: ${storeId}`)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ // Step 3: Use existing voice if available, otherwise pick random
|
|
|
if (existingAiConfig?.voice_type) {
|
|
if (existingAiConfig?.voice_type) {
|
|
|
- // Use existing ai_config
|
|
|
|
|
- console.log(`[VAPI Setup] Using existing ai_config for store: ${storeId}`)
|
|
|
|
|
voiceId = existingAiConfig.voice_type
|
|
voiceId = existingAiConfig.voice_type
|
|
|
- greetingMessage = existingAiConfig.greeting_message || getDefaultGreetingMessage(storeName)
|
|
|
|
|
|
|
+ console.log(`[VAPI Setup] Using existing voice from DB: ${voiceId}`)
|
|
|
} else {
|
|
} else {
|
|
|
- // Step 1: Pick a random voice
|
|
|
|
|
const voiceResult = await pickRandomVoice(supabase)
|
|
const voiceResult = await pickRandomVoice(supabase)
|
|
|
if (!voiceResult) {
|
|
if (!voiceResult) {
|
|
|
const error = 'Failed to pick a voice from database'
|
|
const error = 'Failed to pick a voice from database'
|
|
@@ -117,53 +163,71 @@ export async function setupVapiForStore(
|
|
|
return { success: false, error }
|
|
return { success: false, error }
|
|
|
}
|
|
}
|
|
|
voiceId = voiceResult.voiceId
|
|
voiceId = voiceResult.voiceId
|
|
|
-
|
|
|
|
|
- // Step 2: Create default greeting
|
|
|
|
|
- greetingMessage = getDefaultGreetingMessage(storeName)
|
|
|
|
|
|
|
+ console.log(`[VAPI Setup] Picked random voice: ${voiceId}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Step 3: Register phone number with VAPI
|
|
|
|
|
- console.log(`[VAPI Setup] Registering phone number: ${phoneNumber}`)
|
|
|
|
|
- const phoneResult = await registerPhoneNumber(phoneNumber, storeName)
|
|
|
|
|
|
|
+ // Step 4: Load business hours and special hours for opening hours section
|
|
|
|
|
+ console.log(`[VAPI Setup] Loading business hours for store: ${storeId}`)
|
|
|
|
|
+ const { businessHours, isEnabled: hoursEnabled } = await loadStoreBusinessHours(supabase, storeId)
|
|
|
|
|
+ const specialHours = await loadStoreSpecialHours(supabase, storeId)
|
|
|
|
|
+ const transferPhoneNumber = existingAiConfig?.transfer_phone_number || null
|
|
|
|
|
|
|
|
- if (!phoneResult.success) {
|
|
|
|
|
- const error = `Failed to register phone number: ${phoneResult.error}`
|
|
|
|
|
- await updateStoreWithError(supabase, storeId, error)
|
|
|
|
|
- return { success: false, error }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Step 5: Build complete system prompt with opening hours
|
|
|
|
|
+ // When business hours are disabled, also hide special hours and transfer phone
|
|
|
|
|
+ const systemPrompt = buildCompleteSystemPrompt(
|
|
|
|
|
+ promptData.systemPrompt,
|
|
|
|
|
+ storeName,
|
|
|
|
|
+ storeId,
|
|
|
|
|
+ hoursEnabled ? businessHours : null,
|
|
|
|
|
+ hoursEnabled ? specialHours : null, // Hide special hours when business hours disabled
|
|
|
|
|
+ languageCode,
|
|
|
|
|
+ hoursEnabled ? transferPhoneNumber : null // Hide transfer phone when business hours disabled
|
|
|
|
|
+ )
|
|
|
|
|
+ console.log(`[VAPI Setup] Built system prompt (${systemPrompt.length} chars), hours enabled: ${hoursEnabled}`)
|
|
|
|
|
|
|
|
- // Step 4: Create VAPI assistant
|
|
|
|
|
|
|
+ // Step 6: Create VAPI assistant first (we need the ID for phone number registration)
|
|
|
console.log(`[VAPI Setup] Creating assistant for store: ${storeName}`)
|
|
console.log(`[VAPI Setup] Creating assistant for store: ${storeName}`)
|
|
|
const assistantConfig: VapiAssistantConfig = {
|
|
const assistantConfig: VapiAssistantConfig = {
|
|
|
storeName,
|
|
storeName,
|
|
|
storeId,
|
|
storeId,
|
|
|
voiceId,
|
|
voiceId,
|
|
|
greetingMessage,
|
|
greetingMessage,
|
|
|
- phoneNumberId: phoneResult.phoneNumberId
|
|
|
|
|
|
|
+ systemPrompt,
|
|
|
|
|
+ languageCode
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const assistantResult = await createAssistant(assistantConfig)
|
|
const assistantResult = await createAssistant(assistantConfig)
|
|
|
|
|
|
|
|
if (!assistantResult.success) {
|
|
if (!assistantResult.success) {
|
|
|
const error = `Failed to create assistant: ${assistantResult.error}`
|
|
const error = `Failed to create assistant: ${assistantResult.error}`
|
|
|
- // Still store the phone number ID even if assistant creation fails
|
|
|
|
|
|
|
+ await updateStoreWithError(supabase, storeId, error)
|
|
|
|
|
+ return { success: false, error }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Step 7: Register phone number with VAPI (with assistantId to link them)
|
|
|
|
|
+ console.log(`[VAPI Setup] Registering phone number: ${phoneNumber} with assistant: ${assistantResult.assistantId}`)
|
|
|
|
|
+ const phoneResult = await registerPhoneNumber(phoneNumber, storeName, assistantResult.assistantId)
|
|
|
|
|
+
|
|
|
|
|
+ if (!phoneResult.success) {
|
|
|
|
|
+ const error = `Failed to register phone number: ${phoneResult.error}`
|
|
|
|
|
+ // Still store the assistant ID even if phone registration fails
|
|
|
await updateStoreWithPartialSuccess(
|
|
await updateStoreWithPartialSuccess(
|
|
|
supabase,
|
|
supabase,
|
|
|
storeId,
|
|
storeId,
|
|
|
- phoneResult.phoneNumberId!,
|
|
|
|
|
null,
|
|
null,
|
|
|
|
|
+ assistantResult.assistantId!,
|
|
|
voiceId,
|
|
voiceId,
|
|
|
greetingMessage,
|
|
greetingMessage,
|
|
|
error
|
|
error
|
|
|
)
|
|
)
|
|
|
return {
|
|
return {
|
|
|
success: false,
|
|
success: false,
|
|
|
- vapiPhoneNumberId: phoneResult.phoneNumberId,
|
|
|
|
|
|
|
+ vapiAssistantId: assistantResult.assistantId,
|
|
|
error
|
|
error
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Step 5: Update store with VAPI IDs and ai_config
|
|
|
|
|
|
|
+ // Step 8: Update store with VAPI IDs and ai_config
|
|
|
console.log(`[VAPI Setup] Updating store with VAPI IDs`)
|
|
console.log(`[VAPI Setup] Updating store with VAPI IDs`)
|
|
|
await updateStoreWithSuccess(
|
|
await updateStoreWithSuccess(
|
|
|
supabase,
|
|
supabase,
|
|
@@ -236,12 +300,12 @@ async function updateStoreWithSuccess(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Update store alt_data with partial success (phone registered but assistant failed)
|
|
|
|
|
|
|
+ * Update store alt_data with partial success (one of phone/assistant failed)
|
|
|
*/
|
|
*/
|
|
|
async function updateStoreWithPartialSuccess(
|
|
async function updateStoreWithPartialSuccess(
|
|
|
supabase: SupabaseClient,
|
|
supabase: SupabaseClient,
|
|
|
storeId: string,
|
|
storeId: string,
|
|
|
- vapiPhoneNumberId: string,
|
|
|
|
|
|
|
+ vapiPhoneNumberId: string | null,
|
|
|
vapiAssistantId: string | null,
|
|
vapiAssistantId: string | null,
|
|
|
voiceId: string,
|
|
voiceId: string,
|
|
|
greetingMessage: string,
|
|
greetingMessage: string,
|
|
@@ -328,14 +392,16 @@ async function updateStoreWithError(
|
|
|
* @param storeId - The store UUID
|
|
* @param storeId - The store UUID
|
|
|
* @param voiceId - New voice ID (provider_voice_id)
|
|
* @param voiceId - New voice ID (provider_voice_id)
|
|
|
* @param greetingMessage - New greeting message
|
|
* @param greetingMessage - New greeting message
|
|
|
|
|
+ * @param updateSystemPrompt - Whether to also rebuild and update the system prompt (default: false)
|
|
|
*/
|
|
*/
|
|
|
export async function updateVapiAssistant(
|
|
export async function updateVapiAssistant(
|
|
|
supabase: SupabaseClient,
|
|
supabase: SupabaseClient,
|
|
|
storeId: string,
|
|
storeId: string,
|
|
|
voiceId: string,
|
|
voiceId: string,
|
|
|
- greetingMessage: string
|
|
|
|
|
|
|
+ greetingMessage: string,
|
|
|
|
|
+ updateSystemPrompt: boolean = false
|
|
|
): Promise<VapiUpdateResult> {
|
|
): Promise<VapiUpdateResult> {
|
|
|
- console.log(`[VAPI Update] Updating assistant for store: ${storeId}`)
|
|
|
|
|
|
|
+ console.log(`[VAPI Update] Updating assistant for store: ${storeId}${updateSystemPrompt ? ' (including system prompt)' : ''}`)
|
|
|
|
|
|
|
|
// Check if VAPI is configured
|
|
// Check if VAPI is configured
|
|
|
if (!isVapiConfigured()) {
|
|
if (!isVapiConfigured()) {
|
|
@@ -344,10 +410,10 @@ export async function updateVapiAssistant(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // Fetch the store to get vapi_assistant_id
|
|
|
|
|
|
|
+ // Fetch the store to get vapi_assistant_id and store_name
|
|
|
const { data: store, error: fetchError } = await supabase
|
|
const { data: store, error: fetchError } = await supabase
|
|
|
.from('stores')
|
|
.from('stores')
|
|
|
- .select('alt_data')
|
|
|
|
|
|
|
+ .select('store_name, alt_data')
|
|
|
.eq('id', storeId)
|
|
.eq('id', storeId)
|
|
|
.single()
|
|
.single()
|
|
|
|
|
|
|
@@ -358,14 +424,47 @@ export async function updateVapiAssistant(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const vapiAssistantId = store.alt_data?.vapi_assistant_id
|
|
const vapiAssistantId = store.alt_data?.vapi_assistant_id
|
|
|
|
|
+ const storeName = store.store_name || 'Unknown Store'
|
|
|
|
|
+ const languageCode = store.alt_data?.ai_config?.language_code || DEFAULT_LANGUAGE_CODE
|
|
|
|
|
|
|
|
if (!vapiAssistantId) {
|
|
if (!vapiAssistantId) {
|
|
|
console.log('[VAPI Update] No VAPI assistant ID found for store, skipping update')
|
|
console.log('[VAPI Update] No VAPI assistant ID found for store, skipping update')
|
|
|
return { success: false, error: 'No VAPI assistant configured for this store' }
|
|
return { success: false, error: 'No VAPI assistant configured for this store' }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ let systemPrompt: string | undefined
|
|
|
|
|
+
|
|
|
|
|
+ // Rebuild system prompt if requested
|
|
|
|
|
+ if (updateSystemPrompt) {
|
|
|
|
|
+ console.log(`[VAPI Update] Rebuilding system prompt for language: ${languageCode}`)
|
|
|
|
|
+
|
|
|
|
|
+ const promptData = await loadSystemPrompt(supabase, languageCode)
|
|
|
|
|
+ if (!promptData?.systemPrompt) {
|
|
|
|
|
+ console.error(`[VAPI Update] Failed to load system prompt for language: ${languageCode}`)
|
|
|
|
|
+ return { success: false, error: 'Failed to load system prompt' }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Load business hours and special hours
|
|
|
|
|
+ const { businessHours, isEnabled: hoursEnabled } = await loadStoreBusinessHours(supabase, storeId)
|
|
|
|
|
+ const specialHours = await loadStoreSpecialHours(supabase, storeId)
|
|
|
|
|
+ const transferPhoneNumber = store.alt_data?.ai_config?.transfer_phone_number || null
|
|
|
|
|
+
|
|
|
|
|
+ // Build complete system prompt with opening hours
|
|
|
|
|
+ // When business hours are disabled, also hide special hours and transfer phone
|
|
|
|
|
+ systemPrompt = buildCompleteSystemPrompt(
|
|
|
|
|
+ promptData.systemPrompt,
|
|
|
|
|
+ storeName,
|
|
|
|
|
+ storeId,
|
|
|
|
|
+ hoursEnabled ? businessHours : null,
|
|
|
|
|
+ hoursEnabled ? specialHours : null, // Hide special hours when business hours disabled
|
|
|
|
|
+ languageCode,
|
|
|
|
|
+ hoursEnabled ? transferPhoneNumber : null // Hide transfer phone when business hours disabled
|
|
|
|
|
+ )
|
|
|
|
|
+ console.log(`[VAPI Update] Built system prompt (${systemPrompt.length} chars), hours enabled: ${hoursEnabled}`)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// Update the assistant in VAPI
|
|
// Update the assistant in VAPI
|
|
|
- const result = await updateAssistant(vapiAssistantId, voiceId, greetingMessage)
|
|
|
|
|
|
|
+ const result = await updateAssistant(vapiAssistantId, voiceId, greetingMessage, systemPrompt)
|
|
|
|
|
|
|
|
if (!result.success) {
|
|
if (!result.success) {
|
|
|
console.error('[VAPI Update] Failed to update assistant:', result.error)
|
|
console.error('[VAPI Update] Failed to update assistant:', result.error)
|
|
@@ -380,3 +479,94 @@ export async function updateVapiAssistant(
|
|
|
return { success: false, error: errorMessage }
|
|
return { success: false, error: errorMessage }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Update VAPI assistant's system prompt only
|
|
|
|
|
+ * Used when business hours or special hours change
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param supabase - Supabase client
|
|
|
|
|
+ * @param storeId - The store UUID
|
|
|
|
|
+ */
|
|
|
|
|
+export async function updateVapiSystemPrompt(
|
|
|
|
|
+ supabase: SupabaseClient,
|
|
|
|
|
+ storeId: string
|
|
|
|
|
+): Promise<VapiUpdateResult> {
|
|
|
|
|
+ console.log(`[VAPI Update] Updating system prompt only for store: ${storeId}`)
|
|
|
|
|
+
|
|
|
|
|
+ // Check if VAPI is configured
|
|
|
|
|
+ if (!isVapiConfigured()) {
|
|
|
|
|
+ console.log('[VAPI Update] VAPI_API_KEY not configured, skipping update')
|
|
|
|
|
+ return { success: false, error: 'VAPI_API_KEY not configured' }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // Fetch the store to get all needed data
|
|
|
|
|
+ const { data: store, error: fetchError } = await supabase
|
|
|
|
|
+ .from('stores')
|
|
|
|
|
+ .select('store_name, alt_data')
|
|
|
|
|
+ .eq('id', storeId)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ if (fetchError || !store) {
|
|
|
|
|
+ const error = 'Store not found'
|
|
|
|
|
+ console.error('[VAPI Update] Error fetching store:', fetchError)
|
|
|
|
|
+ return { success: false, error }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const vapiAssistantId = store.alt_data?.vapi_assistant_id
|
|
|
|
|
+ const storeName = store.store_name || 'Unknown Store'
|
|
|
|
|
+ const languageCode = store.alt_data?.ai_config?.language_code || DEFAULT_LANGUAGE_CODE
|
|
|
|
|
+ const voiceId = store.alt_data?.ai_config?.voice_type
|
|
|
|
|
+ const greetingMessage = store.alt_data?.ai_config?.greeting_message
|
|
|
|
|
+
|
|
|
|
|
+ if (!vapiAssistantId) {
|
|
|
|
|
+ console.log('[VAPI Update] No VAPI assistant ID found for store, skipping update')
|
|
|
|
|
+ return { success: false, error: 'No VAPI assistant configured for this store' }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!voiceId || !greetingMessage) {
|
|
|
|
|
+ console.log('[VAPI Update] Missing voice or greeting config, skipping update')
|
|
|
|
|
+ return { success: false, error: 'Missing AI configuration for this store' }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Load system prompt
|
|
|
|
|
+ const promptData = await loadSystemPrompt(supabase, languageCode)
|
|
|
|
|
+ if (!promptData?.systemPrompt) {
|
|
|
|
|
+ console.error(`[VAPI Update] Failed to load system prompt for language: ${languageCode}`)
|
|
|
|
|
+ return { success: false, error: 'Failed to load system prompt' }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Load business hours and special hours
|
|
|
|
|
+ const { businessHours, isEnabled: hoursEnabled } = await loadStoreBusinessHours(supabase, storeId)
|
|
|
|
|
+ const specialHours = await loadStoreSpecialHours(supabase, storeId)
|
|
|
|
|
+ const transferPhoneNumber = store.alt_data?.ai_config?.transfer_phone_number || null
|
|
|
|
|
+
|
|
|
|
|
+ // Build complete system prompt with opening hours
|
|
|
|
|
+ // When business hours are disabled, also hide special hours and transfer phone
|
|
|
|
|
+ const systemPrompt = buildCompleteSystemPrompt(
|
|
|
|
|
+ promptData.systemPrompt,
|
|
|
|
|
+ storeName,
|
|
|
|
|
+ storeId,
|
|
|
|
|
+ hoursEnabled ? businessHours : null,
|
|
|
|
|
+ hoursEnabled ? specialHours : null, // Hide special hours when business hours disabled
|
|
|
|
|
+ languageCode,
|
|
|
|
|
+ hoursEnabled ? transferPhoneNumber : null // Hide transfer phone when business hours disabled
|
|
|
|
|
+ )
|
|
|
|
|
+ console.log(`[VAPI Update] Built system prompt (${systemPrompt.length} chars), hours enabled: ${hoursEnabled}, special hours: ${hoursEnabled ? specialHours.length : 0}`)
|
|
|
|
|
+
|
|
|
|
|
+ // Update the assistant in VAPI
|
|
|
|
|
+ const result = await updateAssistant(vapiAssistantId, voiceId, greetingMessage, systemPrompt)
|
|
|
|
|
+
|
|
|
|
|
+ if (!result.success) {
|
|
|
|
|
+ console.error('[VAPI Update] Failed to update assistant:', result.error)
|
|
|
|
|
+ return { success: false, error: result.error }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[VAPI Update] Successfully updated system prompt for assistant: ${vapiAssistantId}`)
|
|
|
|
|
+ return { success: true }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
|
|
|
+ console.error('[VAPI Update] Update failed:', error)
|
|
|
|
|
+ return { success: false, error: errorMessage }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|