@hivetechs/hive-ai
Version:
Real-time streaming AI consensus platform with HTTP+SSE MCP integration for Claude Code, VS Code, Cursor, and Windsurf - powered by OpenRouter's unified API
767 lines • 39.1 kB
JavaScript
/**
* Expert Profile Templates System
*
* Sophisticated pre-built consensus profiles for different use cases,
* with advanced configuration options and intelligent model selection.
*
* Features:
* - 10+ expert-crafted templates
* - Dynamic model selection based on current rankings
* - Budget-aware configurations
* - Performance optimization settings
* - Scope-specific templates (minimal/basic/production)
* - Advanced routing variant control
*/
import { getDatabase, createPipelineProfileWithInternalIds, getAllPipelineProfiles } from '../storage/unified-database.js';
import { OpenRouterRankings } from './openrouter-rankings.js';
import { DynamicModelSelector } from './dynamic-model-selector.js';
import { TemplateMaintenanceManager } from './hiveai/template-maintenance.js';
// ===== EXPERT TEMPLATE CATALOG =====
export const EXPERT_TEMPLATES = [
{
id: 'lightning-fast',
name: 'Lightning Fast',
description: 'Ultra-high-speed consensus optimized for rapid prototyping and quick answers',
category: 'speed',
scope: 'minimal',
expertLevel: 'beginner',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-5', costRange: 'low', fallback: { type: 'speed-optimized', tier: 'standard', providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-10', costRange: 'ultra-low', fallback: { type: 'cost-efficient', tier: 'budget' } },
validator: { rankingPosition: 'cost-efficient', fallback: { type: 'cost-efficient', tier: 'budget', providers: ['google'] } },
curator: { rankingPosition: 'top-5', costRange: 'low', fallback: { type: 'speed-optimized', tier: 'standard', providers: ['anthropic'] } }
},
temperatures: { generator: 0.3, refiner: 0.2, validator: 0.1, curator: 0.3 },
routingPreferences: {
generator: ':nitro',
refiner: ':floor',
validator: ':floor',
curator: ':nitro'
},
budgetProfile: {
priority: 'cost',
preferredCostRange: 'ultra-low',
maxCostPerConversation: 0.05
},
performanceProfile: {
priority: 'speed',
maxLatencyMs: 2000,
qualityThreshold: 0.7
},
useCases: ['Quick prototyping', 'Simple questions', 'Learning', 'Debugging small issues'],
tags: ['speed', 'budget-friendly', 'beginner', 'rapid']
},
{
id: 'precision-architect',
name: 'Precision Architect',
description: 'Maximum quality consensus for complex architectural decisions and critical code',
category: 'quality',
scope: 'production',
expertLevel: 'expert',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-5', contextWindow: 'xl', fallback: { type: 'premium-quality', tier: 'flagship', contextWindow: 'xl', providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-5', contextWindow: 'large', fallback: { type: 'premium-quality', tier: 'flagship', contextWindow: 'large', providers: ['openai'] } },
validator: { rankingPosition: 'top-10', capabilities: ['reasoning'], fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['reasoning'], providers: ['google'] } },
curator: { rankingPosition: 'top-5', contextWindow: 'xl', fallback: { type: 'premium-quality', tier: 'flagship', contextWindow: 'xl', providers: ['anthropic'] } }
},
temperatures: { generator: 0.7, refiner: 0.5, validator: 0.3, curator: 0.6 },
routingPreferences: {
generator: ':nitro',
refiner: ':nitro',
validator: ':default',
curator: ':nitro'
},
budgetProfile: {
priority: 'performance',
preferredCostRange: 'premium',
maxCostPerConversation: 1.00
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.95
},
useCases: ['System architecture', 'Complex algorithms', 'Production code review', 'Security analysis'],
tags: ['quality', 'expert', 'architecture', 'premium', 'production']
},
{
id: 'budget-optimizer',
name: 'Budget Optimizer',
description: 'Cost-efficient consensus that maximizes value while minimizing expenses',
category: 'cost',
scope: 'basic',
expertLevel: 'intermediate',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'cost-efficient', costRange: 'low', fallback: { type: 'cost-efficient', tier: 'standard', providers: ['meta-llama'] } },
refiner: { rankingPosition: 'cost-efficient', costRange: 'ultra-low', fallback: { type: 'cost-efficient', tier: 'budget', providers: ['google'] } },
validator: { rankingPosition: 'cost-efficient', costRange: 'ultra-low', fallback: { type: 'cost-efficient', tier: 'budget', providers: ['anthropic'] } },
curator: { rankingPosition: 'cost-efficient', costRange: 'low', fallback: { type: 'cost-efficient', tier: 'standard', providers: ['mistral', 'mistralai'] } }
},
temperatures: { generator: 0.4, refiner: 0.3, validator: 0.2, curator: 0.4 },
routingPreferences: {
generator: ':floor',
refiner: ':floor',
validator: ':floor',
curator: ':floor'
},
budgetProfile: {
priority: 'cost',
preferredCostRange: 'low',
maxCostPerConversation: 0.10
},
performanceProfile: {
priority: 'balanced',
qualityThreshold: 0.8
},
useCases: ['Learning projects', 'Personal development', 'Small team projects', 'Budget-conscious development'],
tags: ['cost-effective', 'budget', 'efficient', 'balanced']
},
{
id: 'research-deep-dive',
name: 'Research Deep Dive',
description: 'Comprehensive analysis for research, documentation, and knowledge discovery',
category: 'specialized',
scope: 'production',
expertLevel: 'advanced',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-10', contextWindow: 'xl', capabilities: ['research'], fallback: { type: 'premium-quality', tier: 'premium', contextWindow: 'xl', capabilities: ['research'], providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-10', contextWindow: 'large', fallback: { type: 'premium-quality', tier: 'premium', contextWindow: 'large', providers: ['openai'] } },
validator: { rankingPosition: 'top-15', capabilities: ['analysis'], fallback: { type: 'premium-quality', tier: 'standard', capabilities: ['analysis'], providers: ['google'] } },
curator: { rankingPosition: 'top-5', contextWindow: 'xl', fallback: { type: 'premium-quality', tier: 'flagship', contextWindow: 'xl', providers: ['anthropic'] } }
},
temperatures: { generator: 0.8, refiner: 0.6, validator: 0.4, curator: 0.7 },
routingPreferences: {
generator: ':online',
refiner: ':default',
validator: ':default',
curator: ':online'
},
budgetProfile: {
priority: 'performance',
preferredCostRange: 'high'
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.9
},
useCases: ['Technical research', 'Market analysis', 'Academic writing', 'Documentation'],
tags: ['research', 'analysis', 'comprehensive', 'web-enabled']
},
{
id: 'startup-mvp',
name: 'Startup MVP',
description: 'Balanced consensus for MVP development with good quality and reasonable cost',
category: 'production',
scope: 'basic',
expertLevel: 'intermediate',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-10', costRange: 'medium', fallback: { type: 'balanced', tier: 'premium', providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-15', costRange: 'low', fallback: { type: 'balanced', tier: 'standard', providers: ['openai'] } },
validator: { rankingPosition: 'cost-efficient', fallback: { type: 'balanced', tier: 'standard', providers: ['google'] } },
curator: { rankingPosition: 'top-10', costRange: 'medium', fallback: { type: 'balanced', tier: 'premium', providers: ['anthropic'] } }
},
temperatures: { generator: 0.6, refiner: 0.4, validator: 0.3, curator: 0.5 },
routingPreferences: {
generator: ':default',
refiner: ':floor',
validator: ':floor',
curator: ':default'
},
budgetProfile: {
priority: 'balanced',
preferredCostRange: 'medium',
maxCostPerConversation: 0.25
},
performanceProfile: {
priority: 'balanced',
qualityThreshold: 0.85
},
useCases: ['MVP development', 'Startup projects', 'Feature prototyping', 'Small team development'],
tags: ['startup', 'mvp', 'balanced', 'practical']
},
{
id: 'enterprise-grade',
name: 'Enterprise Grade',
description: 'Production-ready consensus with enterprise security, reliability, and compliance',
category: 'production',
scope: 'production',
expertLevel: 'expert',
selectionStrategy: 'hybrid',
fixedModels: {
generator: 1, // anthropic/claude-3.5-sonnet
refiner: 2, // openai/gpt-4o
validator: 5, // google/gemini-pro-1.5
curator: 6 // anthropic/claude-3-opus
},
temperatures: { generator: 0.5, refiner: 0.3, validator: 0.2, curator: 0.4 },
routingPreferences: {
generator: ':nitro',
refiner: ':nitro',
validator: ':default',
curator: ':nitro'
},
budgetProfile: {
priority: 'performance',
preferredCostRange: 'premium'
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.95
},
useCases: ['Enterprise applications', 'Mission-critical systems', 'Financial services', 'Healthcare systems'],
tags: ['enterprise', 'production', 'reliable', 'premium', 'compliance']
},
{
id: 'creative-innovator',
name: 'Creative Innovator',
description: 'High-creativity consensus for innovative solutions and creative problem solving',
category: 'specialized',
scope: 'basic',
expertLevel: 'advanced',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-5', capabilities: ['creative'], fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['creative'], providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-10', fallback: { type: 'premium-quality', tier: 'premium', providers: ['openai'] } },
validator: { rankingPosition: 'top-15', fallback: { type: 'premium-quality', tier: 'standard', providers: ['google'] } },
curator: { rankingPosition: 'top-5', capabilities: ['creative'], fallback: { type: 'premium-quality', tier: 'flagship', capabilities: ['creative'], providers: ['anthropic'] } }
},
temperatures: { generator: 0.9, refiner: 0.7, validator: 0.5, curator: 0.8 },
budgetProfile: {
priority: 'performance',
preferredCostRange: 'high'
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.85
},
useCases: ['Creative coding', 'Innovative solutions', 'Brainstorming', 'Novel algorithms'],
tags: ['creative', 'innovative', 'experimental', 'high-temperature']
},
{
id: 'security-focused',
name: 'Security Focused',
description: 'Security-first consensus optimized for secure coding and vulnerability analysis',
category: 'specialized',
scope: 'production',
expertLevel: 'expert',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-5', capabilities: ['security'], fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['security'], providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-10', capabilities: ['security'], fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['security'], providers: ['openai'] } },
validator: { rankingPosition: 'top-10', capabilities: ['analysis'], fallback: { type: 'premium-quality', tier: 'standard', capabilities: ['analysis'], providers: ['google'] } },
curator: { rankingPosition: 'top-5', capabilities: ['security'], fallback: { type: 'premium-quality', tier: 'flagship', capabilities: ['security'], providers: ['anthropic'] } }
},
temperatures: { generator: 0.4, refiner: 0.3, validator: 0.2, curator: 0.3 },
routingPreferences: {
generator: ':nitro',
refiner: ':nitro',
validator: ':default',
curator: ':nitro'
},
budgetProfile: {
priority: 'performance',
preferredCostRange: 'high'
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.95
},
useCases: ['Security audits', 'Vulnerability analysis', 'Secure coding', 'Compliance reviews'],
tags: ['security', 'analysis', 'compliance', 'expert', 'careful']
},
{
id: 'ml-ai-specialist',
name: 'ML/AI Specialist',
description: 'Specialized consensus for machine learning and AI development projects',
category: 'specialized',
scope: 'production',
expertLevel: 'expert',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-5', capabilities: ['ml', 'ai'], contextWindow: 'xl', fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['ml', 'ai'], contextWindow: 'xl', providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-10', capabilities: ['ml'], fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['ml'], providers: ['openai'] } },
validator: { rankingPosition: 'top-10', capabilities: ['analysis'], fallback: { type: 'premium-quality', tier: 'standard', capabilities: ['analysis'], providers: ['google'] } },
curator: { rankingPosition: 'top-5', capabilities: ['ml', 'ai'], fallback: { type: 'premium-quality', tier: 'flagship', capabilities: ['ml', 'ai'], providers: ['anthropic'] } }
},
temperatures: { generator: 0.6, refiner: 0.4, validator: 0.3, curator: 0.5 },
budgetProfile: {
priority: 'performance',
preferredCostRange: 'high'
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.9
},
useCases: ['ML model development', 'AI system design', 'Data science', 'Neural networks'],
tags: ['ml', 'ai', 'data-science', 'specialist', 'advanced']
},
{
id: 'debugging-detective',
name: 'Debugging Detective',
description: 'Methodical consensus optimized for debugging, troubleshooting, and error analysis',
category: 'specialized',
scope: 'basic',
expertLevel: 'intermediate',
selectionStrategy: 'dynamic',
selectionCriteria: {
generator: { rankingPosition: 'top-10', capabilities: ['debugging'], fallback: { type: 'premium-quality', tier: 'premium', capabilities: ['debugging'], providers: ['anthropic'] } },
refiner: { rankingPosition: 'top-15', capabilities: ['analysis'], fallback: { type: 'balanced', tier: 'standard', capabilities: ['analysis'], providers: ['openai'] } },
validator: { rankingPosition: 'top-10', capabilities: ['reasoning'], fallback: { type: 'premium-quality', tier: 'standard', capabilities: ['reasoning'], providers: ['google'] } },
curator: { rankingPosition: 'top-10', fallback: { type: 'premium-quality', tier: 'premium', providers: ['anthropic'] } }
},
temperatures: { generator: 0.3, refiner: 0.2, validator: 0.1, curator: 0.3 },
budgetProfile: {
priority: 'balanced',
preferredCostRange: 'medium'
},
performanceProfile: {
priority: 'quality',
qualityThreshold: 0.9
},
useCases: ['Bug debugging', 'Error analysis', 'Code troubleshooting', 'System diagnostics'],
tags: ['debugging', 'troubleshooting', 'methodical', 'precise']
}
];
// ===== EXPERT TEMPLATE MANAGER =====
export class ExpertTemplateManager {
rankings;
selector;
maintenance;
constructor() {
this.rankings = new OpenRouterRankings();
this.selector = new DynamicModelSelector();
this.maintenance = new TemplateMaintenanceManager();
}
/**
* Get all available templates, optionally filtered
*/
getTemplates(filter) {
let templates = [...EXPERT_TEMPLATES];
if (filter) {
if (filter.category) {
templates = templates.filter(t => t.category === filter.category);
}
if (filter.scope) {
templates = templates.filter(t => t.scope === filter.scope);
}
if (filter.expertLevel) {
templates = templates.filter(t => t.expertLevel === filter.expertLevel);
}
if (filter.useCases?.length) {
templates = templates.filter(t => filter.useCases.some(useCase => t.useCases.some(tUseCase => tUseCase.toLowerCase().includes(useCase.toLowerCase()))));
}
if (filter.tags?.length) {
templates = templates.filter(t => filter.tags.some(tag => t.tags.includes(tag)));
}
}
return templates;
}
/**
* Find the best template for a specific question or use case
*/
async findBestTemplate(question, preferences) {
const questionLower = question.toLowerCase();
const scores = new Map();
// Analyze question content for relevant templates
for (const template of EXPERT_TEMPLATES) {
let score = 0;
// Use case matching
for (const useCase of template.useCases) {
if (questionLower.includes(useCase.toLowerCase())) {
score += 10;
}
}
// Tag matching
for (const tag of template.tags) {
if (questionLower.includes(tag)) {
score += 5;
}
}
// Category matching
if (questionLower.includes('debug') && template.category === 'specialized' && template.id === 'debugging-detective')
score += 15;
if (questionLower.includes('security') && template.id === 'security-focused')
score += 15;
if (questionLower.includes('ml') || questionLower.includes('ai') && template.id === 'ml-ai-specialist')
score += 15;
if (questionLower.includes('fast') || questionLower.includes('quick') && template.category === 'speed')
score += 10;
if (questionLower.includes('budget') || questionLower.includes('cheap') && template.category === 'cost')
score += 10;
if (questionLower.includes('enterprise') || questionLower.includes('production') && template.id === 'enterprise-grade')
score += 15;
// Preference matching
if (preferences) {
if (preferences.budget === 'low' && template.budgetProfile?.priority === 'cost')
score += 8;
if (preferences.budget === 'high' && template.budgetProfile?.priority === 'performance')
score += 8;
if (preferences.speed === 'fast' && template.category === 'speed')
score += 8;
if (preferences.speed === 'quality' && template.category === 'quality')
score += 8;
if (preferences.expertLevel && template.expertLevel === preferences.expertLevel)
score += 5;
}
scores.set(template.id, score);
}
// Return top 3 templates, sorted by score
return EXPERT_TEMPLATES
.filter(t => scores.get(t.id) > 0)
.sort((a, b) => scores.get(b.id) - scores.get(a.id))
.slice(0, 3);
}
/**
* Create a profile from an expert template
*/
async createProfileFromTemplate(templateId, profileName, userId) {
const template = EXPERT_TEMPLATES.find(t => t.id === templateId);
if (!template) {
throw new Error(`Template not found: ${templateId}`);
}
const name = profileName || `${template.name} Profile`;
let modelInternalIds;
try {
if (template.selectionStrategy === 'fixed' && template.fixedModels) {
// Use fixed models - resolve any that aren't already internal IDs
modelInternalIds = {
generator: typeof template.fixedModels.generator === 'number' ? template.fixedModels.generator : await this.resolveModelToInternalId(template.fixedModels.generator) || await this.findFallbackModelFromDatabase('generator'),
refiner: typeof template.fixedModels.refiner === 'number' ? template.fixedModels.refiner : await this.resolveModelToInternalId(template.fixedModels.refiner) || await this.findFallbackModelFromDatabase('refiner'),
validator: typeof template.fixedModels.validator === 'number' ? template.fixedModels.validator : await this.resolveModelToInternalId(template.fixedModels.validator) || await this.findFallbackModelFromDatabase('validator'),
curator: typeof template.fixedModels.curator === 'number' ? template.fixedModels.curator : await this.resolveModelToInternalId(template.fixedModels.curator) || await this.findFallbackModelFromDatabase('curator')
};
}
else if (template.selectionStrategy === 'hybrid' && template.fixedModels) {
// Hybrid strategy with fixed models - use fixed models as fallback
modelInternalIds = {
generator: typeof template.fixedModels.generator === 'number' ? template.fixedModels.generator : await this.resolveModelToInternalId(template.fixedModels.generator) || await this.findFallbackModelFromDatabase('generator'),
refiner: typeof template.fixedModels.refiner === 'number' ? template.fixedModels.refiner : await this.resolveModelToInternalId(template.fixedModels.refiner) || await this.findFallbackModelFromDatabase('refiner'),
validator: typeof template.fixedModels.validator === 'number' ? template.fixedModels.validator : await this.resolveModelToInternalId(template.fixedModels.validator) || await this.findFallbackModelFromDatabase('validator'),
curator: typeof template.fixedModels.curator === 'number' ? template.fixedModels.curator : await this.resolveModelToInternalId(template.fixedModels.curator) || await this.findFallbackModelFromDatabase('curator')
};
}
else if (template.selectionStrategy === 'dynamic' || (template.selectionStrategy === 'hybrid' && template.selectionCriteria)) {
// Use dynamic selection - this now always returns internal IDs
modelInternalIds = await this.selectModelsFromCriteria(template.selectionCriteria);
}
else {
throw new Error(`Invalid selection strategy: ${template.selectionStrategy}`);
}
// Verify all models have valid internal IDs
for (const [stage, internalId] of Object.entries(modelInternalIds)) {
if (!internalId || internalId <= 0) {
throw new Error(`Invalid internal ID ${internalId} for ${stage} model - run 'hive sync' to update models`);
}
}
}
catch (modelSelectionError) {
throw modelSelectionError;
}
try {
// Check for duplicate profile names to prevent duplicates
const existingProfiles = await getAllPipelineProfiles();
const nameExists = existingProfiles.some(p => p.name.toLowerCase() === name.toLowerCase());
if (nameExists) {
throw new Error(`Profile "${name}" already exists. Please choose a different name or delete the existing profile first.`);
}
// Create the profile using internal IDs
const profile = await createPipelineProfileWithInternalIds(name, modelInternalIds.generator, template.temperatures.generator, modelInternalIds.refiner, template.temperatures.refiner, modelInternalIds.validator, template.temperatures.validator, modelInternalIds.curator, template.temperatures.curator, userId);
console.log(`✅ Created expert profile: ${name}`);
console.log(`📋 Template: ${template.name} (${template.category})`);
console.log(`🎯 Internal IDs: ${modelInternalIds.generator} → ${modelInternalIds.refiner} → ${modelInternalIds.validator} → ${modelInternalIds.curator}`);
return {
profile,
template,
selectedModels: modelInternalIds
};
}
catch (dbError) {
if (process.platform === 'win32' && dbError instanceof Error) {
if (dbError.message.includes('lock')) {
console.log(`💡 Windows database lock issue - try closing other Hive instances`);
}
if (dbError.message.includes('permission')) {
console.log(`💡 Windows permission issue - try running as Administrator`);
}
}
throw dbError;
}
}
/**
* Select models based on criteria - ONLY returns internal IDs from unified database
*/
async selectModelsFromCriteria(criteria) {
const analysis = await this.rankings.getRankingAnalysis();
const models = { generator: 0, refiner: 0, validator: 0, curator: 0 };
for (const [stage, stageCriteria] of Object.entries(criteria)) {
let selectedModelId = '';
let internalId = null;
// Try to get model from rankings first
if (stageCriteria.rankingPosition) {
switch (stageCriteria.rankingPosition) {
case 'top-5':
selectedModelId = analysis.topModelsOverall[0]?.modelId || '';
break;
case 'top-10':
selectedModelId = analysis.topModelsOverall[2]?.modelId || '';
break;
case 'top-15':
selectedModelId = analysis.topModelsOverall[4]?.modelId || '';
break;
case 'top-20':
selectedModelId = analysis.topModelsOverall[5]?.modelId || '';
break;
case 'cost-efficient':
selectedModelId = analysis.costEfficient[0]?.modelId || '';
break;
case 'rising-stars':
selectedModelId = analysis.risingStars[0]?.modelId || '';
break;
}
}
// Try to resolve the selected model to internal ID
if (selectedModelId) {
internalId = await this.resolveModelToInternalId(selectedModelId);
}
// If still no internal ID, try to resolve fallback
if (!internalId && stageCriteria.fallback) {
internalId = await this.resolveModelToInternalId(stageCriteria.fallback);
}
// If still no internal ID, query database for best available model for this stage
if (!internalId) {
console.warn(`⚠️ Could not resolve model for ${stage}, querying database for fallback`);
internalId = await this.findFallbackModelFromDatabase(stage);
}
models[stage] = internalId;
}
return models;
}
/**
* Find fallback model from database for a specific stage
*/
async findFallbackModelFromDatabase(stage) {
try {
const db = await getDatabase();
let query = '';
const params = [];
// Stage-specific fallback queries - optimized for each role
switch (stage) {
case 'generator':
// For generator: prefer top-ranked models with good context
query = `
SELECT om.internal_id
FROM openrouter_models om
LEFT JOIN model_rankings mr ON om.internal_id = mr.model_internal_id
AND mr.ranking_source = 'openrouter_programming_weekly'
WHERE om.is_active = 1
ORDER BY COALESCE(mr.rank_position, 999) ASC, om.context_window DESC
LIMIT 1
`;
break;
case 'refiner':
// For refiner: prefer cost-efficient models with decent ranking
query = `
SELECT om.internal_id
FROM openrouter_models om
LEFT JOIN model_rankings mr ON om.internal_id = mr.model_internal_id
AND mr.ranking_source = 'openrouter_programming_weekly'
WHERE om.is_active = 1
ORDER BY (COALESCE(mr.rank_position, 999) + COALESCE(om.pricing_input * 100000, 999)) ASC
LIMIT 1
`;
break;
case 'validator':
// For validator: prefer very cost-efficient models
query = `
SELECT om.internal_id
FROM openrouter_models om
WHERE om.is_active = 1
ORDER BY COALESCE(om.pricing_input, 999) ASC, om.internal_id ASC
LIMIT 1
`;
break;
case 'curator':
// For curator: prefer top-ranked models for final polish
query = `
SELECT om.internal_id
FROM openrouter_models om
LEFT JOIN model_rankings mr ON om.internal_id = mr.model_internal_id
AND mr.ranking_source = 'openrouter_programming_weekly'
WHERE om.is_active = 1
ORDER BY COALESCE(mr.rank_position, 999) ASC, om.context_window DESC
LIMIT 1
`;
break;
default:
// Generic fallback: any active model
query = `
SELECT om.internal_id
FROM openrouter_models om
WHERE om.is_active = 1
ORDER BY om.internal_id ASC
LIMIT 1
`;
}
const result = await db.get(query, params);
if (!result) {
throw new Error(`No active models found in database for ${stage} - run 'hive sync' to populate models`);
}
console.log(`✅ Found database fallback for ${stage}: internal_id ${result.internal_id}`);
return result.internal_id;
}
catch (error) {
console.error(`❌ Error finding fallback model for ${stage}:`, error);
throw new Error(`Could not find fallback model for ${stage} - run 'hive sync' to populate models`);
}
}
/**
* Resolve semantic model descriptor to internal ID using existing AI evolution architecture
*/
async resolveSemanticModel(descriptor) {
try {
const db = await getDatabase();
const analysis = await this.rankings.getRankingAnalysis();
// Build query based on semantic descriptor
let query = `
SELECT om.internal_id, om.openrouter_id, om.provider_name,
COALESCE(mr.rank_position, 999) as rank_position
FROM openrouter_models om
LEFT JOIN model_rankings mr ON om.internal_id = mr.model_internal_id
AND mr.ranking_source = 'openrouter_programming_weekly'
WHERE om.is_active = 1
`;
const params = [];
// Apply provider filter
if (descriptor.providers?.length) {
query += ` AND om.provider_name IN (${descriptor.providers.map(() => '?').join(',')})`;
params.push(...descriptor.providers);
}
// Apply context window filter
if (descriptor.contextWindow) {
const contextLimits = {
'small': [0, 8000],
'medium': [8000, 32000],
'large': [32000, 128000],
'xl': [128000, Infinity]
};
const [min, max] = contextLimits[descriptor.contextWindow];
query += ` AND om.context_window >= ? AND om.context_window < ?`;
params.push(min, max === Infinity ? 999999999 : max);
}
// Order by semantic type
switch (descriptor.type) {
case 'speed-optimized':
query += ` ORDER BY rank_position ASC, om.context_window ASC`;
break;
case 'cost-efficient':
query += ` ORDER BY om.pricing_input ASC, rank_position ASC`;
break;
case 'premium-quality':
query += ` ORDER BY rank_position ASC, om.context_window DESC`;
break;
case 'balanced':
query += ` ORDER BY (rank_position + COALESCE(om.pricing_input * 1000000, 0)) ASC`;
break;
case 'latest-from-provider':
query += ` ORDER BY om.last_updated DESC, rank_position ASC`;
break;
}
query += ` LIMIT 5`;
const models = await db.all(query, params);
if (models.length === 0) {
console.warn(`⚠️ No models found matching semantic descriptor:`, descriptor);
return null;
}
// Return the best match
const selectedModel = models[0];
console.log(`✅ Resolved semantic model ${descriptor.type} to: ${selectedModel.openrouter_id} (internal_id: ${selectedModel.internal_id})`);
return selectedModel.internal_id;
}
catch (error) {
console.error(`❌ Error resolving semantic model:`, error);
return null;
}
}
/**
* Resolve any model reference (string, number, or semantic descriptor) to internal ID
*/
async resolveModelToInternalId(modelRef) {
if (typeof modelRef === 'number') {
return modelRef; // Already an internal ID
}
if (typeof modelRef === 'string') {
return await this.getModelInternalId(modelRef); // OpenRouter ID
}
if (typeof modelRef === 'object' && modelRef.type) {
return await this.resolveSemanticModel(modelRef); // Semantic descriptor
}
console.error('❌ Invalid model reference type:', typeof modelRef);
return null;
}
/**
* Get internal ID for a model by OpenRouter ID, with automatic fallback resolution
*/
async getModelInternalId(openrouterId) {
try {
const db = await getDatabase();
const result = await db.get('SELECT internal_id FROM openrouter_models WHERE openrouter_id = ? AND is_active = 1', [openrouterId]);
if (!result) {
console.warn(`⚠️ Model ${openrouterId} not found in database or inactive - attempting automatic replacement...`);
// Use existing template maintenance system to find replacement
const replacement = await this.maintenance.findModelReplacement(openrouterId);
if (replacement) {
console.log(`🔄 Found automatic replacement: ${openrouterId} → ${replacement}`);
return await this.getModelInternalId(replacement);
}
return null;
}
return result.internal_id;
}
catch (error) {
console.error(`❌ Error getting internal ID for model ${openrouterId}:`, error);
return null;
}
}
/**
* Get template recommendations for a user
*/
getRecommendations(userLevel = 'intermediate') {
const recommendations = [];
// Always recommend speed and cost templates for beginners
if (userLevel === 'beginner') {
recommendations.push(EXPERT_TEMPLATES.find(t => t.id === 'lightning-fast'), EXPERT_TEMPLATES.find(t => t.id === 'budget-optimizer'), EXPERT_TEMPLATES.find(t => t.id === 'startup-mvp'));
}
else if (userLevel === 'intermediate') {
recommendations.push(EXPERT_TEMPLATES.find(t => t.id === 'startup-mvp'), EXPERT_TEMPLATES.find(t => t.id === 'debugging-detective'), EXPERT_TEMPLATES.find(t => t.id === 'research-deep-dive'));
}
else if (userLevel === 'advanced') {
recommendations.push(EXPERT_TEMPLATES.find(t => t.id === 'precision-architect'), EXPERT_TEMPLATES.find(t => t.id === 'creative-innovator'), EXPERT_TEMPLATES.find(t => t.id === 'ml-ai-specialist'));
}
else { // expert
recommendations.push(EXPERT_TEMPLATES.find(t => t.id === 'enterprise-grade'), EXPERT_TEMPLATES.find(t => t.id === 'security-focused'), EXPERT_TEMPLATES.find(t => t.id === 'precision-architect'));
}
return recommendations.filter(Boolean);
}
}
// ===== CONVENIENCE FUNCTIONS =====
export async function createExpertProfile(templateId, profileName, userId) {
const manager = new ExpertTemplateManager();
return await manager.createProfileFromTemplate(templateId, profileName, userId);
}
export function getAvailableTemplates() {
return EXPERT_TEMPLATES;
}
export async function findTemplateForQuestion(question, preferences) {
const manager = new ExpertTemplateManager();
return await manager.findBestTemplate(question, preferences);
}
export function getTemplateRecommendations(userLevel) {
const manager = new ExpertTemplateManager();
return manager.getRecommendations(userLevel);
}
export default ExpertTemplateManager;
//# sourceMappingURL=expert-profile-templates.js.map