@specforge/mcp 2.6.0 → 3.0.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 +73 -0
- package/bin/{specforge-mcp → specforge} +0 -5
- package/dist/ai-provider/circuit-breaker.d.ts +63 -0
- package/dist/ai-provider/circuit-breaker.d.ts.map +1 -0
- package/dist/ai-provider/circuit-breaker.js +160 -0
- package/dist/ai-provider/circuit-breaker.js.map +1 -0
- package/dist/ai-provider/cli-version.d.ts +50 -0
- package/dist/ai-provider/cli-version.d.ts.map +1 -0
- package/dist/ai-provider/cli-version.js +141 -0
- package/dist/ai-provider/cli-version.js.map +1 -0
- package/dist/ai-provider/config-loader.d.ts +45 -0
- package/dist/ai-provider/config-loader.d.ts.map +1 -0
- package/dist/ai-provider/config-loader.js +106 -0
- package/dist/ai-provider/config-loader.js.map +1 -0
- package/dist/ai-provider/errors.d.ts +48 -0
- package/dist/ai-provider/errors.d.ts.map +1 -0
- package/dist/ai-provider/errors.js +102 -0
- package/dist/ai-provider/errors.js.map +1 -0
- package/dist/ai-provider/events.d.ts +73 -0
- package/dist/ai-provider/events.d.ts.map +1 -0
- package/dist/ai-provider/events.js +75 -0
- package/dist/ai-provider/events.js.map +1 -0
- package/dist/ai-provider/factory.d.ts +31 -0
- package/dist/ai-provider/factory.d.ts.map +1 -0
- package/dist/ai-provider/factory.js +100 -0
- package/dist/ai-provider/factory.js.map +1 -0
- package/dist/ai-provider/index.d.ts +24 -0
- package/dist/ai-provider/index.d.ts.map +1 -0
- package/dist/ai-provider/index.js +46 -0
- package/dist/ai-provider/index.js.map +1 -0
- package/dist/ai-provider/instance-coordinator.d.ts +54 -0
- package/dist/ai-provider/instance-coordinator.d.ts.map +1 -0
- package/dist/ai-provider/instance-coordinator.js +199 -0
- package/dist/ai-provider/instance-coordinator.js.map +1 -0
- package/dist/ai-provider/jsonl-parser.d.ts +43 -0
- package/dist/ai-provider/jsonl-parser.d.ts.map +1 -0
- package/dist/ai-provider/jsonl-parser.js +107 -0
- package/dist/ai-provider/jsonl-parser.js.map +1 -0
- package/dist/ai-provider/lifecycle.d.ts +50 -0
- package/dist/ai-provider/lifecycle.d.ts.map +1 -0
- package/dist/ai-provider/lifecycle.js +145 -0
- package/dist/ai-provider/lifecycle.js.map +1 -0
- package/dist/ai-provider/logger.d.ts +69 -0
- package/dist/ai-provider/logger.d.ts.map +1 -0
- package/dist/ai-provider/logger.js +161 -0
- package/dist/ai-provider/logger.js.map +1 -0
- package/dist/ai-provider/metrics.d.ts +91 -0
- package/dist/ai-provider/metrics.d.ts.map +1 -0
- package/dist/ai-provider/metrics.js +187 -0
- package/dist/ai-provider/metrics.js.map +1 -0
- package/dist/ai-provider/process-manager.d.ts +97 -0
- package/dist/ai-provider/process-manager.d.ts.map +1 -0
- package/dist/ai-provider/process-manager.js +477 -0
- package/dist/ai-provider/process-manager.js.map +1 -0
- package/dist/ai-provider/providers/claude-code.d.ts +64 -0
- package/dist/ai-provider/providers/claude-code.d.ts.map +1 -0
- package/dist/ai-provider/providers/claude-code.js +205 -0
- package/dist/ai-provider/providers/claude-code.js.map +1 -0
- package/dist/ai-provider/retry-executor.d.ts +52 -0
- package/dist/ai-provider/retry-executor.d.ts.map +1 -0
- package/dist/ai-provider/retry-executor.js +138 -0
- package/dist/ai-provider/retry-executor.js.map +1 -0
- package/dist/ai-provider/safe-args.d.ts +58 -0
- package/dist/ai-provider/safe-args.d.ts.map +1 -0
- package/dist/ai-provider/safe-args.js +176 -0
- package/dist/ai-provider/safe-args.js.map +1 -0
- package/dist/ai-provider/semaphore.d.ts +50 -0
- package/dist/ai-provider/semaphore.d.ts.map +1 -0
- package/dist/ai-provider/semaphore.js +97 -0
- package/dist/ai-provider/semaphore.js.map +1 -0
- package/dist/ai-provider/tracer.d.ts +67 -0
- package/dist/ai-provider/tracer.d.ts.map +1 -0
- package/dist/ai-provider/tracer.js +209 -0
- package/dist/ai-provider/tracer.js.map +1 -0
- package/dist/ai-provider/types.d.ts +181 -0
- package/dist/ai-provider/types.d.ts.map +1 -0
- package/dist/ai-provider/types.js +8 -0
- package/dist/ai-provider/types.js.map +1 -0
- package/dist/autopilot/agents/agent-runner.d.ts +109 -0
- package/dist/autopilot/agents/agent-runner.d.ts.map +1 -0
- package/dist/autopilot/agents/agent-runner.js +731 -0
- package/dist/autopilot/agents/agent-runner.js.map +1 -0
- package/dist/autopilot/agents/agent-selector.d.ts +59 -0
- package/dist/autopilot/agents/agent-selector.d.ts.map +1 -0
- package/dist/autopilot/agents/agent-selector.js +234 -0
- package/dist/autopilot/agents/agent-selector.js.map +1 -0
- package/dist/autopilot/agents/model-selector.d.ts +49 -0
- package/dist/autopilot/agents/model-selector.d.ts.map +1 -0
- package/dist/autopilot/agents/model-selector.js +62 -0
- package/dist/autopilot/agents/model-selector.js.map +1 -0
- package/dist/autopilot/agents/profiles/builtin.d.ts +55 -0
- package/dist/autopilot/agents/profiles/builtin.d.ts.map +1 -0
- package/dist/autopilot/agents/profiles/builtin.js +323 -0
- package/dist/autopilot/agents/profiles/builtin.js.map +1 -0
- package/dist/autopilot/agents/profiles/types.d.ts +98 -0
- package/dist/autopilot/agents/profiles/types.d.ts.map +1 -0
- package/dist/autopilot/agents/profiles/types.js +17 -0
- package/dist/autopilot/agents/profiles/types.js.map +1 -0
- package/dist/autopilot/api/autopilot-api-client.d.ts +217 -0
- package/dist/autopilot/api/autopilot-api-client.d.ts.map +1 -0
- package/dist/autopilot/api/autopilot-api-client.js +402 -0
- package/dist/autopilot/api/autopilot-api-client.js.map +1 -0
- package/dist/autopilot/cli/abort.d.ts +20 -0
- package/dist/autopilot/cli/abort.d.ts.map +1 -0
- package/dist/autopilot/cli/abort.js +201 -0
- package/dist/autopilot/cli/abort.js.map +1 -0
- package/dist/autopilot/cli/display.d.ts +63 -0
- package/dist/autopilot/cli/display.d.ts.map +1 -0
- package/dist/autopilot/cli/display.js +260 -0
- package/dist/autopilot/cli/display.js.map +1 -0
- package/dist/autopilot/cli/index.d.ts +24 -0
- package/dist/autopilot/cli/index.d.ts.map +1 -0
- package/dist/autopilot/cli/index.js +79 -0
- package/dist/autopilot/cli/index.js.map +1 -0
- package/dist/autopilot/cli/pause.d.ts +18 -0
- package/dist/autopilot/cli/pause.d.ts.map +1 -0
- package/dist/autopilot/cli/pause.js +110 -0
- package/dist/autopilot/cli/pause.js.map +1 -0
- package/dist/autopilot/cli/resume.d.ts +22 -0
- package/dist/autopilot/cli/resume.d.ts.map +1 -0
- package/dist/autopilot/cli/resume.js +172 -0
- package/dist/autopilot/cli/resume.js.map +1 -0
- package/dist/autopilot/cli/run.d.ts +25 -0
- package/dist/autopilot/cli/run.d.ts.map +1 -0
- package/dist/autopilot/cli/run.js +220 -0
- package/dist/autopilot/cli/run.js.map +1 -0
- package/dist/autopilot/cli/status.d.ts +20 -0
- package/dist/autopilot/cli/status.d.ts.map +1 -0
- package/dist/autopilot/cli/status.js +217 -0
- package/dist/autopilot/cli/status.js.map +1 -0
- package/dist/autopilot/config.d.ts +45 -0
- package/dist/autopilot/config.d.ts.map +1 -0
- package/dist/autopilot/config.js +269 -0
- package/dist/autopilot/config.js.map +1 -0
- package/dist/autopilot/core/dependency-resolver.d.ts +108 -0
- package/dist/autopilot/core/dependency-resolver.d.ts.map +1 -0
- package/dist/autopilot/core/dependency-resolver.js +394 -0
- package/dist/autopilot/core/dependency-resolver.js.map +1 -0
- package/dist/autopilot/core/dispatcher.d.ts +215 -0
- package/dist/autopilot/core/dispatcher.d.ts.map +1 -0
- package/dist/autopilot/core/dispatcher.js +594 -0
- package/dist/autopilot/core/dispatcher.js.map +1 -0
- package/dist/autopilot/core/failure-handler.d.ts +145 -0
- package/dist/autopilot/core/failure-handler.d.ts.map +1 -0
- package/dist/autopilot/core/failure-handler.js +308 -0
- package/dist/autopilot/core/failure-handler.js.map +1 -0
- package/dist/autopilot/core/rate-limit-handler.d.ts +108 -0
- package/dist/autopilot/core/rate-limit-handler.d.ts.map +1 -0
- package/dist/autopilot/core/rate-limit-handler.js +195 -0
- package/dist/autopilot/core/rate-limit-handler.js.map +1 -0
- package/dist/autopilot/core/state-manager.d.ts +160 -0
- package/dist/autopilot/core/state-manager.d.ts.map +1 -0
- package/dist/autopilot/core/state-manager.js +393 -0
- package/dist/autopilot/core/state-manager.js.map +1 -0
- package/dist/autopilot/core/timeout-manager.d.ts +95 -0
- package/dist/autopilot/core/timeout-manager.d.ts.map +1 -0
- package/dist/autopilot/core/timeout-manager.js +188 -0
- package/dist/autopilot/core/timeout-manager.js.map +1 -0
- package/dist/autopilot/git/branch-manager.d.ts +117 -0
- package/dist/autopilot/git/branch-manager.d.ts.map +1 -0
- package/dist/autopilot/git/branch-manager.js +238 -0
- package/dist/autopilot/git/branch-manager.js.map +1 -0
- package/dist/autopilot/git/index.d.ts +9 -0
- package/dist/autopilot/git/index.d.ts.map +1 -0
- package/dist/autopilot/git/index.js +9 -0
- package/dist/autopilot/git/index.js.map +1 -0
- package/dist/autopilot/git/merge-manager.d.ts +118 -0
- package/dist/autopilot/git/merge-manager.d.ts.map +1 -0
- package/dist/autopilot/git/merge-manager.js +304 -0
- package/dist/autopilot/git/merge-manager.js.map +1 -0
- package/dist/autopilot/git/worktree-manager.d.ts +128 -0
- package/dist/autopilot/git/worktree-manager.d.ts.map +1 -0
- package/dist/autopilot/git/worktree-manager.js +298 -0
- package/dist/autopilot/git/worktree-manager.js.map +1 -0
- package/dist/autopilot/index.d.ts +30 -0
- package/dist/autopilot/index.d.ts.map +1 -0
- package/dist/autopilot/index.js +55 -0
- package/dist/autopilot/index.js.map +1 -0
- package/dist/autopilot/sync/index.d.ts +7 -0
- package/dist/autopilot/sync/index.d.ts.map +1 -0
- package/dist/autopilot/sync/index.js +7 -0
- package/dist/autopilot/sync/index.js.map +1 -0
- package/dist/autopilot/sync/sync-manager.d.ts +168 -0
- package/dist/autopilot/sync/sync-manager.d.ts.map +1 -0
- package/dist/autopilot/sync/sync-manager.js +303 -0
- package/dist/autopilot/sync/sync-manager.js.map +1 -0
- package/dist/autopilot/types.d.ts +454 -0
- package/dist/autopilot/types.d.ts.map +1 -0
- package/dist/autopilot/types.js +26 -0
- package/dist/autopilot/types.js.map +1 -0
- package/dist/autopilot/utils/audit-logger.d.ts +176 -0
- package/dist/autopilot/utils/audit-logger.d.ts.map +1 -0
- package/dist/autopilot/utils/audit-logger.js +308 -0
- package/dist/autopilot/utils/audit-logger.js.map +1 -0
- package/dist/autopilot/utils/cost-tracker.d.ts +162 -0
- package/dist/autopilot/utils/cost-tracker.d.ts.map +1 -0
- package/dist/autopilot/utils/cost-tracker.js +269 -0
- package/dist/autopilot/utils/cost-tracker.js.map +1 -0
- package/dist/autopilot/utils/index.d.ts +9 -0
- package/dist/autopilot/utils/index.d.ts.map +1 -0
- package/dist/autopilot/utils/index.js +9 -0
- package/dist/autopilot/utils/index.js.map +1 -0
- package/dist/autopilot/utils/progress-reporter.d.ts +132 -0
- package/dist/autopilot/utils/progress-reporter.d.ts.map +1 -0
- package/dist/autopilot/utils/progress-reporter.js +290 -0
- package/dist/autopilot/utils/progress-reporter.js.map +1 -0
- package/dist/autopilot/worker/worker-pool.d.ts +179 -0
- package/dist/autopilot/worker/worker-pool.d.ts.map +1 -0
- package/dist/autopilot/worker/worker-pool.js +331 -0
- package/dist/autopilot/worker/worker-pool.js.map +1 -0
- package/dist/autopilot/worker/worker-session.d.ts +171 -0
- package/dist/autopilot/worker/worker-session.d.ts.map +1 -0
- package/dist/autopilot/worker/worker-session.js +295 -0
- package/dist/autopilot/worker/worker-session.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +4 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/core/epic.js +1 -1
- package/dist/tools/core/epic.js.map +1 -1
- package/dist/tools/core/lookup.d.ts.map +1 -1
- package/dist/tools/core/lookup.js +3 -2
- package/dist/tools/core/lookup.js.map +1 -1
- package/dist/tools/core/specification.js +1 -1
- package/dist/tools/core/specification.js.map +1 -1
- package/dist/tools/core/ticket.d.ts.map +1 -1
- package/dist/tools/core/ticket.js +4 -6
- package/dist/tools/core/ticket.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +60 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +4 -1
- package/dist/validation/index.js.map +1 -1
- package/package.json +8 -4
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failure Handler
|
|
3
|
+
*
|
|
4
|
+
* Retry logic, systemic failure detection, and pause decisions.
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import type { AutopilotConfig } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Failure category
|
|
10
|
+
*/
|
|
11
|
+
export type FailureCategory = 'transient' | 'rate_limit' | 'auth' | 'timeout' | 'validation' | 'implementation' | 'systemic' | 'unknown';
|
|
12
|
+
/**
|
|
13
|
+
* Failure info
|
|
14
|
+
*/
|
|
15
|
+
export interface FailureInfo {
|
|
16
|
+
ticketId: string;
|
|
17
|
+
workerId: number;
|
|
18
|
+
error: string;
|
|
19
|
+
category: FailureCategory;
|
|
20
|
+
attempt: number;
|
|
21
|
+
timestamp: Date;
|
|
22
|
+
retryable: boolean;
|
|
23
|
+
retryAfterMs?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Failure Handler Events
|
|
27
|
+
*/
|
|
28
|
+
export interface FailureHandlerEvents {
|
|
29
|
+
'failure:recorded': FailureInfo;
|
|
30
|
+
'failure:systemic': {
|
|
31
|
+
count: number;
|
|
32
|
+
recentFailures: FailureInfo[];
|
|
33
|
+
};
|
|
34
|
+
'failure:should_pause': {
|
|
35
|
+
reason: string;
|
|
36
|
+
};
|
|
37
|
+
'failure:retry_scheduled': {
|
|
38
|
+
ticketId: string;
|
|
39
|
+
retryAfterMs: number;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Failure Handler
|
|
44
|
+
*/
|
|
45
|
+
export declare class FailureHandler extends EventEmitter {
|
|
46
|
+
private failures;
|
|
47
|
+
private ticketAttempts;
|
|
48
|
+
private config;
|
|
49
|
+
constructor(config: AutopilotConfig | Partial<{
|
|
50
|
+
maxTicketRetries: number;
|
|
51
|
+
systemicThreshold: number;
|
|
52
|
+
systemicWindowMs: number;
|
|
53
|
+
}>);
|
|
54
|
+
/**
|
|
55
|
+
* Record a failure
|
|
56
|
+
*/
|
|
57
|
+
recordFailure(info: Omit<FailureInfo, 'attempt' | 'timestamp' | 'retryable' | 'category'>): FailureInfo;
|
|
58
|
+
/**
|
|
59
|
+
* Categorize error message
|
|
60
|
+
*/
|
|
61
|
+
private categorizeError;
|
|
62
|
+
/**
|
|
63
|
+
* Determine if failure is retryable
|
|
64
|
+
*/
|
|
65
|
+
private isRetryable;
|
|
66
|
+
/**
|
|
67
|
+
* Calculate retry delay based on category and attempt
|
|
68
|
+
*/
|
|
69
|
+
private calculateRetryDelay;
|
|
70
|
+
/**
|
|
71
|
+
* Detect systemic failures (many failures in short window)
|
|
72
|
+
* Excludes rate_limit failures as they are handled separately
|
|
73
|
+
*/
|
|
74
|
+
private detectSystemicFailure;
|
|
75
|
+
/**
|
|
76
|
+
* Get attempt count for a ticket
|
|
77
|
+
*/
|
|
78
|
+
getAttemptCount(ticketId: string): number;
|
|
79
|
+
/**
|
|
80
|
+
* Check if ticket should be retried
|
|
81
|
+
* Returns false if ticket has no recorded failures (nothing to retry)
|
|
82
|
+
*/
|
|
83
|
+
shouldRetry(ticketId: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Get last failure for a ticket
|
|
86
|
+
*/
|
|
87
|
+
getLastFailure(ticketId: string): FailureInfo | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Get all failures for a ticket
|
|
90
|
+
*/
|
|
91
|
+
getTicketFailures(ticketId: string): FailureInfo[];
|
|
92
|
+
/**
|
|
93
|
+
* Clear failures for a ticket (e.g., after success)
|
|
94
|
+
*/
|
|
95
|
+
clearTicketFailures(ticketId: string): void;
|
|
96
|
+
/**
|
|
97
|
+
* Get failure statistics
|
|
98
|
+
*/
|
|
99
|
+
getStats(): {
|
|
100
|
+
totalFailures: number;
|
|
101
|
+
byCategory: Record<FailureCategory, number>;
|
|
102
|
+
recentCount: number;
|
|
103
|
+
uniqueTickets: number;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Check if should pause due to failures
|
|
107
|
+
*/
|
|
108
|
+
shouldPause(): {
|
|
109
|
+
should: boolean;
|
|
110
|
+
reason?: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Reset all failure tracking
|
|
114
|
+
*/
|
|
115
|
+
reset(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Alias for reset - clear all failures
|
|
118
|
+
*/
|
|
119
|
+
clearAll(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Get total failure count
|
|
122
|
+
*/
|
|
123
|
+
getFailureCount(): number;
|
|
124
|
+
/**
|
|
125
|
+
* Get failures within a time window
|
|
126
|
+
*/
|
|
127
|
+
getRecentFailures(windowMs?: number): FailureInfo[];
|
|
128
|
+
/**
|
|
129
|
+
* Get failure rate (failures per minute) within a time window
|
|
130
|
+
*/
|
|
131
|
+
getFailureRate(windowMs?: number): number;
|
|
132
|
+
/**
|
|
133
|
+
* Update configuration
|
|
134
|
+
*/
|
|
135
|
+
updateConfig(updates: Partial<typeof this.config>): void;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create a failure handler
|
|
139
|
+
*/
|
|
140
|
+
export declare function createFailureHandler(config?: Partial<{
|
|
141
|
+
maxTicketRetries: number;
|
|
142
|
+
systemicThreshold: number;
|
|
143
|
+
systemicWindowMs: number;
|
|
144
|
+
}>): FailureHandler;
|
|
145
|
+
//# sourceMappingURL=failure-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failure-handler.d.ts","sourceRoot":"","sources":["../../../src/autopilot/core/failure-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failure Handler
|
|
3
|
+
*
|
|
4
|
+
* Retry logic, systemic failure detection, and pause decisions.
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
/**
|
|
8
|
+
* Failure Handler
|
|
9
|
+
*/
|
|
10
|
+
export class FailureHandler extends EventEmitter {
|
|
11
|
+
failures = [];
|
|
12
|
+
ticketAttempts = new Map();
|
|
13
|
+
config;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
super();
|
|
16
|
+
this.config = {
|
|
17
|
+
maxTicketRetries: config?.maxTicketRetries ?? 2,
|
|
18
|
+
systemicThreshold: ('systemicThreshold' in config ? config.systemicThreshold : undefined) ?? 5,
|
|
19
|
+
systemicWindowMs: ('systemicWindowMs' in config ? config.systemicWindowMs : undefined) ?? 5 * 60 * 1000,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Record a failure
|
|
24
|
+
*/
|
|
25
|
+
recordFailure(info) {
|
|
26
|
+
// Get current attempt count
|
|
27
|
+
const currentAttempt = (this.ticketAttempts.get(info.ticketId) || 0) + 1;
|
|
28
|
+
this.ticketAttempts.set(info.ticketId, currentAttempt);
|
|
29
|
+
// Categorize the failure
|
|
30
|
+
const category = this.categorizeError(info.error);
|
|
31
|
+
// Determine if retryable
|
|
32
|
+
const retryable = this.isRetryable(category, currentAttempt);
|
|
33
|
+
// Calculate retry delay if applicable
|
|
34
|
+
const retryAfterMs = retryable ? this.calculateRetryDelay(category, currentAttempt) : undefined;
|
|
35
|
+
const failure = {
|
|
36
|
+
...info,
|
|
37
|
+
category,
|
|
38
|
+
attempt: currentAttempt,
|
|
39
|
+
timestamp: new Date(),
|
|
40
|
+
retryable,
|
|
41
|
+
retryAfterMs,
|
|
42
|
+
};
|
|
43
|
+
this.failures.push(failure);
|
|
44
|
+
this.emit('failure:recorded', failure);
|
|
45
|
+
// Check for systemic failures
|
|
46
|
+
if (this.detectSystemicFailure()) {
|
|
47
|
+
const recentFailures = this.getRecentFailures();
|
|
48
|
+
this.emit('failure:systemic', {
|
|
49
|
+
count: recentFailures.length,
|
|
50
|
+
recentFailures,
|
|
51
|
+
});
|
|
52
|
+
this.emit('failure:should_pause', {
|
|
53
|
+
reason: `Systemic failure detected: ${recentFailures.length} failures in last 5 minutes`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Schedule retry if applicable
|
|
57
|
+
if (retryable && retryAfterMs) {
|
|
58
|
+
this.emit('failure:retry_scheduled', {
|
|
59
|
+
ticketId: info.ticketId,
|
|
60
|
+
retryAfterMs,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return failure;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Categorize error message
|
|
67
|
+
*/
|
|
68
|
+
categorizeError(error) {
|
|
69
|
+
const errorLower = error.toLowerCase();
|
|
70
|
+
// Rate limit
|
|
71
|
+
if (errorLower.includes('rate limit') ||
|
|
72
|
+
errorLower.includes('quota') ||
|
|
73
|
+
errorLower.includes('too many requests')) {
|
|
74
|
+
return 'rate_limit';
|
|
75
|
+
}
|
|
76
|
+
// Authentication
|
|
77
|
+
if (errorLower.includes('auth') ||
|
|
78
|
+
errorLower.includes('unauthorized') ||
|
|
79
|
+
errorLower.includes('not logged in')) {
|
|
80
|
+
return 'auth';
|
|
81
|
+
}
|
|
82
|
+
// Timeout
|
|
83
|
+
if (errorLower.includes('timeout') || errorLower.includes('timed out')) {
|
|
84
|
+
return 'timeout';
|
|
85
|
+
}
|
|
86
|
+
// Transient network errors
|
|
87
|
+
if (errorLower.includes('network') ||
|
|
88
|
+
errorLower.includes('econnrefused') ||
|
|
89
|
+
errorLower.includes('econnreset') ||
|
|
90
|
+
errorLower.includes('etimedout') ||
|
|
91
|
+
errorLower.includes('connection')) {
|
|
92
|
+
return 'transient';
|
|
93
|
+
}
|
|
94
|
+
// Validation failures (includes compilation errors)
|
|
95
|
+
if (errorLower.includes('test') ||
|
|
96
|
+
errorLower.includes('lint') ||
|
|
97
|
+
errorLower.includes('type error') ||
|
|
98
|
+
errorLower.includes('validation') ||
|
|
99
|
+
errorLower.includes('compile') ||
|
|
100
|
+
errorLower.includes('compilation')) {
|
|
101
|
+
return 'validation';
|
|
102
|
+
}
|
|
103
|
+
// Implementation errors (syntax, build failures)
|
|
104
|
+
if (errorLower.includes('syntax') ||
|
|
105
|
+
errorLower.includes('build')) {
|
|
106
|
+
return 'implementation';
|
|
107
|
+
}
|
|
108
|
+
return 'unknown';
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Determine if failure is retryable
|
|
112
|
+
*/
|
|
113
|
+
isRetryable(category, attempt) {
|
|
114
|
+
// Never retry auth failures
|
|
115
|
+
if (category === 'auth') {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
// Check attempt count
|
|
119
|
+
if (attempt >= this.config.maxTicketRetries) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
// Transient and timeout are always retryable if under limit
|
|
123
|
+
if (category === 'transient' || category === 'timeout') {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
// Rate limit is retryable after backoff
|
|
127
|
+
if (category === 'rate_limit') {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
// Validation and implementation might be retried once
|
|
131
|
+
if (category === 'validation' || category === 'implementation') {
|
|
132
|
+
return attempt < 2;
|
|
133
|
+
}
|
|
134
|
+
// Unknown errors get one retry
|
|
135
|
+
return attempt < 2;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Calculate retry delay based on category and attempt
|
|
139
|
+
*/
|
|
140
|
+
calculateRetryDelay(category, attempt) {
|
|
141
|
+
// Base delay with exponential backoff
|
|
142
|
+
const baseDelay = 1000; // 1 second
|
|
143
|
+
const maxDelay = 60000; // 1 minute
|
|
144
|
+
const exponentialDelay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
145
|
+
// Add jitter (10%)
|
|
146
|
+
const jitter = exponentialDelay * 0.1 * Math.random();
|
|
147
|
+
// Category-specific adjustments
|
|
148
|
+
switch (category) {
|
|
149
|
+
case 'rate_limit':
|
|
150
|
+
// Rate limits need longer backoff
|
|
151
|
+
return Math.min(exponentialDelay * 2 + 30000, 5 * 60 * 1000);
|
|
152
|
+
case 'transient':
|
|
153
|
+
// Quick retry for transient errors
|
|
154
|
+
return exponentialDelay + jitter;
|
|
155
|
+
case 'timeout':
|
|
156
|
+
// Moderate delay for timeouts
|
|
157
|
+
return exponentialDelay * 1.5 + jitter;
|
|
158
|
+
default:
|
|
159
|
+
return exponentialDelay + jitter;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Detect systemic failures (many failures in short window)
|
|
164
|
+
* Excludes rate_limit failures as they are handled separately
|
|
165
|
+
*/
|
|
166
|
+
detectSystemicFailure() {
|
|
167
|
+
const recentFailures = this.getRecentFailures();
|
|
168
|
+
// Exclude rate limit failures from systemic detection
|
|
169
|
+
const nonRateLimitFailures = recentFailures.filter(f => f.category !== 'rate_limit');
|
|
170
|
+
return nonRateLimitFailures.length >= this.config.systemicThreshold;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get attempt count for a ticket
|
|
174
|
+
*/
|
|
175
|
+
getAttemptCount(ticketId) {
|
|
176
|
+
return this.ticketAttempts.get(ticketId) || 0;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check if ticket should be retried
|
|
180
|
+
* Returns false if ticket has no recorded failures (nothing to retry)
|
|
181
|
+
*/
|
|
182
|
+
shouldRetry(ticketId) {
|
|
183
|
+
const attempts = this.getAttemptCount(ticketId);
|
|
184
|
+
// Must have at least one failure to retry, and be under the retry limit
|
|
185
|
+
if (attempts === 0) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
// Also check if the last failure was marked as retryable
|
|
189
|
+
const lastFailure = this.getLastFailure(ticketId);
|
|
190
|
+
return lastFailure?.retryable ?? false;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Get last failure for a ticket
|
|
194
|
+
*/
|
|
195
|
+
getLastFailure(ticketId) {
|
|
196
|
+
const ticketFailures = this.failures.filter(f => f.ticketId === ticketId);
|
|
197
|
+
return ticketFailures[ticketFailures.length - 1];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get all failures for a ticket
|
|
201
|
+
*/
|
|
202
|
+
getTicketFailures(ticketId) {
|
|
203
|
+
return this.failures.filter(f => f.ticketId === ticketId);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Clear failures for a ticket (e.g., after success)
|
|
207
|
+
*/
|
|
208
|
+
clearTicketFailures(ticketId) {
|
|
209
|
+
this.failures = this.failures.filter(f => f.ticketId !== ticketId);
|
|
210
|
+
this.ticketAttempts.delete(ticketId);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get failure statistics
|
|
214
|
+
*/
|
|
215
|
+
getStats() {
|
|
216
|
+
const byCategory = {
|
|
217
|
+
transient: 0,
|
|
218
|
+
rate_limit: 0,
|
|
219
|
+
auth: 0,
|
|
220
|
+
timeout: 0,
|
|
221
|
+
validation: 0,
|
|
222
|
+
implementation: 0,
|
|
223
|
+
systemic: 0,
|
|
224
|
+
unknown: 0,
|
|
225
|
+
};
|
|
226
|
+
const uniqueTickets = new Set();
|
|
227
|
+
for (const failure of this.failures) {
|
|
228
|
+
byCategory[failure.category]++;
|
|
229
|
+
uniqueTickets.add(failure.ticketId);
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
totalFailures: this.failures.length,
|
|
233
|
+
byCategory,
|
|
234
|
+
recentCount: this.getRecentFailures().length,
|
|
235
|
+
uniqueTickets: uniqueTickets.size,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Check if should pause due to failures
|
|
240
|
+
*/
|
|
241
|
+
shouldPause() {
|
|
242
|
+
// Check for auth failure - always pause
|
|
243
|
+
const authFailures = this.failures.filter(f => f.category === 'auth');
|
|
244
|
+
if (authFailures.length > 0) {
|
|
245
|
+
return { should: true, reason: 'Authentication failure' };
|
|
246
|
+
}
|
|
247
|
+
// Check for rate limit
|
|
248
|
+
const rateLimitFailures = this.getRecentFailures().filter(f => f.category === 'rate_limit');
|
|
249
|
+
if (rateLimitFailures.length >= 2) {
|
|
250
|
+
return { should: true, reason: 'Rate limit hit multiple times' };
|
|
251
|
+
}
|
|
252
|
+
// Check for systemic failure
|
|
253
|
+
if (this.detectSystemicFailure()) {
|
|
254
|
+
return {
|
|
255
|
+
should: true,
|
|
256
|
+
reason: `Systemic failure: ${this.getRecentFailures().length} failures in 5 minutes`,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return { should: false };
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Reset all failure tracking
|
|
263
|
+
*/
|
|
264
|
+
reset() {
|
|
265
|
+
this.failures = [];
|
|
266
|
+
this.ticketAttempts.clear();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Alias for reset - clear all failures
|
|
270
|
+
*/
|
|
271
|
+
clearAll() {
|
|
272
|
+
this.reset();
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get total failure count
|
|
276
|
+
*/
|
|
277
|
+
getFailureCount() {
|
|
278
|
+
return this.failures.length;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Get failures within a time window
|
|
282
|
+
*/
|
|
283
|
+
getRecentFailures(windowMs = this.config.systemicWindowMs) {
|
|
284
|
+
const cutoff = Date.now() - windowMs;
|
|
285
|
+
return this.failures.filter(f => f.timestamp.getTime() > cutoff);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Get failure rate (failures per minute) within a time window
|
|
289
|
+
*/
|
|
290
|
+
getFailureRate(windowMs = this.config.systemicWindowMs) {
|
|
291
|
+
const recentFailures = this.getRecentFailures(windowMs);
|
|
292
|
+
const windowMinutes = windowMs / (60 * 1000);
|
|
293
|
+
return recentFailures.length / windowMinutes;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Update configuration
|
|
297
|
+
*/
|
|
298
|
+
updateConfig(updates) {
|
|
299
|
+
Object.assign(this.config, updates);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Create a failure handler
|
|
304
|
+
*/
|
|
305
|
+
export function createFailureHandler(config) {
|
|
306
|
+
return new FailureHandler(config ?? {});
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=failure-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failure-handler.js","sourceRoot":"","sources":["../../../src/autopilot/core/failure-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limit Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles rate limit events from AI Provider and pauses workers.
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import type { RateLimitInfo } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Rate Limit Handler Events
|
|
10
|
+
*/
|
|
11
|
+
export interface RateLimitHandlerEvents {
|
|
12
|
+
'rate_limit:detected': RateLimitInfo;
|
|
13
|
+
'rate_limit:cleared': void;
|
|
14
|
+
'rate_limit:workers_should_pause': void;
|
|
15
|
+
'rate_limit:workers_can_resume': void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Rate Limit Handler
|
|
19
|
+
*/
|
|
20
|
+
export declare class RateLimitHandler extends EventEmitter {
|
|
21
|
+
private isRateLimited;
|
|
22
|
+
private rateLimitInfo?;
|
|
23
|
+
private autoResumeTimeout?;
|
|
24
|
+
private resumeCheckInterval?;
|
|
25
|
+
private subscribed;
|
|
26
|
+
/**
|
|
27
|
+
* Default backoff time when rate limited (5 minutes)
|
|
28
|
+
*/
|
|
29
|
+
private backoffMs;
|
|
30
|
+
/**
|
|
31
|
+
* Bound event handlers (stored to enable proper unsubscription)
|
|
32
|
+
*/
|
|
33
|
+
private boundHandleRateLimitHit;
|
|
34
|
+
private boundHandleRateLimitCleared;
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to AI Provider rate limit events
|
|
37
|
+
*/
|
|
38
|
+
subscribe(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Unsubscribe from AI Provider events
|
|
41
|
+
*/
|
|
42
|
+
unsubscribe(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Handle rate limit hit event
|
|
45
|
+
*/
|
|
46
|
+
private handleRateLimitHit;
|
|
47
|
+
/**
|
|
48
|
+
* Handle rate limit cleared event
|
|
49
|
+
*/
|
|
50
|
+
private handleRateLimitCleared;
|
|
51
|
+
/**
|
|
52
|
+
* Schedule a check to see if we can resume
|
|
53
|
+
*/
|
|
54
|
+
private scheduleResumeCheck;
|
|
55
|
+
/**
|
|
56
|
+
* Attempt to resume after backoff
|
|
57
|
+
*/
|
|
58
|
+
private attemptResume;
|
|
59
|
+
/**
|
|
60
|
+
* Clear rate limit state
|
|
61
|
+
*/
|
|
62
|
+
clearRateLimit(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Clear all timers
|
|
65
|
+
*/
|
|
66
|
+
private clearTimers;
|
|
67
|
+
/**
|
|
68
|
+
* Manually trigger rate limit (e.g., from failure detection)
|
|
69
|
+
*/
|
|
70
|
+
triggerRateLimit(message: string, backoffMs?: number): void;
|
|
71
|
+
/**
|
|
72
|
+
* Check if currently rate limited
|
|
73
|
+
*/
|
|
74
|
+
isCurrentlyRateLimited(): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Get rate limit info
|
|
77
|
+
*/
|
|
78
|
+
getRateLimitInfo(): RateLimitInfo | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Get estimated time until resume
|
|
81
|
+
*/
|
|
82
|
+
getEstimatedResumeTime(): Date | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Get remaining backoff time in ms
|
|
85
|
+
*/
|
|
86
|
+
getRemainingBackoffMs(): number;
|
|
87
|
+
/**
|
|
88
|
+
* Update backoff duration
|
|
89
|
+
*/
|
|
90
|
+
setBackoffMs(ms: number): void;
|
|
91
|
+
/**
|
|
92
|
+
* Get backoff duration
|
|
93
|
+
*/
|
|
94
|
+
getBackoffMs(): number;
|
|
95
|
+
/**
|
|
96
|
+
* Force resume (skip backoff)
|
|
97
|
+
*/
|
|
98
|
+
forceResume(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Destroy handler and cleanup
|
|
101
|
+
*/
|
|
102
|
+
destroy(): void;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Create a rate limit handler instance
|
|
106
|
+
*/
|
|
107
|
+
export declare function createRateLimitHandler(): RateLimitHandler;
|
|
108
|
+
//# sourceMappingURL=rate-limit-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit-handler.d.ts","sourceRoot":"","sources":["../../../src/autopilot/core/rate-limit-handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qBAAqB,EAAE,aAAa,CAAC;IACrC,oBAAoB,EAAE,IAAI,CAAC;IAC3B,iCAAiC,EAAE,IAAI,CAAC;IACxC,+BAA+B,EAAE,IAAI,CAAC;CACvC;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,iBAAiB,CAAC,CAAiB;IAC3C,OAAO,CAAC,mBAAmB,CAAC,CAAiB;IAC7C,OAAO,CAAC,UAAU,CAAkB;IAEpC;;OAEG;IACH,OAAO,CAAC,SAAS,CAAyB;IAE1C;;OAEG;IACH,OAAO,CAAC,uBAAuB,CAAsC;IACrE,OAAO,CAAC,2BAA2B,CAA0C;IAE7E;;OAEG;IACH,SAAS,IAAI,IAAI;IASjB;;OAEG;IACH,WAAW,IAAI,IAAI;IAUnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,aAAa;IAMrB;;OAEG;IACH,cAAc,IAAI,IAAI;IAatB;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAW3D;;OAEG;IACH,sBAAsB,IAAI,OAAO;IAIjC;;OAEG;IACH,gBAAgB,IAAI,aAAa,GAAG,SAAS;IAI7C;;OAEG;IACH,sBAAsB,IAAI,IAAI,GAAG,SAAS;IAI1C;;OAEG;IACH,qBAAqB,IAAI,MAAM;IAO/B;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB;;OAEG;IACH,OAAO,IAAI,IAAI;CAOhB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD"}
|