@x12i/ai-gateway 7.9.1

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 (179) hide show
  1. package/README.md +4259 -0
  2. package/config.defaults.json +31 -0
  3. package/dist/activity-manager.d.ts +206 -0
  4. package/dist/activity-manager.js +1051 -0
  5. package/dist/config/activity-tracking-config.d.ts +11 -0
  6. package/dist/config/activity-tracking-config.js +15 -0
  7. package/dist/config.defaults.json +31 -0
  8. package/dist/content-normalizer/content-normalizer.d.ts +46 -0
  9. package/dist/content-normalizer/content-normalizer.js +393 -0
  10. package/dist/content-normalizer/index.d.ts +7 -0
  11. package/dist/content-normalizer/index.js +6 -0
  12. package/dist/content-normalizer/types.d.ts +33 -0
  13. package/dist/content-normalizer/types.js +4 -0
  14. package/dist/defaults/instructions-blocks.json +61 -0
  15. package/dist/defaults/model-config.json +16 -0
  16. package/dist/defaults/template-rendering.json +6 -0
  17. package/dist/flex-md-loader.d.ts +109 -0
  18. package/dist/flex-md-loader.js +940 -0
  19. package/dist/gateway-config.d.ts +49 -0
  20. package/dist/gateway-config.js +292 -0
  21. package/dist/gateway-conversion.d.ts +29 -0
  22. package/dist/gateway-conversion.js +174 -0
  23. package/dist/gateway-instructions.d.ts +30 -0
  24. package/dist/gateway-instructions.js +62 -0
  25. package/dist/gateway-memory.d.ts +51 -0
  26. package/dist/gateway-memory.js +207 -0
  27. package/dist/gateway-messages.d.ts +23 -0
  28. package/dist/gateway-messages.js +83 -0
  29. package/dist/gateway-meta.d.ts +25 -0
  30. package/dist/gateway-meta.js +87 -0
  31. package/dist/gateway-provider-auto-register.d.ts +17 -0
  32. package/dist/gateway-provider-auto-register.js +159 -0
  33. package/dist/gateway-provider.d.ts +54 -0
  34. package/dist/gateway-provider.js +202 -0
  35. package/dist/gateway-rate-limiter-constants.d.ts +16 -0
  36. package/dist/gateway-rate-limiter-constants.js +16 -0
  37. package/dist/gateway-rate-limiter.d.ts +56 -0
  38. package/dist/gateway-rate-limiter.js +107 -0
  39. package/dist/gateway-retry.d.ts +49 -0
  40. package/dist/gateway-retry.js +204 -0
  41. package/dist/gateway-utils.d.ts +21 -0
  42. package/dist/gateway-utils.js +181 -0
  43. package/dist/gateway-validation.d.ts +13 -0
  44. package/dist/gateway-validation.js +50 -0
  45. package/dist/gateway.d.ts +39 -0
  46. package/dist/gateway.js +430 -0
  47. package/dist/index.d.ts +36 -0
  48. package/dist/index.js +55 -0
  49. package/dist/instruction-errors.d.ts +16 -0
  50. package/dist/instruction-errors.js +29 -0
  51. package/dist/instruction-optimizer.d.ts +113 -0
  52. package/dist/instruction-optimizer.js +293 -0
  53. package/dist/instructions-parser.d.ts +31 -0
  54. package/dist/instructions-parser.js +56 -0
  55. package/dist/logger-factory.d.ts +17 -0
  56. package/dist/logger-factory.js +42 -0
  57. package/dist/message-builder.d.ts +41 -0
  58. package/dist/message-builder.js +522 -0
  59. package/dist/object-types-library-integration.d.ts +22 -0
  60. package/dist/object-types-library-integration.js +27 -0
  61. package/dist/object-types-library.d.ts +351 -0
  62. package/dist/object-types-library.js +210 -0
  63. package/dist/output-auditor.d.ts +44 -0
  64. package/dist/output-auditor.js +49 -0
  65. package/dist/request-report-generator.d.ts +60 -0
  66. package/dist/request-report-generator.js +169 -0
  67. package/dist/response-analyzer/format-type-detector.d.ts +35 -0
  68. package/dist/response-analyzer/format-type-detector.js +115 -0
  69. package/dist/response-analyzer/index.d.ts +9 -0
  70. package/dist/response-analyzer/index.js +8 -0
  71. package/dist/response-analyzer/object-type-detector.d.ts +42 -0
  72. package/dist/response-analyzer/object-type-detector.js +95 -0
  73. package/dist/response-analyzer/response-analyzer.d.ts +38 -0
  74. package/dist/response-analyzer/response-analyzer.js +97 -0
  75. package/dist/response-analyzer/types.d.ts +97 -0
  76. package/dist/response-analyzer/types.js +4 -0
  77. package/dist/response-fallback-fixer.d.ts +11 -0
  78. package/dist/response-fallback-fixer.js +123 -0
  79. package/dist/runtime-objects.d.ts +52 -0
  80. package/dist/runtime-objects.js +46 -0
  81. package/dist/template-parser.d.ts +58 -0
  82. package/dist/template-parser.js +99 -0
  83. package/dist/template-render-merge.d.ts +9 -0
  84. package/dist/template-render-merge.js +40 -0
  85. package/dist/troubleshooting-helper.d.ts +123 -0
  86. package/dist/troubleshooting-helper.js +596 -0
  87. package/dist/types.d.ts +1173 -0
  88. package/dist/types.js +6 -0
  89. package/dist/usage-tracker.d.ts +78 -0
  90. package/dist/usage-tracker.js +79 -0
  91. package/dist-cjs/activity-manager.cjs +1056 -0
  92. package/dist-cjs/activity-manager.d.ts +206 -0
  93. package/dist-cjs/config/activity-tracking-config.cjs +18 -0
  94. package/dist-cjs/config/activity-tracking-config.d.ts +11 -0
  95. package/dist-cjs/config.defaults.json +31 -0
  96. package/dist-cjs/content-normalizer/content-normalizer.cjs +398 -0
  97. package/dist-cjs/content-normalizer/content-normalizer.d.ts +46 -0
  98. package/dist-cjs/content-normalizer/index.cjs +12 -0
  99. package/dist-cjs/content-normalizer/index.d.ts +7 -0
  100. package/dist-cjs/content-normalizer/types.cjs +5 -0
  101. package/dist-cjs/content-normalizer/types.d.ts +33 -0
  102. package/dist-cjs/defaults/instructions-blocks.json +61 -0
  103. package/dist-cjs/defaults/model-config.json +16 -0
  104. package/dist-cjs/defaults/template-rendering.json +6 -0
  105. package/dist-cjs/flex-md-loader.cjs +986 -0
  106. package/dist-cjs/flex-md-loader.d.ts +109 -0
  107. package/dist-cjs/gateway-config.cjs +331 -0
  108. package/dist-cjs/gateway-config.d.ts +49 -0
  109. package/dist-cjs/gateway-conversion.cjs +212 -0
  110. package/dist-cjs/gateway-conversion.d.ts +29 -0
  111. package/dist-cjs/gateway-instructions.cjs +67 -0
  112. package/dist-cjs/gateway-instructions.d.ts +30 -0
  113. package/dist-cjs/gateway-memory.cjs +211 -0
  114. package/dist-cjs/gateway-memory.d.ts +51 -0
  115. package/dist-cjs/gateway-messages.cjs +86 -0
  116. package/dist-cjs/gateway-messages.d.ts +23 -0
  117. package/dist-cjs/gateway-meta.cjs +90 -0
  118. package/dist-cjs/gateway-meta.d.ts +25 -0
  119. package/dist-cjs/gateway-provider-auto-register.cjs +195 -0
  120. package/dist-cjs/gateway-provider-auto-register.d.ts +17 -0
  121. package/dist-cjs/gateway-provider.cjs +214 -0
  122. package/dist-cjs/gateway-provider.d.ts +54 -0
  123. package/dist-cjs/gateway-rate-limiter-constants.cjs +19 -0
  124. package/dist-cjs/gateway-rate-limiter-constants.d.ts +16 -0
  125. package/dist-cjs/gateway-rate-limiter.cjs +111 -0
  126. package/dist-cjs/gateway-rate-limiter.d.ts +56 -0
  127. package/dist-cjs/gateway-retry.cjs +212 -0
  128. package/dist-cjs/gateway-retry.d.ts +49 -0
  129. package/dist-cjs/gateway-utils.cjs +219 -0
  130. package/dist-cjs/gateway-utils.d.ts +21 -0
  131. package/dist-cjs/gateway-validation.cjs +54 -0
  132. package/dist-cjs/gateway-validation.d.ts +13 -0
  133. package/dist-cjs/gateway.cjs +434 -0
  134. package/dist-cjs/gateway.d.ts +39 -0
  135. package/dist-cjs/index.cjs +108 -0
  136. package/dist-cjs/index.d.ts +36 -0
  137. package/dist-cjs/instruction-errors.cjs +34 -0
  138. package/dist-cjs/instruction-errors.d.ts +16 -0
  139. package/dist-cjs/instruction-optimizer.cjs +299 -0
  140. package/dist-cjs/instruction-optimizer.d.ts +113 -0
  141. package/dist-cjs/instructions-parser.cjs +61 -0
  142. package/dist-cjs/instructions-parser.d.ts +31 -0
  143. package/dist-cjs/logger-factory.cjs +45 -0
  144. package/dist-cjs/logger-factory.d.ts +17 -0
  145. package/dist-cjs/message-builder.cjs +558 -0
  146. package/dist-cjs/message-builder.d.ts +41 -0
  147. package/dist-cjs/object-types-library-integration.cjs +32 -0
  148. package/dist-cjs/object-types-library-integration.d.ts +22 -0
  149. package/dist-cjs/object-types-library.cjs +215 -0
  150. package/dist-cjs/object-types-library.d.ts +351 -0
  151. package/dist-cjs/output-auditor.cjs +52 -0
  152. package/dist-cjs/output-auditor.d.ts +44 -0
  153. package/dist-cjs/request-report-generator.cjs +172 -0
  154. package/dist-cjs/request-report-generator.d.ts +60 -0
  155. package/dist-cjs/response-analyzer/format-type-detector.cjs +119 -0
  156. package/dist-cjs/response-analyzer/format-type-detector.d.ts +35 -0
  157. package/dist-cjs/response-analyzer/index.cjs +14 -0
  158. package/dist-cjs/response-analyzer/index.d.ts +9 -0
  159. package/dist-cjs/response-analyzer/object-type-detector.cjs +99 -0
  160. package/dist-cjs/response-analyzer/object-type-detector.d.ts +42 -0
  161. package/dist-cjs/response-analyzer/response-analyzer.cjs +101 -0
  162. package/dist-cjs/response-analyzer/response-analyzer.d.ts +38 -0
  163. package/dist-cjs/response-analyzer/types.cjs +5 -0
  164. package/dist-cjs/response-analyzer/types.d.ts +97 -0
  165. package/dist-cjs/response-fallback-fixer.cjs +126 -0
  166. package/dist-cjs/response-fallback-fixer.d.ts +11 -0
  167. package/dist-cjs/runtime-objects.cjs +52 -0
  168. package/dist-cjs/runtime-objects.d.ts +52 -0
  169. package/dist-cjs/template-parser.cjs +136 -0
  170. package/dist-cjs/template-parser.d.ts +58 -0
  171. package/dist-cjs/template-render-merge.cjs +43 -0
  172. package/dist-cjs/template-render-merge.d.ts +9 -0
  173. package/dist-cjs/troubleshooting-helper.cjs +611 -0
  174. package/dist-cjs/troubleshooting-helper.d.ts +123 -0
  175. package/dist-cjs/types.cjs +7 -0
  176. package/dist-cjs/types.d.ts +1173 -0
  177. package/dist-cjs/usage-tracker.cjs +83 -0
  178. package/dist-cjs/usage-tracker.d.ts +78 -0
  179. package/package.json +91 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Gateway Provider Module
