@bernierllc/ai-provider-anthropic 1.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.
@@ -0,0 +1,337 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code only within the scope of the project it was delivered for.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AnthropicProvider = void 0;
14
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
15
+ const ai_provider_core_1 = require("@bernierllc/ai-provider-core");
16
+ const model_registry_1 = require("./models/model-registry");
17
+ const message_conversion_1 = require("./utils/message-conversion");
18
+ const error_handling_1 = require("./utils/error-handling");
19
+ /**
20
+ * Anthropic Provider Implementation
21
+ * Concrete implementation of the AI provider interface for Anthropic's Claude API
22
+ */
23
+ class AnthropicProvider extends ai_provider_core_1.AIProvider {
24
+ constructor(config) {
25
+ super(config);
26
+ this.client = new sdk_1.default({
27
+ apiKey: config.apiKey,
28
+ baseURL: config.baseURL,
29
+ timeout: config.timeout || 60000,
30
+ maxRetries: config.maxRetries || 3
31
+ });
32
+ }
33
+ // ============================================
34
+ // CORE OPERATIONS
35
+ // ============================================
36
+ /**
37
+ * Generate text completion using Anthropic Claude API
38
+ */
39
+ async complete(request) {
40
+ // Validate request
41
+ const validation = this.validateRequest(request);
42
+ if (!validation.isValid) {
43
+ return {
44
+ success: false,
45
+ error: validation.errors.join(', ')
46
+ };
47
+ }
48
+ // Validate messages
49
+ const messageValidation = (0, message_conversion_1.validateMessages)(request.messages);
50
+ if (!messageValidation.isValid) {
51
+ return {
52
+ success: false,
53
+ error: messageValidation.error
54
+ };
55
+ }
56
+ try {
57
+ // Convert messages to Anthropic format
58
+ const { system, messages } = (0, message_conversion_1.convertMessagesToAnthropicFormat)(request.messages);
59
+ const completion = await this.client.messages.create({
60
+ model: request.model || this.config.defaultModel || 'claude-3-opus-20240229',
61
+ system,
62
+ messages,
63
+ max_tokens: request.maxTokens || 4096,
64
+ temperature: request.temperature,
65
+ top_p: request.topP,
66
+ stop_sequences: request.stop,
67
+ metadata: request.user ? {
68
+ user_id: request.user
69
+ } : undefined
70
+ });
71
+ // Extract content from response
72
+ const content = completion.content
73
+ .filter((block) => block.type === 'text')
74
+ .map(block => block.text)
75
+ .join('');
76
+ return {
77
+ success: true,
78
+ content,
79
+ finishReason: this.mapStopReason(completion.stop_reason),
80
+ usage: {
81
+ promptTokens: completion.usage.input_tokens,
82
+ completionTokens: completion.usage.output_tokens,
83
+ totalTokens: completion.usage.input_tokens + completion.usage.output_tokens
84
+ },
85
+ model: completion.model,
86
+ metadata: {
87
+ id: completion.id,
88
+ type: completion.type,
89
+ role: completion.role,
90
+ stopSequence: completion.stop_sequence
91
+ }
92
+ };
93
+ }
94
+ catch (error) {
95
+ const aiError = (0, error_handling_1.handleAnthropicError)(error);
96
+ return {
97
+ success: false,
98
+ error: aiError.message
99
+ };
100
+ }
101
+ }
102
+ /**
103
+ * Generate streaming text completion
104
+ */
105
+ async *streamComplete(request) {
106
+ const validation = this.validateRequest(request);
107
+ if (!validation.isValid) {
108
+ throw new Error(validation.errors.join(', '));
109
+ }
110
+ const messageValidation = (0, message_conversion_1.validateMessages)(request.messages);
111
+ if (!messageValidation.isValid) {
112
+ throw new Error(messageValidation.error || 'Invalid messages');
113
+ }
114
+ try {
115
+ const { system, messages } = (0, message_conversion_1.convertMessagesToAnthropicFormat)(request.messages);
116
+ const stream = this.client.messages.stream({
117
+ model: request.model || this.config.defaultModel || 'claude-3-opus-20240229',
118
+ system,
119
+ messages,
120
+ max_tokens: request.maxTokens || 4096,
121
+ temperature: request.temperature,
122
+ top_p: request.topP,
123
+ stop_sequences: request.stop
124
+ });
125
+ let finalUsage;
126
+ let finalStopReason;
127
+ for await (const event of stream) {
128
+ if (event.type === 'content_block_delta') {
129
+ const delta = event.delta;
130
+ if (delta.type === 'text_delta') {
131
+ yield {
132
+ delta: delta.text,
133
+ finishReason: undefined
134
+ };
135
+ }
136
+ }
137
+ if (event.type === 'message_delta') {
138
+ // Capture usage information from message_delta event
139
+ const usage = event.usage;
140
+ if (usage) {
141
+ finalUsage = {
142
+ promptTokens: usage.input_tokens,
143
+ completionTokens: usage.output_tokens,
144
+ totalTokens: usage.input_tokens + usage.output_tokens
145
+ };
146
+ }
147
+ }
148
+ if (event.type === 'message_stop') {
149
+ // Capture stop reason
150
+ finalStopReason = null; // message_stop doesn't provide stop_reason directly
151
+ yield {
152
+ delta: '',
153
+ finishReason: this.mapStopReason(finalStopReason),
154
+ usage: finalUsage
155
+ };
156
+ }
157
+ }
158
+ }
159
+ catch (error) {
160
+ throw (0, error_handling_1.handleAnthropicError)(error);
161
+ }
162
+ }
163
+ /**
164
+ * Generate embeddings (Anthropic doesn't provide embeddings API)
165
+ * Returns error indicating feature not supported
166
+ */
167
+ generateEmbeddings(_request) {
168
+ return Promise.resolve({
169
+ success: false,
170
+ error: 'Anthropic does not provide an embeddings API. Use OpenAI provider for embeddings.'
171
+ });
172
+ }
173
+ /**
174
+ * Check content moderation (Anthropic doesn't provide moderation API)
175
+ * Returns success with no flags (Claude has built-in safety)
176
+ */
177
+ moderate(_content) {
178
+ // Claude has built-in safety features
179
+ // We can return success with no flags as Claude refuses unsafe content
180
+ return Promise.resolve({
181
+ success: true,
182
+ flagged: false,
183
+ categories: {},
184
+ categoryScores: {}
185
+ });
186
+ }
187
+ /**
188
+ * Get available Anthropic models
189
+ */
190
+ getAvailableModels() {
191
+ // Anthropic doesn't provide a models list endpoint
192
+ // Return cached model information
193
+ return Promise.resolve(model_registry_1.ClaudeModelRegistry.getAllModels());
194
+ }
195
+ /**
196
+ * Check Anthropic API health
197
+ */
198
+ async checkHealth() {
199
+ const startTime = Date.now();
200
+ try {
201
+ // Simple test request with minimal tokens
202
+ await this.client.messages.create({
203
+ model: 'claude-3-haiku-20240307',
204
+ max_tokens: 10,
205
+ messages: [
206
+ { role: 'user', content: 'Hi' }
207
+ ]
208
+ });
209
+ return {
210
+ status: 'healthy',
211
+ latency: Date.now() - startTime,
212
+ lastChecked: new Date()
213
+ };
214
+ }
215
+ catch (error) {
216
+ return {
217
+ status: 'unavailable',
218
+ latency: Date.now() - startTime,
219
+ lastChecked: new Date(),
220
+ details: {
221
+ error: error instanceof Error ? error.message : 'Unknown error'
222
+ }
223
+ };
224
+ }
225
+ }
226
+ // ============================================
227
+ // ANTHROPIC-SPECIFIC FEATURES
228
+ // ============================================
229
+ /**
230
+ * Extended context completion (200K tokens for all Claude 3 models)
231
+ */
232
+ async extendedContextCompletion(request) {
233
+ // All Claude 3 models support 200K context window
234
+ const model = request.model || 'claude-3-opus-20240229';
235
+ return this.complete({
236
+ ...request,
237
+ model
238
+ });
239
+ }
240
+ /**
241
+ * Vision analysis (All Claude 3 models support vision)
242
+ */
243
+ async analyzeImage(imageData, prompt, model = 'claude-3-opus-20240229', maxTokens, temperature) {
244
+ try {
245
+ // Convert image to base64 if needed
246
+ const base64Image = Buffer.isBuffer(imageData)
247
+ ? imageData.toString('base64')
248
+ : imageData;
249
+ const completion = await this.client.messages.create({
250
+ model,
251
+ max_tokens: maxTokens || 4096,
252
+ temperature,
253
+ messages: [
254
+ {
255
+ role: 'user',
256
+ content: [
257
+ {
258
+ type: 'image',
259
+ source: {
260
+ type: 'base64',
261
+ media_type: 'image/jpeg',
262
+ data: base64Image
263
+ }
264
+ },
265
+ {
266
+ type: 'text',
267
+ text: prompt
268
+ }
269
+ ]
270
+ }
271
+ ]
272
+ });
273
+ const content = completion.content
274
+ .filter((block) => block.type === 'text')
275
+ .map(block => block.text)
276
+ .join('');
277
+ return {
278
+ success: true,
279
+ content,
280
+ finishReason: this.mapStopReason(completion.stop_reason),
281
+ usage: {
282
+ promptTokens: completion.usage.input_tokens,
283
+ completionTokens: completion.usage.output_tokens,
284
+ totalTokens: completion.usage.input_tokens + completion.usage.output_tokens
285
+ },
286
+ model: completion.model
287
+ };
288
+ }
289
+ catch (error) {
290
+ const aiError = (0, error_handling_1.handleAnthropicError)(error);
291
+ return {
292
+ success: false,
293
+ error: aiError.message
294
+ };
295
+ }
296
+ }
297
+ // ============================================
298
+ // COST ESTIMATION (OVERRIDE)
299
+ // ============================================
300
+ /**
301
+ * Estimate cost using Anthropic pricing
302
+ */
303
+ estimateCost(request) {
304
+ const model = request.model || this.config.defaultModel || 'claude-3-opus-20240229';
305
+ const pricing = model_registry_1.ClaudeModelRegistry.getModelPricing(model);
306
+ const inputTokens = this.estimateTokens(request.messages.map(m => m.content).join(' '));
307
+ const outputTokens = request.maxTokens || 4096;
308
+ const inputCost = (inputTokens / 1000000) * pricing.inputPrice;
309
+ const outputCost = (outputTokens / 1000000) * pricing.outputPrice;
310
+ return {
311
+ inputTokens,
312
+ outputTokens,
313
+ totalTokens: inputTokens + outputTokens,
314
+ estimatedCostUSD: inputCost + outputCost,
315
+ currency: 'USD'
316
+ };
317
+ }
318
+ // ============================================
319
+ // PRIVATE METHODS
320
+ // ============================================
321
+ /**
322
+ * Map Anthropic stop reason to unified format
323
+ */
324
+ mapStopReason(stopReason) {
325
+ switch (stopReason) {
326
+ case 'end_turn':
327
+ return 'stop';
328
+ case 'max_tokens':
329
+ return 'length';
330
+ case 'stop_sequence':
331
+ return 'stop';
332
+ default:
333
+ return 'stop';
334
+ }
335
+ }
336
+ }
337
+ exports.AnthropicProvider = AnthropicProvider;
@@ -0,0 +1,4 @@
1
+ export { AnthropicProvider } from './AnthropicProvider';
2
+ export * from './types';
3
+ export { ClaudeModelRegistry } from './models/model-registry';
4
+ export * from './utils';
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code only within the scope of the project it was delivered for.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.ClaudeModelRegistry = exports.AnthropicProvider = void 0;
25
+ // Main provider class
26
+ var AnthropicProvider_1 = require("./AnthropicProvider");
27
+ Object.defineProperty(exports, "AnthropicProvider", { enumerable: true, get: function () { return AnthropicProvider_1.AnthropicProvider; } });
28
+ // Types
29
+ __exportStar(require("./types"), exports);
30
+ // Models
31
+ var model_registry_1 = require("./models/model-registry");
32
+ Object.defineProperty(exports, "ClaudeModelRegistry", { enumerable: true, get: function () { return model_registry_1.ClaudeModelRegistry; } });
33
+ // Utilities
34
+ __exportStar(require("./utils"), exports);
@@ -0,0 +1,31 @@
1
+ import { ModelInfo } from '@bernierllc/ai-provider-core';
2
+ /**
3
+ * Claude 3 Model Registry
4
+ * Contains information about all available Claude models
5
+ */
6
+ export declare class ClaudeModelRegistry {
7
+ private static models;
8
+ /**
9
+ * Initialize the model registry with Claude 3 models
10
+ */
11
+ static initialize(): void;
12
+ /**
13
+ * Get a specific model by ID
14
+ */
15
+ static getModel(modelId: string): ModelInfo | undefined;
16
+ /**
17
+ * Get all available models
18
+ */
19
+ static getAllModels(): ModelInfo[];
20
+ /**
21
+ * Check if a model ID is valid
22
+ */
23
+ static isValidModel(modelId: string): boolean;
24
+ /**
25
+ * Get pricing for a specific model
26
+ */
27
+ static getModelPricing(modelId: string): {
28
+ inputPrice: number;
29
+ outputPrice: number;
30
+ };
31
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code only within the scope of the project it was delivered for.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ClaudeModelRegistry = void 0;
11
+ /**
12
+ * Claude 3 Model Registry
13
+ * Contains information about all available Claude models
14
+ */
15
+ class ClaudeModelRegistry {
16
+ /**
17
+ * Initialize the model registry with Claude 3 models
18
+ */
19
+ static initialize() {
20
+ const models = [
21
+ {
22
+ id: 'claude-3-opus-20240229',
23
+ name: 'Claude 3 Opus',
24
+ contextWindow: 200000,
25
+ maxOutputTokens: 4096,
26
+ pricing: {
27
+ inputPricePerToken: 15 / 1000000,
28
+ outputPricePerToken: 75 / 1000000,
29
+ currency: 'USD'
30
+ },
31
+ capabilities: ['chat', 'completion', 'vision', 'extended-context', 'analysis'],
32
+ description: 'Most capable Claude model for complex tasks with superior reasoning'
33
+ },
34
+ {
35
+ id: 'claude-3-sonnet-20240229',
36
+ name: 'Claude 3 Sonnet',
37
+ contextWindow: 200000,
38
+ maxOutputTokens: 4096,
39
+ pricing: {
40
+ inputPricePerToken: 3 / 1000000,
41
+ outputPricePerToken: 15 / 1000000,
42
+ currency: 'USD'
43
+ },
44
+ capabilities: ['chat', 'completion', 'vision', 'extended-context'],
45
+ description: 'Balanced performance and speed for most tasks'
46
+ },
47
+ {
48
+ id: 'claude-3-haiku-20240307',
49
+ name: 'Claude 3 Haiku',
50
+ contextWindow: 200000,
51
+ maxOutputTokens: 4096,
52
+ pricing: {
53
+ inputPricePerToken: 0.25 / 1000000,
54
+ outputPricePerToken: 1.25 / 1000000,
55
+ currency: 'USD'
56
+ },
57
+ capabilities: ['chat', 'completion', 'vision', 'extended-context'],
58
+ description: 'Fastest and most compact model for quick responses'
59
+ }
60
+ ];
61
+ models.forEach(model => {
62
+ this.models.set(model.id, model);
63
+ });
64
+ }
65
+ /**
66
+ * Get a specific model by ID
67
+ */
68
+ static getModel(modelId) {
69
+ if (this.models.size === 0) {
70
+ this.initialize();
71
+ }
72
+ return this.models.get(modelId);
73
+ }
74
+ /**
75
+ * Get all available models
76
+ */
77
+ static getAllModels() {
78
+ if (this.models.size === 0) {
79
+ this.initialize();
80
+ }
81
+ return Array.from(this.models.values());
82
+ }
83
+ /**
84
+ * Check if a model ID is valid
85
+ */
86
+ static isValidModel(modelId) {
87
+ if (this.models.size === 0) {
88
+ this.initialize();
89
+ }
90
+ return this.models.has(modelId);
91
+ }
92
+ /**
93
+ * Get pricing for a specific model
94
+ */
95
+ static getModelPricing(modelId) {
96
+ const model = this.getModel(modelId);
97
+ if (model?.pricing) {
98
+ return {
99
+ inputPrice: model.pricing.inputPricePerToken * 1000000,
100
+ outputPrice: model.pricing.outputPricePerToken * 1000000
101
+ };
102
+ }
103
+ // Default to Sonnet pricing
104
+ return {
105
+ inputPrice: 3,
106
+ outputPrice: 15
107
+ };
108
+ }
109
+ }
110
+ exports.ClaudeModelRegistry = ClaudeModelRegistry;
111
+ ClaudeModelRegistry.models = new Map();
112
+ // Initialize on module load
113
+ ClaudeModelRegistry.initialize();
@@ -0,0 +1,46 @@
1
+ import { AIProviderConfig, CompletionRequest } from '@bernierllc/ai-provider-core';
2
+ /**
3
+ * Anthropic Provider Configuration
4
+ */
5
+ export interface AnthropicProviderConfig extends AIProviderConfig {
6
+ providerName: 'anthropic';
7
+ }
8
+ /**
9
+ * Anthropic Extended Context Request
10
+ */
11
+ export interface AnthropicExtendedContextRequest extends CompletionRequest {
12
+ enableExtendedContext?: boolean;
13
+ }
14
+ /**
15
+ * Anthropic Vision Request
16
+ */
17
+ export interface AnthropicVisionRequest {
18
+ imageData: string | Buffer;
19
+ prompt: string;
20
+ model?: string;
21
+ maxTokens?: number;
22
+ temperature?: number;
23
+ }
24
+ /**
25
+ * Anthropic Message Content Block
26
+ */
27
+ export interface AnthropicMessageContent {
28
+ type: 'text' | 'image';
29
+ text?: string;
30
+ source?: {
31
+ type: 'base64';
32
+ media_type: string;
33
+ data: string;
34
+ };
35
+ }
36
+ /**
37
+ * Anthropic Message Format (Internal)
38
+ */
39
+ export interface AnthropicMessage {
40
+ role: 'user' | 'assistant';
41
+ content: string | AnthropicMessageContent[];
42
+ }
43
+ /**
44
+ * Anthropic Stop Reason
45
+ */
46
+ export type AnthropicStopReason = 'end_turn' | 'max_tokens' | 'stop_sequence' | null;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code only within the scope of the project it was delivered for.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from './anthropic-types';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code only within the scope of the project it was delivered for.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ __exportStar(require("./anthropic-types"), exports);
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Handle Anthropic API errors and convert to provider error format
3
+ */
4
+ export declare function handleAnthropicError(error: unknown): Error;
5
+ /**
6
+ * Check if error is retryable
7
+ */
8
+ export declare function isRetryableError(error: unknown): boolean;
9
+ /**
10
+ * Get retry delay from error (if available)
11
+ */
12
+ export declare function getRetryDelay(error: unknown): number | undefined;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code only within the scope of the project it was delivered for.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.handleAnthropicError = handleAnthropicError;
14
+ exports.isRetryableError = isRetryableError;
15
+ exports.getRetryDelay = getRetryDelay;
16
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
17
+ /**
18
+ * Handle Anthropic API errors and convert to provider error format
19
+ */
20
+ function handleAnthropicError(error) {
21
+ if (error instanceof sdk_1.default.APIError) {
22
+ const status = error.status || 'unknown';
23
+ const message = `Anthropic API Error (${status}): ${error.message}`;
24
+ const providerError = new Error(message);
25
+ providerError.name = 'AnthropicAPIError';
26
+ return providerError;
27
+ }
28
+ if (error instanceof sdk_1.default.AuthenticationError) {
29
+ const providerError = new Error('Anthropic authentication failed. Check your API key.');
30
+ providerError.name = 'AnthropicAuthError';
31
+ return providerError;
32
+ }
33
+ if (error instanceof sdk_1.default.RateLimitError) {
34
+ const providerError = new Error('Anthropic rate limit exceeded. Please retry after a delay.');
35
+ providerError.name = 'AnthropicRateLimitError';
36
+ return providerError;
37
+ }
38
+ if (error instanceof Error) {
39
+ return error;
40
+ }
41
+ return new Error(`Unknown Anthropic error: ${String(error)}`);
42
+ }
43
+ /**
44
+ * Check if error is retryable
45
+ */
46
+ function isRetryableError(error) {
47
+ if (error instanceof sdk_1.default.APIError) {
48
+ // Retry on 5xx errors and rate limits
49
+ const status = error.status || 0;
50
+ return status >= 500 || status === 429;
51
+ }
52
+ if (error instanceof sdk_1.default.RateLimitError) {
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ /**
58
+ * Get retry delay from error (if available)
59
+ */
60
+ function getRetryDelay(error) {
61
+ if (error instanceof sdk_1.default.RateLimitError) {
62
+ // Check for Retry-After header if available
63
+ // Default to 1 second if not specified
64
+ return 1000;
65
+ }
66
+ return undefined;
67
+ }