converse-mcp-server 2.3.1 → 2.4.1

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.
Files changed (42) hide show
  1. package/README.md +771 -738
  2. package/docs/API.md +10 -1
  3. package/docs/PROVIDERS.md +8 -4
  4. package/package.json +12 -12
  5. package/src/async/asyncJobStore.js +82 -52
  6. package/src/async/eventBus.js +25 -20
  7. package/src/async/fileCache.js +121 -40
  8. package/src/async/jobRunner.js +65 -39
  9. package/src/async/providerStreamNormalizer.js +203 -117
  10. package/src/config.js +374 -102
  11. package/src/continuationStore.js +32 -24
  12. package/src/index.js +45 -25
  13. package/src/prompts/helpPrompt.js +328 -305
  14. package/src/providers/anthropic.js +303 -119
  15. package/src/providers/codex.js +103 -45
  16. package/src/providers/deepseek.js +24 -8
  17. package/src/providers/google.js +337 -93
  18. package/src/providers/index.js +1 -1
  19. package/src/providers/interface.js +16 -11
  20. package/src/providers/mistral.js +179 -69
  21. package/src/providers/openai-compatible.js +231 -94
  22. package/src/providers/openai.js +1094 -914
  23. package/src/providers/openrouter-endpoints-client.js +220 -216
  24. package/src/providers/openrouter.js +426 -381
  25. package/src/providers/xai.js +153 -56
  26. package/src/resources/helpResource.js +70 -67
  27. package/src/router.js +95 -67
  28. package/src/services/summarizationService.js +51 -24
  29. package/src/systemPrompts.js +89 -89
  30. package/src/tools/cancelJob.js +31 -19
  31. package/src/tools/chat.js +997 -883
  32. package/src/tools/checkStatus.js +86 -65
  33. package/src/tools/consensus.js +400 -234
  34. package/src/tools/index.js +39 -16
  35. package/src/transport/httpTransport.js +82 -55
  36. package/src/utils/contextProcessor.js +54 -37
  37. package/src/utils/errorHandler.js +95 -45
  38. package/src/utils/fileValidator.js +107 -98
  39. package/src/utils/formatStatus.js +122 -64
  40. package/src/utils/logger.js +459 -449
  41. package/src/utils/pathUtils.js +2 -2
  42. package/src/utils/tokenLimiter.js +216 -216
@@ -26,8 +26,23 @@ const SUPPORTED_MODELS = {
26
26
  minThinkingTokens: 1024,
27
27
  maxThinkingTokens: 32000,
28
28
  timeout: 300000,
29
- description: 'Claude Opus 4.1 - Highest level of intelligence and capability with extended thinking',
30
- aliases: ['claude-opus-4-1', 'claude-4.1-opus', 'claude-4-1-opus', 'opus-4.1', 'opus-4-1', 'claude-4-opus', 'opus-4', 'opus', 'claude-opus', 'claude-opus-4', 'opus4', 'opus4.1', 'claude-opus-4.1']
29
+ description:
30
+ 'Claude Opus 4.1 - Highest level of intelligence and capability with extended thinking',
31
+ aliases: [
32
+ 'claude-opus-4-1',
33
+ 'claude-4.1-opus',
34
+ 'claude-4-1-opus',
35
+ 'opus-4.1',
36
+ 'opus-4-1',
37
+ 'claude-4-opus',
38
+ 'opus-4',
39
+ 'opus',
40
+ 'claude-opus',
41
+ 'claude-opus-4',
42
+ 'opus4',
43
+ 'opus4.1',
44
+ 'claude-opus-4.1',
45
+ ],
31
46
  },
