@juspay/neurolink 7.1.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -2
- package/README.md +16 -11
- package/dist/cli/commands/config.d.ts +2 -2
- package/dist/cli/commands/config.js +22 -21
- package/dist/cli/commands/mcp.d.ts +79 -0
- package/dist/cli/commands/mcp.js +916 -0
- package/dist/cli/commands/models.d.ts +63 -0
- package/dist/cli/commands/models.js +653 -0
- package/dist/cli/commands/ollama.js +56 -55
- package/dist/cli/factories/commandFactory.d.ts +14 -0
- package/dist/cli/factories/commandFactory.js +346 -47
- package/dist/cli/index.js +25 -10
- package/dist/cli/utils/completeSetup.js +9 -8
- package/dist/cli/utils/envManager.js +7 -6
- package/dist/cli/utils/interactiveSetup.js +20 -19
- package/dist/core/analytics.js +25 -38
- package/dist/core/baseProvider.d.ts +8 -0
- package/dist/core/baseProvider.js +177 -68
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.js +17 -0
- package/dist/core/evaluation.js +25 -14
- package/dist/core/factory.js +19 -18
- package/dist/core/streamAnalytics.d.ts +65 -0
- package/dist/core/streamAnalytics.js +125 -0
- package/dist/lib/core/analytics.js +25 -38
- package/dist/lib/core/baseProvider.d.ts +8 -0
- package/dist/lib/core/baseProvider.js +177 -68
- package/dist/lib/core/constants.d.ts +11 -0
- package/dist/lib/core/constants.js +17 -0
- package/dist/lib/core/evaluation.js +25 -14
- package/dist/lib/core/factory.js +19 -18
- package/dist/lib/core/streamAnalytics.d.ts +65 -0
- package/dist/lib/core/streamAnalytics.js +125 -0
- package/dist/lib/models/modelRegistry.d.ts +132 -0
- package/dist/lib/models/modelRegistry.js +483 -0
- package/dist/lib/models/modelResolver.d.ts +115 -0
- package/dist/lib/models/modelResolver.js +467 -0
- package/dist/lib/neurolink.d.ts +4 -1
- package/dist/lib/neurolink.js +101 -67
- package/dist/lib/providers/anthropic.js +3 -0
- package/dist/lib/providers/googleAiStudio.js +13 -0
- package/dist/lib/providers/huggingFace.js +15 -3
- package/dist/lib/providers/mistral.js +19 -7
- package/dist/lib/providers/ollama.js +31 -7
- package/dist/lib/providers/openAI.js +12 -0
- package/dist/lib/sdk/toolRegistration.js +2 -2
- package/dist/lib/types/cli.d.ts +56 -1
- package/dist/lib/types/contextTypes.d.ts +110 -0
- package/dist/lib/types/contextTypes.js +176 -0
- package/dist/lib/types/index.d.ts +4 -1
- package/dist/lib/types/mcpTypes.d.ts +118 -7
- package/dist/lib/types/providers.d.ts +81 -0
- package/dist/lib/types/streamTypes.d.ts +44 -7
- package/dist/lib/types/tools.d.ts +9 -0
- package/dist/lib/types/universalProviderOptions.d.ts +3 -1
- package/dist/lib/types/universalProviderOptions.js +2 -1
- package/dist/lib/utils/logger.d.ts +7 -0
- package/dist/lib/utils/logger.js +11 -0
- package/dist/lib/utils/performance.d.ts +105 -0
- package/dist/lib/utils/performance.js +210 -0
- package/dist/lib/utils/retryHandler.d.ts +89 -0
- package/dist/lib/utils/retryHandler.js +269 -0
- package/dist/models/modelRegistry.d.ts +132 -0
- package/dist/models/modelRegistry.js +483 -0
- package/dist/models/modelResolver.d.ts +115 -0
- package/dist/models/modelResolver.js +468 -0
- package/dist/neurolink.d.ts +4 -1
- package/dist/neurolink.js +101 -67
- package/dist/providers/anthropic.js +3 -0
- package/dist/providers/googleAiStudio.js +13 -0
- package/dist/providers/huggingFace.js +15 -3
- package/dist/providers/mistral.js +19 -7
- package/dist/providers/ollama.js +31 -7
- package/dist/providers/openAI.js +12 -0
- package/dist/sdk/toolRegistration.js +2 -2
- package/dist/types/cli.d.ts +56 -1
- package/dist/types/contextTypes.d.ts +110 -0
- package/dist/types/contextTypes.js +177 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/mcpTypes.d.ts +118 -7
- package/dist/types/providers.d.ts +81 -0
- package/dist/types/streamTypes.d.ts +44 -7
- package/dist/types/tools.d.ts +9 -0
- package/dist/types/universalProviderOptions.d.ts +3 -1
- package/dist/types/universalProviderOptions.js +3 -1
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.js +11 -0
- package/dist/utils/performance.d.ts +105 -0
- package/dist/utils/performance.js +210 -0
- package/dist/utils/retryHandler.d.ts +89 -0
- package/dist/utils/retryHandler.js +269 -0
- package/package.json +2 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Resolver for NeuroLink CLI Commands
|
|
3
|
+
* Provides model resolution, search, and recommendation functionality
|
|
4
|
+
* Part of Phase 4.1 - Models Command System
|
|
5
|
+
*/
|
|
6
|
+
import { AIProviderName } from "../core/types.js";
|
|
7
|
+
import type { JsonValue } from "../types/common.js";
|
|
8
|
+
import { type ModelInfo, type ModelSearchFilters, type ModelSearchResult, type ModelCapabilities, type UseCaseSuitability } from "./modelRegistry.js";
|
|
9
|
+
/**
|
|
10
|
+
* Model recommendation context
|
|
11
|
+
*/
|
|
12
|
+
export interface RecommendationContext {
|
|
13
|
+
useCase?: keyof UseCaseSuitability;
|
|
14
|
+
maxCost?: number;
|
|
15
|
+
minQuality?: "low" | "medium" | "high";
|
|
16
|
+
requireCapabilities?: (keyof ModelCapabilities)[];
|
|
17
|
+
excludeProviders?: AIProviderName[];
|
|
18
|
+
contextSize?: number;
|
|
19
|
+
preferLocal?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Model recommendation result
|
|
23
|
+
*/
|
|
24
|
+
export interface ModelRecommendation {
|
|
25
|
+
model: ModelInfo;
|
|
26
|
+
score: number;
|
|
27
|
+
reasoning: string[];
|
|
28
|
+
alternatives: ModelInfo[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Model comparison result
|
|
32
|
+
*/
|
|
33
|
+
export interface ModelComparison {
|
|
34
|
+
models: ModelInfo[];
|
|
35
|
+
comparison: {
|
|
36
|
+
capabilities: Record<keyof ModelCapabilities, ModelInfo[]>;
|
|
37
|
+
pricing: {
|
|
38
|
+
cheapest: ModelInfo;
|
|
39
|
+
mostExpensive: ModelInfo;
|
|
40
|
+
};
|
|
41
|
+
performance: Record<string, ModelInfo[]>;
|
|
42
|
+
contextSize: {
|
|
43
|
+
largest: ModelInfo;
|
|
44
|
+
smallest: ModelInfo;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Model resolver class with advanced search and recommendation functionality
|
|
50
|
+
*/
|
|
51
|
+
export declare class ModelResolver {
|
|
52
|
+
/**
|
|
53
|
+
* Resolve model ID from alias or fuzzy name
|
|
54
|
+
*/
|
|
55
|
+
static resolveModel(query: string): ModelInfo | null;
|
|
56
|
+
/**
|
|
57
|
+
* Search models with advanced filtering
|
|
58
|
+
*/
|
|
59
|
+
static searchModels(filters: ModelSearchFilters): ModelSearchResult[];
|
|
60
|
+
/**
|
|
61
|
+
* Get best model for specific use case
|
|
62
|
+
*/
|
|
63
|
+
static getBestModel(context: RecommendationContext): ModelRecommendation;
|
|
64
|
+
/**
|
|
65
|
+
* Compare multiple models
|
|
66
|
+
*/
|
|
67
|
+
static compareModels(modelIds: string[]): ModelComparison;
|
|
68
|
+
/**
|
|
69
|
+
* Get models by category
|
|
70
|
+
*/
|
|
71
|
+
static getModelsByCategory(category: ModelInfo["category"]): ModelInfo[];
|
|
72
|
+
/**
|
|
73
|
+
* Get recommended models for use case
|
|
74
|
+
*/
|
|
75
|
+
static getRecommendedModelsForUseCase(useCase: string): ModelInfo[];
|
|
76
|
+
/**
|
|
77
|
+
* Calculate cost comparison for models
|
|
78
|
+
*/
|
|
79
|
+
static calculateCostComparison(models: ModelInfo[], inputTokens?: number, outputTokens?: number): Array<{
|
|
80
|
+
model: ModelInfo;
|
|
81
|
+
cost: number;
|
|
82
|
+
costPer1K: number;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Get model statistics
|
|
86
|
+
*/
|
|
87
|
+
static getModelStatistics(): JsonValue;
|
|
88
|
+
/**
|
|
89
|
+
* Evaluate how well a model matches search filters
|
|
90
|
+
*/
|
|
91
|
+
private static evaluateModelMatch;
|
|
92
|
+
/**
|
|
93
|
+
* Score model for recommendation context
|
|
94
|
+
*/
|
|
95
|
+
private static scoreModelForContext;
|
|
96
|
+
/**
|
|
97
|
+
* Generate recommendation reasoning
|
|
98
|
+
*/
|
|
99
|
+
private static generateRecommendationReasoning;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Utility functions for CLI integration
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* Format search results for CLI display
|
|
106
|
+
*/
|
|
107
|
+
export declare function formatSearchResults(results: ModelSearchResult[]): JsonValue;
|
|
108
|
+
/**
|
|
109
|
+
* Format recommendation for CLI display
|
|
110
|
+
*/
|
|
111
|
+
export declare function formatRecommendation(recommendation: ModelRecommendation): JsonValue;
|
|
112
|
+
/**
|
|
113
|
+
* Format model comparison for CLI display
|
|
114
|
+
*/
|
|
115
|
+
export declare function formatComparison(comparison: ModelComparison): JsonValue;
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Resolver for NeuroLink CLI Commands
|
|
3
|
+
* Provides model resolution, search, and recommendation functionality
|
|
4
|
+
* Part of Phase 4.1 - Models Command System
|
|
5
|
+
*/
|
|
6
|
+
import { AIProviderName } from "../core/types.js";
|
|
7
|
+
import { MODEL_REGISTRY, MODEL_ALIASES, USE_CASE_RECOMMENDATIONS, getAllModels, getModelById, getModelsByProvider, getAvailableProviders, calculateCost, formatModelForDisplay, } from "./modelRegistry.js";
|
|
8
|
+
/**
|
|
9
|
+
* Model resolver class with advanced search and recommendation functionality
|
|
10
|
+
*/
|
|
11
|
+
export class ModelResolver {
|
|
12
|
+
/**
|
|
13
|
+
* Resolve model ID from alias or fuzzy name
|
|
14
|
+
*/
|
|
15
|
+
static resolveModel(query) {
|
|
16
|
+
const normalizedQuery = query.toLowerCase().trim();
|
|
17
|
+
// Exact match first
|
|
18
|
+
if (MODEL_REGISTRY[query]) {
|
|
19
|
+
return MODEL_REGISTRY[query];
|
|
20
|
+
}
|
|
21
|
+
// Alias match
|
|
22
|
+
if (MODEL_ALIASES[normalizedQuery]) {
|
|
23
|
+
const resolvedId = MODEL_ALIASES[normalizedQuery];
|
|
24
|
+
return MODEL_REGISTRY[resolvedId] || null;
|
|
25
|
+
}
|
|
26
|
+
// Fuzzy matching
|
|
27
|
+
const allModels = getAllModels();
|
|
28
|
+
// Try partial matching on ID
|
|
29
|
+
const idMatch = allModels.find((model) => model.id.toLowerCase().includes(normalizedQuery) ||
|
|
30
|
+
normalizedQuery.includes(model.id.toLowerCase()));
|
|
31
|
+
if (idMatch) {
|
|
32
|
+
return idMatch;
|
|
33
|
+
}
|
|
34
|
+
// Try partial matching on name
|
|
35
|
+
const nameMatch = allModels.find((model) => model.name.toLowerCase().includes(normalizedQuery) ||
|
|
36
|
+
normalizedQuery.includes(model.name.toLowerCase()));
|
|
37
|
+
if (nameMatch) {
|
|
38
|
+
return nameMatch;
|
|
39
|
+
}
|
|
40
|
+
// Try provider-specific matching
|
|
41
|
+
const providerMatch = allModels.find((model) => {
|
|
42
|
+
const providerQuery = `${model.provider}-${normalizedQuery}`;
|
|
43
|
+
return (model.id.toLowerCase().includes(providerQuery) ||
|
|
44
|
+
model.name.toLowerCase().includes(normalizedQuery));
|
|
45
|
+
});
|
|
46
|
+
if (providerMatch) {
|
|
47
|
+
return providerMatch;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Search models with advanced filtering
|
|
53
|
+
*/
|
|
54
|
+
static searchModels(filters) {
|
|
55
|
+
const allModels = getAllModels();
|
|
56
|
+
const results = [];
|
|
57
|
+
for (const model of allModels) {
|
|
58
|
+
const matchResult = this.evaluateModelMatch(model, filters);
|
|
59
|
+
if (matchResult.score > 0) {
|
|
60
|
+
results.push(matchResult);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Sort by score (highest first)
|
|
64
|
+
return results.sort((a, b) => b.score - a.score);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get best model for specific use case
|
|
68
|
+
*/
|
|
69
|
+
static getBestModel(context) {
|
|
70
|
+
const allModels = getAllModels();
|
|
71
|
+
const scored = allModels.map((model) => ({
|
|
72
|
+
model,
|
|
73
|
+
score: this.scoreModelForContext(model, context),
|
|
74
|
+
}));
|
|
75
|
+
// Sort by score
|
|
76
|
+
scored.sort((a, b) => b.score - a.score);
|
|
77
|
+
const best = scored[0];
|
|
78
|
+
const alternatives = scored.slice(1, 4).map((s) => s.model);
|
|
79
|
+
return {
|
|
80
|
+
model: best.model,
|
|
81
|
+
score: best.score,
|
|
82
|
+
reasoning: this.generateRecommendationReasoning(best.model, context),
|
|
83
|
+
alternatives,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Compare multiple models
|
|
88
|
+
*/
|
|
89
|
+
static compareModels(modelIds) {
|
|
90
|
+
const models = modelIds
|
|
91
|
+
.map((id) => this.resolveModel(id))
|
|
92
|
+
.filter((model) => model !== null);
|
|
93
|
+
if (models.length === 0) {
|
|
94
|
+
throw new Error(`No valid models found for comparison. Invalid IDs: ${modelIds.join(", ")}. Use 'models list' to see available model IDs.`);
|
|
95
|
+
}
|
|
96
|
+
// Build comparison data
|
|
97
|
+
const capabilities = {
|
|
98
|
+
vision: [],
|
|
99
|
+
functionCalling: [],
|
|
100
|
+
codeGeneration: [],
|
|
101
|
+
reasoning: [],
|
|
102
|
+
multimodal: [],
|
|
103
|
+
streaming: [],
|
|
104
|
+
jsonMode: [],
|
|
105
|
+
};
|
|
106
|
+
// Group models by capabilities
|
|
107
|
+
for (const model of models) {
|
|
108
|
+
for (const [capability, supported] of Object.entries(model.capabilities)) {
|
|
109
|
+
if (supported) {
|
|
110
|
+
capabilities[capability].push(model);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Find pricing extremes
|
|
115
|
+
const sortedByCost = [...models].sort((a, b) => a.pricing.inputCostPer1K +
|
|
116
|
+
a.pricing.outputCostPer1K -
|
|
117
|
+
(b.pricing.inputCostPer1K + b.pricing.outputCostPer1K));
|
|
118
|
+
// Find context size extremes
|
|
119
|
+
const sortedByContext = [...models].sort((a, b) => b.limits.maxContextTokens - a.limits.maxContextTokens);
|
|
120
|
+
// Group by performance
|
|
121
|
+
const performance = {
|
|
122
|
+
fast: models.filter((m) => m.performance.speed === "fast"),
|
|
123
|
+
medium: models.filter((m) => m.performance.speed === "medium"),
|
|
124
|
+
slow: models.filter((m) => m.performance.speed === "slow"),
|
|
125
|
+
highQuality: models.filter((m) => m.performance.quality === "high"),
|
|
126
|
+
mediumQuality: models.filter((m) => m.performance.quality === "medium"),
|
|
127
|
+
lowQuality: models.filter((m) => m.performance.quality === "low"),
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
models,
|
|
131
|
+
comparison: {
|
|
132
|
+
capabilities,
|
|
133
|
+
pricing: {
|
|
134
|
+
cheapest: sortedByCost[0],
|
|
135
|
+
mostExpensive: sortedByCost[sortedByCost.length - 1],
|
|
136
|
+
},
|
|
137
|
+
performance,
|
|
138
|
+
contextSize: {
|
|
139
|
+
largest: sortedByContext[0],
|
|
140
|
+
smallest: sortedByContext[sortedByContext.length - 1],
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get models by category
|
|
147
|
+
*/
|
|
148
|
+
static getModelsByCategory(category) {
|
|
149
|
+
return getAllModels().filter((model) => model.category === category);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get recommended models for use case
|
|
153
|
+
*/
|
|
154
|
+
static getRecommendedModelsForUseCase(useCase) {
|
|
155
|
+
const recommendedIds = USE_CASE_RECOMMENDATIONS[useCase] || [];
|
|
156
|
+
return recommendedIds
|
|
157
|
+
.map((id) => getModelById(id))
|
|
158
|
+
.filter((model) => model !== null);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Calculate cost comparison for models
|
|
162
|
+
*/
|
|
163
|
+
static calculateCostComparison(models, inputTokens = 1000, outputTokens = 500) {
|
|
164
|
+
return models
|
|
165
|
+
.map((model) => ({
|
|
166
|
+
model,
|
|
167
|
+
cost: calculateCost(model, inputTokens, outputTokens),
|
|
168
|
+
costPer1K: model.pricing.inputCostPer1K + model.pricing.outputCostPer1K,
|
|
169
|
+
}))
|
|
170
|
+
.sort((a, b) => a.cost - b.cost);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get model statistics
|
|
174
|
+
*/
|
|
175
|
+
static getModelStatistics() {
|
|
176
|
+
const allModels = getAllModels();
|
|
177
|
+
const providers = getAvailableProviders();
|
|
178
|
+
// Count by provider
|
|
179
|
+
const byProvider = providers.reduce((acc, provider) => {
|
|
180
|
+
acc[provider] = getModelsByProvider(provider).length;
|
|
181
|
+
return acc;
|
|
182
|
+
}, {});
|
|
183
|
+
// Count by category
|
|
184
|
+
const byCategory = allModels.reduce((acc, model) => {
|
|
185
|
+
acc[model.category] = (acc[model.category] || 0) + 1;
|
|
186
|
+
return acc;
|
|
187
|
+
}, {});
|
|
188
|
+
// Capability statistics
|
|
189
|
+
const capabilityStats = allModels.reduce((acc, model) => {
|
|
190
|
+
for (const [capability, supported] of Object.entries(model.capabilities)) {
|
|
191
|
+
if (supported) {
|
|
192
|
+
acc[capability] = (acc[capability] || 0) + 1;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return acc;
|
|
196
|
+
}, {});
|
|
197
|
+
// Cost statistics
|
|
198
|
+
const costs = allModels.map((m) => m.pricing.inputCostPer1K + m.pricing.outputCostPer1K);
|
|
199
|
+
const avgCost = costs.reduce((a, b) => a + b, 0) / costs.length;
|
|
200
|
+
const minCost = Math.min(...costs);
|
|
201
|
+
const maxCost = Math.max(...costs);
|
|
202
|
+
return {
|
|
203
|
+
total: allModels.length,
|
|
204
|
+
providers: Object.keys(byProvider).length,
|
|
205
|
+
byProvider,
|
|
206
|
+
byCategory,
|
|
207
|
+
capabilities: capabilityStats,
|
|
208
|
+
pricing: {
|
|
209
|
+
average: avgCost,
|
|
210
|
+
min: minCost,
|
|
211
|
+
max: maxCost,
|
|
212
|
+
free: allModels.filter((m) => m.pricing.inputCostPer1K === 0).length,
|
|
213
|
+
},
|
|
214
|
+
deprecated: allModels.filter((m) => m.deprecated).length,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Evaluate how well a model matches search filters
|
|
219
|
+
*/
|
|
220
|
+
static evaluateModelMatch(model, filters) {
|
|
221
|
+
let score = 0;
|
|
222
|
+
const matchReasons = [];
|
|
223
|
+
// Provider filter
|
|
224
|
+
if (filters.provider) {
|
|
225
|
+
const providers = Array.isArray(filters.provider)
|
|
226
|
+
? filters.provider
|
|
227
|
+
: [filters.provider];
|
|
228
|
+
if (providers.includes(model.provider)) {
|
|
229
|
+
score += 10;
|
|
230
|
+
matchReasons.push(`Provider: ${model.provider}`);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
return { model, score: 0, matchReasons: [] };
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// Capability filter
|
|
237
|
+
if (filters.capability) {
|
|
238
|
+
const capabilities = Array.isArray(filters.capability)
|
|
239
|
+
? filters.capability
|
|
240
|
+
: [filters.capability];
|
|
241
|
+
for (const capability of capabilities) {
|
|
242
|
+
if (model.capabilities[capability]) {
|
|
243
|
+
score += 15;
|
|
244
|
+
matchReasons.push(`Has capability: ${capability}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Use case filter
|
|
249
|
+
if (filters.useCase) {
|
|
250
|
+
const useCaseScore = model.useCases[filters.useCase];
|
|
251
|
+
if (useCaseScore >= 7) {
|
|
252
|
+
score += useCaseScore * 2;
|
|
253
|
+
matchReasons.push(`Good for ${filters.useCase} (${useCaseScore}/10)`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Cost filter
|
|
257
|
+
if (filters.maxCost) {
|
|
258
|
+
const totalCost = model.pricing.inputCostPer1K + model.pricing.outputCostPer1K;
|
|
259
|
+
if (totalCost <= filters.maxCost) {
|
|
260
|
+
score += 5;
|
|
261
|
+
matchReasons.push(`Within cost limit ($${totalCost.toFixed(6)}/1K)`);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
score -= 5;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Context size filters
|
|
268
|
+
if (filters.minContextSize &&
|
|
269
|
+
model.limits.maxContextTokens >= filters.minContextSize) {
|
|
270
|
+
score += 5;
|
|
271
|
+
matchReasons.push(`Meets min context: ${model.limits.maxContextTokens}`);
|
|
272
|
+
}
|
|
273
|
+
if (filters.maxContextSize &&
|
|
274
|
+
model.limits.maxContextTokens <= filters.maxContextSize) {
|
|
275
|
+
score += 3;
|
|
276
|
+
matchReasons.push(`Within max context: ${model.limits.maxContextTokens}`);
|
|
277
|
+
}
|
|
278
|
+
// Performance filters
|
|
279
|
+
if (filters.performance) {
|
|
280
|
+
if (model.performance.speed === filters.performance ||
|
|
281
|
+
model.performance.quality === filters.performance) {
|
|
282
|
+
score += 8;
|
|
283
|
+
matchReasons.push(`Performance: ${filters.performance}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Category filter
|
|
287
|
+
if (filters.category) {
|
|
288
|
+
const categories = Array.isArray(filters.category)
|
|
289
|
+
? filters.category
|
|
290
|
+
: [filters.category];
|
|
291
|
+
if (categories.includes(model.category)) {
|
|
292
|
+
score += 7;
|
|
293
|
+
matchReasons.push(`Category: ${model.category}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Base relevance score
|
|
297
|
+
if (score === 0) {
|
|
298
|
+
score = 1; // Minimal relevance for any model
|
|
299
|
+
matchReasons.push("Basic match");
|
|
300
|
+
}
|
|
301
|
+
return { model, score, matchReasons };
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Score model for recommendation context
|
|
305
|
+
*/
|
|
306
|
+
static scoreModelForContext(model, context) {
|
|
307
|
+
let score = 0;
|
|
308
|
+
// Use case scoring
|
|
309
|
+
if (context.useCase) {
|
|
310
|
+
score += model.useCases[context.useCase] * 10;
|
|
311
|
+
}
|
|
312
|
+
// Cost scoring
|
|
313
|
+
if (context.maxCost) {
|
|
314
|
+
const totalCost = model.pricing.inputCostPer1K + model.pricing.outputCostPer1K;
|
|
315
|
+
if (totalCost <= context.maxCost) {
|
|
316
|
+
score += 20;
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
score -= 30; // Heavy penalty for exceeding cost
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Quality scoring
|
|
323
|
+
if (context.minQuality) {
|
|
324
|
+
const qualityScore = context.minQuality === "high"
|
|
325
|
+
? 3
|
|
326
|
+
: context.minQuality === "medium"
|
|
327
|
+
? 2
|
|
328
|
+
: 1;
|
|
329
|
+
const modelQuality = model.performance.quality === "high"
|
|
330
|
+
? 3
|
|
331
|
+
: model.performance.quality === "medium"
|
|
332
|
+
? 2
|
|
333
|
+
: 1;
|
|
334
|
+
if (modelQuality >= qualityScore) {
|
|
335
|
+
score += 15;
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
score -= 10;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Required capabilities
|
|
342
|
+
if (context.requireCapabilities) {
|
|
343
|
+
for (const capability of context.requireCapabilities) {
|
|
344
|
+
if (model.capabilities[capability]) {
|
|
345
|
+
score += 12;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
score -= 25; // Heavy penalty for missing required capability
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// Provider exclusions
|
|
353
|
+
if (context.excludeProviders?.includes(model.provider)) {
|
|
354
|
+
score -= 50;
|
|
355
|
+
}
|
|
356
|
+
// Context size requirements
|
|
357
|
+
if (context.contextSize &&
|
|
358
|
+
model.limits.maxContextTokens >= context.contextSize) {
|
|
359
|
+
score += 10;
|
|
360
|
+
}
|
|
361
|
+
// Local preference
|
|
362
|
+
if (context.preferLocal && model.isLocal) {
|
|
363
|
+
score += 15;
|
|
364
|
+
}
|
|
365
|
+
// Deprecated models penalty
|
|
366
|
+
if (model.deprecated) {
|
|
367
|
+
score -= 20;
|
|
368
|
+
}
|
|
369
|
+
return Math.max(0, score); // Ensure non-negative score
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Generate recommendation reasoning
|
|
373
|
+
*/
|
|
374
|
+
static generateRecommendationReasoning(model, context) {
|
|
375
|
+
const reasons = [];
|
|
376
|
+
if (context.useCase) {
|
|
377
|
+
const score = model.useCases[context.useCase];
|
|
378
|
+
reasons.push(`Excellent for ${context.useCase} (${score}/10 rating)`);
|
|
379
|
+
}
|
|
380
|
+
if (model.pricing.inputCostPer1K === 0) {
|
|
381
|
+
reasons.push("Free to use (local execution)");
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
const costPer1K = model.pricing.inputCostPer1K + model.pricing.outputCostPer1K;
|
|
385
|
+
if (costPer1K < 0.001) {
|
|
386
|
+
reasons.push("Very cost-effective");
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (model.performance.quality === "high") {
|
|
390
|
+
reasons.push("High-quality outputs");
|
|
391
|
+
}
|
|
392
|
+
if (model.performance.speed === "fast") {
|
|
393
|
+
reasons.push("Fast response times");
|
|
394
|
+
}
|
|
395
|
+
if (model.limits.maxContextTokens > 100000) {
|
|
396
|
+
reasons.push("Large context window for complex tasks");
|
|
397
|
+
}
|
|
398
|
+
const strongCapabilities = Object.entries(model.capabilities)
|
|
399
|
+
.filter(([_, supported]) => supported)
|
|
400
|
+
.map(([capability]) => capability);
|
|
401
|
+
if (strongCapabilities.length > 0) {
|
|
402
|
+
reasons.push(`Supports: ${strongCapabilities.join(", ")}`);
|
|
403
|
+
}
|
|
404
|
+
if (model.releaseDate) {
|
|
405
|
+
const releaseYear = new Date(model.releaseDate).getFullYear();
|
|
406
|
+
if (releaseYear >= 2024) {
|
|
407
|
+
reasons.push("Recent model with latest capabilities");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return reasons;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Utility functions for CLI integration
|
|
415
|
+
*/
|
|
416
|
+
/**
|
|
417
|
+
* Format search results for CLI display
|
|
418
|
+
*/
|
|
419
|
+
export function formatSearchResults(results) {
|
|
420
|
+
return results.map((result) => {
|
|
421
|
+
const modelDisplay = formatModelForDisplay(result.model);
|
|
422
|
+
return {
|
|
423
|
+
...(typeof modelDisplay === "object" && modelDisplay !== null
|
|
424
|
+
? modelDisplay
|
|
425
|
+
: {}),
|
|
426
|
+
relevanceScore: result.score,
|
|
427
|
+
matchReasons: result.matchReasons,
|
|
428
|
+
};
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Format recommendation for CLI display
|
|
433
|
+
*/
|
|
434
|
+
export function formatRecommendation(recommendation) {
|
|
435
|
+
return {
|
|
436
|
+
recommended: formatModelForDisplay(recommendation.model),
|
|
437
|
+
score: recommendation.score,
|
|
438
|
+
reasoning: recommendation.reasoning,
|
|
439
|
+
alternatives: recommendation.alternatives.map(formatModelForDisplay),
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Format model comparison for CLI display
|
|
444
|
+
*/
|
|
445
|
+
export function formatComparison(comparison) {
|
|
446
|
+
return {
|
|
447
|
+
models: comparison.models.map(formatModelForDisplay),
|
|
448
|
+
summary: {
|
|
449
|
+
capabilities: Object.entries(comparison.comparison.capabilities).map(([capability, models]) => ({
|
|
450
|
+
capability,
|
|
451
|
+
supportedBy: models.map((m) => m.id),
|
|
452
|
+
count: models.length,
|
|
453
|
+
})),
|
|
454
|
+
pricing: {
|
|
455
|
+
cheapest: comparison.comparison.pricing.cheapest.id,
|
|
456
|
+
mostExpensive: comparison.comparison.pricing.mostExpensive.id,
|
|
457
|
+
},
|
|
458
|
+
contextSize: {
|
|
459
|
+
largest: comparison.comparison.contextSize.largest.id,
|
|
460
|
+
smallest: comparison.comparison.contextSize.smallest.id,
|
|
461
|
+
},
|
|
462
|
+
performance: Object.entries(comparison.comparison.performance).map(([type, models]) => ({
|
|
463
|
+
type,
|
|
464
|
+
models: models.map((m) => m.id),
|
|
465
|
+
})),
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
}
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export interface MCPStatus {
|
|
|
29
29
|
customToolsCount: number;
|
|
30
30
|
inMemoryServersCount: number;
|
|
31
31
|
error?: string;
|
|
32
|
+
[key: string]: unknown;
|
|
32
33
|
}
|
|
33
34
|
export interface MCPServerInfo {
|
|
34
35
|
id: string;
|
|
@@ -143,7 +144,9 @@ export declare class NeuroLink {
|
|
|
143
144
|
* Get comprehensive status of all AI providers
|
|
144
145
|
* Primary method for provider health checking and diagnostics
|
|
145
146
|
*/
|
|
146
|
-
getProviderStatus(
|
|
147
|
+
getProviderStatus(options?: {
|
|
148
|
+
quiet?: boolean;
|
|
149
|
+
}): Promise<ProviderStatus[]>;
|
|
147
150
|
/**
|
|
148
151
|
* Test a specific AI provider's connectivity and authentication
|
|
149
152
|
* @param providerName - Name of the provider to test
|