@juspay/neurolink 7.35.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 (63) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/adapters/providerImageAdapter.d.ts +56 -0
  3. package/dist/adapters/providerImageAdapter.js +257 -0
  4. package/dist/cli/commands/config.d.ts +20 -20
  5. package/dist/cli/factories/commandFactory.d.ts +1 -0
  6. package/dist/cli/factories/commandFactory.js +26 -3
  7. package/dist/config/taskClassificationConfig.d.ts +51 -0
  8. package/dist/config/taskClassificationConfig.js +148 -0
  9. package/dist/core/baseProvider.js +99 -45
  10. package/dist/core/types.d.ts +3 -0
  11. package/dist/lib/adapters/providerImageAdapter.d.ts +56 -0
  12. package/dist/lib/adapters/providerImageAdapter.js +257 -0
  13. package/dist/lib/config/taskClassificationConfig.d.ts +51 -0
  14. package/dist/lib/config/taskClassificationConfig.js +148 -0
  15. package/dist/lib/core/baseProvider.js +99 -45
  16. package/dist/lib/core/types.d.ts +3 -0
  17. package/dist/lib/neurolink.d.ts +20 -0
  18. package/dist/lib/neurolink.js +276 -8
  19. package/dist/lib/types/content.d.ts +78 -0
  20. package/dist/lib/types/content.js +5 -0
  21. package/dist/lib/types/conversation.d.ts +19 -0
  22. package/dist/lib/types/generateTypes.d.ts +4 -1
  23. package/dist/lib/types/index.d.ts +2 -0
  24. package/dist/lib/types/index.js +2 -0
  25. package/dist/lib/types/streamTypes.d.ts +6 -3
  26. package/dist/lib/types/taskClassificationTypes.d.ts +52 -0
  27. package/dist/lib/types/taskClassificationTypes.js +5 -0
  28. package/dist/lib/utils/imageProcessor.d.ts +84 -0
  29. package/dist/lib/utils/imageProcessor.js +362 -0
  30. package/dist/lib/utils/messageBuilder.d.ts +8 -1
  31. package/dist/lib/utils/messageBuilder.js +279 -0
  32. package/dist/lib/utils/modelRouter.d.ts +107 -0
  33. package/dist/lib/utils/modelRouter.js +292 -0
  34. package/dist/lib/utils/promptRedaction.d.ts +29 -0
  35. package/dist/lib/utils/promptRedaction.js +62 -0
  36. package/dist/lib/utils/taskClassificationUtils.d.ts +55 -0
  37. package/dist/lib/utils/taskClassificationUtils.js +149 -0
  38. package/dist/lib/utils/taskClassifier.d.ts +23 -0
  39. package/dist/lib/utils/taskClassifier.js +94 -0
  40. package/dist/neurolink.d.ts +20 -0
  41. package/dist/neurolink.js +276 -8
  42. package/dist/types/content.d.ts +78 -0
  43. package/dist/types/content.js +5 -0
  44. package/dist/types/conversation.d.ts +19 -0
  45. package/dist/types/generateTypes.d.ts +4 -1
  46. package/dist/types/index.d.ts +2 -0
  47. package/dist/types/index.js +2 -0
  48. package/dist/types/streamTypes.d.ts +6 -3
  49. package/dist/types/taskClassificationTypes.d.ts +52 -0
  50. package/dist/types/taskClassificationTypes.js +5 -0
  51. package/dist/utils/imageProcessor.d.ts +84 -0
  52. package/dist/utils/imageProcessor.js +362 -0
  53. package/dist/utils/messageBuilder.d.ts +8 -1
  54. package/dist/utils/messageBuilder.js +279 -0
  55. package/dist/utils/modelRouter.d.ts +107 -0
  56. package/dist/utils/modelRouter.js +292 -0
  57. package/dist/utils/promptRedaction.d.ts +29 -0
  58. package/dist/utils/promptRedaction.js +62 -0
  59. package/dist/utils/taskClassificationUtils.d.ts +55 -0
  60. package/dist/utils/taskClassificationUtils.js +149 -0
  61. package/dist/utils/taskClassifier.d.ts +23 -0
  62. package/dist/utils/taskClassifier.js +94 -0
  63. package/package.json +1 -1
