import axios from 'axios'; import { loadSecrets } from '../../config/secrets.js'; const secrets = loadSecrets(); import { logger } from '../../utils/logger.js'; /** * Summarizes the initial ticket description when a WorkOrderCreated webhook arrives. * This produces a short, clean, professional summary suitable for posting as the * first message in a new ServChan Webex space. */ export async function summarizeTicketDescription( rawDescription, xaiApiKey, options = {} ) { const startTime = Date.now(); const { model = secrets.xai.model, maxTokens = 300, includeOriginal = false, } = options; if (!rawDescription?.trim()) { return { summary: 'No description provided.' }; } const token = xaiApiKey || secrets.xai.token; if (!token) { return { summary: `(xAI not configured) Original: ${rawDescription.substring(0, 400)}${rawDescription.length > 400 ? '...' : ''}`, }; } const systemPrompt = ` You are an expert at turning messy, form-generated ticket descriptions into clear, concise, professional summaries that someone can read in 10–15 seconds and immediately understand the issue. Rules: - Focus on: WHO is affected, WHAT is broken, WHERE it happens, WHEN it started / how often, IMPACT / severity - Remove repetition, form boilerplate, labels like "Field1:", "Please select:", etc. - Use natural, professional language — no emojis unless very clearly needed - Keep technical terms if they are meaningful - Aim for 2–6 sentences max - If the text is already short & clear, just lightly clean it up `.trim(); const userPrompt = ` Summarize the following ticket description: """ ${rawDescription.trim()} """ Provide only the clean summary — no extra commentary, no "Here's a summary:", just the readable text. `.trim(); try { const response = await axios.post( 'https://api.x.ai/v1/chat/completions', { model, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }, ], temperature: 0.3, max_tokens: maxTokens, top_p: 0.95, }, { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, timeout: 15000, } ); const summary = response.data.choices?.[0]?.message?.content?.trim() || ''; logger('xai:summarizeTicketDescription', `Finished in ${Date.now() - startTime}ms`); if (includeOriginal) { return { summary, original: rawDescription.trim() }; } return { summary }; } catch (err) { logger('xai:summarizeTicketDescription', `Error: ${err.message}`, 'error'); return { summary: `(Summary unavailable) Original: ${rawDescription.substring(0, 400)}${rawDescription.length > 400 ? '...' : ''}`, }; } } export async function summarizeTicketWithGrokFromContext(context, ticketId) { if (!secrets.xai.token) { return `(xAI not configured) Raw ticket info: ${context.substring(0, 200)}...`; } const systemPrompt = ` You are an expert HVAC/facilities technician and ServiceChannel ticket analyst. Summarize this ticket clearly and concisely. Use the **ticket description** as the primary source for the **main problem / reason for the ticket**. Use the notes to provide timeline, actions, status updates, and pending items. Structure your summary with these sections: - **Main Problem** (from description) - **Key Events & Timeline** (chronological bullets from notes, most recent last) - **Actions Taken** - **Current Status / Blockers** - **Pending / Next Steps** Keep it professional, neutral, factual, under 250 words. Use bullet points where helpful. If notes are repetitive, deduplicate them. If no notes, omit "Key Events & Timeline" or say "No notes recorded." `; const userPrompt = `Summarize this ServiceChannel ticket:\n${context}`; try { const response = await axios.post( 'https://api.x.ai/v1/chat/completions', { model: secrets.xai.model, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ], temperature: 0.3, max_tokens: 500 }, { headers: { Authorization: `Bearer ${secrets.xai.token}`, 'Content-Type': 'application/json' } } ); return response.data.choices[0].message.content.trim(); } catch (err) { console.error('[GROK] Error:', err.response?.data || err.message); return `(Summary failed) Raw ticket info: ${context.substring(0, 200)}...`; } }