@azumag/opencode-rate-limit-fallback 1.31.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +134 -47
- package/dist/index.d.ts +2 -1
- package/dist/index.js +58 -7
- package/dist/src/circuitbreaker/CircuitBreaker.d.ts +60 -0
- package/dist/src/circuitbreaker/CircuitBreaker.js +218 -0
- package/dist/src/circuitbreaker/CircuitState.d.ts +44 -0
- package/dist/src/circuitbreaker/CircuitState.js +128 -0
- package/dist/src/circuitbreaker/index.d.ts +8 -0
- package/dist/src/circuitbreaker/index.js +8 -0
- package/dist/src/config/Validator.d.ts +64 -0
- package/dist/src/config/Validator.js +618 -0
- package/dist/src/diagnostics/Reporter.d.ts +128 -0
- package/dist/src/diagnostics/Reporter.js +285 -0
- package/dist/src/errors/PatternRegistry.d.ts +75 -0
- package/dist/src/errors/PatternRegistry.js +234 -0
- package/dist/src/fallback/FallbackHandler.d.ts +4 -1
- package/dist/src/fallback/FallbackHandler.js +41 -2
- package/dist/src/fallback/ModelSelector.d.ts +9 -1
- package/dist/src/fallback/ModelSelector.js +33 -4
- package/dist/src/health/HealthTracker.d.ts +96 -0
- package/dist/src/health/HealthTracker.js +353 -0
- package/dist/src/metrics/MetricsManager.d.ts +10 -1
- package/dist/src/metrics/MetricsManager.js +137 -0
- package/dist/src/types/index.d.ts +98 -0
- package/dist/src/types/index.js +10 -0
- package/dist/src/utils/config.d.ts +8 -1
- package/dist/src/utils/config.js +26 -11
- package/package.json +1 -1
- package/dist/src/utils/errorDetection.d.ts +0 -7
- package/dist/src/utils/errorDetection.js +0 -34
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit State - State machine for individual circuit breaker state
|
|
3
|
+
*/
|
|
4
|
+
import type { CircuitBreakerConfig, CircuitBreakerState, CircuitBreakerStateType } from '../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Return type for canExecute method
|
|
7
|
+
*/
|
|
8
|
+
export interface CanExecuteResult {
|
|
9
|
+
allowed: boolean;
|
|
10
|
+
transition?: {
|
|
11
|
+
from: CircuitBreakerStateType;
|
|
12
|
+
to: CircuitBreakerStateType;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* CircuitState class - Manages state transitions for a single circuit
|
|
17
|
+
*/
|
|
18
|
+
export declare class CircuitState {
|
|
19
|
+
state: CircuitBreakerState;
|
|
20
|
+
private halfOpenCalls;
|
|
21
|
+
private config;
|
|
22
|
+
constructor(config: CircuitBreakerConfig);
|
|
23
|
+
/**
|
|
24
|
+
* Handle a successful request
|
|
25
|
+
*/
|
|
26
|
+
onSuccess(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Handle a failed request
|
|
29
|
+
*/
|
|
30
|
+
onFailure(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a request can be executed through this circuit
|
|
33
|
+
* @returns Object with allowed flag and optional transition info
|
|
34
|
+
*/
|
|
35
|
+
canExecute(): CanExecuteResult;
|
|
36
|
+
/**
|
|
37
|
+
* Get the current state
|
|
38
|
+
*/
|
|
39
|
+
getState(): CircuitBreakerState;
|
|
40
|
+
/**
|
|
41
|
+
* Reset the circuit to CLOSED state
|
|
42
|
+
*/
|
|
43
|
+
reset(): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit State - State machine for individual circuit breaker state
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* CircuitState class - Manages state transitions for a single circuit
|
|
6
|
+
*/
|
|
7
|
+
export class CircuitState {
|
|
8
|
+
state;
|
|
9
|
+
halfOpenCalls = 0;
|
|
10
|
+
config;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.state = {
|
|
14
|
+
state: 'CLOSED',
|
|
15
|
+
failureCount: 0,
|
|
16
|
+
successCount: 0,
|
|
17
|
+
lastFailureTime: 0,
|
|
18
|
+
lastSuccessTime: 0,
|
|
19
|
+
nextAttemptTime: 0,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Handle a successful request
|
|
24
|
+
*/
|
|
25
|
+
onSuccess() {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
this.state.lastSuccessTime = now;
|
|
28
|
+
switch (this.state.state) {
|
|
29
|
+
case 'CLOSED':
|
|
30
|
+
// Reset failure count on success
|
|
31
|
+
this.state.failureCount = 0;
|
|
32
|
+
break;
|
|
33
|
+
case 'HALF_OPEN':
|
|
34
|
+
this.state.successCount++;
|
|
35
|
+
this.state.failureCount = 0;
|
|
36
|
+
// Close circuit if success threshold reached
|
|
37
|
+
if (this.state.successCount >= this.config.successThreshold) {
|
|
38
|
+
this.state.state = 'CLOSED';
|
|
39
|
+
this.state.successCount = 0;
|
|
40
|
+
this.halfOpenCalls = 0;
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
case 'OPEN':
|
|
44
|
+
// Should not receive success in OPEN state
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Handle a failed request
|
|
50
|
+
*/
|
|
51
|
+
onFailure() {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
this.state.lastFailureTime = now;
|
|
54
|
+
switch (this.state.state) {
|
|
55
|
+
case 'CLOSED':
|
|
56
|
+
this.state.failureCount++;
|
|
57
|
+
// Open circuit if failure threshold reached
|
|
58
|
+
if (this.state.failureCount >= this.config.failureThreshold) {
|
|
59
|
+
this.state.state = 'OPEN';
|
|
60
|
+
this.state.nextAttemptTime = now + this.config.recoveryTimeoutMs;
|
|
61
|
+
this.state.successCount = 0;
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
case 'HALF_OPEN':
|
|
65
|
+
// Re-open circuit on failure
|
|
66
|
+
this.state.state = 'OPEN';
|
|
67
|
+
this.state.nextAttemptTime = now + this.config.recoveryTimeoutMs;
|
|
68
|
+
this.state.failureCount++;
|
|
69
|
+
this.state.successCount = 0;
|
|
70
|
+
this.halfOpenCalls = 0;
|
|
71
|
+
break;
|
|
72
|
+
case 'OPEN':
|
|
73
|
+
// Already open, just update count
|
|
74
|
+
this.state.failureCount++;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if a request can be executed through this circuit
|
|
80
|
+
* @returns Object with allowed flag and optional transition info
|
|
81
|
+
*/
|
|
82
|
+
canExecute() {
|
|
83
|
+
const now = Date.now();
|
|
84
|
+
switch (this.state.state) {
|
|
85
|
+
case 'CLOSED':
|
|
86
|
+
return { allowed: true };
|
|
87
|
+
case 'OPEN':
|
|
88
|
+
// Check if recovery timeout has elapsed
|
|
89
|
+
if (now >= this.state.nextAttemptTime) {
|
|
90
|
+
// Transition to HALF_OPEN for test request
|
|
91
|
+
const transition = { from: 'OPEN', to: 'HALF_OPEN' };
|
|
92
|
+
this.state.state = 'HALF_OPEN';
|
|
93
|
+
this.halfOpenCalls = 0;
|
|
94
|
+
return { allowed: true, transition };
|
|
95
|
+
}
|
|
96
|
+
return { allowed: false };
|
|
97
|
+
case 'HALF_OPEN':
|
|
98
|
+
// Limit calls in HALF_OPEN state
|
|
99
|
+
if (this.halfOpenCalls < this.config.halfOpenMaxCalls) {
|
|
100
|
+
this.halfOpenCalls++;
|
|
101
|
+
return { allowed: true };
|
|
102
|
+
}
|
|
103
|
+
return { allowed: false };
|
|
104
|
+
default:
|
|
105
|
+
return { allowed: false };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the current state
|
|
110
|
+
*/
|
|
111
|
+
getState() {
|
|
112
|
+
return { ...this.state };
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Reset the circuit to CLOSED state
|
|
116
|
+
*/
|
|
117
|
+
reset() {
|
|
118
|
+
this.state = {
|
|
119
|
+
state: 'CLOSED',
|
|
120
|
+
failureCount: 0,
|
|
121
|
+
successCount: 0,
|
|
122
|
+
lastFailureTime: 0,
|
|
123
|
+
lastSuccessTime: 0,
|
|
124
|
+
nextAttemptTime: 0,
|
|
125
|
+
};
|
|
126
|
+
this.halfOpenCalls = 0;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Module
|
|
3
|
+
*
|
|
4
|
+
* Provides circuit breaker pattern implementation to prevent cascading failures
|
|
5
|
+
* by automatically disabling models that are consistently failing.
|
|
6
|
+
*/
|
|
7
|
+
export { CircuitBreaker } from './CircuitBreaker.js';
|
|
8
|
+
export { CircuitState, type CanExecuteResult } from './CircuitState.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Module
|
|
3
|
+
*
|
|
4
|
+
* Provides circuit breaker pattern implementation to prevent cascading failures
|
|
5
|
+
* by automatically disabling models that are consistently failing.
|
|
6
|
+
*/
|
|
7
|
+
export { CircuitBreaker } from './CircuitBreaker.js';
|
|
8
|
+
export { CircuitState } from './CircuitState.js';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration validation and diagnostics
|
|
3
|
+
*/
|
|
4
|
+
import type { PluginConfig } from '../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Validation error details
|
|
7
|
+
*/
|
|
8
|
+
export interface ValidationError {
|
|
9
|
+
path: string;
|
|
10
|
+
message: string;
|
|
11
|
+
severity: 'error' | 'warning';
|
|
12
|
+
value?: unknown;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validation result
|
|
16
|
+
*/
|
|
17
|
+
export interface ValidationResult {
|
|
18
|
+
isValid: boolean;
|
|
19
|
+
errors: ValidationError[];
|
|
20
|
+
warnings: ValidationError[];
|
|
21
|
+
config: PluginConfig;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validation configuration
|
|
25
|
+
*/
|
|
26
|
+
export interface ConfigValidationOptions {
|
|
27
|
+
strict?: boolean;
|
|
28
|
+
logWarnings?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Diagnostics configuration
|
|
32
|
+
*/
|
|
33
|
+
export interface DiagnosticsInfo {
|
|
34
|
+
configSource: string;
|
|
35
|
+
config: PluginConfig;
|
|
36
|
+
validation: ValidationResult;
|
|
37
|
+
defaultsApplied: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Configuration Validator class
|
|
41
|
+
*/
|
|
42
|
+
export declare class ConfigValidator {
|
|
43
|
+
private logger?;
|
|
44
|
+
constructor(logger?: {
|
|
45
|
+
warn: (msg: string) => void;
|
|
46
|
+
error: (msg: string) => void;
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* Validate a configuration object
|
|
50
|
+
*/
|
|
51
|
+
validate(config: Partial<PluginConfig>, options?: ConfigValidationOptions): ValidationResult;
|
|
52
|
+
/**
|
|
53
|
+
* Validate a configuration file
|
|
54
|
+
*/
|
|
55
|
+
validateFile(filePath: string, options?: ConfigValidationOptions): ValidationResult;
|
|
56
|
+
/**
|
|
57
|
+
* Get diagnostics information for the current configuration
|
|
58
|
+
*/
|
|
59
|
+
getDiagnostics(config: PluginConfig, configSource: string, defaultsApplied?: string[]): DiagnosticsInfo;
|
|
60
|
+
/**
|
|
61
|
+
* Format diagnostics as human-readable text
|
|
62
|
+
*/
|
|
63
|
+
formatDiagnostics(diagnostics: DiagnosticsInfo): string;
|
|
64
|
+
}
|