@juspay/neurolink 7.7.0 → 7.8.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 (83) hide show
  1. package/CHANGELOG.md +20 -2
  2. package/README.md +33 -2
  3. package/dist/cli/commands/config.d.ts +3 -3
  4. package/dist/cli/commands/sagemaker.d.ts +11 -0
  5. package/dist/cli/commands/sagemaker.js +778 -0
  6. package/dist/cli/factories/commandFactory.js +1 -0
  7. package/dist/cli/index.js +3 -0
  8. package/dist/cli/utils/interactiveSetup.js +28 -0
  9. package/dist/core/baseProvider.d.ts +2 -2
  10. package/dist/core/types.d.ts +1 -0
  11. package/dist/core/types.js +1 -0
  12. package/dist/factories/providerRegistry.js +5 -0
  13. package/dist/lib/core/baseProvider.d.ts +2 -2
  14. package/dist/lib/core/types.d.ts +1 -0
  15. package/dist/lib/core/types.js +1 -0
  16. package/dist/lib/factories/providerRegistry.js +5 -0
  17. package/dist/lib/providers/amazonSagemaker.d.ts +67 -0
  18. package/dist/lib/providers/amazonSagemaker.js +149 -0
  19. package/dist/lib/providers/index.d.ts +4 -0
  20. package/dist/lib/providers/index.js +4 -0
  21. package/dist/lib/providers/sagemaker/adaptive-semaphore.d.ts +86 -0
  22. package/dist/lib/providers/sagemaker/adaptive-semaphore.js +212 -0
  23. package/dist/lib/providers/sagemaker/client.d.ts +156 -0
  24. package/dist/lib/providers/sagemaker/client.js +462 -0
  25. package/dist/lib/providers/sagemaker/config.d.ts +73 -0
  26. package/dist/lib/providers/sagemaker/config.js +308 -0
  27. package/dist/lib/providers/sagemaker/detection.d.ts +176 -0
  28. package/dist/lib/providers/sagemaker/detection.js +596 -0
  29. package/dist/lib/providers/sagemaker/diagnostics.d.ts +37 -0
  30. package/dist/lib/providers/sagemaker/diagnostics.js +137 -0
  31. package/dist/lib/providers/sagemaker/error-constants.d.ts +78 -0
  32. package/dist/lib/providers/sagemaker/error-constants.js +227 -0
  33. package/dist/lib/providers/sagemaker/errors.d.ts +83 -0
  34. package/dist/lib/providers/sagemaker/errors.js +216 -0
  35. package/dist/lib/providers/sagemaker/index.d.ts +35 -0
  36. package/dist/lib/providers/sagemaker/index.js +67 -0
  37. package/dist/lib/providers/sagemaker/language-model.d.ts +182 -0
  38. package/dist/lib/providers/sagemaker/language-model.js +755 -0
  39. package/dist/lib/providers/sagemaker/parsers.d.ts +136 -0
  40. package/dist/lib/providers/sagemaker/parsers.js +625 -0
  41. package/dist/lib/providers/sagemaker/streaming.d.ts +39 -0
  42. package/dist/lib/providers/sagemaker/streaming.js +320 -0
  43. package/dist/lib/providers/sagemaker/structured-parser.d.ts +117 -0
  44. package/dist/lib/providers/sagemaker/structured-parser.js +625 -0
  45. package/dist/lib/providers/sagemaker/types.d.ts +456 -0
  46. package/dist/lib/providers/sagemaker/types.js +7 -0
  47. package/dist/lib/types/cli.d.ts +36 -1
  48. package/dist/lib/utils/providerConfig.js +6 -2
  49. package/dist/lib/utils/providerHealth.js +45 -9
  50. package/dist/providers/amazonSagemaker.d.ts +67 -0
  51. package/dist/providers/amazonSagemaker.js +149 -0
  52. package/dist/providers/index.d.ts +4 -0
  53. package/dist/providers/index.js +4 -0
  54. package/dist/providers/sagemaker/adaptive-semaphore.d.ts +86 -0
  55. package/dist/providers/sagemaker/adaptive-semaphore.js +212 -0
  56. package/dist/providers/sagemaker/client.d.ts +156 -0
  57. package/dist/providers/sagemaker/client.js +462 -0
  58. package/dist/providers/sagemaker/config.d.ts +73 -0
  59. package/dist/providers/sagemaker/config.js +308 -0
  60. package/dist/providers/sagemaker/detection.d.ts +176 -0
  61. package/dist/providers/sagemaker/detection.js +596 -0
  62. package/dist/providers/sagemaker/diagnostics.d.ts +37 -0
  63. package/dist/providers/sagemaker/diagnostics.js +137 -0
  64. package/dist/providers/sagemaker/error-constants.d.ts +78 -0
  65. package/dist/providers/sagemaker/error-constants.js +227 -0
  66. package/dist/providers/sagemaker/errors.d.ts +83 -0
  67. package/dist/providers/sagemaker/errors.js +216 -0
  68. package/dist/providers/sagemaker/index.d.ts +35 -0
  69. package/dist/providers/sagemaker/index.js +67 -0
  70. package/dist/providers/sagemaker/language-model.d.ts +182 -0
  71. package/dist/providers/sagemaker/language-model.js +755 -0
  72. package/dist/providers/sagemaker/parsers.d.ts +136 -0
  73. package/dist/providers/sagemaker/parsers.js +625 -0
  74. package/dist/providers/sagemaker/streaming.d.ts +39 -0
  75. package/dist/providers/sagemaker/streaming.js +320 -0
  76. package/dist/providers/sagemaker/structured-parser.d.ts +117 -0
  77. package/dist/providers/sagemaker/structured-parser.js +625 -0
  78. package/dist/providers/sagemaker/types.d.ts +456 -0
  79. package/dist/providers/sagemaker/types.js +7 -0
  80. package/dist/types/cli.d.ts +36 -1
  81. package/dist/utils/providerConfig.js +6 -2
  82. package/dist/utils/providerHealth.js +45 -9
  83. package/package.json +4 -1
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Amazon SageMaker Provider Implementation (Simplified)
3
+ *
4
+ * This module provides a simplified SageMaker provider that extends BaseProvider
5
+ * and integrates with the NeuroLink ecosystem using existing patterns.
6
+ */
7
+ import { BaseProvider } from "../core/baseProvider.js";
8
+ import { logger } from "../utils/logger.js";
9
+ // SageMaker-specific imports
10
+ import { getSageMakerConfig, getSageMakerModelConfig, getDefaultSageMakerEndpoint, getSageMakerModel, } from "./sagemaker/config.js";
11
+ import { handleSageMakerError, SageMakerError } from "./sagemaker/errors.js";
12
+ import { SageMakerLanguageModel } from "./sagemaker/language-model.js";
13
+ /**
14
+ * Amazon SageMaker Provider extending BaseProvider
15
+ */
16
+ export class AmazonSageMakerProvider extends BaseProvider {
17
+ sagemakerModel;
18
+ sagemakerConfig;
19
+ modelConfig;
20
+ constructor(modelName, endpointName) {
21
+ super(modelName, "sagemaker");
22
+ try {
23
+ // Load and validate configuration
24
+ this.sagemakerConfig = getSageMakerConfig();
25
+ this.modelConfig = getSageMakerModelConfig(endpointName || getDefaultSageMakerEndpoint());
26
+ // Create the proper LanguageModel (v2) implementation
27
+ this.sagemakerModel = new SageMakerLanguageModel(this.modelName, this.sagemakerConfig, this.modelConfig);
28
+ logger.debug("Amazon SageMaker Provider initialized", {
29
+ modelName: this.modelName,
30
+ endpointName: this.modelConfig.endpointName,
31
+ region: this.sagemakerConfig.region,
32
+ provider: this.providerName,
33
+ });
34
+ }
35
+ catch (error) {
36
+ logger.error("Failed to initialize SageMaker provider", {
37
+ error: error instanceof Error ? error.message : String(error),
38
+ modelName,
39
+ endpointName,
40
+ });
41
+ throw handleSageMakerError(error);
42
+ }
43
+ }
44
+ getProviderName() {
45
+ return "sagemaker";
46
+ }
47
+ getDefaultModel() {
48
+ return getSageMakerModel();
49
+ }
50
+ getAISDKModel() {
51
+ return this.sagemakerModel;
52
+ }
53
+ async executeStream(options, analysisSchema) {
54
+ try {
55
+ // For now, throw an error indicating this is not yet implemented
56
+ throw new SageMakerError("SageMaker streaming not yet fully implemented. Coming in next phase.", "MODEL_ERROR", 501, undefined, this.modelConfig.endpointName);
57
+ }
58
+ catch (error) {
59
+ throw this.handleProviderError(error);
60
+ }
61
+ }
62
+ handleProviderError(error) {
63
+ if (error instanceof SageMakerError) {
64
+ return error;
65
+ }
66
+ if (error instanceof Error && error.name === "TimeoutError") {
67
+ return new SageMakerError(`SageMaker request timed out. Consider increasing timeout.`, "NETWORK_ERROR", 408, error, this.modelConfig.endpointName);
68
+ }
69
+ return handleSageMakerError(error, this.modelConfig.endpointName);
70
+ }
71
+ /**
72
+ * Get SageMaker-specific provider information
73
+ */
74
+ getSageMakerInfo() {
75
+ return {
76
+ endpointName: this.modelConfig.endpointName,
77
+ modelType: this.modelConfig.modelType || "custom",
78
+ region: this.sagemakerConfig.region,
79
+ configured: !!(this.sagemakerConfig.accessKeyId && this.sagemakerConfig.secretAccessKey),
80
+ };
81
+ }
82
+ /**
83
+ * Test basic configuration
84
+ */
85
+ async testConnection() {
86
+ try {
87
+ // Basic validation test
88
+ if (!this.sagemakerConfig.accessKeyId ||
89
+ !this.sagemakerConfig.secretAccessKey) {
90
+ return {
91
+ connected: false,
92
+ error: "AWS credentials not configured",
93
+ };
94
+ }
95
+ if (!this.modelConfig.endpointName ||
96
+ this.modelConfig.endpointName === "default-endpoint") {
97
+ return {
98
+ connected: false,
99
+ error: "SageMaker endpoint not configured",
100
+ };
101
+ }
102
+ // For now, just return that configuration looks valid
103
+ return {
104
+ connected: true,
105
+ };
106
+ }
107
+ catch (error) {
108
+ return {
109
+ connected: false,
110
+ error: error instanceof Error ? error.message : String(error),
111
+ };
112
+ }
113
+ }
114
+ /**
115
+ * Public method to get the AI SDK model for CLI and external usage
116
+ */
117
+ async getModel() {
118
+ return this.getAISDKModel();
119
+ }
120
+ /**
121
+ * Test connectivity to the SageMaker endpoint
122
+ */
123
+ async testConnectivity() {
124
+ const model = this.sagemakerModel;
125
+ return model.testConnectivity
126
+ ? await model.testConnectivity()
127
+ : { success: false, error: "Test method not available" };
128
+ }
129
+ /**
130
+ * Get model capabilities and information
131
+ */
132
+ getModelCapabilities() {
133
+ const model = this.sagemakerModel;
134
+ return model.getModelCapabilities
135
+ ? model.getModelCapabilities()
136
+ : {
137
+ capabilities: {
138
+ streaming: true,
139
+ toolCalling: true,
140
+ structuredOutput: true,
141
+ batchInference: true,
142
+ supportedResponseFormats: ["text", "json_object"],
143
+ supportedToolTypes: ["function"],
144
+ maxBatchSize: 10,
145
+ },
146
+ };
147
+ }
148
+ }
149
+ export default AmazonSageMakerProvider;
@@ -4,6 +4,7 @@
4
4
  */
