attocode 0.1.0 → 0.1.3
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/CHANGELOG.md +64 -1
- package/README.md +138 -10
- package/dist/src/agent.d.ts +75 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +700 -25
- package/dist/src/agent.js.map +1 -1
- package/dist/src/commands/agents-commands.d.ts +24 -0
- package/dist/src/commands/agents-commands.d.ts.map +1 -0
- package/dist/src/commands/agents-commands.js +284 -0
- package/dist/src/commands/agents-commands.js.map +1 -0
- package/dist/src/commands/handler.d.ts.map +1 -1
- package/dist/src/commands/handler.js +135 -19
- package/dist/src/commands/handler.js.map +1 -1
- package/dist/src/commands/init-commands.d.ts +35 -0
- package/dist/src/commands/init-commands.d.ts.map +1 -0
- package/dist/src/commands/init-commands.js +187 -0
- package/dist/src/commands/init-commands.js.map +1 -0
- package/dist/src/commands/skills-commands.d.ts +26 -0
- package/dist/src/commands/skills-commands.d.ts.map +1 -0
- package/dist/src/commands/skills-commands.js +309 -0
- package/dist/src/commands/skills-commands.js.map +1 -0
- package/dist/src/commands/types.d.ts +13 -2
- package/dist/src/commands/types.d.ts.map +1 -1
- package/dist/src/defaults.d.ts +29 -1
- package/dist/src/defaults.d.ts.map +1 -1
- package/dist/src/defaults.js +66 -0
- package/dist/src/defaults.js.map +1 -1
- package/dist/src/integrations/agent-registry.d.ts +68 -2
- package/dist/src/integrations/agent-registry.d.ts.map +1 -1
- package/dist/src/integrations/agent-registry.js +230 -23
- package/dist/src/integrations/agent-registry.js.map +1 -1
- package/dist/src/integrations/cancellation.d.ts +5 -0
- package/dist/src/integrations/cancellation.d.ts.map +1 -1
- package/dist/src/integrations/cancellation.js +7 -0
- package/dist/src/integrations/cancellation.js.map +1 -1
- package/dist/src/integrations/capabilities.d.ts +160 -0
- package/dist/src/integrations/capabilities.d.ts.map +1 -0
- package/dist/src/integrations/capabilities.js +426 -0
- package/dist/src/integrations/capabilities.js.map +1 -0
- package/dist/src/integrations/context-engineering.d.ts +6 -1
- package/dist/src/integrations/context-engineering.d.ts.map +1 -1
- package/dist/src/integrations/context-engineering.js +7 -0
- package/dist/src/integrations/context-engineering.js.map +1 -1
- package/dist/src/integrations/index.d.ts +12 -2
- package/dist/src/integrations/index.d.ts.map +1 -1
- package/dist/src/integrations/index.js +22 -2
- package/dist/src/integrations/index.js.map +1 -1
- package/dist/src/integrations/interactive-planning.d.ts +322 -0
- package/dist/src/integrations/interactive-planning.d.ts.map +1 -0
- package/dist/src/integrations/interactive-planning.js +655 -0
- package/dist/src/integrations/interactive-planning.js.map +1 -0
- package/dist/src/integrations/learning-store.d.ts +291 -0
- package/dist/src/integrations/learning-store.d.ts.map +1 -0
- package/dist/src/integrations/learning-store.js +640 -0
- package/dist/src/integrations/learning-store.js.map +1 -0
- package/dist/src/integrations/pending-plan.d.ts.map +1 -1
- package/dist/src/integrations/pending-plan.js +69 -10
- package/dist/src/integrations/pending-plan.js.map +1 -1
- package/dist/src/integrations/skill-executor.d.ts +113 -0
- package/dist/src/integrations/skill-executor.d.ts.map +1 -0
- package/dist/src/integrations/skill-executor.js +270 -0
- package/dist/src/integrations/skill-executor.js.map +1 -0
- package/dist/src/integrations/skills.d.ts +98 -7
- package/dist/src/integrations/skills.d.ts.map +1 -1
- package/dist/src/integrations/skills.js +210 -11
- package/dist/src/integrations/skills.js.map +1 -1
- package/dist/src/providers/circuit-breaker.d.ts +180 -0
- package/dist/src/providers/circuit-breaker.d.ts.map +1 -0
- package/dist/src/providers/circuit-breaker.js +349 -0
- package/dist/src/providers/circuit-breaker.js.map +1 -0
- package/dist/src/providers/fallback-chain.d.ts +194 -0
- package/dist/src/providers/fallback-chain.d.ts.map +1 -0
- package/dist/src/providers/fallback-chain.js +363 -0
- package/dist/src/providers/fallback-chain.js.map +1 -0
- package/dist/src/providers/llm-resilience.d.ts +126 -0
- package/dist/src/providers/llm-resilience.d.ts.map +1 -0
- package/dist/src/providers/llm-resilience.js +261 -0
- package/dist/src/providers/llm-resilience.js.map +1 -0
- package/dist/src/providers/resilient-provider.d.ts +124 -0
- package/dist/src/providers/resilient-provider.d.ts.map +1 -0
- package/dist/src/providers/resilient-provider.js +242 -0
- package/dist/src/providers/resilient-provider.js.map +1 -0
- package/dist/src/tricks/recursive-context.d.ts +296 -0
- package/dist/src/tricks/recursive-context.d.ts.map +1 -0
- package/dist/src/tricks/recursive-context.js +518 -0
- package/dist/src/tricks/recursive-context.js.map +1 -0
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +226 -29
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -1
- package/dist/src/tui/components/ApprovalDialog.js +1 -1
- package/dist/src/tui/components/ApprovalDialog.js.map +1 -1
- package/dist/src/tui/index.d.ts +1 -0
- package/dist/src/tui/index.d.ts.map +1 -1
- package/dist/src/tui/index.js +2 -0
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/transparency-aggregator.d.ts +100 -0
- package/dist/src/tui/transparency-aggregator.d.ts.map +1 -0
- package/dist/src/tui/transparency-aggregator.js +234 -0
- package/dist/src/tui/transparency-aggregator.js.map +1 -0
- package/dist/src/types.d.ts +155 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Fallback Chain
|
|
3
|
+
*
|
|
4
|
+
* Wraps multiple LLM providers with automatic failover.
|
|
5
|
+
* When the primary provider fails, requests are routed to secondary providers.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Priority-based provider ordering
|
|
9
|
+
* - Cooldown period for failed providers
|
|
10
|
+
* - Circuit breaker integration (optional)
|
|
11
|
+
* - Health tracking and metrics
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const chain = createFallbackChain({
|
|
16
|
+
* providers: [
|
|
17
|
+
* { provider: anthropicProvider, priority: 1 },
|
|
18
|
+
* { provider: openRouterProvider, priority: 2 },
|
|
19
|
+
* { provider: openAIProvider, priority: 3 },
|
|
20
|
+
* ],
|
|
21
|
+
* cooldownMs: 60000, // 1 minute cooldown after failure
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Uses first available provider, fails over automatically
|
|
25
|
+
* const response = await chain.chat(messages);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { ProviderError } from './types.js';
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// FALLBACK CHAIN
|
|
31
|
+
// =============================================================================
|
|
32
|
+
/**
|
|
33
|
+
* Provider fallback chain with automatic failover.
|
|
34
|
+
*/
|
|
35
|
+
export class FallbackChain {
|
|
36
|
+
name = 'fallback-chain';
|
|
37
|
+
defaultModel;
|
|
38
|
+
config;
|
|
39
|
+
healthMap = new Map();
|
|
40
|
+
listeners = [];
|
|
41
|
+
constructor(config) {
|
|
42
|
+
// Sort providers by priority
|
|
43
|
+
const sortedProviders = [...config.providers].sort((a, b) => a.priority - b.priority);
|
|
44
|
+
this.config = {
|
|
45
|
+
providers: sortedProviders,
|
|
46
|
+
cooldownMs: config.cooldownMs ?? 60000,
|
|
47
|
+
failureThreshold: config.failureThreshold ?? 3,
|
|
48
|
+
skipUnconfigured: config.skipUnconfigured ?? true,
|
|
49
|
+
onFallback: config.onFallback,
|
|
50
|
+
onHealthChange: config.onHealthChange,
|
|
51
|
+
};
|
|
52
|
+
// Use first provider's default model
|
|
53
|
+
this.defaultModel = sortedProviders[0]?.provider.defaultModel ?? 'unknown';
|
|
54
|
+
// Initialize health tracking
|
|
55
|
+
for (const { provider } of sortedProviders) {
|
|
56
|
+
this.healthMap.set(provider.name, {
|
|
57
|
+
name: provider.name,
|
|
58
|
+
healthy: true,
|
|
59
|
+
consecutiveFailures: 0,
|
|
60
|
+
totalRequests: 0,
|
|
61
|
+
totalFailures: 0,
|
|
62
|
+
successRate: 1,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check if any provider in the chain is configured.
|
|
68
|
+
*/
|
|
69
|
+
isConfigured() {
|
|
70
|
+
return this.config.providers.some(({ provider }) => provider.isConfigured());
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Send a chat request, falling back through providers on failure.
|
|
74
|
+
*/
|
|
75
|
+
async chat(messages, options) {
|
|
76
|
+
return this.executeWithFallback((provider) => provider.chat(messages, options), 'chat');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Send a chat request with tools, falling back through providers on failure.
|
|
80
|
+
*/
|
|
81
|
+
async chatWithTools(messages, options) {
|
|
82
|
+
return this.executeWithFallback((provider) => {
|
|
83
|
+
if (this.supportsTools(provider)) {
|
|
84
|
+
return provider.chatWithTools(messages, options);
|
|
85
|
+
}
|
|
86
|
+
// Fall back to regular chat if provider doesn't support tools
|
|
87
|
+
const simpleMessages = messages.map(m => ({
|
|
88
|
+
role: m.role,
|
|
89
|
+
content: typeof m.content === 'string' ? m.content : '[complex content]',
|
|
90
|
+
}));
|
|
91
|
+
return provider.chat(simpleMessages, options);
|
|
92
|
+
}, 'chatWithTools');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get health status of all providers.
|
|
96
|
+
*/
|
|
97
|
+
getHealth() {
|
|
98
|
+
return Array.from(this.healthMap.values());
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get health status of a specific provider.
|
|
102
|
+
*/
|
|
103
|
+
getProviderHealth(name) {
|
|
104
|
+
return this.healthMap.get(name);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Manually mark a provider as healthy (e.g., after fixing an issue).
|
|
108
|
+
*/
|
|
109
|
+
markHealthy(name) {
|
|
110
|
+
const health = this.healthMap.get(name);
|
|
111
|
+
if (health) {
|
|
112
|
+
health.healthy = true;
|
|
113
|
+
health.consecutiveFailures = 0;
|
|
114
|
+
health.cooldownUntil = undefined;
|
|
115
|
+
this.emit({ type: 'provider.cooldown.end', provider: name });
|
|
116
|
+
this.config.onHealthChange?.(name, health);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Manually mark a provider as unhealthy (e.g., for maintenance).
|
|
121
|
+
*/
|
|
122
|
+
markUnhealthy(name, duration) {
|
|
123
|
+
const health = this.healthMap.get(name);
|
|
124
|
+
if (health) {
|
|
125
|
+
health.healthy = false;
|
|
126
|
+
health.cooldownUntil = Date.now() + (duration ?? this.config.cooldownMs);
|
|
127
|
+
this.emit({ type: 'provider.cooldown.start', provider: name, until: health.cooldownUntil });
|
|
128
|
+
this.config.onHealthChange?.(name, health);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Subscribe to events.
|
|
133
|
+
*/
|
|
134
|
+
on(listener) {
|
|
135
|
+
this.listeners.push(listener);
|
|
136
|
+
return () => {
|
|
137
|
+
const idx = this.listeners.indexOf(listener);
|
|
138
|
+
if (idx >= 0)
|
|
139
|
+
this.listeners.splice(idx, 1);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// ===========================================================================
|
|
143
|
+
// PRIVATE METHODS
|
|
144
|
+
// ===========================================================================
|
|
145
|
+
async executeWithFallback(operation, operationName) {
|
|
146
|
+
const errors = [];
|
|
147
|
+
const availableProviders = this.getAvailableProviders();
|
|
148
|
+
if (availableProviders.length === 0) {
|
|
149
|
+
throw new ProviderError('No providers available in fallback chain (all in cooldown or unconfigured)', this.name, 'NOT_CONFIGURED');
|
|
150
|
+
}
|
|
151
|
+
for (let i = 0; i < availableProviders.length; i++) {
|
|
152
|
+
const { provider } = availableProviders[i];
|
|
153
|
+
const health = this.healthMap.get(provider.name);
|
|
154
|
+
health.totalRequests++;
|
|
155
|
+
const startTime = Date.now();
|
|
156
|
+
try {
|
|
157
|
+
const result = await operation(provider);
|
|
158
|
+
// Success - update health
|
|
159
|
+
this.recordSuccess(provider.name, Date.now() - startTime);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
164
|
+
errors.push({ provider: provider.name, error: err });
|
|
165
|
+
// Record failure
|
|
166
|
+
this.recordFailure(provider.name, err);
|
|
167
|
+
// Check if we should fall back
|
|
168
|
+
const nextProvider = availableProviders[i + 1];
|
|
169
|
+
if (nextProvider) {
|
|
170
|
+
this.emit({
|
|
171
|
+
type: 'provider.fallback',
|
|
172
|
+
from: provider.name,
|
|
173
|
+
to: nextProvider.provider.name,
|
|
174
|
+
error: err,
|
|
175
|
+
});
|
|
176
|
+
this.config.onFallback?.(provider.name, nextProvider.provider.name, err);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// All providers failed
|
|
181
|
+
this.emit({ type: 'chain.exhausted', errors });
|
|
182
|
+
throw new ProviderError(`All providers in fallback chain failed for ${operationName}. ` +
|
|
183
|
+
`Errors: ${errors.map(e => `${e.provider}: ${e.error.message}`).join('; ')}`, this.name, this.determineErrorCode(errors));
|
|
184
|
+
}
|
|
185
|
+
getAvailableProviders() {
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
return this.config.providers.filter(({ provider }) => {
|
|
188
|
+
// Check if configured
|
|
189
|
+
if (this.config.skipUnconfigured && !provider.isConfigured()) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
// Check health/cooldown
|
|
193
|
+
const health = this.healthMap.get(provider.name);
|
|
194
|
+
if (!health)
|
|
195
|
+
return true;
|
|
196
|
+
// Check if in cooldown
|
|
197
|
+
if (health.cooldownUntil && health.cooldownUntil > now) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
// Cooldown expired - reset health
|
|
201
|
+
if (health.cooldownUntil && health.cooldownUntil <= now) {
|
|
202
|
+
health.healthy = true;
|
|
203
|
+
health.cooldownUntil = undefined;
|
|
204
|
+
this.emit({ type: 'provider.cooldown.end', provider: provider.name });
|
|
205
|
+
}
|
|
206
|
+
return health.healthy;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
recordSuccess(name, duration) {
|
|
210
|
+
const health = this.healthMap.get(name);
|
|
211
|
+
if (!health)
|
|
212
|
+
return;
|
|
213
|
+
health.consecutiveFailures = 0;
|
|
214
|
+
health.healthy = true;
|
|
215
|
+
health.successRate = this.calculateSuccessRate(health);
|
|
216
|
+
this.emit({ type: 'provider.success', provider: name, duration });
|
|
217
|
+
this.config.onHealthChange?.(name, health);
|
|
218
|
+
}
|
|
219
|
+
recordFailure(name, error) {
|
|
220
|
+
const health = this.healthMap.get(name);
|
|
221
|
+
if (!health)
|
|
222
|
+
return;
|
|
223
|
+
health.consecutiveFailures++;
|
|
224
|
+
health.totalFailures++;
|
|
225
|
+
health.lastFailureAt = Date.now();
|
|
226
|
+
health.lastError = error.message;
|
|
227
|
+
health.successRate = this.calculateSuccessRate(health);
|
|
228
|
+
const willRetry = health.consecutiveFailures < this.config.failureThreshold;
|
|
229
|
+
this.emit({
|
|
230
|
+
type: 'provider.failure',
|
|
231
|
+
provider: name,
|
|
232
|
+
error,
|
|
233
|
+
willRetry,
|
|
234
|
+
});
|
|
235
|
+
// Check if we should trigger cooldown
|
|
236
|
+
if (health.consecutiveFailures >= this.config.failureThreshold) {
|
|
237
|
+
health.healthy = false;
|
|
238
|
+
health.cooldownUntil = Date.now() + this.config.cooldownMs;
|
|
239
|
+
this.emit({
|
|
240
|
+
type: 'provider.cooldown.start',
|
|
241
|
+
provider: name,
|
|
242
|
+
until: health.cooldownUntil,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
this.config.onHealthChange?.(name, health);
|
|
246
|
+
}
|
|
247
|
+
calculateSuccessRate(health) {
|
|
248
|
+
if (health.totalRequests === 0)
|
|
249
|
+
return 1;
|
|
250
|
+
return (health.totalRequests - health.totalFailures) / health.totalRequests;
|
|
251
|
+
}
|
|
252
|
+
supportsTools(provider) {
|
|
253
|
+
return 'chatWithTools' in provider && typeof provider.chatWithTools === 'function';
|
|
254
|
+
}
|
|
255
|
+
determineErrorCode(errors) {
|
|
256
|
+
// Check for specific error patterns
|
|
257
|
+
for (const { error } of errors) {
|
|
258
|
+
if (error instanceof ProviderError) {
|
|
259
|
+
// Propagate specific codes (prioritize rate limits and auth)
|
|
260
|
+
if (error.code === 'RATE_LIMITED')
|
|
261
|
+
return 'RATE_LIMITED';
|
|
262
|
+
if (error.code === 'AUTHENTICATION_FAILED')
|
|
263
|
+
return 'AUTHENTICATION_FAILED';
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Check if all errors are network-related
|
|
267
|
+
const allNetwork = errors.every(({ error }) => error.message.toLowerCase().includes('network') ||
|
|
268
|
+
error.message.toLowerCase().includes('timeout') ||
|
|
269
|
+
error.message.toLowerCase().includes('connection'));
|
|
270
|
+
if (allNetwork)
|
|
271
|
+
return 'NETWORK_ERROR';
|
|
272
|
+
return 'UNKNOWN';
|
|
273
|
+
}
|
|
274
|
+
emit(event) {
|
|
275
|
+
for (const listener of this.listeners) {
|
|
276
|
+
try {
|
|
277
|
+
listener(event);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Ignore listener errors
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// =============================================================================
|
|
286
|
+
// FACTORY FUNCTIONS
|
|
287
|
+
// =============================================================================
|
|
288
|
+
/**
|
|
289
|
+
* Create a fallback chain from providers.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* const chain = createFallbackChain({
|
|
294
|
+
* providers: [
|
|
295
|
+
* { provider: anthropicProvider, priority: 1 },
|
|
296
|
+
* { provider: openRouterProvider, priority: 2 },
|
|
297
|
+
* ],
|
|
298
|
+
* cooldownMs: 60000,
|
|
299
|
+
* onFallback: (from, to, error) => {
|
|
300
|
+
* console.log(`Falling back from ${from} to ${to}: ${error.message}`);
|
|
301
|
+
* },
|
|
302
|
+
* });
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
export function createFallbackChain(config) {
|
|
306
|
+
return new FallbackChain(config);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Create a fallback chain from the provider registry.
|
|
310
|
+
* Automatically includes all configured providers sorted by priority.
|
|
311
|
+
*/
|
|
312
|
+
export async function createFallbackChainFromRegistry(overrides) {
|
|
313
|
+
// Dynamic import to avoid circular dependency
|
|
314
|
+
const { listProviders, getProvider } = await import('./provider.js');
|
|
315
|
+
const available = listProviders().filter(p => p.configured);
|
|
316
|
+
const chainedProviders = [];
|
|
317
|
+
for (const { name, priority } of available) {
|
|
318
|
+
try {
|
|
319
|
+
const provider = await getProvider(name);
|
|
320
|
+
chainedProviders.push({ provider, priority });
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// Skip providers that fail to initialize
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (chainedProviders.length === 0) {
|
|
327
|
+
throw new ProviderError('No providers could be initialized for fallback chain', 'fallback-chain', 'NOT_CONFIGURED');
|
|
328
|
+
}
|
|
329
|
+
return createFallbackChain({
|
|
330
|
+
providers: chainedProviders,
|
|
331
|
+
...overrides,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
// =============================================================================
|
|
335
|
+
// UTILITIES
|
|
336
|
+
// =============================================================================
|
|
337
|
+
/**
|
|
338
|
+
* Format health status for display.
|
|
339
|
+
*/
|
|
340
|
+
export function formatHealthStatus(health) {
|
|
341
|
+
const lines = ['Provider Health Status:', ''];
|
|
342
|
+
for (const h of health) {
|
|
343
|
+
const status = h.healthy ? '✓' : '✗';
|
|
344
|
+
const rate = `${(h.successRate * 100).toFixed(1)}%`;
|
|
345
|
+
const cooldown = h.cooldownUntil
|
|
346
|
+
? ` (cooldown until ${new Date(h.cooldownUntil).toLocaleTimeString()})`
|
|
347
|
+
: '';
|
|
348
|
+
lines.push(` ${status} ${h.name}: ${rate} success, ${h.totalRequests} requests${cooldown}`);
|
|
349
|
+
if (h.lastError) {
|
|
350
|
+
lines.push(` Last error: ${h.lastError}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return lines.join('\n');
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Check if an error is from an exhausted fallback chain.
|
|
357
|
+
*/
|
|
358
|
+
export function isChainExhaustedError(error) {
|
|
359
|
+
return (error instanceof ProviderError &&
|
|
360
|
+
error.provider === 'fallback-chain' &&
|
|
361
|
+
error.message.includes('All providers in fallback chain failed'));
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=fallback-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fallback-chain.js","sourceRoot":"","sources":["../../../src/providers/fallback-chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Resilience Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides semantic-level resilience for LLM calls:
|
|
5
|
+
* - Empty response detection and retry
|
|
6
|
+
* - max_tokens truncation handling with continuation
|
|
7
|
+
* - Malformed response recovery
|
|
8
|
+
* - Graceful degradation with informative errors
|
|
9
|
+
*
|
|
10
|
+
* This complements resilient-fetch.ts (network level) with application-level resilience.
|
|
11
|
+
*/
|
|
12
|
+
import type { ChatResponse, Message } from '../types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for LLM resilience.
|
|
15
|
+
*/
|
|
16
|
+
export interface LLMResilienceConfig {
|
|
17
|
+
/** Maximum retries for empty responses (default: 2) */
|
|
18
|
+
maxEmptyRetries?: number;
|
|
19
|
+
/** Maximum continuation attempts for max_tokens (default: 3) */
|
|
20
|
+
maxContinuations?: number;
|
|
21
|
+
/** Whether to auto-continue on max_tokens (default: true) */
|
|
22
|
+
autoContinue?: boolean;
|
|
23
|
+
/** Minimum acceptable content length (default: 1) */
|
|
24
|
+
minContentLength?: number;
|
|
25
|
+
/** Callback for resilience events */
|
|
26
|
+
onEvent?: (event: LLMResilienceEvent) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Events emitted during resilience handling.
|
|
30
|
+
*/
|
|
31
|
+
export type LLMResilienceEvent = {
|
|
32
|
+
type: 'empty_response';
|
|
33
|
+
attempt: number;
|
|
34
|
+
maxAttempts: number;
|
|
35
|
+
} | {
|
|
36
|
+
type: 'empty_response_recovered';
|
|
37
|
+
attempt: number;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'empty_response_failed';
|
|
40
|
+
attempts: number;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'max_tokens_truncated';
|
|
43
|
+
continuation: number;
|
|
44
|
+
maxContinuations: number;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'max_tokens_continued';
|
|
47
|
+
continuation: number;
|
|
48
|
+
totalContent: number;
|
|
49
|
+
} | {
|
|
50
|
+
type: 'max_tokens_completed';
|
|
51
|
+
continuations: number;
|
|
52
|
+
totalContent: number;
|
|
53
|
+
} | {
|
|
54
|
+
type: 'max_tokens_limit_reached';
|
|
55
|
+
continuations: number;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'response_validated';
|
|
58
|
+
contentLength: number;
|
|
59
|
+
hasToolCalls: boolean;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Result of resilient LLM call.
|
|
63
|
+
*/
|
|
64
|
+
export interface ResilientLLMResult {
|
|
65
|
+
/** The validated response */
|
|
66
|
+
response: ChatResponse;
|
|
67
|
+
/** Number of empty response retries used */
|
|
68
|
+
emptyRetries: number;
|
|
69
|
+
/** Number of max_tokens continuations used */
|
|
70
|
+
continuations: number;
|
|
71
|
+
/** Whether response was modified by resilience layer */
|
|
72
|
+
wasRecovered: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Function type for making LLM calls.
|
|
76
|
+
*/
|
|
77
|
+
export type LLMCallFn = (messages: Message[]) => Promise<ChatResponse>;
|
|
78
|
+
/**
|
|
79
|
+
* Wrap an LLM call with semantic resilience.
|
|
80
|
+
*
|
|
81
|
+
* Handles:
|
|
82
|
+
* 1. Empty responses - retries with slight prompt modification
|
|
83
|
+
* 2. max_tokens truncation - auto-continues to get complete response
|
|
84
|
+
* 3. Response validation - ensures response meets minimum quality bar
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const result = await resilientLLMCall(
|
|
89
|
+
* messages,
|
|
90
|
+
* (msgs) => provider.chat(msgs, options),
|
|
91
|
+
* { onEvent: (e) => console.log('Resilience:', e) }
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function resilientLLMCall(messages: Message[], callFn: LLMCallFn, config?: LLMResilienceConfig): Promise<ResilientLLMResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Error thrown when LLM resilience cannot recover.
|
|
98
|
+
*/
|
|
99
|
+
export declare class LLMResilienceError extends Error {
|
|
100
|
+
readonly details: {
|
|
101
|
+
emptyRetries: number;
|
|
102
|
+
continuations: number;
|
|
103
|
+
};
|
|
104
|
+
constructor(message: string, details: {
|
|
105
|
+
emptyRetries: number;
|
|
106
|
+
continuations: number;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check if an error is an LLM resilience error.
|
|
111
|
+
*/
|
|
112
|
+
export declare function isLLMResilienceError(error: unknown): error is LLMResilienceError;
|
|
113
|
+
/**
|
|
114
|
+
* Validate that a response meets minimum quality criteria.
|
|
115
|
+
*/
|
|
116
|
+
export declare function validateResponse(response: ChatResponse, options?: {
|
|
117
|
+
minContentLength?: number;
|
|
118
|
+
}): {
|
|
119
|
+
valid: boolean;
|
|
120
|
+
issues: string[];
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Create a response summary for logging/debugging.
|
|
124
|
+
*/
|
|
125
|
+
export declare function summarizeResponse(response: ChatResponse): string;
|
|
126
|
+
//# sourceMappingURL=llm-resilience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-resilience.d.ts","sourceRoot":"","sources":["../../../src/providers/llm-resilience.ts"],"names":[],"mappings":"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"}
|