Skip to main content
Glama
find-brand-assets.jsβ€’22.8 kB
// api/find-brand-assets.js - Phase 2: Enhanced with OpenAI Intelligence import { BREVILLE_PRODUCTS, ASSET_SECTIONS, REGIONAL_MAPPING, USE_CASE_OPTIMIZATION, findProduct, findBestSections } from '../config/breville-vault-intelligence.js'; import { ENHANCED_INTENT_PARSING_PROMPT, getIntentParsingPrompt } from '../config/openai-prompts.js'; export default async function handler(req, res) { // CORS headers for ChatGPT Enterprise res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); if (req.method === 'OPTIONS') { return res.status(200).end(); } if (req.method !== 'POST') { return res.status(405).json({ error: 'method_not_allowed', message: 'Only POST method allowed for asset search' }); } try { const { request, context = {} } = req.body; // Validate request if (!request || typeof request !== 'string') { return res.status(400).json({ error: 'invalid_request', message: 'Request field is required and must be a string', example: 'Oracle Jet logo for my presentation' }); } if (request.length < 3 || request.length > 500) { return res.status(400).json({ error: 'invalid_request_length', message: 'Request must be between 3 and 500 characters' }); } // Check authentication status const hasOAuth = !!process.env.BRANDFOLDER_CLIENT_ID && !!process.env.BRANDFOLDER_CLIENT_SECRET; if (!hasOAuth) { return res.status(401).json({ error: 'authentication_required', message: 'Brandfolder OAuth not configured. Please complete setup.', auth_url: `https://${req.headers.host}/authenticate`, setup_status: 'oauth_pending' }); } // Execute enhanced asset search with OpenAI const searchResult = await executeAssetSearchWithAI(request, context); // Return results with enhanced intelligence return res.json({ success: true, intent: searchResult.intent, results: searchResult.results, suggestions: searchResult.suggestions, intelligence: { parsing_method: searchResult.parsingMethod, detected_sections: searchResult.intent.sections?.map(s => s.name || s.section?.section || s), regional_context: searchResult.intent.regionalContext, confidence_score: searchResult.intent.confidence, openai_enhanced: !!process.env.OPENAI_API_KEY }, metadata: { query: request, timestamp: new Date().toISOString(), response_time: `${Date.now() - (req.startTime || Date.now())}ms` } }); } catch (error) { console.error('[Phase 2 Enhanced Asset Search Error]', error); // Handle specific error types if (error.message.includes('authenticate')) { return res.status(401).json({ error: 'authentication_required', message: 'Please authenticate with Brandfolder to access assets', auth_url: `https://${req.headers.host}/authenticate` }); } if (error.message.includes('rate limit')) { return res.status(429).json({ error: 'rate_limit_exceeded', message: 'Too many requests. Please wait a moment and try again.', retry_after: 60 }); } // Generic server error return res.status(500).json({ error: 'search_failed', message: 'Asset search failed. Please try again or contact support.', timestamp: new Date().toISOString() }); } } // Enhanced asset search with OpenAI intelligence async function executeAssetSearchWithAI(userRequest, context) { // Try OpenAI-enhanced parsing first, fall back to pattern matching const intent = await parseUserIntentWithAI(userRequest, context); // Generate intelligent mock results based on enhanced intent const mockResults = generateAdvancedIntelligentResults(intent); // Generate AI-powered suggestions const suggestions = generateAIEnhancedSuggestions(intent, mockResults); return { intent: intent, results: mockResults, suggestions: suggestions, parsingMethod: intent.parsingMethod || 'enhanced' }; } // AI-Enhanced Intent Parsing (Phase 2 upgrade) async function parseUserIntentWithAI(userRequest, context = {}) { const hasOpenAI = !!process.env.OPENAI_API_KEY; if (hasOpenAI) { try { console.log('πŸ€– Using OpenAI-enhanced intent parsing'); return await parseIntentWithOpenAI(userRequest, context); } catch (error) { console.error('OpenAI parsing failed, falling back to enhanced pattern matching:', error); return parseUserIntentEnhanced(userRequest, context, 'openai_fallback'); } } else { console.log('πŸ”§ Using enhanced pattern matching (no OpenAI key)'); return parseUserIntentEnhanced(userRequest, context, 'pattern_matching'); } } // OpenAI-powered intent parsing async function parseIntentWithOpenAI(userRequest, context) { try { // Dynamic import of axios (since we can't guarantee it's available) const axios = (await import('axios')).default; const response = await axios.post('https://api.openai.com/v1/chat/completions', { model: 'gpt-4o-mini', messages: [ { role: 'system', content: ENHANCED_INTENT_PARSING_PROMPT }, { role: 'user', content: `Parse this asset request: "${userRequest}"${Object.keys(context).length ? ` (Context: ${JSON.stringify(context)})` : ''}` } ], max_tokens: 1000, temperature: 0.1 }, { headers: { 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`, 'Content-Type': 'application/json' } }); const content = response.data.choices[0].message.content.trim(); // Handle potential markdown wrapping const jsonString = content.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim(); const aiIntent = JSON.parse(jsonString); // Enhance with additional processing const enhancedIntent = { ...aiIntent, originalRequest: userRequest, context: context, parsingMethod: 'openai_enhanced', timestamp: new Date().toISOString(), // Add regional context if detected regionalContext: aiIntent.region && aiIntent.region !== 'global' ? REGIONAL_MAPPING[aiIntent.region.toUpperCase()] : null }; // Validate and ensure required fields enhancedIntent.confidence = Math.min(Math.max(enhancedIntent.confidence || 0.8, 0.1), 1.0); enhancedIntent.products = enhancedIntent.products || []; enhancedIntent.sections = enhancedIntent.sections || []; enhancedIntent.useCase = enhancedIntent.useCase || 'general'; enhancedIntent.formats = enhancedIntent.formats || ['PNG']; console.log('βœ… OpenAI parsing successful, confidence:', enhancedIntent.confidence); return enhancedIntent; } catch (error) { console.error('OpenAI API error:', error.response?.data || error.message); throw new Error(`OpenAI parsing failed: ${error.message}`); } } // Enhanced pattern matching (fallback method, but still intelligent) function parseUserIntentEnhanced(userRequest, context = {}, parsingMethod = 'enhanced') { const intent = { products: [], sections: [], assetTypes: [], specificDeliverables: [], useCase: context.use_case || inferUseCase(userRequest), formats: ['PNG'], region: context.region || inferRegion(userRequest), brand: null, regionalContext: null, confidence: 0.7, originalRequest: userRequest, reasoning: [], parsingMethod: parsingMethod }; // 1. Smart product detection using intelligence config const detectedProduct = findProduct(userRequest); if (detectedProduct) { intent.products.push(detectedProduct); intent.reasoning.push(`Detected product: ${detectedProduct.name} (${detectedProduct.modelNumber})`); intent.confidence += 0.15; } // 2. Smart section detection const bestSections = findBestSections(userRequest, intent.useCase); if (bestSections.length > 0) { intent.sections = bestSections.slice(0, 2).map(match => ({ name: match.section.section, deliverables: match.section.deliverables, confidence: Math.min(match.score / 5, 1.0) })); intent.reasoning.push(`Targeting sections: ${bestSections.map(s => s.section.section).join(', ')}`); intent.confidence += 0.1; } // 3. Regional and brand context if (intent.region && intent.region !== 'global') { const regionalInfo = REGIONAL_MAPPING[intent.region.toUpperCase()]; if (regionalInfo) { intent.brand = regionalInfo.brand; intent.regionalContext = regionalInfo; intent.reasoning.push(`Region: ${intent.region} β†’ Brand: ${intent.brand}`); // Adjust product model for region if (intent.products.length > 0 && intent.brand === 'Sage') { const product = intent.products[0]; if (product.sageModel) { intent.reasoning.push(`Using Sage model: ${product.sageModel} instead of ${product.modelNumber}`); } } } } // 4. Use case optimization const useCaseConfig = USE_CASE_OPTIMIZATION[intent.useCase]; if (useCaseConfig) { intent.formats = useCaseConfig.preferredFormats; intent.usageNotes = useCaseConfig.notes; intent.reasoning.push(`Use case: ${intent.useCase} β†’ Formats: ${intent.formats.join(', ')}`); } // 5. Extract specific deliverables from sections intent.sections.forEach(section => { if (section.deliverables) { // Add relevant deliverables based on the request const relevantDeliverables = section.deliverables.filter(deliverable => { return bestSections.some(match => match.section.keywords.some(keyword => userRequest.toLowerCase().includes(keyword.toLowerCase()) ) ); }); intent.specificDeliverables.push(...relevantDeliverables.slice(0, 3)); } }); // 6. Legacy asset type extraction (for backward compatibility) intent.assetTypes = intent.sections.map(s => s.name?.toLowerCase().replace(/\s+/g, '_') || 'general'); return intent; } // Smart use case inference (enhanced) function inferUseCase(userRequest) { const request = userRequest.toLowerCase(); if (/presentation|slide|ppt|powerpoint|keynote/i.test(request)) return 'presentation'; if (/web|website|online|digital|homepage/i.test(request)) return 'web'; if (/social|instagram|facebook|twitter|linkedin|tiktok/i.test(request)) return 'social'; if (/amazon|marketplace|ecommerce|a\+|aplus/i.test(request)) return 'amazon'; if (/retail|store|pos|point.of.sale|in.?store/i.test(request)) return 'retail'; if (/print|brochure|flyer|poster|catalogue/i.test(request)) return 'print'; if (/email|edm|newsletter|mailchimp/i.test(request)) return 'email'; if (/video|youtube|tutorial|demo/i.test(request)) return 'video'; return 'general'; } // Smart region inference (enhanced) function inferRegion(userRequest) { const request = userRequest.toLowerCase(); if (/australia|australian|au\b|aussie/i.test(request)) return 'AU'; if (/america|usa|us\b|united states|american/i.test(request)) return 'US'; if (/canada|canadian|ca\b/i.test(request)) return 'CA'; if (/uk\b|britain|british|united kingdom|england/i.test(request)) return 'GB'; if (/germany|german|de\b|deutschland/i.test(request)) return 'DE'; if (/europe|european|eu\b|emea/i.test(request)) return 'EU'; if (/sage/i.test(request)) return 'GB'; // Sage implies UK/EU market return 'global'; } // Generate advanced intelligent mock results (Phase 2 enhanced) function generateAdvancedIntelligentResults(intent) { const results = []; // Generate product-specific results with AI insights if (intent.products.length > 0) { const product = intent.products[0]; const modelToUse = (intent.brand === 'Sage' && product.sageModel) ? product.sageModel : product.modelNumber; // Generate assets based on detected sections with AI naming intent.sections.forEach((section, index) => { const sectionName = section.name || section.section?.section; const primaryFormat = intent.formats[0] || 'PNG'; // Create AI-enhanced asset based on section type const asset = { id: `asset_ai_${Date.now()}_${index}`, name: generateAIEnhancedAssetName(product, sectionName, intent), url: `https://vault.breville.com/download/${modelToUse}_${sectionName.replace(/\s+/g, '_').toLowerCase()}`, thumbnail: `https://vault.breville.com/thumb/${modelToUse}_${sectionName.replace(/\s+/g, '_').toLowerCase()}`, format: primaryFormat, size: getAIOptimalSize(sectionName, intent.useCase), section: sectionName, deliverableType: intent.specificDeliverables[index] || section.deliverables?.[0] || 'Standard Asset', aiSummary: generateAIEnhancedSummary(product, sectionName, intent), usageNotes: generateAIEnhancedUsageNotes(sectionName, intent), regionalContext: intent.regionalContext, confidenceScore: section.confidence || 0.85 }; results.push(asset); }); } // If no specific sections detected, generate smart generic result if (results.length === 0) { results.push({ id: 'asset_ai_generic_001', name: intent.products.length > 0 ? `${intent.products[0].name} - ${intent.brand || 'Breville'} Brand Asset` : `${intent.brand || 'Breville'} Logo - Primary`, url: 'https://vault.breville.com/download/generic_brand_asset', thumbnail: 'https://vault.breville.com/thumb/generic_brand_asset', format: intent.formats[0] || 'PNG', size: '2048x1024', section: 'Logos', deliverableType: 'Brands & Logos', aiSummary: `${intent.brand || 'Breville'} brand asset in ${intent.formats[0]} format. Optimized for ${intent.useCase} use.`, usageNotes: generateGenericAIUsageNotes(intent), confidenceScore: 0.75 }); } return results.slice(0, 3); // Limit to top 3 results } // AI-Enhanced asset naming function generateAIEnhancedAssetName(product, sectionName, intent) { const brand = intent.brand || 'Breville'; const useCase = intent.useCase; if (sectionName === 'Logos') { return `${product.name} - ${brand} Logo${useCase === 'presentation' ? ' (Presentation Ready)' : ''}`; } else if (sectionName === 'Product Photography') { return `${product.name} - Hero Photography${useCase === 'amazon' ? ' (Amazon Optimized)' : ''}`; } else if (sectionName === 'Lifestyle Photography') { return `${product.name} - Lifestyle Shot${useCase === 'social' ? ' (Social Media Ready)' : ''}`; } else if (sectionName.includes('Social')) { return `${product.name} - Social Media Asset (${intent.region === 'GB' ? 'Sage' : 'Breville'} Branding)`; } else if (sectionName.includes('Digital')) { return `${product.name} - ${useCase === 'amazon' ? 'Amazon A+' : 'Digital'} Asset`; } else { return `${product.name} - ${sectionName}${intent.regionalContext ? ` (${intent.regionalContext.theater})` : ''}`; } } // AI-Enhanced summaries function generateAIEnhancedSummary(product, sectionName, intent) { const format = intent.formats[0]; const useCase = intent.useCase; const brand = intent.brand || 'Breville'; let summary = `${product.name} asset from ${sectionName} section in ${format} format.`; if (useCase === 'presentation') { summary += ' High-resolution with transparent background, perfect for slide presentations and corporate materials.'; } else if (useCase === 'social') { summary += ' Social media optimized with engaging composition and platform-specific dimensions.'; } else if (useCase === 'amazon') { summary += ' Amazon marketplace optimized meeting A+ content requirements and product listing guidelines.'; } else if (useCase === 'retail') { summary += ' Print-ready with CMYK color profile for retail point-of-sale materials.'; } else if (useCase === 'web') { summary += ' Web-optimized for fast loading and responsive design across devices.'; } if (intent.regionalContext) { summary += ` Features ${brand} branding specifically for ${intent.regionalContext.theater} market compliance.`; } return summary; } // AI-Enhanced usage notes function generateAIEnhancedUsageNotes(sectionName, intent) { const notes = []; const useCaseConfig = USE_CASE_OPTIMIZATION[intent.useCase]; // Format-specific AI notes if (intent.formats.includes('PNG')) { notes.push('βœ… PNG format with alpha channel transparency'); } if (intent.formats.includes('SVG')) { notes.push('βœ… Vector format - infinite scalability without quality loss'); } if (intent.formats.includes('WebP')) { notes.push('βœ… Next-gen WebP format for 30% smaller file sizes'); } // AI-enhanced use case notes if (useCaseConfig && useCaseConfig.notes) { useCaseConfig.notes.forEach(note => notes.push(`🎯 ${note}`)); } // AI-enhanced section-specific notes if (sectionName === 'Product Photography') { notes.push('πŸ“Έ Professional studio photography with optimal lighting'); } else if (sectionName === 'Lifestyle Photography') { notes.push('🏠 Authentic kitchen environment showing product in real use'); } else if (sectionName.includes('Social')) { notes.push('πŸ“± Optimized for social media algorithms and engagement'); } else if (sectionName.includes('Digital')) { notes.push('πŸ’» Optimized for digital platforms and e-commerce'); } // AI-enhanced regional notes if (intent.regionalContext) { notes.push(`🌍 ${intent.brand} branding compliant with ${intent.regionalContext.theater} market standards`); } return notes; } // AI-optimal size detection function getAIOptimalSize(sectionName, useCase) { const sizeMap = { 'Logos': { 'presentation': '4096x2048', 'web': '2048x1024', 'social': '1080x1080', 'print': '5000x2500', 'default': '2048x1024' }, 'Product Photography': { 'amazon': '2000x2000', 'web': '1920x1920', 'social': '1080x1080', 'print': '4000x4000', 'default': '3000x3000' }, 'Social': { 'social': '1080x1080', 'default': '1080x1080' }, 'Digital': { 'amazon': '2000x2000', 'web': '1920x1080', 'default': '1920x1080' } }; const sectionKey = Object.keys(sizeMap).find(key => sectionName.includes(key) || sectionName.toLowerCase().includes(key.toLowerCase()) ); if (sectionKey && sizeMap[sectionKey][useCase]) { return sizeMap[sectionKey][useCase]; } else if (sectionKey) { return sizeMap[sectionKey].default; } return '2048x1024'; } // Generate AI-enhanced generic usage notes function generateGenericAIUsageNotes(intent) { const notes = []; if (intent.useCase === 'presentation') { notes.push('🎯 Presentation-optimized with high DPI for projectors'); notes.push('βœ… Transparent background for flexible slide layouts'); } else if (intent.useCase === 'web') { notes.push('🌐 Web-optimized with progressive loading'); notes.push('πŸ“± Responsive design compatible'); } else if (intent.useCase === 'social') { notes.push('πŸ“± Social media algorithm optimized'); notes.push('🎨 Engaging visual composition for maximum reach'); } else if (intent.useCase === 'amazon') { notes.push('πŸ›’ Amazon A+ content guidelines compliant'); notes.push('⚑ Optimized for marketplace conversion'); } return notes; } // Generate AI-enhanced suggestions function generateAIEnhancedSuggestions(intent, results) { const suggestions = []; if (results.length === 0) { suggestions.push({ type: 'no_results_ai', message: 'AI analysis found no matching assets with current parameters.', action: intent.products.length > 0 ? `Try: "${intent.products[0].name} photography" or "${intent.products[0].name} in kitchen"` : 'Try: "Oracle Jet coffee machine" or "Breville espresso machine logos"' }); } if (intent.products.length === 0) { suggestions.push({ type: 'ai_product_recommendation', message: 'AI detected generic request. Specify a Breville product for 10x better results.', action: 'Try: "Oracle Jet social posts" or "Sage Oracle Dual Boiler Amazon listing"' }); } if (intent.confidence < 0.8) { suggestions.push({ type: 'ai_confidence_boost', message: 'AI confidence can be improved with more specific details.', action: 'Try: "Oracle Jet hero photography for Australian e-commerce site" or "Sage logo white background for UK presentation"' }); } if (intent.useCase === 'general') { suggestions.push({ type: 'ai_use_case_optimization', message: 'AI can optimize format and sizing if you specify intended use.', action: 'Add context: "for my presentation", "for Instagram post", "for Amazon listing", or "for retail display"' }); } if (intent.region === 'global' && intent.products.length > 0) { suggestions.push({ type: 'ai_regional_optimization', message: 'AI can provide region-specific branding (Breville vs Sage).', action: 'Specify market: "for UK customers" (β†’ Sage branding) or "for Australian market" (β†’ Breville branding)' }); } // AI-powered cross-selling suggestions if (results.length > 0 && intent.sections.length === 1) { const currentSection = intent.sections[0].name; if (currentSection === 'Product Photography') { suggestions.push({ type: 'ai_cross_sell', message: 'AI recommends: Lifestyle photography often performs better for engagement.', action: `Try: "${intent.originalRequest.replace(/product|photo/gi, 'lifestyle scene')}"` }); } else if (currentSection.includes('Social')) { suggestions.push({ type: 'ai_video_recommendation', message: 'AI insight: Video content generates 5x more engagement on social platforms.', action: `Try: "${intent.products[0]?.name || 'product'} demo video" or "how to use ${intent.products[0]?.name}"` }); } } // AI-powered format optimization suggestions if (intent.parsingMethod === 'openai_enhanced' && intent.confidence > 0.9) { suggestions.push({ type: 'ai_format_optimization', message: `AI optimized this request for ${intent.useCase} use case with ${intent.formats.join('/')} format${intent.formats.length > 1 ? 's' : ''}.`, action: 'Perfect! This search is AI-optimized for your specific needs.' }); } return suggestions; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vnsavitri/dam-butler-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server