Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'

This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAEpE,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,aAAa,CAAC;IAC/B,YAAY,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,aAAa,CAAC,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,CAAC,EAAE,UAAU,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAA0B;gBAE5B,MAAM,EAAE,YAAY;IAMhC,OAAO,CAAC,gBAAgB;IAsDxB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE;QACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,QAAQ,CAAC,EAAE,aAAa,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,UAAU;IAoDd;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE;IA8BnD;;OAEG;IACH,SAAS,IAAI,UAAU,EAAE;IAIzB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAKjC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG;QACjC,QAAQ,EAAE,aAAa,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;CAOF;AAED,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC"}

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,207 @@
/**
* Model routing logic for Gemini and OpenRouter
*/
import { ModelProvider, ModelRoute, SynthError } from '../types.js';
export interface RouterConfig {
defaultProvider: ModelProvider;
providerKeys: {
gemini?: string;
openrouter?: string;
};
fallbackChain?: ModelProvider[];
customRoutes?: ModelRoute[];
}
/**
* Model router for intelligent provider selection
*/
export class ModelRouter {
private config: RouterConfig;
private routes: Map<string, ModelRoute>;
constructor(config: RouterConfig) {
this.config = config;
this.routes = new Map();
this.initializeRoutes();
}
private initializeRoutes(): void {
// Default Gemini models
const geminiRoutes: ModelRoute[] = [
{
provider: 'gemini',
model: 'gemini-2.0-flash-exp',
priority: 10,
capabilities: ['text', 'json', 'streaming', 'fast']
},
{
provider: 'gemini',
model: 'gemini-1.5-pro',
priority: 8,
capabilities: ['text', 'json', 'complex', 'reasoning']
},
{
provider: 'gemini',
model: 'gemini-1.5-flash',
priority: 9,
capabilities: ['text', 'json', 'fast', 'efficient']
}
];
// Default OpenRouter models
const openrouterRoutes: ModelRoute[] = [
{
provider: 'openrouter',
model: 'anthropic/claude-3.5-sonnet',
priority: 10,
capabilities: ['text', 'json', 'reasoning', 'complex']
},
{
provider: 'openrouter',
model: 'openai/gpt-4-turbo',
priority: 9,
capabilities: ['text', 'json', 'reasoning']
},
{
provider: 'openrouter',
model: 'meta-llama/llama-3.1-70b-instruct',
priority: 7,
capabilities: ['text', 'json', 'fast']
}
];
// Add all routes
[...geminiRoutes, ...openrouterRoutes, ...(this.config.customRoutes || [])].forEach(
route => {
const key = `${route.provider}:${route.model}`;
this.routes.set(key, route);
}
);
}
/**
* Select best model for given requirements
*/
selectModel(requirements: {
capabilities?: string[];
provider?: ModelProvider;
preferredModel?: string;
}): ModelRoute {
const { capabilities = [], provider, preferredModel } = requirements;
// If specific model requested, try to use it
if (provider && preferredModel) {
const key = `${provider}:${preferredModel}`;
const route = this.routes.get(key);
if (route) {
return route;
}
}
// Filter by provider if specified
let candidates = Array.from(this.routes.values());
if (provider) {
candidates = candidates.filter(r => r.provider === provider);
} else {
// Use default provider
candidates = candidates.filter(r => r.provider === this.config.defaultProvider);
}
// Filter by capabilities
if (capabilities.length > 0) {
candidates = candidates.filter(route =>
capabilities.every(cap => route.capabilities.includes(cap))
);
}
// Sort by priority (highest first)
candidates.sort((a, b) => b.priority - a.priority);
if (candidates.length === 0) {
throw new SynthError(
'No suitable model found for requirements',
'NO_MODEL_FOUND',
{ requirements }
);
}
// Safe to access: we've checked length > 0
const selectedRoute = candidates[0];
if (!selectedRoute) {
throw new SynthError(
'Unexpected error: no route selected despite candidates',
'ROUTE_SELECTION_ERROR',
{ candidates }
);
}
return selectedRoute;
}
/**
* Get fallback chain for resilience
*/
getFallbackChain(primary: ModelRoute): ModelRoute[] {
const chain: ModelRoute[] = [primary];
if (this.config.fallbackChain) {
// Only require essential capabilities for fallback models
// Filter out optimization flags like 'streaming', 'fast', 'efficient'
const essentialCapabilities = primary.capabilities.filter(
cap => !['streaming', 'fast', 'efficient', 'complex', 'reasoning'].includes(cap)
);
for (const provider of this.config.fallbackChain) {
try {
const fallback = this.selectModel({
provider,
capabilities: essentialCapabilities.length > 0 ? essentialCapabilities : undefined
});
if (fallback.model !== primary.model) {
chain.push(fallback);
}
} catch (error) {
// Skip this fallback provider if no suitable model found
console.warn(`No suitable fallback model found for provider ${provider}`);
}
}
}
return chain;
}
/**
* Get all available routes
*/
getRoutes(): ModelRoute[] {
return Array.from(this.routes.values());
}
/**
* Add custom route
*/
addRoute(route: ModelRoute): void {
const key = `${route.provider}:${route.model}`;
this.routes.set(key, route);
}
/**
* Get model configuration
*/
getModelConfig(route: ModelRoute): {
provider: ModelProvider;
model: string;
apiKey?: string;
} {
return {
provider: route.provider,
model: route.model,
apiKey: this.config.providerKeys[route.provider]
};
}
}
export { ModelProvider, ModelRoute };