@@ -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
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Binary Task Classifier for NeuroLink Orchestration
3
+ * Classifies tasks as either 'fast' (quick responses) or 'reasoning' (complex analysis)
4
+ */
5
+ import { logger } from "./logger.js";
6
+ import { CLASSIFICATION_THRESHOLDS } from "../config/taskClassificationConfig.js";
7
+ import { analyzePrompt, calculateConfidence, determineTaskType, } from "./taskClassificationUtils.js";
8
+ import { redactForClassification } from "./promptRedaction.js";
9
+ /**
10
+ * Binary Task Classifier
11
+ * Determines if a task requires fast response or deeper reasoning
12
+ */
13
+ export class BinaryTaskClassifier {
14
+ /**
15
+ * Classify a prompt as either fast or reasoning task
16
+ */
17
+ static classify(prompt) {
18
+ const startTime = Date.now();
19
+ // Analyze the prompt using utility functions
20
+ const scores = analyzePrompt(prompt);
21
+ const { fastScore, reasoningScore, reasons } = scores;
22
+ // Determine final classification
23
+ const totalScore = fastScore + reasoningScore;
24
+ let type;
25
+ let confidence;
26
+ if (totalScore === 0) {
27
+ // Default to fast for ambiguous cases
28
+ type = "fast";
29
+ confidence = CLASSIFICATION_THRESHOLDS.DEFAULT_CONFIDENCE;
30
+ reasons.push("default fallback");
31
+ }
32
+ else {
33
+ type = determineTaskType(fastScore, reasoningScore);
34
+ confidence = calculateConfidence(fastScore, reasoningScore);
35
+ }
36
+ const classification = {
37
+ type,
38
+ confidence,
39
+ reasoning: reasons.join(", "),
40
+ };
41
+ const classificationTime = Date.now() - startTime;
42
+ logger.debug("Task classified", {
43
+ prompt: redactForClassification(prompt),
44
+ classification: type,
45
+ confidence: confidence.toFixed(2),
46
+ fastScore,
47
+ reasoningScore,
48
+ reasons: reasons.join(", "),
49
+ classificationTime: `${classificationTime}ms`,
50
+ });
51
+ return classification;
52
+ }
53
+ /**
54
+ * Get classification statistics for multiple prompts
55
+ */
56
+ static getClassificationStats(prompts) {
57
+ // Guard against empty array to prevent divide-by-zero
58
+ if (prompts.length === 0) {
59
+ const stats = {
60
+ total: 0,
61
+ fast: 0,
62
+ reasoning: 0,
63
+ averageConfidence: 0,
64
+ };
65
+ logger.debug("Classification stats", stats);
66
+ return stats;
67
+ }
68
+ const classifications = prompts.map((prompt) => this.classify(prompt));
69
+ const stats = {
70
+ total: classifications.length,
71
+ fast: classifications.filter((c) => c.type === "fast").length,
72
+ reasoning: classifications.filter((c) => c.type === "reasoning").length,
73
+ averageConfidence: classifications.reduce((sum, c) => sum + c.confidence, 0) /
74
+ classifications.length,
75
+ };
76
+ logger.debug("Classification stats", stats);
77
+ return stats;
78
+ }
79
+ /**
80
+ * Validate classification accuracy (for testing/tuning)
81
+ */
82
+ static validateClassification(prompt, expectedType) {
83
+ const classification = this.classify(prompt);
84
+ const correct = classification.type === expectedType;
85
+ logger.debug("Classification validation", {
86
+ prompt: redactForClassification(prompt),
87
+ expected: expectedType,
88
+ actual: classification.type,
89
+ correct,
90
+ confidence: classification.confidence,
91
+ });
92
+ return { correct, classification };
93
+ }
94
+ }
@@ -62,6 +62,7 @@ export declare class NeuroLink {
62
62
  private conversationMemory?;
63
63
  private conversationMemoryNeedsInit;
64
64
  private conversationMemoryConfig?;
65
+ private enableOrchestration;
65
66
  /**
66
67
  * Creates a new NeuroLink instance for AI text generation with MCP tool integration.
67
68
  *
@@ -70,6 +71,7 @@ export declare class NeuroLink {
70
71
  * @param config.conversationMemory.enabled - Whether to enable conversation memory (default: false)
71
72
  * @param config.conversationMemory.maxSessions - Maximum number of concurrent sessions (default: 100)
72
73
  * @param config.conversationMemory.maxTurnsPerSession - Maximum conversation turns per session (default: 50)
74
+ * @param config.enableOrchestration - Whether to enable smart model orchestration (default: false)
73
75
  *
74
76
  * @example
75
77
  * ```typescript
@@ -84,6 +86,11 @@ export declare class NeuroLink {
84
86
  * maxTurnsPerSession: 20
85
87
  * }
86
88
  * });
89
+ *
90
+ * // With orchestration enabled
91
+ * const neurolink = new NeuroLink({
92
+ * enableOrchestration: true
93
+ * });
87
94
  * ```
88
95
  *
89
96
  * @throws {Error} When provider registry setup fails
@@ -92,6 +99,7 @@ export declare class NeuroLink {
92
99
  */
93
100
  constructor(config?: {
94
101
  conversationMemory?: Partial<ConversationMemoryConfig>;
102
+ enableOrchestration?: boolean;
95
103
  });
96
104
  /**
97
105
  * Log constructor start with comprehensive environment analysis
@@ -158,6 +166,18 @@ export declare class NeuroLink {
158
166
  * Log MCP initialization completion
159
167
  */
160
168
  private logMCPInitComplete;
169
+ /**
170
+ * Apply orchestration to determine optimal provider and model
171
+ * @param options - Original GenerateOptions
172
+ * @returns Modified options with orchestrated provider marked in context, or empty object if validation fails
173
+ */
174
+ private applyOrchestration;
175
+ /**
176
+ * Apply orchestration to determine optimal provider and model for streaming
177
+ * @param options - Original StreamOptions
178
+ * @returns Modified options with orchestrated provider marked in context, or empty object if validation fails
179
+ */
180
+ private applyStreamOrchestration;
161
181
  /**
162
182
  * MAIN ENTRY POINT: Enhanced generate method with new function signature
163
183
  * Replaces both generateText and legacy methods