UNPKG

@ruvector/postgres-cli

Version:

Advanced AI vector database CLI for PostgreSQL - pgvector drop-in replacement with 53+ SQL functions, 39 attention mechanisms, GNN layers, hyperbolic embeddings, and self-learning capabilities

335 lines (329 loc) 14.6 kB
/** * Routing/Agent Commands * CLI commands for Tiny Dancer agent routing and management */ import chalk from 'chalk'; import ora from 'ora'; import Table from 'cli-table3'; export class RoutingCommands { static async registerAgent(client, options) { const spinner = ora(`Registering agent '${options.name}'...`).start(); try { await client.connect(); const capabilities = options.capabilities.split(',').map(c => c.trim()); await client.registerAgent(options.name, options.type, capabilities, parseFloat(options.cost), parseFloat(options.latency), parseFloat(options.quality)); spinner.succeed(chalk.green(`Agent '${options.name}' registered successfully`)); console.log(chalk.bold.blue('\nAgent Details:')); console.log(chalk.gray('-'.repeat(40))); console.log(` ${chalk.green('Name:')} ${options.name}`); console.log(` ${chalk.green('Type:')} ${options.type}`); console.log(` ${chalk.green('Capabilities:')} ${capabilities.join(', ')}`); console.log(` ${chalk.green('Cost/Request:')} $${options.cost}`); console.log(` ${chalk.green('Avg Latency:')} ${options.latency}ms`); console.log(` ${chalk.green('Quality Score:')} ${options.quality}`); } catch (err) { spinner.fail(chalk.red('Failed to register agent')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async registerAgentFull(client, options) { const spinner = ora('Registering agent with full config...').start(); try { await client.connect(); const config = JSON.parse(options.config); await client.registerAgentFull(config); spinner.succeed(chalk.green(`Agent '${config.name}' registered successfully`)); } catch (err) { spinner.fail(chalk.red('Failed to register agent')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async updateMetrics(client, options) { const spinner = ora(`Updating metrics for '${options.name}'...`).start(); try { await client.connect(); await client.updateAgentMetrics(options.name, parseFloat(options.latency), options.success, options.quality ? parseFloat(options.quality) : undefined); spinner.succeed(chalk.green('Metrics updated')); console.log(` ${chalk.green('Latency:')} ${options.latency}ms`); console.log(` ${chalk.green('Success:')} ${options.success}`); if (options.quality) { console.log(` ${chalk.green('Quality:')} ${options.quality}`); } } catch (err) { spinner.fail(chalk.red('Failed to update metrics')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async removeAgent(client, name) { const spinner = ora(`Removing agent '${name}'...`).start(); try { await client.connect(); await client.removeAgent(name); spinner.succeed(chalk.green(`Agent '${name}' removed`)); } catch (err) { spinner.fail(chalk.red('Failed to remove agent')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async setActive(client, name, active) { const spinner = ora(`Setting agent '${name}' ${active ? 'active' : 'inactive'}...`).start(); try { await client.connect(); await client.setAgentActive(name, active); spinner.succeed(chalk.green(`Agent '${name}' is now ${active ? 'active' : 'inactive'}`)); } catch (err) { spinner.fail(chalk.red('Failed to update agent status')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async route(client, options) { const spinner = ora('Routing request to best agent...').start(); try { await client.connect(); const embedding = JSON.parse(options.embedding); const optimizeFor = options.optimizeFor || 'balanced'; const constraints = options.constraints ? JSON.parse(options.constraints) : undefined; const decision = await client.route(embedding, optimizeFor, constraints); spinner.succeed(chalk.green('Routing decision made')); console.log(chalk.bold.blue('\nRouting Decision:')); console.log(chalk.gray('-'.repeat(50))); console.log(` ${chalk.green('Selected Agent:')} ${chalk.bold(decision.agent_name)}`); console.log(` ${chalk.green('Confidence:')} ${(decision.confidence * 100).toFixed(1)}%`); console.log(` ${chalk.green('Estimated Cost:')} $${decision.estimated_cost.toFixed(4)}`); console.log(` ${chalk.green('Estimated Latency:')} ${decision.estimated_latency_ms.toFixed(0)}ms`); console.log(` ${chalk.green('Expected Quality:')} ${(decision.expected_quality * 100).toFixed(1)}%`); console.log(` ${chalk.green('Similarity Score:')} ${decision.similarity_score.toFixed(4)}`); if (decision.reasoning) { console.log(` ${chalk.green('Reasoning:')} ${decision.reasoning}`); } if (decision.alternatives && decision.alternatives.length > 0) { console.log(chalk.bold.blue('\nAlternatives:')); for (const alt of decision.alternatives.slice(0, 3)) { console.log(` ${chalk.yellow('-')} ${alt.name} (score: ${alt.score?.toFixed(3) || 'N/A'})`); } } } catch (err) { spinner.fail(chalk.red('Routing failed')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async listAgents(client) { const spinner = ora('Fetching agents...').start(); try { await client.connect(); const agents = await client.listAgents(); spinner.stop(); if (agents.length === 0) { console.log(chalk.yellow('No agents registered')); return; } console.log(chalk.bold.blue(`\nRegistered Agents (${agents.length}):`)); const table = new Table({ head: [ chalk.cyan('Name'), chalk.cyan('Type'), chalk.cyan('Cost'), chalk.cyan('Latency'), chalk.cyan('Quality'), chalk.cyan('Requests'), chalk.cyan('Active'), ], colWidths: [15, 12, 10, 10, 10, 10, 8], }); for (const agent of agents) { table.push([ agent.name, agent.agent_type, `$${agent.cost_per_request.toFixed(3)}`, `${agent.avg_latency_ms.toFixed(0)}ms`, `${(agent.quality_score * 100).toFixed(0)}%`, agent.total_requests.toString(), agent.is_active ? chalk.green('Yes') : chalk.red('No'), ]); } console.log(table.toString()); } catch (err) { spinner.fail(chalk.red('Failed to list agents')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async getAgent(client, name) { const spinner = ora(`Fetching agent '${name}'...`).start(); try { await client.connect(); const agent = await client.getAgent(name); spinner.stop(); console.log(chalk.bold.blue(`\nAgent: ${agent.name}`)); console.log(chalk.gray('-'.repeat(50))); console.log(` ${chalk.green('Type:')} ${agent.agent_type}`); console.log(` ${chalk.green('Capabilities:')} ${agent.capabilities.join(', ')}`); console.log(` ${chalk.green('Active:')} ${agent.is_active ? chalk.green('Yes') : chalk.red('No')}`); console.log(chalk.bold.blue('\nCost Model:')); console.log(` ${chalk.green('Per Request:')} $${agent.cost_model.per_request}`); if (agent.cost_model.per_token) { console.log(` ${chalk.green('Per Token:')} $${agent.cost_model.per_token}`); } console.log(chalk.bold.blue('\nPerformance:')); console.log(` ${chalk.green('Avg Latency:')} ${agent.performance.avg_latency_ms}ms`); console.log(` ${chalk.green('Quality Score:')} ${(agent.performance.quality_score * 100).toFixed(1)}%`); console.log(` ${chalk.green('Success Rate:')} ${(agent.performance.success_rate * 100).toFixed(1)}%`); console.log(` ${chalk.green('Total Requests:')} ${agent.performance.total_requests}`); } catch (err) { spinner.fail(chalk.red('Failed to get agent')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async findByCapability(client, options) { const spinner = ora(`Finding agents with '${options.capability}'...`).start(); try { await client.connect(); const limit = options.limit ? parseInt(options.limit) : 10; const agents = await client.findAgentsByCapability(options.capability, limit); spinner.stop(); if (agents.length === 0) { console.log(chalk.yellow(`No agents found with capability '${options.capability}'`)); return; } console.log(chalk.bold.blue(`\nAgents with '${options.capability}' (${agents.length}):`)); const table = new Table({ head: [ chalk.cyan('Name'), chalk.cyan('Quality'), chalk.cyan('Latency'), chalk.cyan('Cost'), ], colWidths: [20, 12, 12, 12], }); for (const agent of agents) { table.push([ agent.name, `${(agent.quality_score * 100).toFixed(0)}%`, `${agent.avg_latency_ms.toFixed(0)}ms`, `$${agent.cost_per_request.toFixed(3)}`, ]); } console.log(table.toString()); } catch (err) { spinner.fail(chalk.red('Failed to find agents')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async stats(client) { const spinner = ora('Fetching routing statistics...').start(); try { await client.connect(); const stats = await client.routingStats(); spinner.stop(); console.log(chalk.bold.blue('\nRouting Statistics:')); console.log(chalk.gray('-'.repeat(40))); console.log(` ${chalk.green('Total Agents:')} ${stats.total_agents}`); console.log(` ${chalk.green('Active Agents:')} ${stats.active_agents}`); console.log(` ${chalk.green('Total Requests:')} ${stats.total_requests}`); console.log(` ${chalk.green('Avg Quality:')} ${(stats.average_quality * 100).toFixed(1)}%`); } catch (err) { spinner.fail(chalk.red('Failed to get stats')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static async clearAgents(client) { const spinner = ora('Clearing all agents...').start(); try { await client.connect(); await client.clearAgents(); spinner.succeed(chalk.green('All agents cleared')); } catch (err) { spinner.fail(chalk.red('Failed to clear agents')); console.error(chalk.red(err.message)); } finally { await client.disconnect(); } } static showHelp() { console.log(chalk.bold.blue('\nTiny Dancer Routing System:')); console.log(chalk.gray('-'.repeat(60))); console.log(` ${chalk.yellow('Overview:')} Intelligent routing of AI requests to the most suitable agent based on cost, latency, quality, and capabilities. ${chalk.yellow('Agent Types:')} ${chalk.green('llm')} - Large Language Models (GPT-4, Claude, etc.) ${chalk.green('embedding')} - Embedding models ${chalk.green('specialized')} - Domain-specific models ${chalk.green('multimodal')} - Vision/audio models ${chalk.yellow('Optimization Targets:')} ${chalk.green('cost')} - Minimize cost ${chalk.green('latency')} - Minimize response time ${chalk.green('quality')} - Maximize output quality ${chalk.green('balanced')} - Balance all factors (default) ${chalk.yellow('Commands:')} ${chalk.green('routing register')} - Register a new agent ${chalk.green('routing register-full')} - Register with full JSON config ${chalk.green('routing update')} - Update agent metrics ${chalk.green('routing remove')} - Remove an agent ${chalk.green('routing set-active')} - Enable/disable agent ${chalk.green('routing route')} - Route a request ${chalk.green('routing list')} - List all agents ${chalk.green('routing get')} - Get agent details ${chalk.green('routing find')} - Find agents by capability ${chalk.green('routing stats')} - Get routing statistics ${chalk.green('routing clear')} - Clear all agents ${chalk.yellow('Example:')} ${chalk.gray('# Register an agent')} ruvector-pg routing register \\ --name gpt-4 \\ --type llm \\ --capabilities "code,translation,analysis" \\ --cost 0.03 \\ --latency 500 \\ --quality 0.95 ${chalk.gray('# Route a request')} ruvector-pg routing route \\ --embedding "[0.1, 0.2, ...]" \\ --optimize-for balanced \\ --constraints '{"max_cost": 0.1}' `); } } export default RoutingCommands;