View File

@@ -0,0 +1,148 @@
/**
* Model Router for intelligent model selection
*/
export class ModelRouter {
constructor(options = {}) {
this.models = options.models || [];
this.strategy = options.strategy || 'round-robin';
this.currentIndex = 0;
this.modelStats = new Map();
// Initialize stats for provided models
this.models.forEach(model => {
this.modelStats.set(model.id, {
requests: 0,
errors: 0,
totalLatency: 0,
avgLatency: 0
});
});
}
/**
* Route request to appropriate model
* @param {Object} request - Request object
* @returns {string} Selected model ID
*/
route(request) {
if (this.models.length === 0) {
throw new Error('No models available for routing');
}
switch (this.strategy) {
case 'round-robin':
return this._roundRobin();
case 'least-latency':
return this._leastLatency();
case 'cost-optimized':
return this._costOptimized(request);
case 'capability-based':
return this._capabilityBased(request);
default:
return this.models[0];
}
}
/**
* Register model
*/
registerModel(model) {
if (!model.id || !model.endpoint) {
throw new Error('Model must have id and endpoint');
}
this.models.push(model);
this.modelStats.set(model.id, {
requests: 0,
errors: 0,
totalLatency: 0,
avgLatency: 0
});
}
/**
* Record model performance
*/
recordMetrics(modelId, latency, success = true) {
const stats = this.modelStats.get(modelId);
if (!stats) return;
stats.requests++;
if (!success) stats.errors++;
stats.totalLatency += latency;
stats.avgLatency = stats.totalLatency / stats.requests;
}
/**
* Get model statistics
*/
getStats(modelId = null) {
if (modelId) {
return this.modelStats.get(modelId);
}
return Object.fromEntries(this.modelStats);
}
/**
* Round-robin routing
* @private
*/
_roundRobin() {
const model = this.models[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.models.length;
return model.id;
}
/**
* Route to model with least latency
* @private
*/
_leastLatency() {
let bestModel = this.models[0];
let lowestLatency = Infinity;
for (const model of this.models) {
const stats = this.modelStats.get(model.id);
if (stats && stats.avgLatency < lowestLatency) {
lowestLatency = stats.avgLatency;
bestModel = model;
}
}
return bestModel.id;
}
/**
* Cost-optimized routing
* @private
*/
_costOptimized(request) {
const requestSize = JSON.stringify(request).length;
// Route small requests to cheaper models
if (requestSize < 1000) {
return this.models[0].id;
}
return this.models[this.models.length - 1].id;
}
/**
* Capability-based routing
* @private
*/
_capabilityBased(request) {
const requiredCapability = request.capability || 'general';
const capableModels = this.models.filter(model =>
model.capabilities?.includes(requiredCapability)
);
if (capableModels.length === 0) {
return this.models[0].id;
}
return capableModels[0].id;
}
}