@adaptic/lumic-utils 1.0.6 → 1.0.8
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-DE7JUXjy.js +3693 -0
- package/dist/apollo-client.client-DE7JUXjy.js.map +1 -0
- package/dist/apollo-client.client-DlG4HsFm.js +3704 -0
- package/dist/apollo-client.client-DlG4HsFm.js.map +1 -0
- package/dist/apollo-client.server-D1QJea5_.js +16319 -0
- package/dist/apollo-client.server-D1QJea5_.js.map +1 -0
- package/dist/apollo-client.server-uqalq3yp.js +16321 -0
- package/dist/apollo-client.server-uqalq3yp.js.map +1 -0
- package/dist/index-Bd84zcTQ.js +74944 -0
- package/dist/index-Bd84zcTQ.js.map +1 -0
- package/dist/index-CZKOqrJ4.js +75137 -0
- package/dist/index-CZKOqrJ4.js.map +1 -0
- package/dist/index-CsKfs4nG.js +12108 -0
- package/dist/index-CsKfs4nG.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-CcgbRft2.js → index-DZZCd-1T.js} +182 -22
- package/dist/index-DZZCd-1T.js.map +1 -0
- package/dist/index-aP9ow8_W.js +12271 -0
- package/dist/index-aP9ow8_W.js.map +1 -0
- package/dist/index.cjs +122 -11417
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +39 -11399
- package/dist/index.mjs.map +1 -1
- package/dist/test.cjs +24 -7
- package/dist/test.cjs.map +1 -1
- package/dist/test.mjs +24 -7
- package/dist/test.mjs.map +1 -1
- package/dist/types/aws-types.ts +1 -1
- package/dist/types/config/__tests__/secrets.test.d.ts +1 -0
- package/dist/types/config/secrets.d.ts +186 -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-call.d.ts +2 -2
- package/dist/types/functions/llm-deepseek.d.ts +1 -1
- 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/google-types.ts +6 -3
- package/dist/types/index.d.ts +30 -0
- package/dist/types/index.ts +1 -1
- package/dist/types/openai-types.ts +165 -6
- 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 +149 -3
- 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/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 +17 -5
- package/dist/index-CcXQeJz8.js.map +0 -1
- package/dist/index-CcgbRft2.js.map +0 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Possible states for a circuit breaker
|
|
3
|
+
*/
|
|
4
|
+
export declare enum CircuitBreakerState {
|
|
5
|
+
CLOSED = "CLOSED",
|
|
6
|
+
OPEN = "OPEN",
|
|
7
|
+
HALF_OPEN = "HALF_OPEN"
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for the circuit breaker
|
|
11
|
+
*/
|
|
12
|
+
export interface CircuitBreakerConfig {
|
|
13
|
+
/** Number of failures before the circuit opens (default: 5) */
|
|
14
|
+
failureThreshold: number;
|
|
15
|
+
/** Time in milliseconds before attempting recovery from OPEN state (default: 30000) */
|
|
16
|
+
resetTimeoutMs: number;
|
|
17
|
+
/** Number of consecutive successes in HALF_OPEN required to close the circuit (default: 3) */
|
|
18
|
+
successThreshold: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Callback invoked when the circuit breaker changes state
|
|
22
|
+
*/
|
|
23
|
+
export type CircuitBreakerStateChangeCallback = (from: CircuitBreakerState, to: CircuitBreakerState, serviceName: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Default circuit breaker configuration
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_CIRCUIT_BREAKER_CONFIG: CircuitBreakerConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Error thrown when a circuit breaker is open and rejecting calls
|
|
30
|
+
*/
|
|
31
|
+
export declare class CircuitBreakerOpenError extends Error {
|
|
32
|
+
readonly serviceName: string;
|
|
33
|
+
readonly resetTimeoutMs: number;
|
|
34
|
+
constructor(serviceName: string, resetTimeoutMs: number);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generic circuit breaker implementation for external service calls.
|
|
38
|
+
*
|
|
39
|
+
* The circuit breaker monitors failures and transitions through three states:
|
|
40
|
+
* - CLOSED: Normal operation. Calls pass through. Failures are counted.
|
|
41
|
+
* - OPEN: Too many failures. Calls are rejected immediately without executing.
|
|
42
|
+
* - HALF_OPEN: After a reset timeout, allows a limited number of trial calls
|
|
43
|
+
* to test whether the service has recovered.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* const breaker = new CircuitBreaker('slack-api');
|
|
47
|
+
* const result = await breaker.execute(() => sendSlackMessage(channel, msg));
|
|
48
|
+
*/
|
|
49
|
+
export declare class CircuitBreaker {
|
|
50
|
+
readonly serviceName: string;
|
|
51
|
+
private state;
|
|
52
|
+
private failureCount;
|
|
53
|
+
private successCount;
|
|
54
|
+
private lastFailureTime;
|
|
55
|
+
private readonly config;
|
|
56
|
+
private onStateChange;
|
|
57
|
+
constructor(serviceName: string, config?: Partial<CircuitBreakerConfig>, onStateChange?: CircuitBreakerStateChangeCallback);
|
|
58
|
+
/**
|
|
59
|
+
* Returns the current state of the circuit breaker.
|
|
60
|
+
*/
|
|
61
|
+
getState(): CircuitBreakerState;
|
|
62
|
+
/**
|
|
63
|
+
* Returns the current failure count.
|
|
64
|
+
*/
|
|
65
|
+
getFailureCount(): number;
|
|
66
|
+
/**
|
|
67
|
+
* Returns the current success count (relevant in HALF_OPEN state).
|
|
68
|
+
*/
|
|
69
|
+
getSuccessCount(): number;
|
|
70
|
+
/**
|
|
71
|
+
* Resets the circuit breaker to its initial CLOSED state.
|
|
72
|
+
*/
|
|
73
|
+
reset(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Executes the provided function through the circuit breaker.
|
|
76
|
+
*
|
|
77
|
+
* - In CLOSED state: executes normally, tracking failures.
|
|
78
|
+
* - In OPEN state: rejects immediately with CircuitBreakerOpenError
|
|
79
|
+
* unless the reset timeout has elapsed, in which case it transitions to HALF_OPEN.
|
|
80
|
+
* - In HALF_OPEN state: allows trial calls, tracking successes to decide
|
|
81
|
+
* whether to close or re-open the circuit.
|
|
82
|
+
*
|
|
83
|
+
* @template T - The return type of the wrapped function
|
|
84
|
+
* @param fn - The async function to execute
|
|
85
|
+
* @returns The result of the function call
|
|
86
|
+
* @throws CircuitBreakerOpenError if the circuit is open
|
|
87
|
+
* @throws The original error if the function call fails
|
|
88
|
+
*/
|
|
89
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Sets or replaces the state change callback.
|
|
92
|
+
*/
|
|
93
|
+
setOnStateChange(callback: CircuitBreakerStateChangeCallback): void;
|
|
94
|
+
private shouldAttemptReset;
|
|
95
|
+
private onSuccess;
|
|
96
|
+
private onFailure;
|
|
97
|
+
private transitionTo;
|
|
98
|
+
private notifyStateChange;
|
|
99
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Correlation context stored in AsyncLocalStorage.
|
|
3
|
+
* Propagates automatically through async call chains.
|
|
4
|
+
*/
|
|
5
|
+
export interface CorrelationContext {
|
|
6
|
+
/** Unique correlation ID for request tracing */
|
|
7
|
+
correlationId: string;
|
|
8
|
+
/** Additional metadata to propagate */
|
|
9
|
+
metadata?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generates a new unique correlation ID.
|
|
13
|
+
* Uses crypto.randomUUID for high-quality UUIDs.
|
|
14
|
+
* @returns A new UUID string
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateCorrelationId(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Returns the current correlation ID from AsyncLocalStorage, or undefined if none is set.
|
|
19
|
+
* @returns The current correlation ID or undefined
|
|
20
|
+
*/
|
|
21
|
+
export declare function getCorrelationId(): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Returns the full correlation context, or undefined if none is set.
|
|
24
|
+
* @returns The current CorrelationContext or undefined
|
|
25
|
+
*/
|
|
26
|
+
export declare function getCorrelationContext(): CorrelationContext | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Runs a function within a correlation context.
|
|
29
|
+
* All async operations within the callback will have access to the correlation ID.
|
|
30
|
+
*
|
|
31
|
+
* @param fn - The function to run within the context
|
|
32
|
+
* @param correlationId - Optional correlation ID. If not provided, one is generated.
|
|
33
|
+
* @param metadata - Optional metadata to attach to the context
|
|
34
|
+
* @returns The return value of the function
|
|
35
|
+
*/
|
|
36
|
+
export declare function withCorrelationId<T>(fn: () => T, correlationId?: string, metadata?: Record<string, string>): T;
|
|
37
|
+
/**
|
|
38
|
+
* Returns headers object with the correlation ID for external HTTP calls.
|
|
39
|
+
* Returns an empty object if no correlation context is active.
|
|
40
|
+
* @param headerName - The header name to use (default: 'x-correlation-id')
|
|
41
|
+
* @returns Headers object with correlation ID
|
|
42
|
+
*/
|
|
43
|
+
export declare function getCorrelationHeaders(headerName?: string): Record<string, string>;
|
|
@@ -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>;
|