@quantumai/quantum-cli-core
Version:
Quantum CLI Core - Multi-LLM Collaboration System
586 lines • 25.3 kB
JavaScript
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* Category of features
*/
export var FeatureCategory;
(function (FeatureCategory) {
FeatureCategory["PRODUCTIVITY"] = "productivity";
FeatureCategory["COST_OPTIMIZATION"] = "cost_optimization";
FeatureCategory["QUALITY_IMPROVEMENT"] = "quality_improvement";
FeatureCategory["AUTOMATION"] = "automation";
FeatureCategory["COLLABORATION"] = "collaboration";
FeatureCategory["MONITORING"] = "monitoring";
FeatureCategory["CUSTOMIZATION"] = "customization";
})(FeatureCategory || (FeatureCategory = {}));
/**
* Default onboarding configuration
*/
export const DEFAULT_ONBOARDING_CONFIG = {
enableOnboarding: true,
minUsageForAdvanced: 20,
resuggestCooldown: 14,
maxConcurrentSuggestions: 3,
enableAdaptiveOnboarding: true,
confidenceThreshold: 0.7,
priorityCategories: [
FeatureCategory.PRODUCTIVITY,
FeatureCategory.COST_OPTIMIZATION,
FeatureCategory.QUALITY_IMPROVEMENT,
],
};
/**
* Intelligent onboarding system for feature discovery and adoption
*/
export class OnboardingSystem {
config;
userProfiles = new Map();
availableFeatures = new Map();
suggestionHistory = new Map();
constructor(config = {}) {
this.config = { ...DEFAULT_ONBOARDING_CONFIG, ...config };
this.initializeFeatures();
}
/**
* Generates personalized onboarding suggestions
*/
generateSuggestions(userId, queryHistory, _userStats) {
if (!this.config.enableOnboarding) {
return [];
}
// Get or create user profile
let profile = this.userProfiles.get(userId);
if (!profile) {
profile = this.createUserProfile(userId, queryHistory, _userStats);
this.userProfiles.set(userId, profile);
}
// Update profile with recent usage
this.updateUserProfile(profile, queryHistory, _userStats);
// Analyze usage patterns and identify opportunities
const opportunities = this.identifyOnboardingOpportunities(profile, queryHistory, _userStats);
// Generate suggestions based on opportunities
const suggestions = this.generateFeatureSuggestions(profile, opportunities);
// Filter and personalize suggestions
const personalizedSuggestions = this.personalizeAndFilterSuggestions(profile, suggestions);
// Store suggestion history
this.suggestionHistory.set(userId, personalizedSuggestions);
return personalizedSuggestions;
}
/**
* Creates initial user profile
*/
createUserProfile(userId, queryHistory, _userStats) {
// Determine expertise level based on usage patterns
const expertiseLevel = this.determineExpertiseLevel(queryHistory, _userStats);
// Determine learning style based on query patterns
const learningStyle = this.determineLearningStyle(queryHistory);
// Determine preferred pace
const preferredPace = this.determinePreferredPace(queryHistory);
return {
userId,
totalFeatures: this.availableFeatures.size,
adoptedFeatures: 0,
masteredFeatures: 0,
learningStyle,
preferredPace,
expertiseLevel,
lastOnboarding: new Date(),
onboardingPreferences: {
enableSuggestions: true,
maxSuggestionsPerWeek: 2,
preferredTime: 'immediate',
notificationTypes: ['in_app', 'suggestion'],
skipCategories: [],
learningGoals: ['productivity', 'cost_savings'],
},
featureUsage: new Map(),
};
}
/**
* Updates user profile with recent activity
*/
updateUserProfile(profile, queryHistory, _userStats) {
// Update expertise level if usage has grown significantly
const newExpertiseLevel = this.determineExpertiseLevel(queryHistory, _userStats);
if (newExpertiseLevel !== profile.expertiseLevel) {
profile.expertiseLevel = newExpertiseLevel;
}
// Track feature usage from query history
this.trackFeatureUsageFromHistory(profile, queryHistory);
// Update adoption statistics
profile.adoptedFeatures = Array.from(profile.featureUsage.values())
.filter(usage => usage.adoptionStage === 'adopted' || usage.adoptionStage === 'mastered').length;
profile.masteredFeatures = Array.from(profile.featureUsage.values())
.filter(usage => usage.adoptionStage === 'mastered').length;
}
/**
* Identifies onboarding opportunities
*/
identifyOnboardingOpportunities(profile, queryHistory, _userStats) {
const opportunities = [];
// Productivity opportunities
if (this.detectProductivityGaps(queryHistory, _userStats)) {
opportunities.push({
type: 'productivity',
description: 'User could benefit from productivity features',
evidence: ['Repetitive query patterns detected', 'High query frequency'],
confidence: 0.8,
features: ['smart-templates', 'query-shortcuts', 'bulk-processing'],
});
}
// Cost optimization opportunities
if (this.detectCostOptimizationNeeds(queryHistory, _userStats)) {
opportunities.push({
type: 'cost_optimization',
description: 'User has high costs that could be optimized',
evidence: ['Above-average spending', 'Inefficient model usage'],
confidence: 0.9,
features: ['cost-monitoring', 'smart-routing', 'threshold-optimization'],
});
}
// Quality improvement opportunities
if (this.detectQualityIssues(queryHistory, _userStats)) {
opportunities.push({
type: 'quality_improvement',
description: 'User satisfaction could be improved',
evidence: ['Below-average satisfaction ratings', 'Frequent re-queries'],
confidence: 0.7,
features: ['verification-system', 'multi-model-comparison', 'quality-presets'],
});
}
// Automation opportunities
if (this.detectAutomationOpportunities(queryHistory, _userStats)) {
opportunities.push({
type: 'automation',
description: 'Repetitive tasks could be automated',
evidence: ['Consistent query patterns', 'Regular usage times'],
confidence: 0.8,
features: ['scheduled-queries', 'workflow-automation', 'smart-suggestions'],
});
}
// Advanced features for experienced users
if (profile.expertiseLevel === 'advanced' && profile.adoptedFeatures > 5) {
opportunities.push({
type: 'advanced',
description: 'User ready for advanced features',
evidence: ['High feature adoption', 'Advanced usage patterns'],
confidence: 0.9,
features: ['collaboration-engine', 'custom-providers', 'api-integration'],
});
}
return opportunities;
}
/**
* Generates feature suggestions based on opportunities
*/
generateFeatureSuggestions(profile, opportunities) {
const suggestions = [];
for (const opportunity of opportunities) {
for (const featureId of opportunity.features) {
const feature = this.availableFeatures.get(featureId);
if (!feature)
continue;
const usage = profile.featureUsage.get(featureId);
// Skip if already adopted or recently suggested
if (usage && ['adopted', 'mastered'].includes(usage.adoptionStage))
continue;
if (this.wasRecentlySuggested(profile.userId, featureId))
continue;
const suggestion = this.createFeatureSuggestion(feature, opportunity, profile);
suggestions.push(suggestion);
}
}
return suggestions;
}
/**
* Creates a feature suggestion
*/
createFeatureSuggestion(feature, opportunity, profile) {
const relevanceScore = this.calculateRelevanceScore(feature, opportunity, profile);
const timeToMastery = this.estimateTimeToMastery(feature, profile);
return {
id: this.generateId(),
featureId: feature.id,
title: feature.title,
description: feature.description,
category: feature.category,
benefits: feature.benefits,
useCases: feature.useCases,
learningCurve: feature.learningCurve,
estimatedTimeToValue: feature.timeToValue,
priority: this.calculatePriority(relevanceScore, opportunity.confidence),
trigger: {
type: 'opportunity',
condition: opportunity.description,
confidence: opportunity.confidence,
evidence: opportunity.evidence,
threshold: 0.7,
},
guidance: this.generateGuidance(feature, profile),
success: feature.successCriteria,
personalization: {
relevanceScore,
userLevel: profile.expertiseLevel,
similarUsers: [], // Would be populated with similar user IDs
adoptionRate: feature.adoptionRate,
timeToMastery,
},
};
}
/**
* Personalizes and filters suggestions
*/
personalizeAndFilterSuggestions(profile, suggestions) {
return suggestions
.filter(s => {
// Filter by user preferences
if (profile.onboardingPreferences.skipCategories.includes(s.category))
return false;
// Filter by confidence threshold
if (s.trigger.confidence < this.config.confidenceThreshold)
return false;
// Filter by learning curve vs user level
if (s.learningCurve === 'advanced' && profile.expertiseLevel === 'beginner')
return false;
return true;
})
.sort((a, b) => {
// Sort by priority first, then by relevance score
const priorityOrder = { critical: 4, high: 3, medium: 2, low: 1 };
const priorityDiff = priorityOrder[b.priority] - priorityOrder[a.priority];
if (priorityDiff !== 0)
return priorityDiff;
return b.personalization.relevanceScore - a.personalization.relevanceScore;
})
.slice(0, this.config.maxConcurrentSuggestions);
}
/**
* Helper methods for analysis
*/
determineExpertiseLevel(queryHistory, _userStats) {
if (_userStats.totalQueries < 10)
return 'beginner';
if (_userStats.totalQueries < 50)
return 'intermediate';
return 'advanced';
}
determineLearningStyle(_queryHistory) {
// Simplified analysis - would analyze query patterns for learning preferences
return 'hands_on';
}
determinePreferredPace(queryHistory) {
// Analyze query frequency and adaptation speed
if (queryHistory.length > 20 && queryHistory[0]) {
const timespan = Date.now() - queryHistory[queryHistory.length - 1].timestamp.getTime();
const daysActive = timespan / (1000 * 60 * 60 * 24);
const queriesPerDay = queryHistory.length / daysActive;
if (queriesPerDay > 5)
return 'fast';
if (queriesPerDay < 1)
return 'slow';
}
return 'normal';
}
detectProductivityGaps(queryHistory, _userStats) {
// Look for repetitive patterns
const queryTypes = queryHistory.map(q => q.analysis.type);
const typeFrequency = new Map();
for (const type of queryTypes) {
typeFrequency.set(type, (typeFrequency.get(type) || 0) + 1);
}
// If any query type is used more than 30% of the time, suggest productivity features
const maxFrequency = Math.max(...typeFrequency.values());
return maxFrequency / queryHistory.length > 0.3;
}
detectCostOptimizationNeeds(_queryHistory, _userStats) {
return _userStats.averageCost > 0.05 || _userStats.totalCost > 20; // Above threshold spending
}
detectQualityIssues(queryHistory, _userStats) {
return _userStats.averageRating < 3.5; // Below 3.5/5 average rating
}
detectAutomationOpportunities(queryHistory, _userStats) {
// Look for regular patterns in timing and content
const hours = queryHistory.map(q => q.timestamp.getHours());
const hourCounts = new Map();
for (const hour of hours) {
hourCounts.set(hour, (hourCounts.get(hour) || 0) + 1);
}
// If more than 40% of queries happen in the same 3-hour window
const sortedHours = Array.from(hourCounts.entries()).sort((a, b) => b[1] - a[1]);
const topThreeHours = sortedHours.slice(0, 3);
const topThreeCount = topThreeHours.reduce((sum, [, count]) => sum + count, 0);
return topThreeCount / queryHistory.length > 0.4;
}
trackFeatureUsageFromHistory(profile, queryHistory) {
// Track usage of built-in features based on query characteristics
// Verification feature usage
const verificationUsage = queryHistory.filter(q => q.alternativeProviders.length > 0).length;
if (verificationUsage > 0) {
this.updateFeatureUsage(profile, 'verification-system', verificationUsage);
}
// Multi-model comparison usage
const comparisonUsage = queryHistory.filter(q => q.alternativeProviders.length > 1).length;
if (comparisonUsage > 0) {
this.updateFeatureUsage(profile, 'multi-model-comparison', comparisonUsage);
}
// Cost monitoring (implicit usage)
if (queryHistory.length > 10) {
this.updateFeatureUsage(profile, 'cost-monitoring', queryHistory.length);
}
}
updateFeatureUsage(profile, featureId, usageCount) {
let usage = profile.featureUsage.get(featureId);
if (!usage) {
usage = {
featureId,
userId: profile.userId,
firstUsed: new Date(),
usageCount: 0,
successfulUses: 0,
averageSatisfaction: 0.5,
adoptionStage: 'learning',
onboardingCompleted: false,
stepsCompleted: [],
};
profile.featureUsage.set(featureId, usage);
}
usage.usageCount += usageCount;
usage.lastUsed = new Date();
// Update adoption stage based on usage
if (usage.usageCount > 20) {
usage.adoptionStage = 'mastered';
}
else if (usage.usageCount > 5) {
usage.adoptionStage = 'adopted';
}
}
wasRecentlySuggested(userId, featureId) {
const suggestions = this.suggestionHistory.get(userId) || [];
const recentSuggestions = suggestions.filter(s => {
const daysSince = (Date.now() - new Date(s.id).getTime()) / (1000 * 60 * 60 * 24);
return daysSince < this.config.resuggestCooldown;
});
return recentSuggestions.some(s => s.featureId === featureId);
}
calculateRelevanceScore(feature, opportunity, profile) {
let score = 0.5;
// Opportunity confidence contributes
score += opportunity.confidence * 0.3;
// Category priority
if (this.config.priorityCategories.includes(feature.category)) {
score += 0.2;
}
// Learning curve vs user level
const levelMatch = this.calculateLevelMatch(feature.learningCurve, profile.expertiseLevel);
score += levelMatch * 0.2;
// User goals alignment
const goalAlignment = this.calculateGoalAlignment(feature, profile.onboardingPreferences.learningGoals);
score += goalAlignment * 0.3;
return Math.max(0, Math.min(1, score));
}
calculateLevelMatch(learningCurve, expertiseLevel) {
const matches = {
easy: { beginner: 1.0, intermediate: 0.8, advanced: 0.6 },
moderate: { beginner: 0.5, intermediate: 1.0, advanced: 0.8 },
advanced: { beginner: 0.2, intermediate: 0.6, advanced: 1.0 },
};
return matches[learningCurve]?.[expertiseLevel] || 0.5;
}
calculateGoalAlignment(feature, learningGoals) {
const featureGoals = feature.benefits.map(b => b.toLowerCase());
const alignedGoals = learningGoals.filter(goal => featureGoals.some(fg => fg.includes(goal.toLowerCase())));
return learningGoals.length > 0 ? alignedGoals.length / learningGoals.length : 0.5;
}
calculatePriority(relevanceScore, confidence) {
const combinedScore = (relevanceScore + confidence) / 2;
if (combinedScore > 0.9)
return 'critical';
if (combinedScore > 0.7)
return 'high';
if (combinedScore > 0.5)
return 'medium';
return 'low';
}
estimateTimeToMastery(feature, profile) {
const baseTime = feature.timeToMastery;
// Adjust based on user's pace and expertise
if (profile.preferredPace === 'fast' && profile.expertiseLevel === 'advanced') {
return 'Half the usual time';
}
else if (profile.preferredPace === 'slow' || profile.expertiseLevel === 'beginner') {
return 'Longer than average';
}
return baseTime;
}
generateGuidance(feature, profile) {
return {
introduction: `Let's learn ${feature.title}! This feature will help you ${feature.benefits[0]?.toLowerCase()}.`,
steps: feature.onboardingSteps,
tips: feature.tips,
commonMistakes: feature.commonMistakes || [],
resources: feature.resources || [],
interactiveDemo: feature.hasDemo || false,
};
}
/**
* Initialize available features
*/
initializeFeatures() {
const features = [
{
id: 'verification-system',
title: 'Automatic Verification',
description: 'Get second opinions on important queries',
category: FeatureCategory.QUALITY_IMPROVEMENT,
benefits: ['Higher accuracy', 'Reduced errors', 'Increased confidence'],
useCases: ['Critical decisions', 'Complex problems', 'Important code'],
learningCurve: 'easy',
timeToValue: '5 minutes',
timeToMastery: '1 week',
adoptionRate: 0.8,
successCriteria: {
usage: { frequency: 3, timeframe: 'week' },
satisfaction: { minRating: 4, sampleSize: 5 },
outcome: { improvement: '20% higher satisfaction', metric: 'user_rating' },
timeline: '2 weeks',
},
onboardingSteps: [
{
id: 'enable',
title: 'Enable Verification',
description: 'Turn on automatic verification for uncertain queries',
action: 'Go to settings and enable verification',
expected: 'Verification toggle is on',
duration: '1 minute',
difficulty: 'easy',
},
{
id: 'try',
title: 'Try It Out',
description: 'Ask a complex question and see verification in action',
action: 'Submit a challenging query',
expected: 'You receive multiple model responses',
duration: '2 minutes',
difficulty: 'easy',
},
],
tips: ['Use for important decisions', 'Check uncertainty indicators'],
},
{
id: 'cost-monitoring',
title: 'Cost Monitoring',
description: 'Track and optimize your API spending',
category: FeatureCategory.COST_OPTIMIZATION,
benefits: ['Reduce costs', 'Budget awareness', 'Usage insights'],
useCases: ['Budget management', 'Cost optimization', 'Usage analysis'],
learningCurve: 'easy',
timeToValue: '2 minutes',
timeToMastery: '3 days',
adoptionRate: 0.9,
successCriteria: {
usage: { frequency: 5, timeframe: 'week' },
satisfaction: { minRating: 4, sampleSize: 3 },
outcome: { improvement: '15% cost reduction', metric: 'monthly_cost' },
timeline: '1 month',
},
onboardingSteps: [
{
id: 'view',
title: 'View Cost Dashboard',
description: 'Check your current spending and usage patterns',
action: 'Run quantum --stats to see cost breakdown',
expected: 'Cost dashboard shows your spending',
duration: '1 minute',
difficulty: 'easy',
},
{
id: 'set-budget',
title: 'Set Budget Limits',
description: 'Configure monthly spending limits',
action: 'Set budget in preferences',
expected: 'Budget limit is configured',
duration: '2 minutes',
difficulty: 'easy',
},
],
tips: ['Set realistic budgets', 'Review weekly', 'Use cost-effective models'],
},
{
id: 'smart-routing',
title: 'Smart Model Routing',
description: 'Automatically select the best model for each query',
category: FeatureCategory.AUTOMATION,
benefits: ['Better results', 'Cost optimization', 'Time savings'],
useCases: ['Regular usage', 'Varied query types', 'Efficiency gains'],
learningCurve: 'moderate',
timeToValue: '1 day',
timeToMastery: '1 week',
adoptionRate: 0.7,
successCriteria: {
usage: { frequency: 10, timeframe: 'week' },
satisfaction: { minRating: 4, sampleSize: 10 },
outcome: { improvement: '25% better satisfaction', metric: 'user_rating' },
timeline: '2 weeks',
},
onboardingSteps: [
{
id: 'enable-routing',
title: 'Enable Smart Routing',
description: 'Turn on automatic model selection',
action: 'Enable smart routing in settings',
expected: 'Smart routing is active',
duration: '1 minute',
difficulty: 'easy',
},
{
id: 'customize',
title: 'Customize Preferences',
description: 'Set your priorities for model selection',
action: 'Configure cost/quality/speed preferences',
expected: 'Preferences are set',
duration: '3 minutes',
difficulty: 'medium',
},
],
tips: ['Start with balanced settings', 'Adjust based on results', 'Monitor model selection'],
},
];
for (const feature of features) {
this.availableFeatures.set(feature.id, feature);
}
}
generateId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
/**
* Records feature adoption for tracking
*/
recordFeatureAdoption(userId, featureId, stage) {
const profile = this.userProfiles.get(userId);
if (!profile)
return;
const usage = profile.featureUsage.get(featureId);
if (usage) {
usage.adoptionStage = stage;
if (stage === 'adopted' || stage === 'mastered') {
profile.adoptedFeatures++;
}
}
}
/**
* Updates configuration
*/
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
}
/**
* Gets current configuration
*/
getConfig() {
return { ...this.config };
}
}
//# sourceMappingURL=onboarding-system.js.map