5
5
  export { GoogleVertexProvider as GoogleVertexAI } from "./googleVertex.js";
6
6
  export { AmazonBedrockProvider as AmazonBedrock } from "./amazonBedrock.js";
7
+ export { AmazonSageMakerProvider as AmazonSageMaker } from "./amazonSagemaker.js";
7
8
  export { OpenAIProvider as OpenAI } from "./openAI.js";
8
9
  export { OpenAICompatibleProvider as OpenAICompatible } from "./openaiCompatible.js";
9
10
  export { AnthropicProvider as AnthropicProvider } from "./anthropic.js";
@@ -12,6 +13,7 @@ export { GoogleAIStudioProvider as GoogleAIStudio } from "./googleAiStudio.js";
12
13
  export { HuggingFaceProvider as HuggingFace } from "./huggingFace.js";
13
14
  export { OllamaProvider as Ollama } from "./ollama.js";
14
15
  export { MistralProvider as MistralAI } from "./mistral.js";
16
+ export { LiteLLMProvider as LiteLLM } from "./litellm.js";
15
17
  export type { AIProvider } from "../core/types.js";
16
18
  /**
17
19
  * Provider registry for dynamic provider instantiation
@@ -19,6 +21,7 @@ export type { AIProvider } from "../core/types.js";
19
21
  export declare const PROVIDERS: {
20
22
  readonly vertex: "GoogleVertexAI";
21
23
  readonly bedrock: "AmazonBedrock";
24
+ readonly sagemaker: "AmazonSageMaker";
22
25
  readonly openai: "OpenAI";
23
26
  readonly "openai-compatible": "OpenAICompatible";
24
27
  readonly anthropic: "AnthropicProvider";
@@ -27,6 +30,7 @@ export declare const PROVIDERS: {
27
30
  readonly huggingface: "HuggingFace";
28
31
  readonly ollama: "Ollama";
29
32
  readonly mistral: "MistralAI";
33
+ readonly litellm: "LiteLLM";
30
34
  };
31
35
  /**
32
36
  * Type for valid provider names
@@ -4,6 +4,7 @@
4
4
  */
