@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
308 lines ⢠14.2 kB
JavaScript
import { z } from "zod";
import { providerUtils } from './provider-config.js';
import * as readline from 'readline';
// Schema for the list models tool
export const ListModelsToolSchema = z.object({
provider_name: z.string().optional().describe('Optional provider name to filter models (e.g., openai, anthropic, google)')
});
// Schema for the update models tool
export const UpdateModelsToolSchema = z.object({});
// Schema for the add model tool (now deprecated in favor of OpenRouter auto-discovery)
export const AddModelToolSchema = z.object({
provider_name: z.string().describe('Provider name'),
model_id: z.string().describe('Model ID'),
capability: z.string().describe('Capability (e.g., chat, embedding, image)'),
description: z.string().optional().describe('Optional description'),
context_window: z.number().optional().describe('Optional context window size')
});
/**
* Run the list models tool
*/
export async function runListModelsTool(args) {
try {
const { provider_name } = args || {};
// Check if OpenRouter is configured first
const isConfigured = await providerUtils.isConfigured();
if (!isConfigured) {
return {
result: "ā OpenRouter not configured\n\n" +
"Configure OpenRouter to access all models:\n" +
"`hive provider configure openrouter <your-api-key>`\n\n" +
"Get your API key: https://openrouter.ai/keys"
};
}
// Get models directly from our bulletproof database
const { getDatabase } = await import('../../storage/unified-database.js');
const database = await getDatabase();
if (!provider_name) {
// List all providers with their models
const providers = await database.all(`
SELECT DISTINCT provider_name, COUNT(*) as model_count
FROM openrouter_models
WHERE is_active = 1
GROUP BY provider_name
ORDER BY provider_name
`);
if (providers.length === 0) {
return {
result: "ā No models found. Please run:\n\n" +
"`hive models update` to sync model data"
};
}
let result = "# š Available Models Through OpenRouter\n\n";
result += `ā
**${providers.length} providers** with bulletproof model database\n\n`;
for (const provider of providers.slice(0, 10)) { // Show first 10 providers
result += `## ${provider.provider_name}\n`;
try {
const models = await database.all(`
SELECT * FROM openrouter_models
WHERE provider_name = ? AND is_active = 1
ORDER BY name
LIMIT 3
`, [provider.provider_name]);
result += `**${provider.model_count} models** available\n`;
// Show first few models as examples
for (const model of models) {
result += `⢠**${model.openrouter_id}**`;
if (model.context_window) {
result += ` (${model.context_window.toLocaleString()} tokens)`;
}
result += `\n`;
}
if (provider.model_count > 3) {
result += `⢠... and ${provider.model_count - 3} more models\n`;
}
}
catch (error) {
result += "Error loading models\n";
}
result += "\n";
}
if (providers.length > 10) {
result += `... and ${providers.length - 10} more providers\n\n`;
}
result += "**Commands:**\n";
result += "⢠List specific provider: `hive models list <provider-name>`\n";
result += "⢠Setup profiles: `hive setup`\n";
result += "⢠Use consensus: `hive consensus \"your question\"`";
return { result };
}
// Provider-specific listing
const providerModels = await database.all(`
SELECT * FROM openrouter_models
WHERE provider_name = ? AND is_active = 1
ORDER BY name
`, [provider_name]);
if (providerModels.length === 0) {
const availableProviders = await database.all(`
SELECT DISTINCT provider_name FROM openrouter_models WHERE is_active = 1
`);
return {
result: `ā Provider "${provider_name}" not found.\n\n` +
`Available providers: ${availableProviders.map(p => p.provider_name).join(', ')}\n\n` +
"Use: `hive models list` to see all providers"
};
}
let result = `# š¤ Available Models for ${provider_name}\n\n`;
result += `**${providerModels.length} models** available through OpenRouter\n\n`;
// Show all models
for (let i = 0; i < providerModels.length; i++) {
const model = providerModels[i];
result += `${i + 1}. **${model.openrouter_id}**`;
if (model.context_window) {
result += ` (${model.context_window.toLocaleString()} tokens)`;
}
if (model.description) {
result += `: ${model.description}`;
}
result += "\n";
}
// Get API key for display
const apiKey = await import('../../storage/unified-database.js').then(db => db.getOpenRouterApiKey());
const keyDisplay = apiKey ? `...${apiKey.slice(-4)}` : 'configured';
result += `\nā
OpenRouter configured with API key ending in ${keyDisplay}\n`;
result += `\n**Use these models in:**\n`;
result += "⢠Pipeline profiles: `hive setup`\n";
result += "⢠Direct consensus: `hive consensus \"your question\"`";
return { result };
}
catch (error) {
return {
result: `ā Error listing models: ${error.message || 'Unknown error'}\n\n` +
"Try: `hive setup` to refresh provider data"
};
}
}
/**
* Run the update models tool - now updates OpenRouter data
*/
export async function runUpdateModelsTool() {
try {
// Check if OpenRouter is configured
const isConfigured = await providerUtils.isConfigured();
if (!isConfigured) {
return {
result: "ā OpenRouter not configured\n\n" +
"Configure OpenRouter first:\n" +
"`hive provider configure openrouter <your-api-key>`"
};
}
console.log('š Starting bulletproof OpenRouter sync...');
// Get OpenRouter API key for direct fetch
const { getOpenRouterApiKey } = await import('../../storage/unified-database.js');
const apiKey = await getOpenRouterApiKey();
if (!apiKey) {
throw new Error('OpenRouter API key not found');
}
// Fetch models directly from OpenRouter API (bypassing old sync manager)
console.log('š„ Fetching models directly from OpenRouter API...');
const response = await fetch('https://openrouter.ai/api/v1/models', {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`OpenRouter API error: ${response.status} ${response.statusText}`);
}
const apiData = await response.json();
const allModelsData = apiData.data || [];
console.log(`š Fetched ${allModelsData.length} models from OpenRouter API`);
console.log('š Processing and updating database...');
// Run our bulletproof migration sync (handles model ID changes!)
const { syncOpenRouterModelsWithMigration, initializeUnifiedDatabase } = await import('../../storage/unified-database.js');
// Ensure database is properly initialized first
await initializeUnifiedDatabase();
const changes = await syncOpenRouterModelsWithMigration(allModelsData);
// Run template maintenance after model sync
console.log('š§ Running template maintenance...');
try {
const { runTemplateMaintenanceIfDue } = await import('./template-maintenance.js');
await runTemplateMaintenanceIfDue();
console.log('ā
Template maintenance completed');
}
catch (error) {
console.warn('ā ļø Template maintenance failed (non-critical):', error);
}
// Count providers from the data
const providers = [...new Set(allModelsData.map((m) => m.id.split('/')[0]))].length;
let result = `ā
Bulletproof OpenRouter sync completed!\n\n`;
result += `**${providers} providers** with **${allModelsData.length} models** processed\n\n`;
result += `**šÆ Bulletproof Migration Results:**\n`;
result += `⢠ā Added: ${changes.added} new models\n`;
result += `⢠š Updated: ${changes.updated} existing models\n`;
result += `⢠š ID Changed: ${changes.idChanged} model IDs updated (profiles preserved!)\n`;
result += `⢠š¤ Deactivated: ${changes.deactivated} deprecated models\n\n`;
result += `**ā
All profile references remain stable through model changes**\n\n`;
result += `Use: \`hive models list\` to see all available models`;
return { result };
}
catch (error) {
return {
result: `ā Error during bulletproof OpenRouter sync: ${error.message || 'Unknown error'}\n\n` +
"This may be due to:\n" +
"⢠Network connectivity issues\n" +
"⢠Invalid OpenRouter API key\n" +
"⢠OpenRouter API temporarily unavailable\n\n" +
"Your existing profiles remain safe with stable model references."
};
}
}
/**
* Run the add model tool - OpenRouter handles all models dynamically
*/
export async function runAddModelTool(args) {
return {
result: "ā¹ļø **Custom models are no longer needed**\n\n" +
"OpenRouter automatically provides access to 300+ models from 55+ providers.\n" +
"All models are discovered and updated automatically.\n\n" +
"**Instead of adding models manually:**\n" +
"⢠Use: `hive models list` to see all available models\n" +
"⢠Use: `hive models update` to sync latest model data\n" +
"⢠Create profiles: `hive setup`\n\n" +
"**OpenRouter supports:**\n" +
"⢠All major AI providers (OpenAI, Anthropic, Google, Meta, etc.)\n" +
"⢠Automatic model discovery\n" +
"⢠Real-time availability updates\n" +
"⢠Unified API access"
};
}
/**
* Interactive model selection for CLI using OpenRouter data
*/
export async function selectModelInteractive(providerName, capability = 'chat') {
try {
// Get models from unified database
const { getDatabase } = await import('../../storage/unified-database.js');
const database = await getDatabase();
const models = await database.all(`
SELECT * FROM openrouter_models
WHERE provider_name = ? AND is_active = 1
ORDER BY name
`, [providerName]);
if (models.length === 0) {
console.log(`No models found for provider ${providerName}.`);
console.log('Try running: hive models update');
return null;
}
console.log(`\nSelect a model for ${providerName}:\n`);
for (let i = 0; i < models.length; i++) {
const model = models[i];
console.log(`${i + 1}. ${model.openrouter_id}${model.context_window ? ` (${model.context_window.toLocaleString()} tokens)` : ''}`);
if (model.description) {
console.log(` ${model.description}\n`);
}
else {
console.log('');
}
}
console.log(`${models.length + 1}. Enter a custom model ID\n`);
console.log('Please make your selection below:');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question('Enter your choice (number or custom model ID): ', (answer) => {
rl.close();
// Check if the answer is a number
const choice = parseInt(answer);
if (!isNaN(choice) && choice >= 1 && choice <= models.length) {
// Selected from the list
resolve(models[choice - 1].openrouter_id);
}
else if (!isNaN(choice) && choice === models.length + 1) {
// Custom model ID
const rl2 = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl2.question('Enter custom model ID: ', (customId) => {
rl2.close();
resolve(customId.trim());
});
}
else {
// Treat as custom model ID
resolve(answer.trim());
}
});
});
}
catch (error) {
console.error('Error loading models:', error.message);
return null;
}
}
// Tool exports
export const listModelsToolName = 'list_models';
export const listModelsToolDescription = 'List available models from OpenRouter providers';
export const updateModelsToolName = 'update_models';
export const updateModelsToolDescription = 'Update model data from OpenRouter';
export const addModelToolName = 'add_model';
export const addModelToolDescription = 'Add custom model (deprecated - OpenRouter handles all models)';
// Export the model selection utilities
export const modelSelectionUtils = {
selectModelInteractive
};
//# sourceMappingURL=model-selection.js.map