32
47
  'claude-sonnet-4-5-20250929': {
33
48
  modelName: 'claude-sonnet-4-5-20250929',
@@ -43,8 +58,17 @@ const SUPPORTED_MODELS = {
43
58
  maxThinkingTokens: 64000,
44
59
  timeout: 300000,
45
60
  supports1MContext: true, // Beta 1M context support
46
- description: 'Claude Sonnet 4.5 - Latest Sonnet with enhanced intelligence and optional 1M context',
47
- aliases: ['claude-4.5-sonnet', 'sonnet-4.5', 'claude-sonnet-4.5', 'sonnet4.5', 'claude-sonnet-4-5', 'sonnet', 'claude-sonnet']
61
+ description:
62
+ 'Claude Sonnet 4.5 - Latest Sonnet with enhanced intelligence and optional 1M context',
63
+ aliases: [
64
+ 'claude-4.5-sonnet',
65
+ 'sonnet-4.5',
66
+ 'claude-sonnet-4.5',
67
+ 'sonnet4.5',
68
+ 'claude-sonnet-4-5',
69
+ 'sonnet',
70
+ 'claude-sonnet',
71
+ ],
48
72
  },
49
73
  'claude-sonnet-4-20250514': {
50
74
  modelName: 'claude-sonnet-4-20250514',
@@ -60,8 +84,9 @@ const SUPPORTED_MODELS = {
60
84
  maxThinkingTokens: 64000,
61
85
  timeout: 300000,
62
86
  supports1MContext: true, // Beta 1M context support
63
- description: 'Claude Sonnet 4 - High intelligence and balanced performance with extended thinking',
64
- aliases: ['claude-4-sonnet', 'sonnet-4', 'claude-sonnet-4', 'sonnet4']
87
+ description:
88
+ 'Claude Sonnet 4 - High intelligence and balanced performance with extended thinking',
89
+ aliases: ['claude-4-sonnet', 'sonnet-4', 'claude-sonnet-4', 'sonnet4'],
65
90
  },
66
91
  'claude-3-7-sonnet-20250219': {
67
92
  modelName: 'claude-3-7-sonnet-20250219',
@@ -77,7 +102,13 @@ const SUPPORTED_MODELS = {
77
102
  maxThinkingTokens: 64000,
78
103
  timeout: 300000,
79
104
  description: 'Claude 3.7 Sonnet - Enhanced 3.x generation with thinking',
80
- aliases: ['claude-3.7-sonnet', 'sonnet-3.7', 'claude-3-7-sonnet', 'claude 3.7 sonnet', 'sonnet 3.7']
105
+ aliases: [
106
+ 'claude-3.7-sonnet',
107
+ 'sonnet-3.7',
108
+ 'claude-3-7-sonnet',
109
+ 'claude 3.7 sonnet',
110
+ 'sonnet 3.7',
111
+ ],
81
112
  },
82
113
  'claude-haiku-4-5-20251001': {
83
114
  modelName: 'claude-haiku-4-5-20251001',
@@ -92,8 +123,20 @@ const SUPPORTED_MODELS = {
92
123
  minThinkingTokens: 1024,
93
124
  maxThinkingTokens: 64000,
94
125
  timeout: 300000,
95
- description: 'Claude Haiku 4.5 - Fast and intelligent model with extended thinking',
96
- aliases: ['claude-haiku-4-5', 'claude-4.5-haiku', 'claude-4-5-haiku', 'haiku-4.5', 'haiku-4-5', 'claude-haiku-4.5', 'haiku4.5', 'claude-haiku-4', 'haiku', 'claude-haiku']
126
+ description:
127
+ 'Claude Haiku 4.5 - Fast and intelligent model with extended thinking',
128
+ aliases: [
129
+ 'claude-haiku-4-5',
130
+ 'claude-4.5-haiku',
131
+ 'claude-4-5-haiku',
132
+ 'haiku-4.5',
133
+ 'haiku-4-5',
134
+ 'claude-haiku-4.5',
135
+ 'haiku4.5',
136
+ 'claude-haiku-4',
137
+ 'haiku',
138
+ 'claude-haiku',
139
+ ],
97
140
  },
98
141
  'claude-3-5-sonnet-20241022': {
99
142
  modelName: 'claude-3-5-sonnet-20241022',
@@ -107,7 +150,14 @@ const SUPPORTED_MODELS = {
107
150
  supportsThinking: false,
108
151
  timeout: 300000,
109
152
  description: 'Claude 3.5 Sonnet - Fast and intelligent model',
110
- aliases: ['claude-3.5-sonnet', 'claude-3-5-sonnet-latest', 'claude-sonnet-3.5', 'sonnet-3.5', 'claude 3.5 sonnet', 'sonnet 3.5']
153
+ aliases: [
154
+ 'claude-3.5-sonnet',
155
+ 'claude-3-5-sonnet-latest',
156
+ 'claude-sonnet-3.5',
157
+ 'sonnet-3.5',
158
+ 'claude 3.5 sonnet',
159
+ 'sonnet 3.5',
160
+ ],
111
161
  },
112
162
  'claude-3-5-haiku-20241022': {
113
163
  modelName: 'claude-3-5-haiku-20241022',
@@ -121,29 +171,35 @@ const SUPPORTED_MODELS = {
121
171
  supportsThinking: false,
122
172
  timeout: 180000,
123
173
  description: 'Claude 3.5 Haiku - Fastest model, best for simple queries',
124
- aliases: ['claude-3.5-haiku', 'claude-3-5-haiku-latest', 'haiku-3.5', 'claude 3.5 haiku', 'haiku 3.5']
125
- }
174
+ aliases: [
175
+ 'claude-3.5-haiku',
176
+ 'claude-3-5-haiku-latest',
177
+ 'haiku-3.5',
178
+ 'claude 3.5 haiku',
179
+ 'haiku 3.5',
180
+ ],
181
+ },
126
182
  };
127
183
 
128
184
  /**
129
185
  * Map Anthropic stop reasons to unified format
130
186
  */
131
187
  const STOP_REASON_MAP = {
132
- 'end_turn': StopReasons.STOP,
133
- 'max_tokens': StopReasons.LENGTH,
134
- 'stop_sequence': StopReasons.STOP,
135
- 'tool_use': StopReasons.TOOL_USE
188
+ end_turn: StopReasons.STOP,
189
+ max_tokens: StopReasons.LENGTH,
190
+ stop_sequence: StopReasons.STOP,
191
+ tool_use: StopReasons.TOOL_USE,
136
192
  };
137
193
 
138
194
  /**
139
195
  * Thinking budget percentages mapped to reasoning_effort
140
196
  */
141
197
  const THINKING_BUDGETS = {
142
- minimal: 0.05, // 5% of max thinking tokens
143
- low: 0.15, // 15% of max thinking tokens
144
- medium: 0.33, // 33% of max thinking tokens (default)
145
- high: 0.67, // 67% of max thinking tokens
146
- max: 1.0 // 100% of max thinking tokens
198
+ minimal: 0.05, // 5% of max thinking tokens
199
+ low: 0.15, // 15% of max thinking tokens
200
+ medium: 0.33, // 33% of max thinking tokens (default)
201
+ high: 0.67, // 67% of max thinking tokens
202
+ max: 1.0, // 100% of max thinking tokens
147
203
  };
148
204
 
149
205
  /**
@@ -206,13 +262,16 @@ function validateApiKey(apiKey) {
206
262
  */
207
263
  function convertMessagesToAnthropic(messages, options = {}) {
208
264
  if (!Array.isArray(messages)) {
209
- throw new AnthropicProviderError('Messages must be an array', ErrorCodes.INVALID_MESSAGES);
265
+ throw new AnthropicProviderError(
266
+ 'Messages must be an array',
267
+ ErrorCodes.INVALID_MESSAGES,
268
+ );
210
269
  }
211
270
 
212
271
  const {
213
272
  enableSystemCache = true, // Always cache system messages by default
214
273
  cacheUserMessages = false,
215
- cacheMessageThreshold = 5 // Cache messages after this many turns
274
+ cacheMessageThreshold = 5, // Cache messages after this many turns
216
275
  } = options;
217
276
  const systemContent = [];
218
277
  let systemText = '';
@@ -220,17 +279,26 @@ function convertMessagesToAnthropic(messages, options = {}) {
220
279
 
221
280
  for (const [index, msg] of messages.entries()) {
222
281
  if (!msg || typeof msg !== 'object') {
223
- throw new AnthropicProviderError(`Message at index ${index} must be an object`, ErrorCodes.INVALID_MESSAGE);
282
+ throw new AnthropicProviderError(
283
+ `Message at index ${index} must be an object`,
284
+ ErrorCodes.INVALID_MESSAGE,
285
+ );
224
286
  }
225
287
 
226
288
  const { role, content } = msg;
227
289
 
228
290
  if (!role || !['system', 'user', 'assistant'].includes(role)) {
229
- throw new AnthropicProviderError(`Invalid role "${role}" at message index ${index}`, ErrorCodes.INVALID_ROLE);
291
+ throw new AnthropicProviderError(
292
+ `Invalid role "${role}" at message index ${index}`,
293
+ ErrorCodes.INVALID_ROLE,
294
+ );
230
295
  }
231
296
 
232
297
  if (!content) {
233
- throw new AnthropicProviderError(`Message content is required at index ${index}`, ErrorCodes.MISSING_CONTENT);
298
+ throw new AnthropicProviderError(
299
+ `Message content is required at index ${index}`,
300
+ ErrorCodes.MISSING_CONTENT,
301
+ );
234
302
  }
235
303
 
236
304
  if (role === 'system') {
@@ -245,7 +313,7 @@ function convertMessagesToAnthropic(messages, options = {}) {
245
313
  if (item.type === 'text') {
246
314
  anthropicContent.push({
247
315
  type: 'text',
248
- text: item.text
316
+ text: item.text,
249
317
  });
250
318
  } else if (item.type === 'image' && item.source) {
251
319
  // Content is already in Anthropic format
@@ -254,22 +322,24 @@ function convertMessagesToAnthropic(messages, options = {}) {
254
322
  source: {
255
323
  type: 'base64',
256
324
  media_type: item.source.media_type,
257
- data: item.source.data
258
- }
325
+ data: item.source.data,
326
+ },
259
327
  });
260
- debugLog(`[Anthropic] Processing image: ${item.source.media_type}, data length: ${item.source.data.length}`);
328
+ debugLog(
329
+ `[Anthropic] Processing image: ${item.source.media_type}, data length: ${item.source.data.length}`,
330
+ );
261
331
  }
262
332
  }
263
333
 
264
334
  anthropicMessages.push({
265
335
  role,
266
- content: anthropicContent
336
+ content: anthropicContent,
267
337
  });
268
338
  } else {
269
339
  // Simple string content
270
340
  anthropicMessages.push({
271
341
  role,
272
- content
342
+ content,
273
343
  });
274
344
  }
275
345
  }
@@ -277,7 +347,10 @@ function convertMessagesToAnthropic(messages, options = {}) {
277
347
 
278
348
  // Ensure first message is from user
279
349
  if (anthropicMessages.length > 0 && anthropicMessages[0].role !== 'user') {
280
- throw new AnthropicProviderError('First message must be from user role', ErrorCodes.INVALID_MESSAGE);
350
+ throw new AnthropicProviderError(
351
+ 'First message must be from user role',
352
+ ErrorCodes.INVALID_MESSAGE,
353
+ );
281
354
  }
282
355
 
283
356
  // Ensure messages alternate between user and assistant
@@ -288,7 +361,7 @@ function convertMessagesToAnthropic(messages, options = {}) {
288
361
  if (prevRole === currRole) {
289
362
  throw new AnthropicProviderError(
290
363
  `Messages must alternate between user and assistant. Found consecutive ${currRole} messages at index ${i}`,
291
- ErrorCodes.INVALID_MESSAGE
364
+ ErrorCodes.INVALID_MESSAGE,
292
365
  );
293
366
  }
294
367
  }
@@ -298,15 +371,19 @@ function convertMessagesToAnthropic(messages, options = {}) {
298
371
  if (systemText) {
299
372
  if (enableSystemCache) {
300
373
  // Use array format with cache control for system prompt
301
- systemResult = [{
302
- type: 'text',
303
- text: systemText,
304
- cache_control: {
305
- type: 'ephemeral',
306
- ttl: '1h' // 1 hour cache duration
307
- }
308
- }];
309
- debugLog(`[Anthropic] System prompt caching enabled (ephemeral with ttl-extender for 1 hour) - ${systemText.length} chars`);
374
+ systemResult = [
375
+ {
376
+ type: 'text',
377
+ text: systemText,
378
+ cache_control: {
379
+ type: 'ephemeral',
380
+ ttl: '1h', // 1 hour cache duration
381
+ },
382
+ },
383
+ ];
384
+ debugLog(
385
+ `[Anthropic] System prompt caching enabled (ephemeral with ttl-extender for 1 hour) - ${systemText.length} chars`,
386
+ );
310
387
  } else {
311
388
  // Use simple string format without caching
312
389
  systemResult = systemText;
@@ -343,7 +420,7 @@ async function getAnthropicSDK() {
343
420
  throw new AnthropicProviderError(
344
421
  'Failed to load Anthropic SDK. Please install @anthropic-ai/sdk',
345
422
  ErrorCodes.API_ERROR,
346
- error
423
+ error,
347
424
  );
348
425
  }
349
426
  }
@@ -377,11 +454,17 @@ export const anthropicProvider = {
377
454
 
378
455
  // Validate API key
379
456
  if (!config?.apiKeys?.anthropic) {
380
- throw new AnthropicProviderError('Anthropic API key not configured', ErrorCodes.MISSING_API_KEY);
457
+ throw new AnthropicProviderError(
458
+ 'Anthropic API key not configured',
459
+ ErrorCodes.MISSING_API_KEY,
460
+ );
381
461
  }
382
462
 
383
463
  if (!validateApiKey(config.apiKeys.anthropic)) {
384
- throw new AnthropicProviderError('Invalid Anthropic API key format', ErrorCodes.INVALID_API_KEY);
464
+ throw new AnthropicProviderError(
465
+ 'Invalid Anthropic API key format',
466
+ ErrorCodes.INVALID_API_KEY,
467
+ );
385
468
  }
386
469
 
387
470
  // Get Anthropic SDK
@@ -395,21 +478,27 @@ export const anthropicProvider = {
395
478
  const anthropic = new Anthropic({
396
479
  apiKey: config.apiKeys.anthropic,
397
480
  // Increase timeout to 20 minutes for thinking models that may take longer
398
- timeout: 20 * 60 * 1000
481
+ timeout: 20 * 60 * 1000,
399
482
  });
400
483
 
401
484
  // Build beta features array for the request
402
485
  // Use both prompt caching and extended cache duration for 1-hour caching
403
- const betas = ['prompt-caching-2024-07-31', 'extended-cache-ttl-2025-04-11'];
486
+ const betas = [
487
+ 'prompt-caching-2024-07-31',
488
+ 'extended-cache-ttl-2025-04-11',
489
+ ];
404
490
 
405
491
  // Add 1M context beta feature if model supports it
406
492
  if (modelConfig.supports1MContext) {
407
493
  betas.push('context-1m-2025-08-07');
408
- debugLog(`[Anthropic] Model ${resolvedModel} supports 1M context window with beta feature`);
494
+ debugLog(
495
+ `[Anthropic] Model ${resolvedModel} supports 1M context window with beta feature`,
496
+ );
409
497
  }
410
498
 
411
499
  // Convert messages to Anthropic format (system messages are always cached)
412
- const { systemPrompt, messages: anthropicMessages } = convertMessagesToAnthropic(messages);
500
+ const { systemPrompt, messages: anthropicMessages } =
501
+ convertMessagesToAnthropic(messages);
413
502
 
414
503
  // Build request payload
415
504
  const requestPayload = {
@@ -417,7 +506,7 @@ export const anthropicProvider = {
417
506
  messages: anthropicMessages,
418
507
  stream,
419
508
  betas, // Include beta features
420
- ...otherOptions
509
+ ...otherOptions,
421
510
  };
422
511
 
423
512
  // Add system prompt if present
@@ -427,7 +516,10 @@ export const anthropicProvider = {
427
516
 
428
517
  // Set max tokens - API requires this field
429
518
  if (maxTokens) {
430
- requestPayload.max_tokens = Math.min(maxTokens, modelConfig.maxOutputTokens || 8192);
519
+ requestPayload.max_tokens = Math.min(
520
+ maxTokens,
521
+ modelConfig.maxOutputTokens || 8192,
522
+ );
431
523
  } else {
432
524
  // Use model's default max output tokens
433
525
  requestPayload.max_tokens = modelConfig.maxOutputTokens || 8192;
@@ -435,26 +527,39 @@ export const anthropicProvider = {
435
527
 
436
528
  // Add thinking configuration for models that support it
437
529
  if (modelConfig.supportsThinking && reasoning_effort) {
438
- const thinkingBudget = calculateThinkingBudget(modelConfig, reasoning_effort);
439
- debugLog(`[Anthropic] Model ${resolvedModel}: maxOutputTokens=${modelConfig.maxOutputTokens}, maxThinkingTokens=${modelConfig.maxThinkingTokens}, thinkingBudget=${thinkingBudget}`);
530
+ const thinkingBudget = calculateThinkingBudget(
531
+ modelConfig,
532
+ reasoning_effort,
533
+ );
534
+ debugLog(
535
+ `[Anthropic] Model ${resolvedModel}: maxOutputTokens=${modelConfig.maxOutputTokens}, maxThinkingTokens=${modelConfig.maxThinkingTokens}, thinkingBudget=${thinkingBudget}`,
536
+ );
440
537
 
441
538
  // For 4 series models, we trust the SDK defaults work with thinking
442
539
  // For other models, check against max_tokens if set
443
- const maxTokensLimit = requestPayload.max_tokens ||
444
- (resolvedModel.includes('claude-opus-4') ? 32000 :
445
- (resolvedModel.includes('claude-sonnet-4-5') || resolvedModel.includes('claude-sonnet-4')) ? 64000 :
446
- modelConfig.maxOutputTokens);
540
+ const maxTokensLimit =
541
+ requestPayload.max_tokens ||
542
+ (resolvedModel.includes('claude-opus-4')
543
+ ? 32000
544
+ : resolvedModel.includes('claude-sonnet-4-5') ||
545
+ resolvedModel.includes('claude-sonnet-4')
546
+ ? 64000
547
+ : modelConfig.maxOutputTokens);
447
548
 
448
549
  if (thinkingBudget > 0 && thinkingBudget < maxTokensLimit) {
449
550
  // According to Anthropic docs: thinking tokens count towards max_tokens limit
450
551
  // thinking.budget_tokens must be >= 1024 and < max_tokens
451
552
  requestPayload.thinking = {
452
553
  type: 'enabled',
453
- budget_tokens: thinkingBudget
554
+ budget_tokens: thinkingBudget,
454
555
  };
455
- debugLog(`[Anthropic] Thinking enabled with budget: ${thinkingBudget} tokens (${reasoning_effort} effort)`);
556
+ debugLog(
557
+ `[Anthropic] Thinking enabled with budget: ${thinkingBudget} tokens (${reasoning_effort} effort)`,
558
+ );
456
559
  } else {
457
- debugLog(`[Anthropic] Thinking not enabled: budget ${thinkingBudget} must be < max_tokens limit ${maxTokensLimit}`);
560
+ debugLog(
561
+ `[Anthropic] Thinking not enabled: budget ${thinkingBudget} must be < max_tokens limit ${maxTokensLimit}`,
562
+ );
458
563
  }
459
564
  }
460
565
 
@@ -471,28 +576,49 @@ export const anthropicProvider = {
471
576
 
472
577
  // If streaming is requested and model doesn't support it, fall back to non-streaming
473
578
  if (stream && modelConfig.supportsStreaming === false) {
474
- debugLog(`[Anthropic] Model ${resolvedModel} doesn't support streaming, falling back to non-streaming mode`);
579
+ debugLog(
580
+ `[Anthropic] Model ${resolvedModel} doesn't support streaming, falling back to non-streaming mode`,
581
+ );
475
582
  requestPayload.stream = false;
476
583
  }
477
584
 
478
585
  // Handle streaming requests
479
586
  if (stream && requestPayload.stream !== false) {
480
- return this._createStreamingGenerator(anthropic, requestPayload, resolvedModel, modelConfig, reasoning_effort);
587
+ return this._createStreamingGenerator(
588
+ anthropic,
589
+ requestPayload,
590
+ resolvedModel,
591
+ modelConfig,
592
+ reasoning_effort,
593
+ );
481
594
  }
482
595
 
483
596
  try {
484
- debugLog(`[Anthropic] Calling ${resolvedModel} with ${anthropicMessages.length} messages`);
485
- debugLog('[Anthropic] Request payload:', JSON.stringify({
486
- model: requestPayload.model,
487
- max_tokens: requestPayload.max_tokens,
488
- thinking: requestPayload.thinking,
489
- temperature: requestPayload.temperature,
490
- betas: requestPayload.betas,
491
- message_count: requestPayload.messages?.length,
492
- system_length: Array.isArray(requestPayload.system) ? requestPayload.system[0]?.text?.length : requestPayload.system?.length
493
- }, null, 2));
597
+ debugLog(
598
+ `[Anthropic] Calling ${resolvedModel} with ${anthropicMessages.length} messages`,
599
+ );
600
+ debugLog(
601
+ '[Anthropic] Request payload:',
602
+ JSON.stringify(
603
+ {
604
+ model: requestPayload.model,
605
+ max_tokens: requestPayload.max_tokens,
606
+ thinking: requestPayload.thinking,
607
+ temperature: requestPayload.temperature,
608
+ betas: requestPayload.betas,
609
+ message_count: requestPayload.messages?.length,
610
+ system_length: Array.isArray(requestPayload.system)
611
+ ? requestPayload.system[0]?.text?.length
612
+ : requestPayload.system?.length,
613
+ },
614
+ null,
615
+ 2,
616
+ ),
617
+ );
494
618
  if (systemPrompt) {
495
- debugLog(`[Anthropic] System prompt length: ${systemPrompt.length} characters`);
619
+ debugLog(
620
+ `[Anthropic] System prompt length: ${systemPrompt.length} characters`,
621
+ );
496
622
  }
497
623
 
498
624
  const startTime = Date.now();
@@ -519,11 +645,15 @@ export const anthropicProvider = {
519
645
  }
520
646
 
521
647
  if (!content) {
522
- throw new AnthropicProviderError('No content in response from Anthropic', ErrorCodes.NO_RESPONSE_CONTENT);
648
+ throw new AnthropicProviderError(
649
+ 'No content in response from Anthropic',
650
+ ErrorCodes.NO_RESPONSE_CONTENT,
651
+ );
523
652
  }
524
653
 
525
654
  // Map stop reason
526
- const stopReason = STOP_REASON_MAP[response.stop_reason] || StopReasons.OTHER;
655
+ const stopReason =
656
+ STOP_REASON_MAP[response.stop_reason] || StopReasons.OTHER;
527
657
 
528
658
  // Extract usage information
529
659
  const usage = response.usage || {};
@@ -538,18 +668,20 @@ export const anthropicProvider = {
538
668
  usage: {
539
669
  input_tokens: usage.input_tokens || 0,
540
670
  output_tokens: usage.output_tokens || 0,
541
- total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0),
671
+ total_tokens:
672
+ (usage.input_tokens || 0) + (usage.output_tokens || 0),
542
673
  thinking_tokens: usage.thinking_input_tokens || 0,
543
674
  cache_creation_input_tokens: usage.cache_creation_input_tokens || 0,
544
- cache_read_input_tokens: usage.cache_read_input_tokens || 0
675
+ cache_read_input_tokens: usage.cache_read_input_tokens || 0,
545
676
  },
546
677
  response_time_ms: responseTime,
547
678
  finish_reason: response.stop_reason,
548
679
  provider: 'anthropic',
549
- reasoning_effort: modelConfig.supportsThinking ? reasoning_effort : null
550
- }
680
+ reasoning_effort: modelConfig.supportsThinking
681
+ ? reasoning_effort
682
+ : null,
683
+ },
551
684
  };
552
-
553
685
  } catch (error) {
554
686
  debugError('[Anthropic] Error during API call:', error);
555
687
 
@@ -560,28 +692,55 @@ export const anthropicProvider = {
560
692
 
561
693
  // Handle specific Anthropic errors
562
694
  if (error.status === 401) {
563
- throw new AnthropicProviderError('Invalid Anthropic API key', ErrorCodes.INVALID_API_KEY, error);
695
+ throw new AnthropicProviderError(
696
+ 'Invalid Anthropic API key',
697
+ ErrorCodes.INVALID_API_KEY,
698
+ error,
699
+ );
564
700
  } else if (error.status === 429) {
565
- throw new AnthropicProviderError('Anthropic rate limit exceeded', ErrorCodes.RATE_LIMIT_EXCEEDED, error);
701
+ throw new AnthropicProviderError(
702
+ 'Anthropic rate limit exceeded',
703
+ ErrorCodes.RATE_LIMIT_EXCEEDED,
704
+ error,
705
+ );
566
706
  } else if (error.status === 403) {
567
- throw new AnthropicProviderError('Anthropic API quota exceeded or forbidden', ErrorCodes.QUOTA_EXCEEDED, error);
707
+ throw new AnthropicProviderError(
708
+ 'Anthropic API quota exceeded or forbidden',
709
+ ErrorCodes.QUOTA_EXCEEDED,
710
+ error,
711
+ );
568
712
  } else if (error.error?.type === 'invalid_request_error') {
569
- throw new AnthropicProviderError(`Invalid request: ${error.error.message}`, ErrorCodes.INVALID_REQUEST, error);
713
+ throw new AnthropicProviderError(
714
+ `Invalid request: ${error.error.message}`,
715
+ ErrorCodes.INVALID_REQUEST,
716
+ error,
717
+ );
570
718
  } else if (error.error?.type === 'not_found_error') {
571
- throw new AnthropicProviderError(`Model ${resolvedModel} not found`, ErrorCodes.MODEL_NOT_FOUND, error);
572
- } else if (error.message?.includes('context length') || error.message?.includes('context_length') ||
573
- (error.message?.includes('token') && error.message?.includes('limit'))) {
719
+ throw new AnthropicProviderError(
720
+ `Model ${resolvedModel} not found`,
721
+ ErrorCodes.MODEL_NOT_FOUND,
722
+ error,
723
+ );
724
+ } else if (
725
+ error.message?.includes('context length') ||
726
+ error.message?.includes('context_length') ||
727
+ (error.message?.includes('token') && error.message?.includes('limit'))
728
+ ) {
574
729
  debugError('[Anthropic] Context length error - Full error:', error);
575
730
  debugError('[Anthropic] Error message:', error.message);
576
731
  debugError('[Anthropic] Error response:', error.response);
577
- throw new AnthropicProviderError(`Context length exceeded for model: ${error.message}`, ErrorCodes.CONTEXT_LENGTH_EXCEEDED, error);
732
+ throw new AnthropicProviderError(
733
+ `Context length exceeded for model: ${error.message}`,
734
+ ErrorCodes.CONTEXT_LENGTH_EXCEEDED,
735
+ error,
736
+ );
578
737
  }
579
738
 
580
739
  // Generic error handling
581
740
  throw new AnthropicProviderError(
582
741
  `Anthropic API error: ${error.message || 'Unknown error'}`,
583
742
  ErrorCodes.API_ERROR,
584
- error
743
+ error,
585
744
  );
586
745
  }
587
746
  },
@@ -596,8 +755,16 @@ export const anthropicProvider = {
596
755
  * @param {string} reasoning_effort - Reasoning effort level
597
756
  * @returns {AsyncGenerator} - Async generator yielding streaming events
598
757
  */
599
- async *_createStreamingGenerator(anthropic, requestPayload, resolvedModel, modelConfig, reasoning_effort) {
600
- debugLog(`[Anthropic] Starting streaming for ${resolvedModel} with ${requestPayload.messages?.length} messages`);
758
+ async *_createStreamingGenerator(
759
+ anthropic,
760
+ requestPayload,
761
+ resolvedModel,
762
+ modelConfig,
763
+ reasoning_effort,
764
+ ) {
765
+ debugLog(
766
+ `[Anthropic] Starting streaming for ${resolvedModel} with ${requestPayload.messages?.length} messages`,
767
+ );
601
768
 
602
769
  const startTime = Date.now();
603
770
  let totalContent = '';
@@ -612,7 +779,7 @@ export const anthropicProvider = {
612
779
  timestamp: new Date().toISOString(),
613
780
  model: resolvedModel,
614
781
  provider: 'anthropic',
615
- thinking_mode: modelConfig.supportsThinking && !!reasoning_effort
782
+ thinking_mode: modelConfig.supportsThinking && !!reasoning_effort,
616
783
  };
617
784
 
618
785
  // Enable streaming in request payload
@@ -634,7 +801,9 @@ export const anthropicProvider = {
634
801
 
635
802
  case 'content_block_start':
636
803
  // Content block started (text, thinking, etc.)
637
- debugLog(`[Anthropic] Content block started: ${event.content_block?.type}`);
804
+ debugLog(
805
+ `[Anthropic] Content block started: ${event.content_block?.type}`,
806
+ );
638
807
  break;
639
808
 
640
809
  case 'content_block_delta':
@@ -646,7 +815,7 @@ export const anthropicProvider = {
646
815
  yield {
647
816
  type: 'delta',
648
817
  content,
649
- timestamp: new Date().toISOString()
818
+ timestamp: new Date().toISOString(),
650
819
  };
651
820
  }
652
821
  } else if (event.delta?.type === 'thinking_delta') {
@@ -655,14 +824,18 @@ export const anthropicProvider = {
655
824
  if (thinking) {
656
825
  thinkingContent += thinking;
657
826
  // Optionally yield thinking deltas for debugging
658
- debugLog(`[Anthropic] Thinking delta: ${thinking.substring(0, 100)}...`);
827
+ debugLog(
828
+ `[Anthropic] Thinking delta: ${thinking.substring(0, 100)}...`,
829
+ );
659
830
  }
660
831
  }
661
832
  break;
662
833
 
663
834
  case 'content_block_stop':
664
835
  // Content block completed
665
- debugLog(`[Anthropic] Content block stopped at index ${event.index}`);
836
+ debugLog(
837
+ `[Anthropic] Content block stopped at index ${event.index}`,
838
+ );
666
839
  break;
667
840
 
668
841
  case 'message_delta':
@@ -689,11 +862,13 @@ export const anthropicProvider = {
689
862
  throw new AnthropicProviderError(
690
863
  `Streaming error: ${event.error?.message || 'Unknown streaming error'}`,
691
864
  ErrorCodes.API_ERROR,
692
- event.error
865
+ event.error,
693
866
  );
694
867
 
695
868
  default:
696
- debugLog(`[Anthropic] Unknown streaming event type: ${event.type}`);
869
+ debugLog(
870
+ `[Anthropic] Unknown streaming event type: ${event.type}`,
871
+ );
697
872
  break;
698
873
  }
699
874
  } catch (eventError) {
@@ -703,9 +878,9 @@ export const anthropicProvider = {
703
878
  error: {
704
879
  message: `Event processing error: ${eventError.message}`,
705
880
  code: 'EVENT_PROCESSING_ERROR',
706
- recoverable: true
881
+ recoverable: true,
707
882
  },
708
- timestamp: new Date().toISOString()
883
+ timestamp: new Date().toISOString(),
709
884
  };
710
885
  }
711
886
  }
@@ -720,12 +895,14 @@ export const anthropicProvider = {
720
895
  usage: {
721
896
  input_tokens: lastUsage.input_tokens || 0,
722
897
  output_tokens: lastUsage.output_tokens || 0,
723
- total_tokens: (lastUsage.input_tokens || 0) + (lastUsage.output_tokens || 0),
898
+ total_tokens:
899
+ (lastUsage.input_tokens || 0) + (lastUsage.output_tokens || 0),
724
900
  thinking_tokens: lastUsage.thinking_input_tokens || 0,
725
- cache_creation_input_tokens: lastUsage.cache_creation_input_tokens || 0,
726
- cache_read_input_tokens: lastUsage.cache_read_input_tokens || 0
901
+ cache_creation_input_tokens:
902
+ lastUsage.cache_creation_input_tokens || 0,
903
+ cache_read_input_tokens: lastUsage.cache_read_input_tokens || 0,
727
904
  },
728
- timestamp: new Date().toISOString()
905
+ timestamp: new Date().toISOString(),
729
906
  };
730
907
  }
731
908
 
@@ -739,20 +916,23 @@ export const anthropicProvider = {
739
916
  usage: {
740
917
  input_tokens: lastUsage?.input_tokens || 0,
741
918
  output_tokens: lastUsage?.output_tokens || 0,
742
- total_tokens: (lastUsage?.input_tokens || 0) + (lastUsage?.output_tokens || 0),
919
+ total_tokens:
920
+ (lastUsage?.input_tokens || 0) + (lastUsage?.output_tokens || 0),
743
921
  thinking_tokens: lastUsage?.thinking_input_tokens || 0,
744
- cache_creation_input_tokens: lastUsage?.cache_creation_input_tokens || 0,
745
- cache_read_input_tokens: lastUsage?.cache_read_input_tokens || 0
922
+ cache_creation_input_tokens:
923
+ lastUsage?.cache_creation_input_tokens || 0,
924
+ cache_read_input_tokens: lastUsage?.cache_read_input_tokens || 0,
746
925
  },
747
926
  response_time_ms: responseTime,
748
927
  finish_reason: finishReason,
749
928
  provider: 'anthropic',
750
- reasoning_effort: modelConfig.supportsThinking ? reasoning_effort : null,
751
- thinking_content: thinkingContent || null
929
+ reasoning_effort: modelConfig.supportsThinking
930
+ ? reasoning_effort
931
+ : null,
932
+ thinking_content: thinkingContent || null,
752
933
  },
753
- timestamp: new Date().toISOString()
934
+ timestamp: new Date().toISOString(),
754
935
  };
755
-
756
936
  } catch (error) {
757
937
  debugError('[Anthropic] Streaming error:', error);
758
938
 
@@ -781,8 +961,11 @@ export const anthropicProvider = {
781
961
  } else if (error.error?.type === 'not_found_error') {
782
962
  errorCode = 'MODEL_NOT_FOUND';
783
963
  errorMessage = `Model ${resolvedModel} not found`;
784
- } else if (error.message?.includes('context length') || error.message?.includes('context_length') ||
785
- (error.message?.includes('token') && error.message?.includes('limit'))) {
964
+ } else if (
965
+ error.message?.includes('context length') ||
966
+ error.message?.includes('context_length') ||
967
+ (error.message?.includes('token') && error.message?.includes('limit'))
968
+ ) {
786
969
  errorCode = 'CONTEXT_LENGTH_EXCEEDED';
787
970
  errorMessage = `Context length exceeded for model: ${error.message}`;
788
971
  }
@@ -793,9 +976,9 @@ export const anthropicProvider = {
793
976
  message: errorMessage,
794
977
  code: errorCode,
795
978
  recoverable,
796
- originalError: error
979
+ originalError: error,
797
980
  },
798
- timestamp: new Date().toISOString()
981
+ timestamp: new Date().toISOString(),
799
982
  };
800
983
 
801
984
  // Re-throw the error to maintain existing error handling behavior
@@ -809,7 +992,9 @@ export const anthropicProvider = {
809
992
  * @returns {boolean} - True if configuration is valid
810
993
  */
811
994
  validateConfig(config) {
812
- return !!(config?.apiKeys?.anthropic && validateApiKey(config.apiKeys.anthropic));
995
+ return !!(
996
+ config?.apiKeys?.anthropic && validateApiKey(config.apiKeys.anthropic)
997
+ );
813
998
  },
814
999
 
815
1000
  /**
@@ -837,6 +1022,5 @@ export const anthropicProvider = {
837
1022
  getModelConfig(modelName) {
838
1023
  const resolved = resolveModelName(modelName);
839
1024
  return SUPPORTED_MODELS[resolved] || null;
840
- }
1025
+ },
841
1026
  };
842
-