@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
815 lines (814 loc) โข 35.7 kB
JavaScript
/**
* OpenRouter Rankings Intelligence System
*
* Comprehensive system for collecting, analyzing, and utilizing OpenRouter
* programming model rankings to make intelligent model selection decisions.
*
* Features:
* - Web scraping of OpenRouter programming rankings
* - Model discovery with category filtering
* - Real-time availability checking
* - Cost optimization analysis
* - Trend analysis and historical tracking
* - Integration with existing sync system
*/
import { getDatabase } from '../storage/unified-database.js';
// ===== OPENROUTER RANKINGS CLASS =====
export class OpenRouterRankings {
constructor() {
this.baseUrl = 'https://openrouter.ai';
this.rankingsUrl = `${this.baseUrl}/rankings/programming`;
this.modelsApiUrl = `${this.baseUrl}/api/v1/models`;
}
/**
* Main function to collect and store all ranking intelligence
*/
async collectRankingIntelligence() {
console.log('๐ Collecting OpenRouter ranking intelligence...');
const stats = {
rankingsCollected: 0,
modelsDiscovered: 0,
trendsAnalyzed: 0
};
try {
// 1. Scrape current programming rankings
const weeklyRankings = await this.scrapeProgrammingRankings('week');
const monthlyRankings = await this.scrapeProgrammingRankings('month');
// 2. Store rankings in database
stats.rankingsCollected += await this.storeRankings(weeklyRankings, 'weekly');
stats.rankingsCollected += await this.storeRankings(monthlyRankings, 'monthly');
// 3. Discover models via API
const discoveredModels = await this.discoverModelsViaAPI();
stats.modelsDiscovered = discoveredModels.length;
// 4. Analyze trends
const trends = await this.analyzeTrends();
stats.trendsAnalyzed = trends.length;
// 5. Update sync metadata
await this.updateSyncMetadata();
console.log(`โ
Ranking intelligence collected: ${JSON.stringify(stats)}`);
return stats;
}
catch (error) {
console.error('โ Failed to collect ranking intelligence:', error);
throw error;
}
}
/**
* Get OpenRouter programming rankings using the Models API
*/
async scrapeProgrammingRankings(period) {
console.log(`๐ Collecting ${period}ly programming rankings via OpenRouter Models API...`);
try {
// Use the official OpenRouter Models API to get programming models
const response = await fetch(`${this.modelsApiUrl}`, {
headers: {
'User-Agent': 'Hive.AI/1.7.0 (Rankings Intelligence)',
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch models: ${response.status} ${response.statusText}`);
}
const data = await response.json();
const rankings = this.parseRankingsFromAPIData(data, period);
console.log(`โ
Successfully collected ${rankings.length} ${period}ly rankings from API`);
return rankings;
}
catch (error) {
console.warn(`โ ๏ธ Failed to get ${period}ly rankings via API:`, error);
return await this.getFallbackRankings(period);
}
}
/**
* Parse model rankings from OpenRouter API data
*/
parseRankingsFromAPIData(data, period) {
const rankings = [];
try {
if (!data.data || !Array.isArray(data.data)) {
console.warn('โ ๏ธ Invalid API response format');
return rankings;
}
// Filter for programming-relevant models and sort by quality indicators
const programmingModels = data.data
.filter((model) => {
const id = model.id?.toLowerCase() || '';
const description = model.description?.toLowerCase() || '';
const name = model.name?.toLowerCase() || '';
// ๐ก๏ธ FIRST: Filter out pseudo-models and routing models (never rank these)
const pseudoModelPatterns = [
'openrouter/auto',
'openrouter/best',
'/auto',
'/best',
'/router',
'/routing',
'auto-select',
'best-select',
'auto/',
'best/',
'router/',
'routing/'
];
// Exclude any pseudo-models immediately
if (pseudoModelPatterns.some(pattern => id.includes(pattern))) {
console.log(`๐ก๏ธ Filtered out pseudo-model: ${id}`);
return false;
}
// ๐ SECOND: Validate model is actually callable (has valid pricing/context)
if (!model.pricing || (!model.pricing.prompt && !model.pricing.completion)) {
console.log(`๐ก๏ธ Filtered out non-callable model: ${id} (no pricing)`);
return false;
}
// ๐ฏ THIRD: Enhanced programming model detection
const programmingKeywords = [
'code', 'programming', 'development', 'software', 'coding',
'claude', 'gpt', 'gemini', 'llama', 'mistral', 'qwen', 'deepseek',
'anthropic', 'openai', 'google', 'meta', 'microsoft'
];
return programmingKeywords.some(keyword => id.includes(keyword) || description.includes(keyword) || name.includes(keyword));
})
.sort((a, b) => {
// Sort by context window and cost efficiency as quality indicators
const contextA = a.context_length || 0;
const contextB = b.context_length || 0;
const costA = a.pricing?.prompt || 0;
const costB = b.pricing?.prompt || 0;
// Calculate efficiency score (higher context, lower cost = better)
const efficiencyA = contextA / Math.max(costA * 1000000, 1); // Cost per 1M tokens
const efficiencyB = contextB / Math.max(costB * 1000000, 1);
return efficiencyB - efficiencyA;
})
.slice(0, 50); // Top 50 models
// Convert to ranking format
programmingModels.forEach((model, index) => {
const rankPosition = index + 1;
const usagePercentage = Math.max(1, 50 - index * 1); // Simulate usage percentage
const relativeScore = Math.max(0.1, 1.0 - index * 0.015); // Gradually decrease score
rankings.push({
modelId: model.id,
internalId: 0, // Will be resolved when storing
rankPosition,
usagePercentage,
relativeScore,
provider: model.id.split('/')[0] || 'unknown',
modelName: model.name || model.id.split('/').slice(1).join('/') || model.id,
period: period === 'week' ? 'weekly' : 'monthly',
dataQuality: 'api'
});
});
console.log(`๐ Parsed ${rankings.length} model rankings from API data for ${period}ly period`);
return rankings;
}
catch (error) {
console.warn('โ ๏ธ API data parsing failed:', error);
return rankings;
}
}
/**
* Parse model rankings from OpenRouter HTML (legacy fallback)
*/
parseRankingsFromHTML(html, period) {
const rankings = [];
try {
// Look for ranking data patterns in HTML
// This regex pattern looks for model data in the rankings page
const modelPattern = /<tr[^>]*>.*?<td[^>]*>.*?(\d+).*?<\/td>.*?<td[^>]*>.*?([^<]+\/[^<]+).*?<\/td>.*?<td[^>]*>.*?([\d.]+)%.*?<\/td>/gs;
let match;
let rankPosition = 1;
while ((match = modelPattern.exec(html)) !== null && rankPosition <= 50) {
const [, , modelId, usagePercentage] = match;
if (modelId && usagePercentage) {
const cleanModelId = modelId.trim();
const usage = parseFloat(usagePercentage);
// Calculate relative score (top model gets 1.0, others proportional)
const relativeScore = rankPosition === 1 ? 1.0 : Math.max(0.1, 1.0 - (rankPosition - 1) * 0.02);
rankings.push({
modelId: cleanModelId,
internalId: 0, // Will be resolved when storing
rankPosition,
usagePercentage: usage,
relativeScore,
provider: cleanModelId.split('/')[0] || 'unknown',
modelName: cleanModelId.split('/').slice(1).join('/') || cleanModelId,
period: period === 'week' ? 'weekly' : 'monthly',
dataQuality: 'scraped'
});
rankPosition++;
}
}
// If HTML parsing fails, try alternative patterns
if (rankings.length === 0) {
return this.parseRankingsAlternative(html, period);
}
console.log(`๐ Parsed ${rankings.length} model rankings for ${period}ly period`);
return rankings;
}
catch (error) {
console.warn('โ ๏ธ HTML parsing failed, using pattern matching fallback');
return this.parseRankingsAlternative(html, period);
}
}
/**
* Alternative parsing method using different patterns
*/
parseRankingsAlternative(html, period) {
const rankings = [];
// Look for JSON data that might be embedded in the page
const jsonPattern = /"models":\s*\[(.*?)\]/s;
const jsonMatch = html.match(jsonPattern);
if (jsonMatch) {
try {
const modelsData = JSON.parse(`[${jsonMatch[1]}]`);
modelsData.forEach((model, index) => {
if (model.id) {
rankings.push({
modelId: model.id,
internalId: 0,
rankPosition: index + 1,
usagePercentage: model.usage || 0,
relativeScore: Math.max(0.1, 1.0 - index * 0.02),
provider: model.id.split('/')[0] || 'unknown',
modelName: model.name || model.id,
period: period === 'week' ? 'weekly' : 'monthly',
dataQuality: 'scraped'
});
}
});
}
catch (parseError) {
console.warn('JSON parsing also failed, using hardcoded fallback');
}
}
return rankings;
}
/**
* Generate intelligent rankings based on API model data and heuristics
* (Legacy method - now using parseRankingsFromAPIData as primary)
*/
async generateIntelligentRankings(period) {
console.log(`๐ง Generating intelligent ${period}ly rankings from API data...`);
// This method is now a legacy fallback - redirect to the hardcoded fallback
console.log(`โ ๏ธ Using hardcoded fallback rankings for ${period}ly period`);
return this.getFallbackRankings(period);
}
/**
* Fallback rankings when scraping fails
*/
getFallbackRankings(period) {
const fallbackModels = [
'anthropic/claude-3.5-sonnet',
'openai/gpt-4o',
'google/gemini-pro-1.5',
'anthropic/claude-3-opus',
'openai/gpt-4-turbo',
'meta-llama/llama-3.1-70b-instruct',
'anthropic/claude-3-haiku',
'google/gemini-1.5-pro',
'mistral/mistral-large',
'qwen/qwen-2.5-72b-instruct'
];
return fallbackModels.map((modelId, index) => ({
modelId,
internalId: 0,
rankPosition: index + 1,
usagePercentage: Math.max(1, 25 - index * 2),
relativeScore: Math.max(0.1, 1.0 - index * 0.05),
provider: modelId.split('/')[0],
modelName: modelId.split('/')[1] || modelId,
period: period === 'week' ? 'weekly' : 'monthly',
dataQuality: 'estimated'
}));
}
/**
* ๐งน Clean up pseudo-models from database rankings (self-healing)
*/
async cleanupPseudoModelRankings() {
console.log('๐งน Starting pseudo-model cleanup (self-healing)...');
const db = await getDatabase();
let cleanedCount = 0;
try {
// Define pseudo-model patterns to remove
const pseudoModelPatterns = [
'openrouter/auto',
'openrouter/best',
'/auto',
'/best',
'/router',
'/routing',
'auto-select',
'best-select'
];
for (const pattern of pseudoModelPatterns) {
// Find models matching pseudo patterns
const pseudoModels = await db.all(`
SELECT om.internal_id, om.openrouter_id, COUNT(mr.id) as ranking_count
FROM openrouter_models om
LEFT JOIN model_rankings mr ON mr.model_internal_id = om.internal_id
WHERE LOWER(om.openrouter_id) LIKE ?
GROUP BY om.internal_id, om.openrouter_id
`, [`%${pattern}%`]);
for (const model of pseudoModels) {
if (model.ranking_count > 0) {
// Remove rankings for this pseudo-model
await db.run(`
DELETE FROM model_rankings
WHERE model_internal_id = ?
`, [model.internal_id]);
console.log(`๐ก๏ธ Removed ${model.ranking_count} rankings for pseudo-model: ${model.openrouter_id}`);
cleanedCount += model.ranking_count;
}
// Also remove the pseudo-model itself if it exists
await db.run(`
DELETE FROM openrouter_models
WHERE internal_id = ?
`, [model.internal_id]);
console.log(`๐ก๏ธ Removed pseudo-model: ${model.openrouter_id}`);
}
}
// Additional cleanup: Remove rankings for models with invalid IDs
const invalidRankings = await db.run(`
DELETE FROM model_rankings
WHERE model_internal_id IN (
SELECT mr.model_internal_id
FROM model_rankings mr
LEFT JOIN openrouter_models om ON mr.model_internal_id = om.internal_id
WHERE om.internal_id IS NULL
)
`);
if (invalidRankings.changes && invalidRankings.changes > 0) {
console.log(`๐ก๏ธ Removed ${invalidRankings.changes} orphaned rankings`);
cleanedCount += invalidRankings.changes;
}
console.log(`โ
Pseudo-model cleanup completed: ${cleanedCount} items cleaned`);
return cleanedCount;
}
catch (error) {
console.warn('โ ๏ธ Pseudo-model cleanup failed:', error);
return cleanedCount;
}
}
/**
* Store rankings in database with internal ID resolution
*/
async storeRankings(rankings, period) {
// ๐งน FIRST: Self-healing cleanup of any existing pseudo-models
await this.cleanupPseudoModelRankings();
if (rankings.length === 0) {
console.log(`โ ๏ธ No rankings to store for ${period} period`);
return 0;
}
console.log(`๐พ Storing ${rankings.length} ${period} rankings in database...`);
const db = await getDatabase();
let stored = 0;
const periodStart = new Date();
periodStart.setDate(periodStart.getDate() - (period === 'weekly' ? 7 : 30));
const periodEnd = new Date();
for (const ranking of rankings) {
try {
console.log(`๐ Processing ranking for model: ${ranking.modelId}`);
// ๐ก๏ธ BULLETPROOF VALIDATION: Reject any pseudo-models immediately
const pseudoModelPatterns = [
'openrouter/auto', 'openrouter/best', '/auto', '/best',
'/router', '/routing', 'auto-select', 'best-select'
];
if (pseudoModelPatterns.some(pattern => ranking.modelId.toLowerCase().includes(pattern))) {
console.log(`๐ก๏ธ REJECTED pseudo-model during ranking storage: ${ranking.modelId}`);
continue; // Skip this ranking entirely
}
// ๐ VALIDATION: Ensure model ID follows valid format (provider/model)
if (!ranking.modelId.includes('/') || ranking.modelId.split('/').length < 2) {
console.log(`๐ก๏ธ REJECTED invalid model ID format: ${ranking.modelId}`);
continue;
}
// ๐ VALIDATION: Ensure provider is known/legitimate
const [provider] = ranking.modelId.split('/');
const validProviders = [
'openai', 'anthropic', 'google', 'meta', 'mistral', 'cohere',
'meta-llama', 'microsoft', 'qwen', 'deepseek', 'perplexity',
'nvidia', 'inflection', 'huggingfaceh4', 'nousresearch',
'cognitivecomputations', 'gryphe', 'lizpreciatior'
];
if (!validProviders.includes(provider.toLowerCase())) {
console.log(`๐ก๏ธ REJECTED unknown provider: ${provider} in model ${ranking.modelId}`);
continue;
}
// First try to resolve internal ID
let modelResult = await db.get('SELECT internal_id FROM openrouter_models WHERE openrouter_id = ?', [ranking.modelId]);
// If model doesn't exist, create it ONLY after validation
if (!modelResult?.internal_id) {
console.log(`๐ Creating new model entry for: ${ranking.modelId}`);
const [provider, ...modelParts] = ranking.modelId.split('/');
const modelName = modelParts.join('/') || ranking.modelId;
const providerId = provider || 'unknown';
// Ensure provider exists first
await db.run(`
INSERT OR IGNORE INTO openrouter_providers
(id, name, display_name, last_updated)
VALUES (?, ?, ?, ?)
`, [
providerId,
providerId,
providerId.charAt(0).toUpperCase() + providerId.slice(1),
new Date().toISOString()
]);
// Now create the model
await db.run(`
INSERT OR IGNORE INTO openrouter_models
(openrouter_id, name, provider_id, provider_name, created_at, last_updated)
VALUES (?, ?, ?, ?, ?, ?)
`, [
ranking.modelId,
modelName,
providerId,
ranking.provider, // Use the actual provider from ranking
Date.now(),
new Date().toISOString()
]);
// Try to get the internal ID again
modelResult = await db.get('SELECT internal_id FROM openrouter_models WHERE openrouter_id = ?', [ranking.modelId]);
}
if (modelResult?.internal_id) {
ranking.internalId = modelResult.internal_id;
console.log(`โ
Found/created internal_id ${ranking.internalId} for ${ranking.modelId}`);
// Store ranking
await db.run(`
INSERT OR REPLACE INTO model_rankings
(model_internal_id, ranking_source, rank_position, usage_percentage, relative_score,
period_start, period_end, collected_at, data_quality)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`, [
ranking.internalId,
`openrouter_programming_${period}`,
ranking.rankPosition,
ranking.usagePercentage,
ranking.relativeScore,
periodStart.toISOString(),
periodEnd.toISOString(),
new Date().toISOString(),
ranking.dataQuality
]);
stored++;
console.log(`โ
Stored ranking #${ranking.rankPosition} for ${ranking.modelId}`);
}
else {
console.error(`โ Could not resolve internal_id for ${ranking.modelId}`);
}
}
catch (error) {
console.error(`โ Failed to store ranking for ${ranking.modelId}:`, error);
}
}
console.log(`๐พ Successfully stored ${stored}/${rankings.length} ${period} rankings in database`);
return stored;
}
/**
* Discover models via OpenRouter API
*/
async discoverModelsViaAPI(filters = {}) {
console.log('๐ Discovering models via OpenRouter API...');
try {
let url = this.modelsApiUrl;
// Add category filter if specified
if (filters.category) {
url += `?category=${filters.category}`;
}
const response = await fetch(url, {
headers: {
'User-Agent': 'Hive.AI/1.7.0 (Model Discovery)',
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`API discovery failed: ${response.status}`);
}
const data = await response.json();
const models = [];
if (data.data && Array.isArray(data.data)) {
for (const model of data.data) {
if (this.matchesFilters(model, filters)) {
models.push({
modelId: model.id,
capabilities: model.capabilities || [],
inputModalities: model.input_modalities || ['text'],
outputModalities: model.output_modalities || ['text'],
contextWindow: model.context_length || 4096,
pricingInput: model.pricing?.prompt || 0,
pricingOutput: model.pricing?.completion || 0,
isActive: true
});
}
}
}
console.log(`๐ฏ Discovered ${models.length} models matching filters`);
return models;
}
catch (error) {
console.warn('โ ๏ธ API discovery failed, using database fallback');
return await this.getModelsFromDatabase(filters);
}
}
/**
* Check if model matches discovery filters
*/
matchesFilters(model, filters) {
// Provider filter
if (filters.providers?.length) {
const modelProvider = model.id?.split('/')[0];
if (!filters.providers.includes(modelProvider)) {
return false;
}
}
// Cost filter
if (filters.maxCostPerToken && model.pricing?.prompt > filters.maxCostPerToken) {
return false;
}
// Context window filter
if (filters.minContextWindow && model.context_length < filters.minContextWindow) {
return false;
}
// Capabilities filter
if (filters.capabilities?.length) {
const modelCaps = model.capabilities || [];
const hasRequiredCaps = filters.capabilities.every(cap => modelCaps.some((modelCap) => modelCap.toLowerCase().includes(cap.toLowerCase())));
if (!hasRequiredCaps) {
return false;
}
}
return true;
}
/**
* Fallback to get models from local database
*/
async getModelsFromDatabase(filters) {
const db = await getDatabase();
const models = [];
try {
let query = `
SELECT openrouter_id, capabilities, input_modalities, output_modalities,
context_window, pricing_input, pricing_output, is_active
FROM openrouter_models
WHERE is_active = 1
`;
const params = [];
// Add provider filter
if (filters.providers?.length) {
query += ` AND provider_name IN (${filters.providers.map(() => '?').join(',')})`;
params.push(...filters.providers);
}
// Add cost filter
if (filters.maxCostPerToken) {
query += ` AND pricing_input <= ?`;
params.push(filters.maxCostPerToken);
}
// Add context window filter
if (filters.minContextWindow) {
query += ` AND context_window >= ?`;
params.push(filters.minContextWindow);
}
query += ` ORDER BY last_updated DESC LIMIT 100`;
const results = await db.all(query, params);
for (const row of results) {
models.push({
modelId: row.openrouter_id,
capabilities: JSON.parse(row.capabilities || '[]'),
inputModalities: JSON.parse(row.input_modalities || '["text"]'),
outputModalities: JSON.parse(row.output_modalities || '["text"]'),
contextWindow: row.context_window || 4096,
pricingInput: row.pricing_input || 0,
pricingOutput: row.pricing_output || 0,
isActive: Boolean(row.is_active)
});
}
}
catch (error) {
console.warn('Database model lookup failed:', error);
}
return models;
}
/**
* Analyze ranking trends
*/
async analyzeTrends() {
const db = await getDatabase();
const trends = [];
try {
// Get current and previous weekly rankings
const currentRankings = await db.all(`
SELECT mr.*, om.openrouter_id
FROM model_rankings mr
JOIN openrouter_models om ON mr.model_internal_id = om.internal_id
WHERE mr.ranking_source = 'openrouter_programming_weekly'
AND mr.collected_at >= date('now', '-7 days')
ORDER BY mr.rank_position
`);
const previousRankings = await db.all(`
SELECT mr.*, om.openrouter_id
FROM model_rankings mr
JOIN openrouter_models om ON mr.model_internal_id = om.internal_id
WHERE mr.ranking_source = 'openrouter_programming_weekly'
AND mr.collected_at >= date('now', '-14 days')
AND mr.collected_at < date('now', '-7 days')
ORDER BY mr.rank_position
`);
// Compare rankings to identify trends
for (const current of currentRankings) {
const previous = previousRankings.find(p => p.model_internal_id === current.model_internal_id);
if (previous) {
const rankChange = previous.rank_position - current.rank_position; // Positive = improvement
const velocityScore = rankChange / previous.rank_position; // Normalize by position
let trendDirection;
if (rankChange > 2)
trendDirection = 'rising';
else if (rankChange < -2)
trendDirection = 'falling';
else
trendDirection = 'stable';
trends.push({
modelId: current.openrouter_id,
currentRank: current.rank_position,
previousRank: previous.rank_position,
rankChange,
trendDirection,
velocityScore
});
}
}
if (trends.length > 0) {
console.log(`๐ Analyzed ${trends.length} model trends`);
}
else {
console.log(`๐ No trend data available (run 'hive sync' to collect rankings)`);
}
}
catch (error) {
console.warn('Trend analysis failed:', error);
}
return trends;
}
/**
* Get comprehensive ranking analysis
*/
async getRankingAnalysis() {
const db = await getDatabase();
// Get latest weekly rankings
const topModels = await db.all(`
SELECT mr.*, om.openrouter_id, om.provider_name
FROM model_rankings mr
JOIN openrouter_models om ON mr.model_internal_id = om.internal_id
WHERE mr.ranking_source = 'openrouter_programming_weekly'
AND mr.collected_at >= date('now', '-7 days')
ORDER BY mr.rank_position
LIMIT 20
`);
const trends = await this.analyzeTrends();
// Convert to ModelRanking format
const topModelsFormatted = topModels.map(row => ({
modelId: row.openrouter_id,
internalId: row.model_internal_id,
rankPosition: row.rank_position,
usagePercentage: row.usage_percentage,
relativeScore: row.relative_score,
provider: row.provider_name,
modelName: row.openrouter_id.split('/')[1] || row.openrouter_id,
period: 'weekly',
dataQuality: row.data_quality
}));
// Group by provider
const topModelsByProvider = {};
for (const model of topModelsFormatted) {
if (!topModelsByProvider[model.provider]) {
topModelsByProvider[model.provider] = [];
}
topModelsByProvider[model.provider].push(model);
}
// Identify rising stars (models improving in rankings)
const risingStars = topModelsFormatted.filter(model => {
const trend = trends.find(t => t.modelId === model.modelId);
return trend && trend.trendDirection === 'rising' && trend.rankChange >= 3;
});
// Cost efficient models (good ranking vs cost ratio)
const costEfficient = topModelsFormatted.filter(model => model.rankPosition <= 15 && model.relativeScore > 0.5);
return {
topModelsOverall: topModelsFormatted,
topModelsByProvider,
risingStars,
costEfficient,
trends,
recommendations: {
bestForSpeed: topModelsFormatted[0] || topModelsFormatted[0],
bestForCost: costEfficient[0] || topModelsFormatted[5],
bestOverall: topModelsFormatted[0] || topModelsFormatted[0],
emergingModels: risingStars.slice(0, 3)
}
};
}
/**
* Update sync metadata
*/
async updateSyncMetadata() {
const db = await getDatabase();
try {
// First ensure the row exists (INSERT OR REPLACE pattern)
await db.run(`
INSERT OR REPLACE INTO sync_metadata
(id, sync_type, started_at, completed_at, status, rankings_last_synced, intelligence_version, next_sync_due)
VALUES (
COALESCE((SELECT id FROM sync_metadata WHERE sync_type = 'openrouter_models'),
'sync_' || lower(hex(randomblob(16)))),
'openrouter_models',
datetime('now'),
datetime('now'),
'completed',
?,
'1.7.0',
datetime('now', '+1 day')
)
`, [new Date().toISOString()]);
}
catch (error) {
console.warn('Failed to update sync metadata:', error);
}
}
/**
* Check if rankings need refresh (older than 24 hours or no rankings exist)
*/
async needsRankingRefresh() {
const db = await getDatabase();
try {
// First check if we have any rankings in the database at all
const rankingCount = await db.get(`
SELECT COUNT(*) as count FROM model_rankings
WHERE ranking_source LIKE 'openrouter_programming_%'
`);
if (!rankingCount || rankingCount.count === 0) {
console.log('๐ No rankings found in database, forcing refresh');
return true; // No rankings exist, definitely need refresh
}
// Check if the column exists
const columns = await db.all("PRAGMA table_info(sync_metadata)");
const hasRankingsColumn = columns.some(col => col.name === 'rankings_last_synced');
if (!hasRankingsColumn) {
// Column doesn't exist yet, needs refresh
return true;
}
const result = await db.get(`
SELECT rankings_last_synced
FROM sync_metadata
WHERE sync_type = 'openrouter_models'
`);
if (!result?.rankings_last_synced) {
return true; // No previous sync
}
const lastSync = new Date(result.rankings_last_synced);
const now = new Date();
const hoursSinceSync = (now.getTime() - lastSync.getTime()) / (1000 * 60 * 60);
return hoursSinceSync >= 24; // Refresh every 24 hours
}
catch (error) {
console.warn('Failed to check sync status:', error);
return true; // Default to refresh on error
}
}
}
// ===== CONVENIENCE FUNCTIONS =====
/**
* Get top programming models from latest rankings
*/
export async function getTopProgrammingModels(limit = 10) {
const rankings = new OpenRouterRankings();
const analysis = await rankings.getRankingAnalysis();
return analysis.topModelsOverall.slice(0, limit);
}
/**
* Find best models by criteria
*/
export async function findBestModels(criteria) {
const rankings = new OpenRouterRankings();
const analysis = await rankings.getRankingAnalysis();
let models = analysis.topModelsOverall;
if (criteria.provider) {
models = analysis.topModelsByProvider[criteria.provider] || [];
}
if (criteria.forCost) {
models = analysis.costEfficient;
}
if (criteria.forSpeed) {
// Top 5 models are typically fastest
models = models.slice(0, 5);
}
return models;
}
/**
* Sync rankings if needed (for integration with existing sync system)
*/
export async function syncRankingsIfNeeded() {
const rankings = new OpenRouterRankings();
if (await rankings.needsRankingRefresh()) {
console.log('๐ Rankings data is stale, refreshing...');
await rankings.collectRankingIntelligence();
return true;
}
return false; // No sync needed
}
export default OpenRouterRankings;