@adaptic/lumic-utils 1.0.12 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apollo-client.client-Lu1K9ohp.js +3694 -0
- package/dist/apollo-client.client-Lu1K9ohp.js.map +1 -0
- package/dist/apollo-client.client-YFsBF7bL.js +3705 -0
- package/dist/apollo-client.client-YFsBF7bL.js.map +1 -0
- package/dist/apollo-client.server-CAtwy7W4.js +16320 -0
- package/dist/apollo-client.server-CAtwy7W4.js.map +1 -0
- package/dist/apollo-client.server-CWrxRFr9.js +16322 -0
- package/dist/apollo-client.server-CWrxRFr9.js.map +1 -0
- package/dist/index-Bc3hrZJm.js +12108 -0
- package/dist/index-Bc3hrZJm.js.map +1 -0
- package/dist/index-CZkVRs3j.js +75962 -0
- package/dist/index-CZkVRs3j.js.map +1 -0
- package/dist/{index-CcXQeJz8.js → index-Cstek604.js} +182 -22
- package/dist/index-Cstek604.js.map +1 -0
- package/dist/index-DT2sMbfH.js +76169 -0
- package/dist/index-DT2sMbfH.js.map +1 -0
- package/dist/index-DZUGtDjj.js +12271 -0
- package/dist/index-DZUGtDjj.js.map +1 -0
- package/dist/{index-CcgbRft2.js → index-DZZCd-1T.js} +182 -22
- package/dist/index-DZZCd-1T.js.map +1 -0
- package/dist/index.cjs +137 -11417
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +40 -11399
- package/dist/index.mjs.map +1 -1
- package/dist/test.cjs +25 -7
- package/dist/test.cjs.map +1 -1
- package/dist/test.mjs +25 -7
- package/dist/test.mjs.map +1 -1
- package/dist/types/config/__tests__/secrets.test.d.ts +1 -0
- package/dist/types/config/secrets.d.ts +286 -0
- package/dist/types/errors/__tests__/errors.test.d.ts +1 -0
- package/dist/types/errors/index.d.ts +77 -0
- package/dist/types/functions/__tests__/aws-lambda.test.d.ts +1 -0
- package/dist/types/functions/__tests__/aws-s3-utils.test.d.ts +1 -0
- package/dist/types/functions/__tests__/json-llm-tools.test.d.ts +1 -0
- package/dist/types/functions/__tests__/json-tools.test.d.ts +1 -0
- package/dist/types/functions/__tests__/slack-utils.test.d.ts +1 -0
- package/dist/types/functions/aws-lambda.d.ts +1 -1
- package/dist/types/functions/aws-s3-utils.d.ts +2 -2
- package/dist/types/functions/google-sheets.d.ts +4 -4
- package/dist/types/functions/json-llm-tools.d.ts +25 -3
- package/dist/types/functions/llm-anthropic.d.ts +14 -0
- package/dist/types/functions/llm-call.d.ts +14 -3
- package/dist/types/functions/llm-config.d.ts +13 -8
- package/dist/types/functions/llm-deepseek.d.ts +1 -1
- package/dist/types/functions/llm-openai-compatible.d.ts +15 -0
- package/dist/types/functions/llm-openai.d.ts +3 -2
- package/dist/types/functions/llm-utils.d.ts +24 -1
- package/dist/types/functions/slack-utils.d.ts +3 -4
- package/dist/types/functions/utils.d.ts +2 -14
- package/dist/types/functions/zip-utils.d.ts +12 -10
- package/dist/types/index.d.ts +33 -0
- package/dist/types/schemas/aws-schemas.d.ts +210 -0
- package/dist/types/schemas/google-sheets-schemas.d.ts +32 -0
- package/dist/types/schemas/index.d.ts +17 -0
- package/dist/types/schemas/openai-schemas.d.ts +834 -0
- package/dist/types/schemas/perplexity-schemas.d.ts +338 -0
- package/dist/types/schemas/validation-helpers.d.ts +33 -0
- package/dist/types/types/aws-types.d.ts +1 -1
- package/dist/types/types/google-types.d.ts +5 -3
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/openai-types.d.ts +396 -6
- package/dist/types/utils/__tests__/circuit-breaker.test.d.ts +1 -0
- package/dist/types/utils/__tests__/correlation.test.d.ts +1 -0
- package/dist/types/utils/__tests__/input-validator.test.d.ts +1 -0
- package/dist/types/utils/__tests__/llm-cost-tracker.test.d.ts +1 -0
- package/dist/types/utils/__tests__/logger.test.d.ts +1 -0
- package/dist/types/utils/__tests__/metrics.test.d.ts +1 -0
- package/dist/types/utils/__tests__/retry.test.d.ts +1 -0
- package/dist/types/utils/__tests__/sanitizer.test.d.ts +1 -0
- package/dist/types/utils/__tests__/timeouts.test.d.ts +1 -0
- package/dist/types/utils/aws-initialise.d.ts +6 -1
- package/dist/types/utils/circuit-breaker.d.ts +99 -0
- package/dist/types/utils/config.d.ts +40 -2
- package/dist/types/utils/correlation.d.ts +43 -0
- package/dist/types/utils/health-check.d.ts +50 -0
- package/dist/types/utils/input-validator.d.ts +51 -0
- package/dist/types/utils/llm-cost-tracker.d.ts +174 -0
- package/dist/types/utils/logger.d.ts +8 -0
- package/dist/types/utils/metrics.d.ts +61 -0
- package/dist/types/utils/rate-limiter.d.ts +85 -0
- package/dist/types/utils/retry.d.ts +58 -0
- package/dist/types/utils/sanitizer.d.ts +30 -0
- package/dist/types/utils/timeouts.d.ts +44 -0
- package/package.json +2 -1
- package/dist/index-CcXQeJz8.js.map +0 -1
- package/dist/index-CcgbRft2.js.map +0 -1
- package/dist/types/aws-types.ts +0 -64
- package/dist/types/google-types.ts +0 -48
- package/dist/types/index.ts +0 -57
- package/dist/types/openai-types.ts +0 -92
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status of an individual integration health check.
|
|
3
|
+
*/
|
|
4
|
+
export interface IntegrationHealthStatus {
|
|
5
|
+
/** Name of the integration being checked */
|
|
6
|
+
service: string;
|
|
7
|
+
/** Whether the integration is reachable */
|
|
8
|
+
healthy: boolean;
|
|
9
|
+
/** Human-readable status message */
|
|
10
|
+
message: string;
|
|
11
|
+
/** Time taken to check in milliseconds */
|
|
12
|
+
latencyMs: number;
|
|
13
|
+
/** Error details if unhealthy */
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Overall health check result for all configured integrations.
|
|
18
|
+
*/
|
|
19
|
+
export interface HealthCheckResult {
|
|
20
|
+
/** Whether all checked integrations are healthy */
|
|
21
|
+
healthy: boolean;
|
|
22
|
+
/** Timestamp of the health check */
|
|
23
|
+
timestamp: string;
|
|
24
|
+
/** Individual integration statuses */
|
|
25
|
+
integrations: IntegrationHealthStatus[];
|
|
26
|
+
/** Total time taken for all checks in milliseconds */
|
|
27
|
+
totalLatencyMs: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Runs health checks for all configured integrations.
|
|
31
|
+
*
|
|
32
|
+
* Checks credential configuration for each external service. Does not make
|
|
33
|
+
* actual API calls (to avoid side effects and rate limit consumption).
|
|
34
|
+
* For connectivity verification, consumers should use the individual service
|
|
35
|
+
* functions with appropriate error handling.
|
|
36
|
+
*
|
|
37
|
+
* @param services - Optional list of service names to check. If omitted, checks all.
|
|
38
|
+
* @returns Health check result with individual integration statuses
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* const result = await checkIntegrationHealth();
|
|
42
|
+
* if (!result.healthy) {
|
|
43
|
+
* console.error('Unhealthy integrations:', result.integrations.filter(i => !i.healthy));
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Check specific services only
|
|
48
|
+
* const result = await checkIntegrationHealth(['openai', 'slack']);
|
|
49
|
+
*/
|
|
50
|
+
export declare function checkIntegrationHealth(services?: string[]): Promise<HealthCheckResult>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation utilities to prevent injection and traversal attacks
|
|
3
|
+
* on external service inputs (Slack, S3, Google Sheets).
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Result of a validation check
|
|
7
|
+
*/
|
|
8
|
+
export interface ValidationResult {
|
|
9
|
+
valid: boolean;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validates a Slack channel name format.
|
|
14
|
+
*
|
|
15
|
+
* Valid channel names:
|
|
16
|
+
* - May optionally start with '#'
|
|
17
|
+
* - Must start with a lowercase letter or number (after optional '#')
|
|
18
|
+
* - May contain lowercase letters, numbers, hyphens, and underscores
|
|
19
|
+
* - Must be between 1 and 80 characters (excluding optional '#' prefix)
|
|
20
|
+
*
|
|
21
|
+
* @param channel - The channel name to validate
|
|
22
|
+
* @returns ValidationResult indicating whether the channel name is valid
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateSlackChannel(channel: string): ValidationResult;
|
|
25
|
+
/**
|
|
26
|
+
* Validates an S3 key to prevent directory traversal and other attacks.
|
|
27
|
+
*
|
|
28
|
+
* Invalid keys:
|
|
29
|
+
* - Contain '..' (directory traversal)
|
|
30
|
+
* - Start with '/' (absolute paths)
|
|
31
|
+
* - Contain null bytes
|
|
32
|
+
* - Are empty
|
|
33
|
+
* - Exceed 1024 characters (S3 key limit)
|
|
34
|
+
*
|
|
35
|
+
* @param key - The S3 key to validate
|
|
36
|
+
* @returns ValidationResult indicating whether the key is valid
|
|
37
|
+
*/
|
|
38
|
+
export declare function validateS3Key(key: string): ValidationResult;
|
|
39
|
+
/**
|
|
40
|
+
* Validates a Google Sheets A1 notation range.
|
|
41
|
+
*
|
|
42
|
+
* Valid formats:
|
|
43
|
+
* - Simple cell: 'A1', 'B2', 'AA100'
|
|
44
|
+
* - Cell range: 'A1:B10', 'A1:Z999'
|
|
45
|
+
* - With sheet name: 'Sheet1!A1', 'Sheet1!A1:B10'
|
|
46
|
+
* - With quoted sheet name: "'My Sheet'!A1:B10"
|
|
47
|
+
*
|
|
48
|
+
* @param range - The A1 notation string to validate
|
|
49
|
+
* @returns ValidationResult indicating whether the range is valid
|
|
50
|
+
*/
|
|
51
|
+
export declare function validateGoogleSheetsRange(range: string): ValidationResult;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage record for a single LLM call
|
|
3
|
+
*/
|
|
4
|
+
export interface LLMUsageRecord {
|
|
5
|
+
provider: string;
|
|
6
|
+
model: string;
|
|
7
|
+
inputTokens: number;
|
|
8
|
+
outputTokens: number;
|
|
9
|
+
reasoningTokens: number;
|
|
10
|
+
cacheHitTokens: number;
|
|
11
|
+
cost: number;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Image generation usage record
|
|
16
|
+
*/
|
|
17
|
+
export interface ImageUsageRecord {
|
|
18
|
+
model: string;
|
|
19
|
+
imageCount: number;
|
|
20
|
+
cost: number;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Aggregated cost data for a single model
|
|
25
|
+
*/
|
|
26
|
+
export interface ModelCostSummary {
|
|
27
|
+
provider: string;
|
|
28
|
+
model: string;
|
|
29
|
+
totalCost: number;
|
|
30
|
+
callCount: number;
|
|
31
|
+
totalInputTokens: number;
|
|
32
|
+
totalOutputTokens: number;
|
|
33
|
+
totalReasoningTokens: number;
|
|
34
|
+
totalCacheHitTokens: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Aggregated cost data for image generation by model
|
|
38
|
+
*/
|
|
39
|
+
export interface ImageCostSummary {
|
|
40
|
+
model: string;
|
|
41
|
+
totalCost: number;
|
|
42
|
+
totalImages: number;
|
|
43
|
+
callCount: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Complete cost summary across all models and providers
|
|
47
|
+
*/
|
|
48
|
+
export interface CostSummary {
|
|
49
|
+
totalCost: number;
|
|
50
|
+
totalCalls: number;
|
|
51
|
+
totalInputTokens: number;
|
|
52
|
+
totalOutputTokens: number;
|
|
53
|
+
totalReasoningTokens: number;
|
|
54
|
+
byModel: Record<string, ModelCostSummary>;
|
|
55
|
+
images: Record<string, ImageCostSummary>;
|
|
56
|
+
startTime: number;
|
|
57
|
+
endTime: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Formatted cost summary for display
|
|
61
|
+
*/
|
|
62
|
+
export interface FormattedCostSummary {
|
|
63
|
+
totalCost: string;
|
|
64
|
+
totalCalls: number;
|
|
65
|
+
totalTokens: number;
|
|
66
|
+
duration: string;
|
|
67
|
+
models: Array<{
|
|
68
|
+
model: string;
|
|
69
|
+
provider: string;
|
|
70
|
+
cost: string;
|
|
71
|
+
calls: number;
|
|
72
|
+
inputTokens: number;
|
|
73
|
+
outputTokens: number;
|
|
74
|
+
}>;
|
|
75
|
+
images: Array<{
|
|
76
|
+
model: string;
|
|
77
|
+
cost: string;
|
|
78
|
+
images: number;
|
|
79
|
+
calls: number;
|
|
80
|
+
}>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Tracks and accumulates LLM usage costs across all providers and models.
|
|
84
|
+
*
|
|
85
|
+
* This class provides a centralized way to monitor LLM spending,
|
|
86
|
+
* aggregating costs by model and provider. It can be used by consumers
|
|
87
|
+
* (such as the engine) to build cost dashboards and spending reports.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* import { LLMCostTracker } from '@adaptic/lumic-utils';
|
|
91
|
+
*
|
|
92
|
+
* const tracker = getLLMCostTracker();
|
|
93
|
+
* // ... make LLM calls (cost tracking is automatic when wired in) ...
|
|
94
|
+
* const summary = tracker.getCostSummary();
|
|
95
|
+
* console.log(`Total cost: $${summary.totalCost}`);
|
|
96
|
+
*/
|
|
97
|
+
export declare class LLMCostTracker {
|
|
98
|
+
private usageRecords;
|
|
99
|
+
private imageRecords;
|
|
100
|
+
private startTime;
|
|
101
|
+
/**
|
|
102
|
+
* Records usage from an LLM call.
|
|
103
|
+
*
|
|
104
|
+
* @param provider - The LLM provider ('openai' or 'deepseek')
|
|
105
|
+
* @param model - The model name (e.g., 'gpt-5', 'deepseek-chat')
|
|
106
|
+
* @param inputTokens - Number of input/prompt tokens
|
|
107
|
+
* @param outputTokens - Number of output/completion tokens
|
|
108
|
+
* @param reasoningTokens - Number of reasoning tokens (default: 0)
|
|
109
|
+
* @param cacheHitTokens - Number of cache hit tokens (default: 0)
|
|
110
|
+
*/
|
|
111
|
+
trackUsage(provider: string, model: string, inputTokens: number, outputTokens: number, reasoningTokens?: number, cacheHitTokens?: number): void;
|
|
112
|
+
/**
|
|
113
|
+
* Records usage from an image generation call.
|
|
114
|
+
*
|
|
115
|
+
* @param model - The image model name (e.g., 'gpt-image-1')
|
|
116
|
+
* @param imageCount - Number of images generated
|
|
117
|
+
*/
|
|
118
|
+
trackImageUsage(model: string, imageCount: number): void;
|
|
119
|
+
/**
|
|
120
|
+
* Returns accumulated costs aggregated by model.
|
|
121
|
+
*
|
|
122
|
+
* @returns Record of model name to ModelCostSummary
|
|
123
|
+
*/
|
|
124
|
+
getCosts(): Record<string, ModelCostSummary>;
|
|
125
|
+
/**
|
|
126
|
+
* Returns accumulated image generation costs aggregated by model.
|
|
127
|
+
*
|
|
128
|
+
* @returns Record of model name to ImageCostSummary
|
|
129
|
+
*/
|
|
130
|
+
getImageCosts(): Record<string, ImageCostSummary>;
|
|
131
|
+
/**
|
|
132
|
+
* Returns a complete cost summary across all models and providers.
|
|
133
|
+
*
|
|
134
|
+
* @returns CostSummary with totals and per-model breakdowns
|
|
135
|
+
*/
|
|
136
|
+
getCostSummary(): CostSummary;
|
|
137
|
+
/**
|
|
138
|
+
* Returns a human-readable formatted cost summary.
|
|
139
|
+
*
|
|
140
|
+
* @returns FormattedCostSummary with dollar amounts and readable durations
|
|
141
|
+
*/
|
|
142
|
+
getFormattedCostSummary(): FormattedCostSummary;
|
|
143
|
+
/**
|
|
144
|
+
* Resets all accumulated cost data and restarts the tracking period.
|
|
145
|
+
*/
|
|
146
|
+
resetCosts(): void;
|
|
147
|
+
/**
|
|
148
|
+
* Returns the total number of tracked LLM calls (not including images).
|
|
149
|
+
*/
|
|
150
|
+
getCallCount(): number;
|
|
151
|
+
/**
|
|
152
|
+
* Returns the total number of tracked image generation calls.
|
|
153
|
+
*/
|
|
154
|
+
getImageCallCount(): number;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Returns the global LLM cost tracker instance.
|
|
158
|
+
* Use this for application-wide cost tracking.
|
|
159
|
+
*
|
|
160
|
+
* @returns The global LLMCostTracker instance
|
|
161
|
+
*/
|
|
162
|
+
export declare function getLLMCostTracker(): LLMCostTracker;
|
|
163
|
+
/**
|
|
164
|
+
* Replaces the global LLM cost tracker instance.
|
|
165
|
+
* Useful for testing or providing a custom implementation.
|
|
166
|
+
*
|
|
167
|
+
* @param tracker - The new LLMCostTracker instance to use
|
|
168
|
+
*/
|
|
169
|
+
export declare function setLLMCostTracker(tracker: LLMCostTracker): void;
|
|
170
|
+
/**
|
|
171
|
+
* Resets the global LLM cost tracker to a fresh instance.
|
|
172
|
+
* Convenience function equivalent to `setLLMCostTracker(new LLMCostTracker())`.
|
|
173
|
+
*/
|
|
174
|
+
export declare function resetLLMCostTracker(): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface LumicLogger {
|
|
2
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
3
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
4
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
5
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
6
|
+
}
|
|
7
|
+
export declare function setLumicLogger(logger: LumicLogger): void;
|
|
8
|
+
export declare function getLumicLogger(): LumicLogger;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for collecting metrics from lumic-utils operations.
|
|
3
|
+
* Consumers (e.g., engine) can inject a real implementation (Prometheus, etc.)
|
|
4
|
+
* while the default no-op implementation ensures zero overhead when not needed.
|
|
5
|
+
*/
|
|
6
|
+
export interface MetricsCollector {
|
|
7
|
+
/**
|
|
8
|
+
* Increment a counter for a given operation.
|
|
9
|
+
* @param service - The service name (e.g., 'slack', 'llm', 'aws-s3')
|
|
10
|
+
* @param operation - The operation name (e.g., 'sendMessage', 'createCompletion')
|
|
11
|
+
* @param labels - Additional labels (e.g., { status: 'success' })
|
|
12
|
+
*/
|
|
13
|
+
incrementCounter(service: string, operation: string, labels?: Record<string, string>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Record a latency measurement for a given operation.
|
|
16
|
+
* @param service - The service name
|
|
17
|
+
* @param operation - The operation name
|
|
18
|
+
* @param durationMs - Duration in milliseconds
|
|
19
|
+
* @param labels - Additional labels
|
|
20
|
+
*/
|
|
21
|
+
recordLatency(service: string, operation: string, durationMs: number, labels?: Record<string, string>): void;
|
|
22
|
+
/**
|
|
23
|
+
* Increment the error counter for a given operation.
|
|
24
|
+
* @param service - The service name
|
|
25
|
+
* @param operation - The operation name
|
|
26
|
+
* @param errorType - The type/code of the error
|
|
27
|
+
*/
|
|
28
|
+
incrementError(service: string, operation: string, errorType: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Increment the retry counter for a given operation.
|
|
31
|
+
* @param service - The service name
|
|
32
|
+
* @param operation - The operation name
|
|
33
|
+
*/
|
|
34
|
+
incrementRetry(service: string, operation: string): void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sets the global metrics collector.
|
|
38
|
+
* Call this during application bootstrap to inject a real collector.
|
|
39
|
+
* @param collector - The MetricsCollector implementation to use
|
|
40
|
+
*/
|
|
41
|
+
export declare function setMetricsCollector(collector: MetricsCollector): void;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the current metrics collector.
|
|
44
|
+
* @returns The active MetricsCollector instance
|
|
45
|
+
*/
|
|
46
|
+
export declare function getMetricsCollector(): MetricsCollector;
|
|
47
|
+
/**
|
|
48
|
+
* Resets the metrics collector to the default no-op implementation.
|
|
49
|
+
* Useful for testing.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resetMetricsCollector(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Wraps an async function with automatic metrics collection.
|
|
54
|
+
* Records call count, latency, errors, and retries.
|
|
55
|
+
*
|
|
56
|
+
* @param service - The service name for metrics labels
|
|
57
|
+
* @param operation - The operation name for metrics labels
|
|
58
|
+
* @param fn - The async function to wrap
|
|
59
|
+
* @returns The result of the wrapped function
|
|
60
|
+
*/
|
|
61
|
+
export declare function withMetrics<T>(service: string, operation: string, fn: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token bucket rate limiter configuration.
|
|
3
|
+
*/
|
|
4
|
+
export interface RateLimiterConfig {
|
|
5
|
+
/** Maximum number of tokens in the bucket */
|
|
6
|
+
maxTokens: number;
|
|
7
|
+
/** Number of tokens refilled per interval */
|
|
8
|
+
refillRate: number;
|
|
9
|
+
/** Refill interval in milliseconds */
|
|
10
|
+
refillIntervalMs: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Pre-configured rate limit profiles for known external APIs.
|
|
14
|
+
* These defaults are conservative estimates based on published API rate limits.
|
|
15
|
+
* Consumers can override with custom configurations.
|
|
16
|
+
*/
|
|
17
|
+
export declare const RATE_LIMIT_PROFILES: Record<string, RateLimiterConfig>;
|
|
18
|
+
/**
|
|
19
|
+
* Token bucket rate limiter.
|
|
20
|
+
*
|
|
21
|
+
* Implements the token bucket algorithm for client-side rate limiting.
|
|
22
|
+
* Each API call consumes one token. Tokens are refilled at a configurable rate.
|
|
23
|
+
* When the bucket is empty, callers must wait for tokens to become available.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const limiter = new TokenBucketRateLimiter(RATE_LIMIT_PROFILES.openai);
|
|
27
|
+
* await limiter.acquire(); // Waits if necessary
|
|
28
|
+
* const result = await callOpenAI();
|
|
29
|
+
*/
|
|
30
|
+
export declare class TokenBucketRateLimiter {
|
|
31
|
+
private tokens;
|
|
32
|
+
private readonly maxTokens;
|
|
33
|
+
private readonly refillRate;
|
|
34
|
+
private readonly refillIntervalMs;
|
|
35
|
+
private lastRefillTime;
|
|
36
|
+
private readonly name;
|
|
37
|
+
constructor(config: RateLimiterConfig, name?: string);
|
|
38
|
+
/**
|
|
39
|
+
* Refills tokens based on elapsed time since last refill.
|
|
40
|
+
* Tokens accumulate proportionally to elapsed time.
|
|
41
|
+
*/
|
|
42
|
+
private refill;
|
|
43
|
+
/**
|
|
44
|
+
* Attempts to acquire a token without waiting.
|
|
45
|
+
* @returns true if a token was acquired, false if the bucket is empty
|
|
46
|
+
*/
|
|
47
|
+
tryAcquire(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Acquires a token, waiting if necessary until one becomes available.
|
|
50
|
+
* Logs a warning when rate limiting is active.
|
|
51
|
+
*
|
|
52
|
+
* @param maxWaitMs - Maximum time to wait in milliseconds (default: 30000)
|
|
53
|
+
* @throws Error if the maximum wait time is exceeded
|
|
54
|
+
*/
|
|
55
|
+
acquire(maxWaitMs?: number): Promise<void>;
|
|
56
|
+
/** Returns the current number of available tokens */
|
|
57
|
+
get availableTokens(): number;
|
|
58
|
+
/** Resets the bucket to full capacity */
|
|
59
|
+
reset(): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns the rate limiter for a given service.
|
|
63
|
+
* Creates one using the default profile if it doesn't exist.
|
|
64
|
+
*
|
|
65
|
+
* @param service - Service name (must match a key in RATE_LIMIT_PROFILES or custom config must be provided)
|
|
66
|
+
* @param config - Optional custom configuration (overrides the default profile)
|
|
67
|
+
* @returns The TokenBucketRateLimiter for the service
|
|
68
|
+
*/
|
|
69
|
+
export declare function getRateLimiter(service: string, config?: RateLimiterConfig): TokenBucketRateLimiter;
|
|
70
|
+
/**
|
|
71
|
+
* Resets all rate limiters. Useful for testing.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resetAllRateLimiters(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Wraps an async function with automatic rate limiting.
|
|
76
|
+
*
|
|
77
|
+
* @param service - Service name for rate limit lookup
|
|
78
|
+
* @param fn - The async function to rate-limit
|
|
79
|
+
* @param config - Optional custom rate limit configuration
|
|
80
|
+
* @returns The result of the wrapped function
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const result = await withRateLimit('openai', () => callOpenAI());
|
|
84
|
+
*/
|
|
85
|
+
export declare function withRateLimit<T>(service: string, fn: () => Promise<T>, config?: RateLimiterConfig): Promise<T>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { CircuitBreaker } from './circuit-breaker';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for retry mechanism with exponential backoff
|
|
4
|
+
*/
|
|
5
|
+
export interface RetryConfig {
|
|
6
|
+
maxRetries: number;
|
|
7
|
+
baseDelayMs: number;
|
|
8
|
+
maxDelayMs: number;
|
|
9
|
+
retryableErrors?: (error: unknown) => boolean;
|
|
10
|
+
/** Optional circuit breaker to check before each attempt */
|
|
11
|
+
circuitBreaker?: CircuitBreaker;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Default retry configuration
|
|
15
|
+
* - 3 retries maximum
|
|
16
|
+
* - 1 second base delay
|
|
17
|
+
* - 30 second max delay
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Executes a function with retry logic using exponential backoff.
|
|
22
|
+
*
|
|
23
|
+
* This utility provides automatic retry handling for transient failures in external API calls.
|
|
24
|
+
* It implements exponential backoff with jitter to avoid thundering herd problems.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Basic usage
|
|
28
|
+
* const result = await withRetry(
|
|
29
|
+
* () => fetch('https://api.example.com/data'),
|
|
30
|
+
* {},
|
|
31
|
+
* 'API Call'
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // With custom retry logic
|
|
36
|
+
* const result = await withRetry(
|
|
37
|
+
* () => makeApiCall(),
|
|
38
|
+
* {
|
|
39
|
+
* maxRetries: 5,
|
|
40
|
+
* baseDelayMs: 2000,
|
|
41
|
+
* retryableErrors: (error) => {
|
|
42
|
+
* if (error instanceof Error) {
|
|
43
|
+
* return error.message.includes('rate limit');
|
|
44
|
+
* }
|
|
45
|
+
* return false;
|
|
46
|
+
* }
|
|
47
|
+
* },
|
|
48
|
+
* 'Custom API'
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* @template T - The return type of the function being retried
|
|
52
|
+
* @param fn - The function to execute and retry if needed. Must return a Promise.
|
|
53
|
+
* @param config - Partial retry configuration to override defaults
|
|
54
|
+
* @param label - Descriptive label for logging purposes (default: 'unknown')
|
|
55
|
+
* @returns Promise<T> - Resolves with the result of the function if successful
|
|
56
|
+
* @throws The last error encountered if all retry attempts fail or if a non-retryable error occurs
|
|
57
|
+
*/
|
|
58
|
+
export declare function withRetry<T>(fn: () => Promise<T>, config?: Partial<RetryConfig>, label?: string): Promise<T>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizes sensitive values for logging by showing only a few visible characters
|
|
3
|
+
* @param value The sensitive value to sanitize
|
|
4
|
+
* @param visibleChars Number of characters to show before masking (default: 4)
|
|
5
|
+
* @returns A sanitized string safe for logging
|
|
6
|
+
*/
|
|
7
|
+
export declare function sanitizeForLog(value: string, visibleChars?: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* Sanitizes error messages by removing sensitive credentials and tokens
|
|
10
|
+
* @param error The error to sanitize
|
|
11
|
+
* @returns A sanitized error message safe for logging
|
|
12
|
+
*/
|
|
13
|
+
export declare function sanitizeError(error: unknown): string;
|
|
14
|
+
/**
|
|
15
|
+
* Sanitizes AWS credentials for logging
|
|
16
|
+
* @param auth AWS auth object or null
|
|
17
|
+
* @returns Sanitized string representation safe for logging
|
|
18
|
+
*/
|
|
19
|
+
export declare function sanitizeAWSAuth(auth: {
|
|
20
|
+
AWS_ACCESS_KEY_ID?: string;
|
|
21
|
+
AWS_SECRET_ACCESS_KEY?: string;
|
|
22
|
+
AWS_REGION?: string;
|
|
23
|
+
} | null): string;
|
|
24
|
+
/**
|
|
25
|
+
* Sanitizes an object by removing or masking sensitive fields
|
|
26
|
+
* @param obj The object to sanitize
|
|
27
|
+
* @param sensitiveFields Array of field names to mask
|
|
28
|
+
* @returns A new sanitized object safe for logging
|
|
29
|
+
*/
|
|
30
|
+
export declare function sanitizeObject<T extends Record<string, unknown>>(obj: T, sensitiveFields?: string[]): Record<string, unknown>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default timeout values (in milliseconds) for external service calls.
|
|
3
|
+
* These values help prevent hanging requests and provide predictable failure behavior.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Slack API timeout: 5 seconds
|
|
7
|
+
* Used for Slack message posting operations
|
|
8
|
+
*/
|
|
9
|
+
export declare const SLACK_TIMEOUT_MS = 5000;
|
|
10
|
+
/**
|
|
11
|
+
* Perplexity API timeout: 30 seconds
|
|
12
|
+
* Used for Perplexity AI API completion requests
|
|
13
|
+
*/
|
|
14
|
+
export declare const PERPLEXITY_TIMEOUT_MS = 30000;
|
|
15
|
+
/**
|
|
16
|
+
* Google Sheets API timeout: 15 seconds
|
|
17
|
+
* Used for Google Sheets read/write operations
|
|
18
|
+
*/
|
|
19
|
+
export declare const GOOGLE_SHEETS_TIMEOUT_MS = 15000;
|
|
20
|
+
/**
|
|
21
|
+
* LLM API timeout: 120 seconds (2 minutes)
|
|
22
|
+
* Used for OpenAI and Deepseek completion requests
|
|
23
|
+
*/
|
|
24
|
+
export declare const LLM_TIMEOUT_MS = 120000;
|
|
25
|
+
/**
|
|
26
|
+
* AWS Lambda timeout: 60 seconds (1 minute)
|
|
27
|
+
* Used for Lambda function invocations
|
|
28
|
+
*/
|
|
29
|
+
export declare const AWS_LAMBDA_TIMEOUT_MS = 60000;
|
|
30
|
+
/**
|
|
31
|
+
* AWS S3 timeout: 30 seconds
|
|
32
|
+
* Used for S3 operations (upload, download, list, etc.)
|
|
33
|
+
*/
|
|
34
|
+
export declare const AWS_S3_TIMEOUT_MS = 30000;
|
|
35
|
+
/**
|
|
36
|
+
* OpenWeather API timeout: 10 seconds
|
|
37
|
+
* Used for weather data fetching
|
|
38
|
+
*/
|
|
39
|
+
export declare const OPENWEATHER_TIMEOUT_MS = 10000;
|
|
40
|
+
/**
|
|
41
|
+
* Generic fetch timeout: 30 seconds
|
|
42
|
+
* Used for generic HTTP fetch operations (e.g., PDF image fetching)
|
|
43
|
+
*/
|
|
44
|
+
export declare const GENERIC_FETCH_TIMEOUT_MS = 30000;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptic/lumic-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "NPM repo set of utility functions usable across the entire organisation.",
|
|
5
5
|
"always-build-npm": false,
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"build:js": "rollup -c",
|
|
24
24
|
"build:tools": "node --loader ts-node/esm compile-tool-definitions.ts",
|
|
25
25
|
"build:types": "rm -rf dist/types && tsc --emitDeclarationOnly --declaration --declarationDir dist/types",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
26
27
|
"test": "vitest run",
|
|
27
28
|
"test:watch": "vitest",
|
|
28
29
|
"test:legacy": "npm run build && node dist/test.mjs",
|