5
5
  export { GoogleVertexProvider as GoogleVertexAI } from "./googleVertex.js";
6
6
  export { AmazonBedrockProvider as AmazonBedrock } from "./amazonBedrock.js";
7
+ export { AmazonSageMakerProvider as AmazonSageMaker } from "./amazonSagemaker.js";
7
8
  export { OpenAIProvider as OpenAI } from "./openAI.js";
8
9
  export { OpenAICompatibleProvider as OpenAICompatible } from "./openaiCompatible.js";
9
10
  export { AnthropicProvider as AnthropicProvider } from "./anthropic.js";
@@ -12,12 +13,14 @@ export { GoogleAIStudioProvider as GoogleAIStudio } from "./googleAiStudio.js";
12
13
  export { HuggingFaceProvider as HuggingFace } from "./huggingFace.js";
13
14
  export { OllamaProvider as Ollama } from "./ollama.js";
14
15
  export { MistralProvider as MistralAI } from "./mistral.js";
16
+ export { LiteLLMProvider as LiteLLM } from "./litellm.js";
15
17
  /**
16
18
  * Provider registry for dynamic provider instantiation
17
19
  */
18
20
  export const PROVIDERS = {
19
21
  vertex: "GoogleVertexAI",
20
22
  bedrock: "AmazonBedrock",
23
+ sagemaker: "AmazonSageMaker",
21
24
  openai: "OpenAI",
22
25
  "openai-compatible": "OpenAICompatible",
23
26
  anthropic: "AnthropicProvider",
@@ -26,6 +29,7 @@ export const PROVIDERS = {
26
29
  huggingface: "HuggingFace",
27
30
  ollama: "Ollama",
28
31
  mistral: "MistralAI",
32
+ litellm: "LiteLLM",
29
33
  };
30
34
  /**
31
35
  * List of all available provider names
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Adaptive Semaphore Utility
3
+ *
4
+ * Provides a sophisticated semaphore implementation with dynamic concurrency adjustment
5
+ * for optimal resource utilization and performance tuning based on response times and error rates.
6
+ */
7
+ export interface AdaptiveSemaphoreConfig {
8
+ initialConcurrency: number;
9
+ maxConcurrency: number;
10
+ minConcurrency: number;
11
+ }
12
+ export interface AdaptiveSemaphoreMetrics {
13
+ activeRequests: number;
14
+ currentConcurrency: number;
15
+ completedCount: number;
16
+ errorCount: number;
17
+ averageResponseTime: number;
18
+ waitingCount: number;
19
+ }
20
+ /**
21
+ * Adaptive semaphore that automatically adjusts concurrency based on performance metrics
22
+ */
23
+ export declare class AdaptiveSemaphore {
24
+ private count;
25
+ private waiters;
26
+ private currentConcurrency;
27
+ private activeRequests;
28
+ private completedCount;
29
+ private errorCount;
30
+ private responseTimes;
31
+ private readonly maxConcurrency;
32
+ private readonly minConcurrency;
33
+ constructor(config: AdaptiveSemaphoreConfig);
34
+ /**
35
+ * Acquire a semaphore permit, waiting if necessary
36
+ */
37
+ acquire(): Promise<void>;
38
+ /**
39
+ * Release a semaphore permit and wake up waiting requests
40
+ */
41
+ release(): void;
42
+ /**
43
+ * Record successful completion with response time for adaptive adjustment
44
+ */
45
+ recordSuccess(responseTimeMs: number): void;
46
+ /**
47
+ * Record error for adaptive adjustment
48
+ */
49
+ recordError(responseTimeMs?: number): void;
50
+ /**
51
+ * Manually adjust concurrency level
52
+ */
53
+ adjustConcurrency(newLimit: number): void;
54
+ /**
55
+ * Get current performance metrics
56
+ */
57
+ getMetrics(): AdaptiveSemaphoreMetrics;
58
+ /**
59
+ * Reset metrics for new batch or session
60
+ */
61
+ resetMetrics(): void;
62
+ /**
63
+ * Automatically adjust concurrency based on performance indicators
64
+ */
65
+ private adjustConcurrencyBasedOnPerformance;
66
+ /**
67
+ * Check if semaphore is idle (no active or waiting requests)
68
+ */
69
+ isIdle(): boolean;
70
+ /**
71
+ * Get current concurrency limit
72
+ */
73
+ getCurrentConcurrency(): number;
74
+ /**
75
+ * Get number of active requests
76
+ */
77
+ getActiveRequestCount(): number;
78
+ /**
79
+ * Get number of waiting requests
80
+ */
81
+ getWaitingRequestCount(): number;
82
+ }
83
+ /**
84
+ * Factory function to create an adaptive semaphore with default configuration
85
+ */
86
+ export declare function createAdaptiveSemaphore(initialConcurrency: number, maxConcurrency?: number, minConcurrency?: number): AdaptiveSemaphore;
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Adaptive Semaphore Utility
3
+ *
4
+ * Provides a sophisticated semaphore implementation with dynamic concurrency adjustment
5
+ * for optimal resource utilization and performance tuning based on response times and error rates.
6
+ */
7
+ import { logger } from "../../utils/logger.js";
8
+ /**
9
+ * Adaptive semaphore that automatically adjusts concurrency based on performance metrics
10
+ */
11
+ export class AdaptiveSemaphore {
12
+ count;
13
+ waiters = [];
14
+ currentConcurrency;
15
+ activeRequests = 0;
16
+ completedCount = 0;
17
+ errorCount = 0;
18
+ responseTimes = [];
19
+ maxConcurrency;
20
+ minConcurrency;
21
+ constructor(config) {
22
+ this.currentConcurrency = config.initialConcurrency;
23
+ this.count = config.initialConcurrency;
24
+ this.maxConcurrency = config.maxConcurrency;
25
+ this.minConcurrency = config.minConcurrency;
26
+ logger.debug("AdaptiveSemaphore initialized", {
27
+ initialConcurrency: config.initialConcurrency,
28
+ maxConcurrency: config.maxConcurrency,
29
+ minConcurrency: config.minConcurrency,
30
+ });
31
+ }
32
+ /**
33
+ * Acquire a semaphore permit, waiting if necessary
34
+ */
35
+ async acquire() {
36
+ return new Promise((resolve) => {
37
+ if (this.count > 0) {
38
+ this.count--;
39
+ this.activeRequests++;
40
+ resolve();
41
+ }
42
+ else {
43
+ this.waiters.push(() => {
44
+ this.count--;
45
+ this.activeRequests++;
46
+ resolve();
47
+ });
48
+ }
49
+ });
50
+ }
51
+ /**
52
+ * Release a semaphore permit and wake up waiting requests
53
+ */
54
+ release() {
55
+ this.activeRequests--;
56
+ if (this.waiters.length > 0) {
57
+ const waiter = this.waiters.shift();
58
+ waiter();
59
+ }
60
+ else {
61
+ this.count++;
62
+ }
63
+ }
64
+ /**
65
+ * Record successful completion with response time for adaptive adjustment
66
+ */
67
+ recordSuccess(responseTimeMs) {
68
+ this.completedCount++;
69
+ this.responseTimes.push(responseTimeMs);
70
+ // Keep only recent response times for calculation (last 10 responses)
71
+ if (this.responseTimes.length > 10) {
72
+ this.responseTimes.shift();
73
+ }
74
+ this.adjustConcurrencyBasedOnPerformance(responseTimeMs, false);
75
+ }
76
+ /**
77
+ * Record error for adaptive adjustment
78
+ */
79
+ recordError(responseTimeMs) {
80
+ this.errorCount++;
81
+ if (responseTimeMs) {
82
+ this.responseTimes.push(responseTimeMs);
83
+ if (this.responseTimes.length > 10) {
84
+ this.responseTimes.shift();
85
+ }
86
+ }
87
+ this.adjustConcurrencyBasedOnPerformance(responseTimeMs || 0, true);
88
+ }
89
+ /**
90
+ * Manually adjust concurrency level
91
+ */
92
+ adjustConcurrency(newLimit) {
93
+ const clampedLimit = Math.max(this.minConcurrency, Math.min(this.maxConcurrency, newLimit));
94
+ const diff = clampedLimit - (this.currentConcurrency - this.count);
95
+ this.count += diff;
96
+ this.currentConcurrency = clampedLimit;
97
+ logger.debug("Concurrency adjusted", {
98
+ newConcurrency: clampedLimit,
99
+ previousConcurrency: this.currentConcurrency - diff,
100
+ availableCount: this.count,
101
+ activeRequests: this.activeRequests,
102
+ });
103
+ // Wake up waiting requests if we increased concurrency
104
+ while (this.count > 0 && this.waiters.length > 0) {
105
+ const waiter = this.waiters.shift();
106
+ this.count--;
107
+ this.activeRequests++;
108
+ waiter();
109
+ }
110
+ }
111
+ /**
112
+ * Get current performance metrics
113
+ */
114
+ getMetrics() {
115
+ const averageResponseTime = this.responseTimes.length > 0
116
+ ? this.responseTimes.reduce((sum, time) => sum + time, 0) /
117
+ this.responseTimes.length
118
+ : 0;
119
+ return {
120
+ activeRequests: this.activeRequests,
121
+ currentConcurrency: this.currentConcurrency,
122
+ completedCount: this.completedCount,
123
+ errorCount: this.errorCount,
124
+ averageResponseTime,
125
+ waitingCount: this.waiters.length,
126
+ };
127
+ }
128
+ /**
129
+ * Reset metrics for new batch or session
130
+ */
131
+ resetMetrics() {
132
+ this.completedCount = 0;
133
+ this.errorCount = 0;
134
+ this.responseTimes = [];
135
+ }
136
+ /**
137
+ * Automatically adjust concurrency based on performance indicators
138
+ */
139
+ adjustConcurrencyBasedOnPerformance(responseTimeMs, isError) {
140
+ const metrics = this.getMetrics();
141
+ if (isError) {
142
+ // On error, reduce concurrency to be more conservative
143
+ if (this.currentConcurrency > this.minConcurrency) {
144
+ this.adjustConcurrency(Math.max(this.minConcurrency, this.currentConcurrency - 1));
145
+ logger.warn("Reduced concurrency due to error", {
146
+ newConcurrency: this.currentConcurrency,
147
+ errorCount: this.errorCount,
148
+ });
149
+ }
150
+ return;
151
+ }
152
+ // Only adjust after we have some data to work with
153
+ if (this.completedCount < 3) {
154
+ return;
155
+ }
156
+ const fastResponseThreshold = 2000; // 2 seconds
157
+ const slowResponseThreshold = 5000; // 5 seconds
158
+ if (responseTimeMs < fastResponseThreshold &&
159
+ metrics.averageResponseTime < fastResponseThreshold &&
160
+ this.currentConcurrency < this.maxConcurrency) {
161
+ // Fast responses and no bottleneck - increase concurrency
162
+ this.adjustConcurrency(Math.min(this.maxConcurrency, this.currentConcurrency + 1));
163
+ logger.debug("Increased concurrency due to fast responses", {
164
+ newConcurrency: this.currentConcurrency,
165
+ averageResponseTime: metrics.averageResponseTime,
166
+ });
167
+ }
168
+ else if (responseTimeMs > slowResponseThreshold &&
169
+ this.currentConcurrency > this.minConcurrency) {
170
+ // Slow responses - decrease concurrency
171
+ this.adjustConcurrency(Math.max(this.minConcurrency, this.currentConcurrency - 1));
172
+ logger.debug("Decreased concurrency due to slow responses", {
173
+ newConcurrency: this.currentConcurrency,
174
+ responseTime: responseTimeMs,
175
+ });
176
+ }
177
+ }
178
+ /**
179
+ * Check if semaphore is idle (no active or waiting requests)
180
+ */
181
+ isIdle() {
182
+ return this.activeRequests === 0 && this.waiters.length === 0;
183
+ }
184
+ /**
185
+ * Get current concurrency limit
186
+ */
187
+ getCurrentConcurrency() {
188
+ return this.currentConcurrency;
189
+ }
190
+ /**
191
+ * Get number of active requests
192
+ */
193
+ getActiveRequestCount() {
194
+ return this.activeRequests;
195
+ }
196
+ /**
197
+ * Get number of waiting requests
198
+ */
199
+ getWaitingRequestCount() {
200
+ return this.waiters.length;
201
+ }
202
+ }
203
+ /**
204
+ * Factory function to create an adaptive semaphore with default configuration
205
+ */
206
+ export function createAdaptiveSemaphore(initialConcurrency, maxConcurrency = 10, minConcurrency = 1) {
207
+ return new AdaptiveSemaphore({
208
+ initialConcurrency,
209
+ maxConcurrency,
210
+ minConcurrency,
211
+ });
212
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * AWS SageMaker Runtime Client Wrapper
3
+ *
4
+ * This module provides a wrapper around the AWS SDK SageMaker Runtime client
5
+ * with enhanced error handling, retry logic, and NeuroLink-specific features.
6
+ */
7
+ import type { SageMakerConfig, InvokeEndpointParams, InvokeEndpointResponse } from "./types.js";
8
+ /**
9
+ * Enhanced SageMaker Runtime client with retry logic and error handling
10
+ */
11
+ export declare class SageMakerRuntimeClient {
12
+ private client;
13
+ private config;
14
+ private isDisposed;
15
+ constructor(config: SageMakerConfig);
16
+ /**
17
+ * Invoke a SageMaker endpoint for synchronous inference
18
+ *
19
+ * @param params - Endpoint invocation parameters
20
+ * @returns Promise resolving to the inference response
21
+ * @throws {SageMakerError} When the request fails
22
+ */
23
+ invokeEndpoint(params: InvokeEndpointParams): Promise<InvokeEndpointResponse>;
24
+ /**
25
+ * Invoke a SageMaker endpoint with streaming response
26
+ *
27
+ * @param params - Endpoint invocation parameters for streaming
28
+ * @returns Promise resolving to async iterable of response chunks
29
+ * @throws {SageMakerError} When the request fails
30
+ */
31
+ invokeEndpointWithStreaming(params: InvokeEndpointParams): Promise<{
32
+ Body: AsyncIterable<Uint8Array>;
33
+ ContentType?: string;
34
+ InvokedProductionVariant?: string;
35
+ }>;
36
+ /**
37
+ * Execute a request with automatic retry logic
38
+ *
39
+ * @param operation - Function that executes the AWS SDK command
40
+ * @param endpointName - Endpoint name for error context
41
+ * @param attempt - Current attempt number (for recursive retries)
42
+ * @returns Promise resolving to the operation result
43
+ */
44
+ private executeWithRetry;
45
+ /**
46
+ * Validate endpoint connectivity and permissions
47
+ *
48
+ * @param endpointName - Name of the endpoint to validate
49
+ * @returns Promise resolving to validation result
50
+ */
51
+ validateEndpoint(endpointName: string): Promise<{
52
+ isValid: boolean;
53
+ status?: string;
54
+ error?: string;
55
+ }>;
56
+ /**
57
+ * Get client configuration summary for debugging
58
+ *
59
+ * @returns Configuration summary (with sensitive data masked)
60
+ */
61
+ getConfigSummary(): Record<string, unknown>;
62
+ /**
63
+ * Check if the client is properly configured
64
+ *
65
+ * @returns True if client appears to be properly configured
66
+ */
67
+ isConfigured(): boolean;
68
+ /**
69
+ * Convert AWS SDK async iterable stream with payload structure
70
+ */
71
+ private convertAsyncIterableStream;
72
+ /**
73
+ * Convert Node.js readable stream with reader interface
74
+ */
75
+ private convertReadableStream;
76
+ /**
77
+ * Convert non-stream data to single Uint8Array chunk as fallback
78
+ */
79
+ private convertFallbackData;
80
+ /**
81
+ * Convert AWS response stream to async iterable of Uint8Array chunks
82
+ * Refactored into smaller focused methods for different stream types
83
+ */
84
+ private convertAWSStreamToIterable;
85
+ /**
86
+ * Check if the client has been disposed
87
+ */
88
+ get disposed(): boolean;
89
+ /**
90
+ * Dispose of the client and clean up resources using explicit disposed state pattern
91
+ *
92
+ * AWS SDK v3 Automatic Resource Management:
93
+ * ========================================
94
+ *
95
+ * The AWS SDK v3 uses automatic resource cleanup and doesn't require explicit disposal
96
+ * of client instances in most cases. Here's how it works:
97
+ *
98
+ * 1. **HTTP Connection Pools**: AWS SDK v3 uses Node.js's built-in HTTP agent with
99
+ * connection pooling. These connections are automatically managed and will be
100
+ * closed when the Node.js process exits or becomes idle.
101
+ *
102
+ * 2. **Memory Management**: SDK clients don't hold significant resources that require
103
+ * manual cleanup. The JavaScript garbage collector handles memory deallocation
104
+ * when client references are removed.
105
+ *
106
+ * 3. **Background Timers**: Any internal timers (for retries, timeouts) are automatically
107
+ * cleared when operations complete or the client goes out of scope.
108
+ *
109
+ * 4. **Keep-Alive Connections**: HTTP keep-alive connections are managed by the
110
+ * underlying HTTP agent and will timeout automatically based on the configured
111
+ * keep-alive timeout (typically 15 seconds).
112
+ *
113
+ * Why We Still Implement dispose():
114
+ * =================================
115
+ *
116
+ * 1. **Explicit State Management**: Provides clear lifecycle control and prevents
117
+ * accidental usage of disposed clients.
118
+ *
119
+ * 2. **Resource Tracking**: Allows our application to track when clients are no
120
+ * longer needed, which is useful for debugging and monitoring.
121
+ *
122
+ * 3. **Defensive Programming**: Ensures we don't rely on automatic cleanup in
123
+ * environments where it might not work as expected.
124
+ *
125
+ * 4. **Future Compatibility**: If future SDK versions require explicit cleanup,
126
+ * we already have the infrastructure in place.
127
+ *
128
+ * For more information, see:
129
+ * - https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/
130
+ * - https://aws.amazon.com/blogs/developer/node-js-configuring-maxsockets-in-sdk-for-javascript/
131
+ */
132
+ dispose(): void;
133
+ /**
134
+ * Ensure client is not disposed before operations
135
+ */
136
+ private ensureNotDisposed;
137
+ }
138
+ /**
139
+ * Factory function to create a SageMaker Runtime client
140
+ *
141
+ * @param config - SageMaker configuration
142
+ * @returns Configured SageMakerRuntimeClient instance
143
+ */
144
+ export declare function createSageMakerRuntimeClient(config: SageMakerConfig): SageMakerRuntimeClient;
145
+ /**
146
+ * Utility function to test SageMaker connectivity
147
+ *
148
+ * @param config - SageMaker configuration
149
+ * @param endpointName - Endpoint to test
150
+ * @returns Promise resolving to connectivity test result
151
+ */
152
+ export declare function testSageMakerConnectivity(config: SageMakerConfig, endpointName: string): Promise<{
153
+ connected: boolean;
154
+ latency?: number;
155
+ error?: string;
156
+ }>;