@juspay/neurolink 7.36.0 → 7.37.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/config/taskClassificationConfig.d.ts +51 -0
  3. package/dist/config/taskClassificationConfig.js +148 -0
  4. package/dist/lib/config/taskClassificationConfig.d.ts +51 -0
  5. package/dist/lib/config/taskClassificationConfig.js +148 -0
  6. package/dist/lib/neurolink.d.ts +20 -0
  7. package/dist/lib/neurolink.js +268 -5
  8. package/dist/lib/types/index.d.ts +2 -0
  9. package/dist/lib/types/index.js +2 -0
  10. package/dist/lib/types/taskClassificationTypes.d.ts +52 -0
  11. package/dist/lib/types/taskClassificationTypes.js +5 -0
  12. package/dist/lib/utils/modelRouter.d.ts +107 -0
  13. package/dist/lib/utils/modelRouter.js +292 -0
  14. package/dist/lib/utils/promptRedaction.d.ts +29 -0
  15. package/dist/lib/utils/promptRedaction.js +62 -0
  16. package/dist/lib/utils/taskClassificationUtils.d.ts +55 -0
  17. package/dist/lib/utils/taskClassificationUtils.js +149 -0
  18. package/dist/lib/utils/taskClassifier.d.ts +23 -0
  19. package/dist/lib/utils/taskClassifier.js +94 -0
  20. package/dist/neurolink.d.ts +20 -0
  21. package/dist/neurolink.js +268 -5
  22. package/dist/types/index.d.ts +2 -0
  23. package/dist/types/index.js +2 -0
  24. package/dist/types/taskClassificationTypes.d.ts +52 -0
  25. package/dist/types/taskClassificationTypes.js +5 -0
  26. package/dist/utils/modelRouter.d.ts +107 -0
  27. package/dist/utils/modelRouter.js +292 -0
  28. package/dist/utils/promptRedaction.d.ts +29 -0
  29. package/dist/utils/promptRedaction.js +62 -0
  30. package/dist/utils/taskClassificationUtils.d.ts +55 -0
  31. package/dist/utils/taskClassificationUtils.js +149 -0
  32. package/dist/utils/taskClassifier.d.ts +23 -0
  33. package/dist/utils/taskClassifier.js +94 -0
  34. package/package.json +1 -1
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Model Router for NeuroLink Orchestration
3
+ * Routes tasks to optimal models based on classification and requirements
4
+ */
5
+ import { logger } from "./logger.js";
6
+ import { BinaryTaskClassifier } from "./taskClassifier.js";
7
+ import { redactForRouting } from "./promptRedaction.js";
8
+ /**
9
+ * Routing configuration constants
10
+ */
11
+ const ROUTING_CONFIG = {
12
+ minRouteConfidence: 0.3,
13
+ maxRouteConfidence: 0.95,
14
+ confidenceBoost: 0.1,
15
+ };
16
+ /**
17
+ * Model configurations for different task types and providers
18
+ */
19
+ const MODEL_CONFIGS = {
20
+ fast: {
21
+ primary: {
22
+ provider: "vertex",
23
+ model: "gemini-2.5-flash",
24
+ capabilities: ["speed", "general", "code", "basic-reasoning"],
25
+ avgResponseTime: 800, // ms
26
+ costPerToken: 0.0001,
27
+ reasoning: "Optimized for speed and efficiency via Vertex AI",
28
+ },
29
+ fallback: {
30
+ provider: "vertex",
31
+ model: "gemini-2.5-pro",
32
+ capabilities: ["speed", "general", "basic-reasoning"],
33
+ avgResponseTime: 1200,
34
+ costPerToken: 0.0002,
35
+ reasoning: "Vertex AI Gemini Pro fallback",
36
+ },
37
+ },
38
+ reasoning: {
39
+ primary: {
40
+ provider: "vertex",
41
+ model: "claude-sonnet-4@20250514",
42
+ capabilities: [
43
+ "reasoning",
44
+ "analysis",
45
+ "complex-logic",
46
+ "code",
47
+ "creativity",
48
+ ],
49
+ avgResponseTime: 3000, // ms
50
+ costPerToken: 0.003,
51
+ reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI",
52
+ },
53
+ fallback: {
54
+ provider: "vertex",
55
+ model: "claude-opus-4@20250514",
56
+ capabilities: [
57
+ "reasoning",
58
+ "analysis",
59
+ "complex-logic",
60
+ "code",
61
+ "creativity",
62
+ "agentic",
63
+ ],
64
+ avgResponseTime: 4000,
65
+ costPerToken: 0.005,
66
+ reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks",
67
+ },
68
+ },
69
+ };
70
+ /**
71
+ * Model Router
72
+ * Intelligently routes tasks to optimal models based on classification
73
+ */
74
+ export class ModelRouter {
75
+ /**
76
+ * Route a prompt to the optimal model configuration
77
+ */
78
+ static route(prompt, options = {}) {
79
+ const startTime = Date.now();
80
+ // 1. Classify the task if not overridden
81
+ let classification;
82
+ if (options.forceTaskType) {
83
+ classification = {
84
+ type: options.forceTaskType,
85
+ confidence: ROUTING_CONFIG.maxRouteConfidence, // Use maxRouteConfidence instead of 1.0
86
+ reasoning: "forced task type",
87
+ };
88
+ }
89
+ else {
90
+ classification = BinaryTaskClassifier.classify(prompt);
91
+ }
92
+ // 2. Apply special requirements
93
+ let taskType = classification.type;
94
+ const reasons = [classification.reasoning];
95
+ if (options.requireFast) {
96
+ taskType = "fast";
97
+ reasons.push("speed required");
98
+ }
99
+ if (options.requireCapability) {
100
+ // Check if the capability suggests a specific task type
101
+ const capability = options.requireCapability.toLowerCase();
102
+ if (["analysis", "reasoning", "complex", "research"].some((c) => capability.includes(c))) {
103
+ taskType = "reasoning";
104
+ reasons.push(`capability: ${capability}`);
105
+ }
106
+ else if (["speed", "quick", "fast", "simple"].some((c) => capability.includes(c))) {
107
+ taskType = "fast";
108
+ reasons.push(`capability: ${capability}`);
109
+ }
110
+ }
111
+ // 3. Select model configuration
112
+ const config = MODEL_CONFIGS[taskType];
113
+ const selectedConfig = config.primary;
114
+ // 4. Calculate confidence based on multiple factors
115
+ let confidence = classification.confidence;
116
+ // Adjust confidence based on prompt characteristics
117
+ if (taskType === "fast" && prompt.length < 30) {
118
+ confidence = Math.min(ROUTING_CONFIG.maxRouteConfidence, confidence + ROUTING_CONFIG.confidenceBoost);
119
+ reasons.push("very short prompt");
120
+ }
121
+ if (taskType === "reasoning" && prompt.length > 150) {
122
+ confidence = Math.min(ROUTING_CONFIG.maxRouteConfidence, confidence + ROUTING_CONFIG.confidenceBoost);
123
+ reasons.push("detailed prompt");
124
+ }
125
+ // Ensure final confidence is within configured bounds
126
+ confidence = Math.max(ROUTING_CONFIG.minRouteConfidence, Math.min(ROUTING_CONFIG.maxRouteConfidence, confidence));
127
+ // 5. Create route result
128
+ const route = {
129
+ provider: selectedConfig.provider,
130
+ model: selectedConfig.model,
131
+ reasoning: reasons.join(", "),
132
+ confidence,
133
+ };
134
+ const routingTime = Date.now() - startTime;
135
+ logger.debug("Model routing decision", {
136
+ prompt: redactForRouting(prompt),
137
+ taskType,
138
+ route: {
139
+ provider: route.provider,
140
+ model: route.model,
141
+ confidence: route.confidence.toFixed(2),
142
+ },
143
+ reasoning: route.reasoning,
144
+ routingTime: `${routingTime}ms`,
145
+ options: Object.keys(options).length > 0 ? options : undefined,
146
+ });
147
+ return route;
148
+ }
149
+ /**
150
+ * Get fallback route if primary route fails
151
+ */
152
+ static getFallbackRoute(prompt, primaryRoute, options = {}) {
153
+ // Determine fallback strategy
154
+ let fallbackType;
155
+ if (options.fallbackStrategy) {
156
+ if (options.fallbackStrategy === "auto") {
157
+ // Use opposite of primary for fallback
158
+ const primaryType = this.getTaskTypeFromRoute(primaryRoute);
159
+ fallbackType = primaryType === "fast" ? "reasoning" : "fast";
160
+ }
161
+ else {
162
+ fallbackType = options.fallbackStrategy;
163
+ }
164
+ }
165
+ else {
166
+ // Default: use fallback model of same type
167
+ fallbackType = this.getTaskTypeFromRoute(primaryRoute);
168
+ }
169
+ const config = MODEL_CONFIGS[fallbackType];
170
+ const fallbackConfig = config.fallback;
171
+ const route = {
172
+ provider: fallbackConfig.provider,
173
+ model: fallbackConfig.model,
174
+ reasoning: `fallback from ${primaryRoute.provider}/${primaryRoute.model}`,
175
+ confidence: Math.max(ROUTING_CONFIG.minRouteConfidence, Math.min(ROUTING_CONFIG.maxRouteConfidence, primaryRoute.confidence - 0.2)),
176
+ };
177
+ logger.debug("Fallback route selected", {
178
+ originalRoute: `${primaryRoute.provider}/${primaryRoute.model}`,
179
+ fallbackRoute: `${route.provider}/${route.model}`,
180
+ fallbackType,
181
+ strategy: options.fallbackStrategy || "default",
182
+ });
183
+ return route;
184
+ }
185
+ /**
186
+ * Determine task type from a model route
187
+ */
188
+ static getTaskTypeFromRoute(route) {
189
+ // Check which config matches this route
190
+ for (const [taskType, config] of Object.entries(MODEL_CONFIGS)) {
191
+ if (config.primary.provider === route.provider &&
192
+ config.primary.model === route.model) {
193
+ return taskType;
194
+ }
195
+ if (config.fallback.provider === route.provider &&
196
+ config.fallback.model === route.model) {
197
+ return taskType;
198
+ }
199
+ }
200
+ // Default fallback based on model name patterns
201
+ if (route.model.includes("flash") || route.model.includes("mini")) {
202
+ return "fast";
203
+ }
204
+ return "reasoning";
205
+ }
206
+ /**
207
+ * Get all available model configurations
208
+ */
209
+ static getAvailableModels() {
210
+ return MODEL_CONFIGS;
211
+ }
212
+ /**
213
+ * Validate model availability for a given route
214
+ */
215
+ static async validateRoute(route) {
216
+ try {
217
+ // This would typically check provider availability
218
+ // For now, just validate the configuration exists
219
+ const configs = Object.values(MODEL_CONFIGS).flatMap((config) => [
220
+ config.primary,
221
+ config.fallback,
222
+ ]);
223
+ return configs.some((config) => config.provider === route.provider && config.model === route.model);
224
+ }
225
+ catch (error) {
226
+ logger.error("Route validation failed", {
227
+ route,
228
+ error: error instanceof Error ? error.message : String(error),
229
+ });
230
+ return false;
231
+ }
232
+ }
233
+ /**
234
+ * Get routing statistics for multiple prompts
235
+ */
236
+ static getRoutingStats(prompts) {
237
+ const routes = prompts.map((prompt) => this.route(prompt));
238
+ // Handle empty prompts array to avoid divide-by-zero
239
+ if (routes.length === 0) {
240
+ const stats = {
241
+ total: 0,
242
+ fastRoutes: 0,
243
+ reasoningRoutes: 0,
244
+ averageConfidence: 0,
245
+ providerDistribution: {},
246
+ };
247
+ logger.debug("Routing statistics", stats);
248
+ return stats;
249
+ }
250
+ const stats = {
251
+ total: routes.length,
252
+ fastRoutes: routes.filter((r) => {
253
+ const taskType = this.getTaskTypeFromRoute(r);
254
+ return taskType === "fast";
255
+ }).length,
256
+ reasoningRoutes: routes.filter((r) => {
257
+ const taskType = this.getTaskTypeFromRoute(r);
258
+ return taskType === "reasoning";
259
+ }).length,
260
+ averageConfidence: routes.reduce((sum, r) => sum + r.confidence, 0) / routes.length,
261
+ providerDistribution: routes.reduce((dist, r) => {
262
+ dist[r.provider] = (dist[r.provider] || 0) + 1;
263
+ return dist;
264
+ }, {}),
265
+ };
266
+ logger.debug("Routing statistics", stats);
267
+ return stats;
268
+ }
269
+ /**
270
+ * Estimate cost and performance for a route
271
+ */
272
+ static getRouteEstimates(route, estimatedTokens = 500) {
273
+ // Find the config for this route
274
+ const allConfigs = Object.values(MODEL_CONFIGS).flatMap((config) => [
275
+ config.primary,
276
+ config.fallback,
277
+ ]);
278
+ const config = allConfigs.find((c) => c.provider === route.provider && c.model === route.model);
279
+ if (!config) {
280
+ return {
281
+ estimatedCost: 0,
282
+ estimatedResponseTime: 2000,
283
+ capabilities: [],
284
+ };
285
+ }
286
+ return {
287
+ estimatedCost: config.costPerToken * estimatedTokens,
288
+ estimatedResponseTime: config.avgResponseTime,
289
+ capabilities: [...config.capabilities],
290
+ };
291
+ }
292
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Prompt redaction utilities for safe logging
3
+ * Provides consistent prompt masking across NeuroLink components
4
+ */
5
+ export interface PromptRedactionOptions {
6
+ /** Maximum length of redacted prompt */
7
+ maxLength?: number;
8
+ /** Whether to show word count */
9
+ showWordCount?: boolean;
10
+ /** Mask character to use for redaction */
11
+ maskChar?: string;
12
+ }
13
+ /**
14
+ * Redact a prompt for safe logging
15
+ * Truncates to maxLength and optionally shows word count
16
+ */
17
+ export declare function redactPrompt(prompt: string, options?: PromptRedactionOptions): string;
18
+ /**
19
+ * Create a short safe mask for highly sensitive contexts
20
+ */
21
+ export declare function createSafeMask(prompt: string, _maskLength?: number): string;
22
+ /**
23
+ * Redact for classification context (matches classifier behavior)
24
+ */
25
+ export declare function redactForClassification(prompt: string): string;
26
+ /**
27
+ * Redact for routing context (matches router behavior)
28
+ */
29
+ export declare function redactForRouting(prompt: string): string;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Prompt redaction utilities for safe logging
3
+ * Provides consistent prompt masking across NeuroLink components
4
+ */
5
+ /**
6
+ * Default redaction options
7
+ */
8
+ const DEFAULT_REDACTION_OPTIONS = {
9
+ maxLength: 100,
10
+ showWordCount: true,
11
+ maskChar: "*",
12
+ };
13
+ /**
14
+ * Redact a prompt for safe logging
15
+ * Truncates to maxLength and optionally shows word count
16
+ */
17
+ export function redactPrompt(prompt, options = {}) {
18
+ const opts = { ...DEFAULT_REDACTION_OPTIONS, ...options };
19
+ if (!prompt || typeof prompt !== 'string') {
20
+ return '[INVALID_PROMPT]';
21
+ }
22
+ const wordCount = prompt.trim().split(/\s+/).length;
23
+ let redacted = prompt.substring(0, opts.maxLength);
24
+ // Add ellipsis if truncated
25
+ if (prompt.length > opts.maxLength) {
26
+ redacted = redacted.substring(0, opts.maxLength - 3) + "...";
27
+ }
28
+ // Optionally append word count
29
+ if (opts.showWordCount) {
30
+ redacted += ` [${wordCount} words]`;
31
+ }
32
+ return redacted;
33
+ }
34
+ /**
35
+ * Create a short safe mask for highly sensitive contexts
36
+ */
37
+ export function createSafeMask(prompt, _maskLength = 20) {
38
+ if (!prompt || typeof prompt !== 'string') {
39
+ return '[INVALID_PROMPT]';
40
+ }
41
+ const wordCount = prompt.trim().split(/\s+/).length;
42
+ const charCount = prompt.length;
43
+ return `[REDACTED: ${charCount} chars, ${wordCount} words]`;
44
+ }
45
+ /**
46
+ * Redact for classification context (matches classifier behavior)
47
+ */
48
+ export function redactForClassification(prompt) {
49
+ return redactPrompt(prompt, {
50
+ maxLength: 100,
51
+ showWordCount: false,
52
+ });
53
+ }
54
+ /**
55
+ * Redact for routing context (matches router behavior)
56
+ */
57
+ export function redactForRouting(prompt) {
58
+ return redactPrompt(prompt, {
59
+ maxLength: 100,
60
+ showWordCount: true,
61
+ });
62
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Task Classification Utility Functions
3
+ * Helper functions for analyzing prompts and calculating scores
4
+ */
5
+ import type { ClassificationScores } from "../types/taskClassificationTypes.js";
6
+ /**
7
+ * Analyze prompt length and apply scoring bonuses
8
+ */
9
+ export declare function analyzeLengthFactors(prompt: string, reasons: string[]): {
10
+ fastScore: number;
11
+ reasoningScore: number;
12
+ };
13
+ /**
14
+ * Check prompt against fast task patterns
15
+ */
16
+ export declare function checkFastPatterns(normalizedPrompt: string, reasons: string[]): number;
17
+ /**
18
+ * Check prompt against reasoning task patterns
19
+ */
20
+ export declare function checkReasoningPatterns(normalizedPrompt: string, reasons: string[]): number;
21
+ /**
22
+ * Analyze keyword matches in the prompt
23
+ */
24
+ export declare function analyzeKeywords(normalizedPrompt: string, reasons: string[]): {
25
+ fastScore: number;
26
+ reasoningScore: number;
27
+ };
28
+ /**
29
+ * Analyze question complexity
30
+ */
31
+ export declare function analyzeQuestionComplexity(prompt: string, reasons: string[]): number;
32
+ /**
33
+ * Analyze prompt structure and punctuation
34
+ */
35
+ export declare function analyzePromptStructure(prompt: string, reasons: string[]): number;
36
+ /**
37
+ * Analyze domain-specific indicators
38
+ */
39
+ export declare function analyzeDomainIndicators(normalizedPrompt: string, prompt: string, reasons: string[]): {
40
+ fastScore: number;
41
+ reasoningScore: number;
42
+ };
43
+ /**
44
+ * Calculate final confidence score
45
+ */
46
+ export declare function calculateConfidence(fastScore: number, reasoningScore: number): number;
47
+ /**
48
+ * Determine task type based on scores
49
+ */
50
+ export declare function determineTaskType(fastScore: number, reasoningScore: number): "fast" | "reasoning";
51
+ /**
52
+ * Comprehensive prompt analysis
53
+ * Runs all analysis functions and returns combined scores
54
+ */
55
+ export declare function analyzePrompt(prompt: string): ClassificationScores;
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Task Classification Utility Functions
3
+ * Helper functions for analyzing prompts and calculating scores
4
+ */
5
+ import { FAST_PATTERNS, REASONING_PATTERNS, FAST_KEYWORDS, REASONING_KEYWORDS, SCORING_WEIGHTS, CLASSIFICATION_THRESHOLDS, DOMAIN_PATTERNS, } from "../config/taskClassificationConfig.js";
6
+ /**
7
+ * Analyze prompt length and apply scoring bonuses
8
+ */
9
+ export function analyzeLengthFactors(prompt, reasons) {
10
+ let fastScore = 0;
11
+ let reasoningScore = 0;
12
+ if (prompt.length < CLASSIFICATION_THRESHOLDS.SHORT_PROMPT_LENGTH) {
13
+ fastScore += SCORING_WEIGHTS.SHORT_PROMPT_BONUS;
14
+ reasons.push("short prompt");
15
+ }
16
+ else if (prompt.length > CLASSIFICATION_THRESHOLDS.LONG_PROMPT_LENGTH) {
17
+ reasoningScore += SCORING_WEIGHTS.LONG_PROMPT_BONUS;
18
+ reasons.push("detailed prompt");
19
+ }
20
+ return { fastScore, reasoningScore };
21
+ }
22
+ /**
23
+ * Check prompt against fast task patterns
24
+ */
25
+ export function checkFastPatterns(normalizedPrompt, reasons) {
26
+ for (const pattern of FAST_PATTERNS) {
27
+ if (pattern.test(normalizedPrompt)) {
28
+ reasons.push("fast pattern match");
29
+ return SCORING_WEIGHTS.PATTERN_MATCH_SCORE;
30
+ }
31
+ }
32
+ return 0;
33
+ }
34
+ /**
35
+ * Check prompt against reasoning task patterns
36
+ */
37
+ export function checkReasoningPatterns(normalizedPrompt, reasons) {
38
+ for (const pattern of REASONING_PATTERNS) {
39
+ if (pattern.test(normalizedPrompt)) {
40
+ reasons.push("reasoning pattern match");
41
+ return SCORING_WEIGHTS.PATTERN_MATCH_SCORE;
42
+ }
43
+ }
44
+ return 0;
45
+ }
46
+ /**
47
+ * Analyze keyword matches in the prompt
48
+ */
49
+ export function analyzeKeywords(normalizedPrompt, reasons) {
50
+ const fastKeywordMatches = FAST_KEYWORDS.filter((keyword) => normalizedPrompt.includes(keyword)).length;
51
+ const reasoningKeywordMatches = REASONING_KEYWORDS.filter((keyword) => normalizedPrompt.includes(keyword)).length;
52
+ const fastScore = fastKeywordMatches * SCORING_WEIGHTS.KEYWORD_MATCH_SCORE;
53
+ const reasoningScore = reasoningKeywordMatches * SCORING_WEIGHTS.KEYWORD_MATCH_SCORE;
54
+ if (fastKeywordMatches > 0) {
55
+ reasons.push(`${fastKeywordMatches} fast keywords`);
56
+ }
57
+ if (reasoningKeywordMatches > 0) {
58
+ reasons.push(`${reasoningKeywordMatches} reasoning keywords`);
59
+ }
60
+ return { fastScore, reasoningScore };
61
+ }
62
+ /**
63
+ * Analyze question complexity
64
+ */
65
+ export function analyzeQuestionComplexity(prompt, reasons) {
66
+ const questionMarks = (prompt.match(/\?/g) || []).length;
67
+ if (questionMarks > 1) {
68
+ reasons.push("multiple questions");
69
+ return SCORING_WEIGHTS.MULTIPLE_QUESTIONS_BONUS;
70
+ }
71
+ return 0;
72
+ }
73
+ /**
74
+ * Analyze prompt structure and punctuation
75
+ */
76
+ export function analyzePromptStructure(prompt, reasons) {
77
+ const sentences = prompt.split(/[.!?]+/).filter((s) => s.trim().length > 0);
78
+ if (sentences.length > 3) {
79
+ reasons.push("multi-sentence structure");
80
+ return SCORING_WEIGHTS.MULTI_SENTENCE_BONUS;
81
+ }
82
+ return 0;
83
+ }
84
+ /**
85
+ * Analyze domain-specific indicators
86
+ */
87
+ export function analyzeDomainIndicators(normalizedPrompt, prompt, reasons) {
88
+ let fastScore = 0;
89
+ let reasoningScore = 0;
90
+ // Check for technical domain
91
+ if (DOMAIN_PATTERNS.TECHNICAL.test(normalizedPrompt)) {
92
+ reasoningScore += SCORING_WEIGHTS.TECHNICAL_DOMAIN_BONUS;
93
+ reasons.push("technical domain");
94
+ }
95
+ // Check for simple definition requests
96
+ if (DOMAIN_PATTERNS.SIMPLE_DEFINITION.test(normalizedPrompt) &&
97
+ prompt.length < CLASSIFICATION_THRESHOLDS.SIMPLE_DEFINITION_LENGTH) {
98
+ fastScore += SCORING_WEIGHTS.SIMPLE_DEFINITION_BONUS;
99
+ reasons.push("simple definition request");
100
+ }
101
+ return { fastScore, reasoningScore };
102
+ }
103
+ /**
104
+ * Calculate final confidence score
105
+ */
106
+ export function calculateConfidence(fastScore, reasoningScore) {
107
+ const totalScore = fastScore + reasoningScore;
108
+ if (totalScore === 0) {
109
+ return CLASSIFICATION_THRESHOLDS.DEFAULT_CONFIDENCE;
110
+ }
111
+ const rawConfidence = Math.max(fastScore, reasoningScore) / totalScore;
112
+ return Math.max(CLASSIFICATION_THRESHOLDS.MIN_CONFIDENCE, Math.min(CLASSIFICATION_THRESHOLDS.MAX_CONFIDENCE, rawConfidence));
113
+ }
114
+ /**
115
+ * Determine task type based on scores
116
+ */
117
+ export function determineTaskType(fastScore, reasoningScore) {
118
+ return fastScore >= reasoningScore ? "fast" : "reasoning";
119
+ }
120
+ /**
121
+ * Comprehensive prompt analysis
122
+ * Runs all analysis functions and returns combined scores
123
+ */
124
+ export function analyzePrompt(prompt) {
125
+ const normalizedPrompt = prompt.toLowerCase().trim();
126
+ const reasons = [];
127
+ let fastScore = 0;
128
+ let reasoningScore = 0;
129
+ // 1. Length analysis
130
+ const lengthScores = analyzeLengthFactors(prompt, reasons);
131
+ fastScore += lengthScores.fastScore;
132
+ reasoningScore += lengthScores.reasoningScore;
133
+ // 2. Pattern matching
134
+ fastScore += checkFastPatterns(normalizedPrompt, reasons);
135
+ reasoningScore += checkReasoningPatterns(normalizedPrompt, reasons);
136
+ // 3. Keyword analysis
137
+ const keywordScores = analyzeKeywords(normalizedPrompt, reasons);
138
+ fastScore += keywordScores.fastScore;
139
+ reasoningScore += keywordScores.reasoningScore;
140
+ // 4. Question complexity
141
+ reasoningScore += analyzeQuestionComplexity(prompt, reasons);
142
+ // 5. Structure analysis
143
+ reasoningScore += analyzePromptStructure(prompt, reasons);
144
+ // 6. Domain analysis
145
+ const domainScores = analyzeDomainIndicators(normalizedPrompt, prompt, reasons);
146
+ fastScore += domainScores.fastScore;
147
+ reasoningScore += domainScores.reasoningScore;
148
+ return { fastScore, reasoningScore, reasons };
149
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Binary Task Classifier for NeuroLink Orchestration
3
+ * Classifies tasks as either 'fast' (quick responses) or 'reasoning' (complex analysis)
4
+ */
5
+ import type { TaskType, TaskClassification, ClassificationStats, ClassificationValidation } from "../types/taskClassificationTypes.js";
6
+ /**
7
+ * Binary Task Classifier
8
+ * Determines if a task requires fast response or deeper reasoning
9
+ */
10
+ export declare class BinaryTaskClassifier {
11
+ /**
12
+ * Classify a prompt as either fast or reasoning task
13
+ */
14
+ static classify(prompt: string): TaskClassification;
15
+ /**
16
+ * Get classification statistics for multiple prompts
17
+ */
18
+ static getClassificationStats(prompts: string[]): ClassificationStats;
19
+ /**
20
+ * Validate classification accuracy (for testing/tuning)
21
+ */
22
+ static validateClassification(prompt: string, expectedType: TaskType): ClassificationValidation;
23
+ }