Skip to content

Commit 4390d70

Browse files
committed
Merge branch 'claude/peaceful-tereshkova'
2 parents 23a691f + 1e6d4da commit 4390d70

File tree

3 files changed

+33
-213
lines changed

3 files changed

+33
-213
lines changed

src/components/AppSidebar.tsx

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
ListOrdered,
1010
Scroll,
1111
Tags,
12-
Brain,
1312
Sparkles,
1413
Terminal,
1514
CreditCard,
@@ -23,7 +22,6 @@ import {
2322
Wand2,
2423
ShieldCheck,
2524
FileText,
26-
TrendingUp,
2725
Activity,
2826
Webhook,
2927
Settings,
@@ -157,17 +155,6 @@ export function AppSidebar({ activeTab, setActiveTab, hasAccess = false, ...prop
157155
<span>{t('dashboard.tab.monitor')}</span>
158156
</SidebarMenuButton>
159157
</SidebarMenuItem>
160-
<SidebarMenuItem>
161-
<SidebarMenuButton
162-
isActive={activeTab === 'knowledge'}
163-
onClick={() => handleTabClick('knowledge')}
164-
tooltip={t('dashboard.tab.config')}
165-
className={menuButtonClass}
166-
>
167-
<Brain />
168-
<span>{t('dashboard.tab.config')}</span>
169-
</SidebarMenuButton>
170-
</SidebarMenuItem>
171158
<SidebarMenuItem>
172159
<SidebarMenuButton
173160
isActive={activeTab === 'history'}
@@ -190,17 +177,6 @@ export function AppSidebar({ activeTab, setActiveTab, hasAccess = false, ...prop
190177
<span>{t('sidebar.customerGraph')}</span>
191178
</SidebarMenuButton>
192179
</SidebarMenuItem>
193-
<SidebarMenuItem>
194-
<SidebarMenuButton
195-
isActive={activeTab === 'analytics'}
196-
onClick={() => handleTabClick('analytics')}
197-
tooltip={t('sidebar.analytics')}
198-
className={menuButtonClass}
199-
>
200-
<TrendingUp />
201-
<span>{t('sidebar.analytics')}</span>
202-
</SidebarMenuButton>
203-
</SidebarMenuItem>
204180
</SidebarMenu>
205181
</SidebarGroupContent>
206182
</SidebarGroup>

src/pages/DemoDashboard.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import MonitorView from '../components/DashboardViews/MonitorView';
2222
import IntegrationView from '../components/DashboardViews/IntegrationView';
2323
import CustomerGraphView from '../components/DashboardViews/CustomerGraphView';
2424
import DocumentsView from '../components/DashboardViews/DocumentsView';
25-
import AnalyticsView from '../components/DashboardViews/AnalyticsView';
2625
import SettingsView from '../components/DashboardViews/SettingsView';
2726
import ActivityLogView from '../components/DashboardViews/ActivityLogView';
2827
import WebhooksView from '../components/DashboardViews/WebhooksView';
@@ -72,7 +71,7 @@ function DemoDashboardContent() {
7271
if (action === 'ai') {
7372
setActiveTab('onboarding');
7473
} else if (action === 'manual') {
75-
setActiveTab('knowledge');
74+
setActiveTab('system_prompt');
7675
}
7776
};
7877

@@ -82,7 +81,6 @@ function DemoDashboardContent() {
8281
monitor: t('dashboard.tab.monitor'),
8382
history: t('history.title'),
8483
customer_graph: t('sidebar.customerGraph'),
85-
knowledge: t('config.title'),
8684
system_prompt: t('sidebar.systemPrompt'),
8785
rescue_playbooks: t('sidebar.rescuePlaybooks'),
8886

@@ -203,7 +201,6 @@ function DemoDashboardContent() {
203201
{activeTab === 'customer_graph' && <CustomerGraphView isDark={isDark} />}
204202

205203
{/* Knowledge Base Sections */}
206-
{activeTab === 'knowledge' && <KnowledgeBase isDark={isDark} activeSection="prompt" />}
207204
{activeTab === 'system_prompt' && <KnowledgeBase isDark={isDark} activeSection="prompt" />}
208205
{activeTab === 'rescue_playbooks' && <KnowledgeBase isDark={isDark} activeSection="rescue_playbooks" />}
209206

@@ -221,7 +218,6 @@ function DemoDashboardContent() {
221218
{activeTab === 'keys' && <KeysView isDark={isDark} hasAccess={hasAccess} />}
222219
{activeTab === 'team' && <TeamView isDark={isDark} />}
223220
{activeTab === 'integrations' && <IntegrationView isDark={isDark} />}
224-
{activeTab === 'analytics' && <AnalyticsView isDark={isDark} />}
225221
{activeTab === 'activity_log' && <ActivityLogView isDark={isDark} />}
226222
{activeTab === 'webhooks' && <WebhooksView isDark={isDark} />}
227223
{activeTab === 'settings' && <SettingsView isDark={isDark} />}

src/services/aiService.ts

Lines changed: 32 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
PriorityLevel,
1313
CallMessage,
1414
CallSummary,
15-
ActionItem
1615
} from '../contexts/DemoCallContext';
1716
import { localLLMService, LocalLLMResponse } from './localLLMService';
1817

@@ -224,197 +223,46 @@ class AIService {
224223
category?: CallCategory,
225224
priority?: PriorityLevel
226225
): Promise<SummaryResponse> {
227-
const kb = this.knowledgeBase;
228-
229-
if (!kb) {
230-
return this.mockGenerateSummary(messages, extractedFields, category, priority);
231-
}
226+
// Always use Groq via localLLMService — it manages its own availability.
227+
// No knowledge-base guard, no groqAvailable flag, no mock fallback.
228+
console.log('🤖 Calling Groq for summary...');
229+
const result = await localLLMService.summarizeCall(
230+
messages,
231+
extractedFields,
232+
category,
233+
priority
234+
);
232235

233-
// Use Groq API for summary
234-
if (this.config.useGroq && this.groqAvailable) {
235-
try {
236-
console.log('� Calling Groq for summary...');
237-
const result = await localLLMService.summarizeCall(
238-
messages,
239-
extractedFields,
240-
category,
241-
priority
242-
);
243-
244-
const tags: string[] = [];
245-
if (category) tags.push(category.id);
246-
if (result.followUpRequired) tags.push('follow-up');
247-
// Add tags based on enhanced analysis
248-
if (result.seriousnessLevel?.priority_level === 'critical') tags.push('critical');
249-
if (result.seriousnessLevel?.priority_level === 'high') tags.push('high-priority');
250-
if (result.issueTopics?.issue_category) tags.push(result.issueTopics.issue_category);
251-
252-
// Include caller name in notes if extracted
253-
let notes = result.notes;
254-
if (result.callerName && !notes.toLowerCase().includes(result.callerName.toLowerCase())) {
255-
notes = `Caller: ${result.callerName}. ${notes}`.trim();
256-
}
257-
258-
console.log('✅ Enhanced summary with function calling complete');
259-
if (result.sentimentCards) {
260-
console.log(` 📊 Generated ${result.sentimentCards.length} sentiment cards`);
261-
}
262-
263-
return {
264-
summary: {
265-
mainPoints: result.mainPoints,
266-
sentiment: result.sentiment as CallSummary['sentiment'],
267-
actionItems: [],
268-
followUpRequired: result.followUpRequired,
269-
notes,
270-
// Enhanced fields
271-
summaryText: result.summary, // Clean summary text for preview
272-
suggestions: result.suggestions,
273-
callerIntent: result.callerIntent,
274-
moodIndicators: result.moodIndicators,
275-
topics: result.topics,
276-
resolution: result.resolution,
277-
riskLevel: result.riskLevel,
278-
estimatedPriority: result.estimatedPriority,
279-
},
280-
tags,
281-
callerName: result.callerName,
282-
// Enhanced function calling results
283-
analysis: result.analysis,
284-
sentimentCards: result.sentimentCards,
285-
seriousnessLevel: result.seriousnessLevel,
286-
issueTopics: result.issueTopics,
287-
};
288-
289-
} catch (error) {
290-
console.error('❌ Local LLM summary error:', error);
291-
}
292-
}
293-
294-
// Step 3: Fallback to mock
295-
return this.mockGenerateSummary(messages, extractedFields, category, priority);
296-
}
297-
298-
/**
299-
* Smart mock response generator with conversation state tracking
300-
*/
301-
private async smartMockResponse(
302-
_userMessage: string,
303-
_conversationHistory: CallMessage[],
304-
_existingFields: ExtractedField[]
305-
): Promise<AIResponse> {
306-
// All responses must come from the cloudflare model
307-
// This function should never be called - model must be available
308-
throw new Error('AI model unavailable - all responses must be generated by the cloudflare model. Ensure your cloudflare tunnel is running.');
309-
}
310-
311-
/**
312-
* Mock summary generator
313-
*/
314-
private async mockGenerateSummary(
315-
messages: CallMessage[],
316-
extractedFields: ExtractedField[],
317-
category?: CallCategory,
318-
priority?: PriorityLevel
319-
): Promise<SummaryResponse> {
320-
await this.delay(400);
321-
322-
const userMessages = messages.filter(m => m.speaker === 'user');
323-
const mainPoints: string[] = [];
324236
const tags: string[] = [];
325-
const actionItems: ActionItem[] = [];
326-
327-
const callerName = extractedFields.find(f => f.id === 'name')?.value;
328-
const purpose = extractedFields.find(f => f.id === 'purpose')?.value;
329-
330-
if (callerName) {
331-
mainPoints.push(`Caller: ${callerName}`);
332-
}
333-
if (purpose) {
334-
mainPoints.push(`Purpose: ${purpose}`);
335-
}
336-
337-
userMessages.slice(0, 3).forEach((msg) => {
338-
if (msg.text.length > 15) {
339-
mainPoints.push(msg.text.substring(0, 80) + (msg.text.length > 80 ? '...' : ''));
340-
}
341-
});
342-
343-
extractedFields.forEach(field => {
344-
if (field.id !== 'name' && field.id !== 'purpose' && field.value) {
345-
mainPoints.push(`${field.label}: ${field.value}`);
346-
}
347-
});
348-
349237
if (category) tags.push(category.id);
350-
if (priority === 'critical' || priority === 'high') {
351-
tags.push('priority');
352-
tags.push('follow-up-needed');
353-
}
354-
355-
const allText = messages.map(m => m.text).join(' ').toLowerCase();
356-
let sentiment: 'positive' | 'neutral' | 'negative' = 'neutral';
357-
358-
const positiveWords = ['thank', 'great', 'awesome', 'excellent', 'appreciate', 'helpful', 'wonderful'];
359-
const negativeWords = ['frustrated', 'angry', 'terrible', 'awful', 'disappointed', 'upset', 'worst'];
360-
361-
const positiveCount = positiveWords.filter(w => allText.includes(w)).length;
362-
const negativeCount = negativeWords.filter(w => allText.includes(w)).length;
363-
364-
if (positiveCount > negativeCount) sentiment = 'positive';
365-
else if (negativeCount > positiveCount) sentiment = 'negative';
366-
367-
if (priority === 'critical' || priority === 'high') {
368-
actionItems.push({
369-
id: `action-${Date.now()}-1`,
370-
text: 'Follow up with caller urgently',
371-
completed: false,
372-
});
373-
}
374-
if (purpose?.toLowerCase().includes('appointment') || purpose?.toLowerCase().includes('schedule')) {
375-
actionItems.push({
376-
id: `action-${Date.now()}-2`,
377-
text: 'Schedule appointment as requested',
378-
completed: false,
379-
});
380-
}
381-
if (category?.id === 'support') {
382-
actionItems.push({
383-
id: `action-${Date.now()}-3`,
384-
text: 'Create support ticket for issue resolution',
385-
completed: false,
386-
});
387-
}
388-
389-
let notes = '';
390-
if (callerName) {
391-
notes += `Call from ${callerName}. `;
392-
}
393-
if (purpose) {
394-
notes += `Regarding: ${purpose}. `;
395-
}
396-
if (category) {
397-
notes += `Categorized as ${category.name}. `;
398-
}
399-
if (priority && priority !== 'medium') {
400-
notes += `Priority: ${priority}. `;
401-
}
402-
if (!notes) {
403-
notes = 'Call completed successfully.';
404-
}
238+
if (result.followUpRequired) tags.push('follow-up');
239+
if (result.seriousnessLevel?.priority_level === 'critical') tags.push('critical');
240+
if (result.seriousnessLevel?.priority_level === 'high') tags.push('high-priority');
241+
if (result.issueTopics?.issue_category) tags.push(result.issueTopics.issue_category);
405242

243+
console.log('✅ Groq summary complete');
406244
return {
407245
summary: {
408-
mainPoints: mainPoints.length > 0 ? mainPoints : ['Call completed'],
409-
sentiment,
410-
actionItems,
411-
followUpRequired: priority === 'critical' || priority === 'high',
412-
notes,
413-
summaryText: notes,
414-
topics: tags,
415-
suggestions: actionItems.map(a => a.text),
246+
mainPoints: result.mainPoints,
247+
sentiment: result.sentiment as CallSummary['sentiment'],
248+
actionItems: [],
249+
followUpRequired: result.followUpRequired,
250+
notes: result.notes,
251+
summaryText: result.summary,
252+
suggestions: result.suggestions,
253+
callerIntent: result.callerIntent,
254+
moodIndicators: result.moodIndicators,
255+
topics: result.topics,
256+
resolution: result.resolution,
257+
riskLevel: result.riskLevel,
258+
estimatedPriority: result.estimatedPriority,
416259
},
417260
tags,
261+
callerName: result.callerName,
262+
analysis: result.analysis,
263+
sentimentCards: result.sentimentCards,
264+
seriousnessLevel: result.seriousnessLevel,
265+
issueTopics: result.issueTopics,
418266
};
419267
}
420268

0 commit comments

Comments
 (0)