3
+ * Handles provider management
4
+ */
5
+ import type { LLMProviderRouter } from '@x12i/ai-providers-router';
6
+ import type { Logxer } from '@x12i/logxer';
7
+ /**
8
+ * Register a provider with the router
9
+ */
10
+ export declare function registerProvider(provider: any, router: LLMProviderRouter, logger: Logxer): void;
11
+ /**
12
+ * Unregister a provider
13
+ */
14
+ export declare function unregisterProvider(providerName: string, router: LLMProviderRouter, logger: Logxer): void;
15
+ /**
16
+ * Get a provider module
17
+ */
18
+ export declare function getProvider(providerName: string, router: LLMProviderRouter): any;
19
+ /**
20
+ * List all registered providers
21
+ */
22
+ export declare function listProviders(router: LLMProviderRouter): string[];
23
+ /**
24
+ * Set default provider
25
+ *
26
+ * NOTE: Router doesn't support changing default provider after initialization.
27
+ * This method is kept for API compatibility but does nothing.
28
+ * Default provider must be set in router config during initialization.
29
+ */
30
+ export declare function setDefaultProvider(provider: string, router: LLMProviderRouter, logger: Logxer): void;
31
+ /**
32
+ * Set fallback chain
33
+ *
34
+ * NOTE: Router doesn't support changing fallback chain after initialization.
35
+ * This method is kept for API compatibility but does nothing.
36
+ * Fallback chain must be set in router config during initialization.
37
+ */
38
+ export declare function setFallbackChain(chain: string[], router: LLMProviderRouter, logger: Logxer): void;
39
+ /**
40
+ * Add request interceptor
41
+ */
42
+ export declare function addRequestInterceptor(interceptor: any, router: LLMProviderRouter): void;
43
+ /**
44
+ * Add response interceptor
45
+ */
46
+ export declare function addResponseInterceptor(interceptor: any, router: LLMProviderRouter): void;
47
+ /**
48
+ * Check health of a provider
49
+ */
50
+ export declare function checkHealth(provider: string, router: LLMProviderRouter): Promise<import("@x12i/ai-providers-router").HealthCheckResult>;
51
+ /**
52
+ * Check health of all providers
53
+ */
54
+ export declare function checkAllHealth(router: LLMProviderRouter): Promise<Record<string, any>>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * Rate Limiter Constants
4
+ *
5
+ * Default values for rate limiting configuration.
6
+ * These defaults ensure the system works safely even if config is missing.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DEFAULT_RATE_LIMIT_ENABLED = exports.DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS = void 0;
10
+ /**
11
+ * Default minimum interval between API calls (in milliseconds)
12
+ * Used when rateLimit.defaultMinIntervalMs is not specified
13
+ */
14
+ exports.DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS = 500;
15
+ /**
16
+ * Default enabled state for rate limiting
17
+ * Used when rateLimit.enabled is not specified
18
+ */
19
+ exports.DEFAULT_RATE_LIMIT_ENABLED = true;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Rate Limiter Constants
3
+ *
4
+ * Default values for rate limiting configuration.
5
+ * These defaults ensure the system works safely even if config is missing.
6
+ */
7
+ /**
8
+ * Default minimum interval between API calls (in milliseconds)
9
+ * Used when rateLimit.defaultMinIntervalMs is not specified
10
+ */
11
+ export declare const DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS = 500;
12
+ /**
13
+ * Default enabled state for rate limiting
14
+ * Used when rateLimit.enabled is not specified
15
+ */
16
+ export declare const DEFAULT_RATE_LIMIT_ENABLED = true;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ /**
3
+ * Gateway Rate Limiter
4
+ *
5
+ * Smart rate limiting for BETWEEN-CALLS (not retries).
6
+ *
7
+ * Two types of rate limiting in the system:
8
+ * 1. RETRY delays (in gateway-retry.ts) - Simple sleep, not smart. Used when retrying after errors.
9
+ * 2. BETWEEN-CALLS rate limiting (this class) - Smart, tracks last call time and only waits if needed.
10
+ *
11
+ * This class handles #2: it tracks when the last API call was made per provider
12
+ * and only waits if necessary to maintain minimum intervals between separate API calls.
13
+ * This prevents unnecessary delays when enough time has already passed.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.GatewayRateLimiter = void 0;
17
+ const gateway_retry_js_1 = require("./gateway-retry.cjs");
18
+ const gateway_rate_limiter_constants_js_1 = require("./gateway-rate-limiter-constants.cjs");
19
+ /**
20
+ * Smart Rate Limiter (Between-Calls Only)
21
+ *
22
+ * Tracks the last API call time per provider and only waits if necessary.
23
+ * Supports per-provider rate limits with safe defaults.
24
+ *
25
+ * NOTE: This is for BETWEEN-CALLS rate limiting (smart).
26
+ * Retry delays are handled separately in gateway-retry.ts (simple sleep).
27
+ *
28
+ * This ensures minimum intervals between separate API calls regardless of what happens between them.
29
+ */
30
+ class GatewayRateLimiter {
31
+ lastCallTimes = new Map(); // provider -> last call timestamp
32
+ defaultMinIntervalMs;
33
+ providerIntervals = new Map(); // provider -> min interval
34
+ logger;
35
+ constructor(defaultMinIntervalMs = gateway_rate_limiter_constants_js_1.DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS, providerIntervals, logger) {
36
+ this.defaultMinIntervalMs = defaultMinIntervalMs;
37
+ this.logger = logger;
38
+ // Store per-provider intervals
39
+ if (providerIntervals) {
40
+ for (const [provider, interval] of Object.entries(providerIntervals)) {
41
+ this.providerIntervals.set(provider.toLowerCase(), interval);
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * Gets the minimum interval for a specific provider
47
+ * Falls back to default if provider-specific interval not set
48
+ */
49
+ getMinIntervalForProvider(provider) {
50
+ const providerKey = provider.toLowerCase();
51
+ return this.providerIntervals.get(providerKey) ?? this.defaultMinIntervalMs;
52
+ }
53
+ /**
54
+ * Waits only if necessary to maintain the minimum interval between calls for a provider
55
+ * @param provider - Provider name (e.g., 'openai', 'grok')
56
+ * @returns Promise that resolves when it's safe to make the next call
57
+ */
58
+ async waitIfNeeded(provider = 'global') {
59
+ const minIntervalMs = this.getMinIntervalForProvider(provider);
60
+ const now = Date.now();
61
+ const lastCallTime = this.lastCallTimes.get(provider) || 0;
62
+ const timeSinceLastCall = now - lastCallTime;
63
+ if (timeSinceLastCall < minIntervalMs) {
64
+ const waitTime = minIntervalMs - timeSinceLastCall;
65
+ this.logger?.debug('Rate limiting: waiting before API call', {
66
+ provider,
67
+ waitTimeMs: waitTime,
68
+ timeSinceLastCallMs: timeSinceLastCall,
69
+ minIntervalMs,
70
+ usingProviderSpecific: this.providerIntervals.has(provider.toLowerCase())
71
+ });
72
+ await (0, gateway_retry_js_1.sleep)(waitTime);
73
+ }
74
+ else {
75
+ this.logger?.verbose('Rate limit OK: enough time has passed', {
76
+ provider,
77
+ timeSinceLastCallMs: timeSinceLastCall,
78
+ minIntervalMs,
79
+ usingProviderSpecific: this.providerIntervals.has(provider.toLowerCase())
80
+ });
81
+ }
82
+ // Record the call time (after waiting if needed)
83
+ this.lastCallTimes.set(provider, Date.now());
84
+ }
85
+ /**
86
+ * Records that an API call was made (call this after the API call completes)
87
+ * This ensures we track the actual call time, accounting for call duration
88
+ */
89
+ recordCall(provider = 'global') {
90
+ this.lastCallTimes.set(provider, Date.now());
91
+ }
92
+ /**
93
+ * Gets the time since the last call for a provider
94
+ */
95
+ getTimeSinceLastCall(provider = 'global') {
96
+ const lastCallTime = this.lastCallTimes.get(provider) || 0;
97
+ return Date.now() - lastCallTime;
98
+ }
99
+ /**
100
+ * Resets the rate limiter for a provider (useful for testing or reset scenarios)
101
+ */
102
+ reset(provider) {
103
+ if (provider) {
104
+ this.lastCallTimes.delete(provider);
105
+ }
106
+ else {
107
+ this.lastCallTimes.clear();
108
+ }
109
+ }
110
+ }
111
+ exports.GatewayRateLimiter = GatewayRateLimiter;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Gateway Rate Limiter
3
+ *
4
+ * Smart rate limiting for BETWEEN-CALLS (not retries).
5
+ *
6
+ * Two types of rate limiting in the system:
7
+ * 1. RETRY delays (in gateway-retry.ts) - Simple sleep, not smart. Used when retrying after errors.
8
+ * 2. BETWEEN-CALLS rate limiting (this class) - Smart, tracks last call time and only waits if needed.
9
+ *
10
+ * This class handles #2: it tracks when the last API call was made per provider
11
+ * and only waits if necessary to maintain minimum intervals between separate API calls.
12
+ * This prevents unnecessary delays when enough time has already passed.
13
+ */
14
+ import type { Logxer } from '@x12i/logxer';
15
+ /**
16
+ * Smart Rate Limiter (Between-Calls Only)
17
+ *
18
+ * Tracks the last API call time per provider and only waits if necessary.
19
+ * Supports per-provider rate limits with safe defaults.
20
+ *
21
+ * NOTE: This is for BETWEEN-CALLS rate limiting (smart).
22
+ * Retry delays are handled separately in gateway-retry.ts (simple sleep).
23
+ *
24
+ * This ensures minimum intervals between separate API calls regardless of what happens between them.
25
+ */
26
+ export declare class GatewayRateLimiter {
27
+ private lastCallTimes;
28
+ private defaultMinIntervalMs;
29
+ private providerIntervals;
30
+ private logger?;
31
+ constructor(defaultMinIntervalMs?: number, providerIntervals?: Record<string, number>, logger?: Logxer);
32
+ /**
33
+ * Gets the minimum interval for a specific provider
34
+ * Falls back to default if provider-specific interval not set
35
+ */
36
+ private getMinIntervalForProvider;
37
+ /**
38
+ * Waits only if necessary to maintain the minimum interval between calls for a provider
39
+ * @param provider - Provider name (e.g., 'openai', 'grok')
40
+ * @returns Promise that resolves when it's safe to make the next call
41
+ */
42
+ waitIfNeeded(provider?: string): Promise<void>;
43
+ /**
44
+ * Records that an API call was made (call this after the API call completes)
45
+ * This ensures we track the actual call time, accounting for call duration
46
+ */
47
+ recordCall(provider?: string): void;
48
+ /**
49
+ * Gets the time since the last call for a provider
50
+ */
51
+ getTimeSinceLastCall(provider?: string): number;
52
+ /**
53
+ * Resets the rate limiter for a provider (useful for testing or reset scenarios)
54
+ */
55
+ reset(provider?: string): void;
56
+ }
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ /**
3
+ * Gateway Retry Module
4
+ * Handles retry logic for network and server errors
5
+ *
6
+ * NOTE: Retry delays use SIMPLE SLEEP (not smart rate limiting).
7
+ * Between-calls rate limiting is handled separately in gateway-rate-limiter.ts (smart).
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.isNetworkError = isNetworkError;
11
+ exports.extractHttpStatusCode = extractHttpStatusCode;
12
+ exports.isRetryableHttpError = isRetryableHttpError;
13
+ exports.isRetryableError = isRetryableError;
14
+ exports.sleep = sleep;
15
+ exports.invokeWithRetry = invokeWithRetry;
16
+ /**
17
+ * Determines if an error is a network error (fetch failed, DNS, connectivity)
18
+ */
19
+ function isNetworkError(error) {
20
+ const message = error.message.toLowerCase();
21
+ const networkPatterns = [
22
+ 'fetch failed',
23
+ 'network error',
24
+ 'dns',
25
+ 'connectivity',
26
+ 'connection',
27
+ 'econnrefused',
28
+ 'enotfound',
29
+ 'etimedout',
30
+ 'econnreset',
31
+ 'api endpoint unavailability'
32
+ ];
33
+ return networkPatterns.some(pattern => message.includes(pattern));
34
+ }
35
+ /**
36
+ * Extracts HTTP status code from error message or error object properties
37
+ */
38
+ function extractHttpStatusCode(error) {
39
+ // Try to extract from error message
40
+ const statusMatch = error.message.match(/\b(4\d{2}|5\d{2})\b/);
41
+ if (statusMatch) {
42
+ return parseInt(statusMatch[1], 10);
43
+ }
44
+ // Try to extract from error object properties
45
+ const errorAny = error;
46
+ if (errorAny.statusCode) {
47
+ return errorAny.statusCode;
48
+ }
49
+ if (errorAny.status) {
50
+ return errorAny.status;
51
+ }
52
+ if (errorAny.response?.status) {
53
+ return errorAny.response.status;
54
+ }
55
+ return undefined;
56
+ }
57
+ /**
58
+ * Determines if an HTTP error should be retried
59
+ * Retryable: 429 (throttling), 5xx (server errors)
60
+ * Non-retryable: 4xx except 429 (client errors)
61
+ */
62
+ function isRetryableHttpError(error, statusCode) {
63
+ // 429 (throttling) is retryable
64
+ if (statusCode === 429) {
65
+ return true;
66
+ }
67
+ // 5xx (server errors) are retryable
68
+ if (statusCode >= 500 && statusCode < 600) {
69
+ return true;
70
+ }
71
+ // 4xx (client errors) are NOT retryable except 429
72
+ return false;
73
+ }
74
+ /**
75
+ * Determines if an error should be retried
76
+ */
77
+ function isRetryableError(error) {
78
+ // Network errors are always retryable
79
+ if (isNetworkError(error)) {
80
+ return true;
81
+ }
82
+ // Check HTTP status code
83
+ const statusCode = extractHttpStatusCode(error);
84
+ if (statusCode !== undefined) {
85
+ return isRetryableHttpError(error, statusCode);
86
+ }
87
+ // Timeout errors are retryable
88
+ if (error.name === 'TimeoutError' || error.message.toLowerCase().includes('timeout')) {
89
+ return true;
90
+ }
91
+ // Default: don't retry unknown errors
92
+ return false;
93
+ }
94
+ /**
95
+ * Sleep helper for retry delays
96
+ */
97
+ function sleep(ms) {
98
+ return new Promise(resolve => setTimeout(resolve, ms));
99
+ }
100
+ /**
101
+ * Invokes router with retry logic for network and server errors
102
+ * Returns response and retry metadata
103
+ */
104
+ async function invokeWithRetry(routerRequest, retryConfig, jobId, router, logger) {
105
+ const maxRetries = retryConfig.maxRetries ?? 3;
106
+ const initialDelay = retryConfig.initialDelay ?? 1000;
107
+ const maxDelay = retryConfig.maxDelay ?? 30000;
108
+ const backoffMultiplier = retryConfig.backoffMultiplier ?? 2;
109
+ const enableJitter = retryConfig.enableJitter ?? true;
110
+ const throttlingDelay = retryConfig.throttlingDelay ?? 5000;
111
+ let lastError;
112
+ const retryAttempts = [];
113
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
114
+ try {
115
+ const response = await router.invoke(routerRequest);
116
+ // Log success after retry if this wasn't the first attempt
117
+ if (attempt > 0) {
118
+ logger.info('Request succeeded after retry', {
119
+ jobId,
120
+ attempt: attempt + 1,
121
+ totalAttempts: attempt + 1,
122
+ retryCount: retryAttempts.length
123
+ });
124
+ }
125
+ // Return response with retry metadata if there were retries
126
+ if (retryAttempts.length > 0) {
127
+ return {
128
+ response,
129
+ retryMetadata: {
130
+ retryCount: retryAttempts.length,
131
+ retryAttempts
132
+ }
133
+ };
134
+ }
135
+ return { response };
136
+ }
137
+ catch (error) {
138
+ lastError = error instanceof Error ? error : new Error(String(error));
139
+ // Check if error is retryable
140
+ if (!isRetryableError(lastError)) {
141
+ logger.debug('Non-retryable error, not retrying', {
142
+ jobId,
143
+ error: lastError.message,
144
+ errorName: lastError.name,
145
+ attempt: attempt + 1
146
+ });
147
+ throw lastError;
148
+ }
149
+ // If this was the last attempt, throw the error
150
+ if (attempt >= maxRetries) {
151
+ logger.warn('Max retries exceeded', {
152
+ jobId,
153
+ error: lastError.message,
154
+ errorName: lastError.name,
155
+ totalAttempts: attempt + 1,
156
+ maxRetries
157
+ });
158
+ throw lastError;
159
+ }
160
+ // Calculate delay with exponential backoff
161
+ const baseDelay = initialDelay * Math.pow(backoffMultiplier, attempt);
162
+ let delay = Math.min(baseDelay, maxDelay);
163
+ // Add extra delay for throttling
164
+ const statusCode = extractHttpStatusCode(lastError);
165
+ if (statusCode === 429) {
166
+ delay += throttlingDelay;
167
+ logger.debug('Throttling detected, adding extra delay', {
168
+ jobId,
169
+ throttlingDelay,
170
+ baseDelay: Math.round(delay - throttlingDelay)
171
+ });
172
+ }
173
+ // Add jitter if enabled
174
+ if (enableJitter) {
175
+ const jitter = Math.random() * delay * 0.3; // Up to 30% jitter
176
+ delay += jitter;
177
+ }
178
+ // Classify error type for logging
179
+ const errorType = isNetworkError(lastError)
180
+ ? 'network'
181
+ : statusCode !== undefined
182
+ ? `http-${statusCode}`
183
+ : 'timeout';
184
+ // Record retry attempt for activity tracking
185
+ retryAttempts.push({
186
+ attempt: attempt + 1,
187
+ timestamp: Date.now(),
188
+ error: lastError.message,
189
+ errorType,
190
+ delayMs: Math.round(delay)
191
+ });
192
+ logger.warn('Retrying request after error', {
193
+ jobId,
194
+ error: lastError.message,
195
+ errorName: lastError.name,
196
+ errorType,
197
+ attempt: attempt + 1,
198
+ maxRetries: maxRetries + 1,
199
+ delayMs: Math.round(delay),
200
+ statusCode
201
+ });
202
+ await sleep(delay);
203
+ }
204
+ }
205
+ // If we get here, all retries exhausted - throw error with retry metadata
206
+ const errorWithRetries = lastError;
207
+ errorWithRetries.retryMetadata = {
208
+ retryCount: retryAttempts.length,
209
+ retryAttempts
210
+ };
211
+ throw errorWithRetries;
212
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Gateway Retry Module
3
+ * Handles retry logic for network and server errors
4
+ *
5
+ * NOTE: Retry delays use SIMPLE SLEEP (not smart rate limiting).
6
+ * Between-calls rate limiting is handled separately in gateway-rate-limiter.ts (smart).
7
+ */
8
+ import type { RetryConfig } from './types.js';
9
+ import type { LLMProviderRouter } from '@x12i/ai-providers-router';
10
+ import type { Logxer } from '@x12i/logxer';
11
+ /**
12
+ * Determines if an error is a network error (fetch failed, DNS, connectivity)
13
+ */
14
+ export declare function isNetworkError(error: Error): boolean;
15
+ /**
16
+ * Extracts HTTP status code from error message or error object properties
17
+ */
18
+ export declare function extractHttpStatusCode(error: Error): number | undefined;
19
+ /**
20
+ * Determines if an HTTP error should be retried
21
+ * Retryable: 429 (throttling), 5xx (server errors)
22
+ * Non-retryable: 4xx except 429 (client errors)
23
+ */
24
+ export declare function isRetryableHttpError(error: Error, statusCode: number): boolean;
25
+ /**
26
+ * Determines if an error should be retried
27
+ */
28
+ export declare function isRetryableError(error: Error): boolean;
29
+ /**
30
+ * Sleep helper for retry delays
31
+ */
32
+ export declare function sleep(ms: number): Promise<void>;
33
+ /**
34
+ * Invokes router with retry logic for network and server errors
35
+ * Returns response and retry metadata
36
+ */
37
+ export declare function invokeWithRetry(routerRequest: any, retryConfig: RetryConfig, jobId: string, router: LLMProviderRouter, logger: Logxer): Promise<{
38
+ response: any;
39
+ retryMetadata?: {
40
+ retryCount: number;
41
+ retryAttempts: Array<{
42
+ attempt: number;
43
+ timestamp: number;
44
+ error: string;
45
+ errorType: string;
46
+ delayMs: number;
47
+ }>;
48
+ };
49
+ }>;