@happyvertical/ai 0.78.3 → 0.79.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.
Files changed (54) hide show
  1. package/README.md +63 -5
  2. package/dist/chunks/{anthropic-BRwbhwIl.js → anthropic-2z-82zgr.js} +75 -8
  3. package/dist/chunks/anthropic-2z-82zgr.js.map +1 -0
  4. package/dist/chunks/{bedrock-Cf1xUerN.js → bedrock-Dc2eVPUD.js} +153 -41
  5. package/dist/chunks/bedrock-Dc2eVPUD.js.map +1 -0
  6. package/dist/chunks/{bifrost-3mXtQsTj.js → bifrost-CEnCsciy.js} +36 -11
  7. package/dist/chunks/bifrost-CEnCsciy.js.map +1 -0
  8. package/dist/chunks/{claude-cli-BrHRfkry.js → claude-cli-X1ONjE8K.js} +3 -3
  9. package/dist/chunks/{claude-cli-BrHRfkry.js.map → claude-cli-X1ONjE8K.js.map} +1 -1
  10. package/dist/chunks/{gateway-admin-C4GFPbZF.js → gateway-admin-BUhBzXZb.js} +2 -2
  11. package/dist/chunks/{gateway-admin-C4GFPbZF.js.map → gateway-admin-BUhBzXZb.js.map} +1 -1
  12. package/dist/chunks/{gemini-BfpHXDIQ.js → gemini-CS56gY0D.js} +138 -32
  13. package/dist/chunks/gemini-CS56gY0D.js.map +1 -0
  14. package/dist/chunks/{huggingface-280qv9iv.js → huggingface-wQSfO5xA.js} +64 -19
  15. package/dist/chunks/huggingface-wQSfO5xA.js.map +1 -0
  16. package/dist/chunks/{index-BT4thAvS.js → index-DCXO0nZA.js} +383 -24
  17. package/dist/chunks/index-DCXO0nZA.js.map +1 -0
  18. package/dist/chunks/{litellm-DhPKa_Jz.js → litellm-BMFTYbWc.js} +36 -11
  19. package/dist/chunks/litellm-BMFTYbWc.js.map +1 -0
  20. package/dist/chunks/{ollama-Di1ldur0.js → ollama-DsGDrA-c.js} +171 -60
  21. package/dist/chunks/ollama-DsGDrA-c.js.map +1 -0
  22. package/dist/chunks/{openai-5snI2diE.js → openai-CJEo69jb.js} +145 -12
  23. package/dist/chunks/openai-CJEo69jb.js.map +1 -0
  24. package/dist/chunks/{qwen-tts-DgPgdXxG.js → qwen-tts-BLYZ6d9s.js} +2 -2
  25. package/dist/chunks/{qwen-tts-DgPgdXxG.js.map → qwen-tts-BLYZ6d9s.js.map} +1 -1
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +15 -12
  29. package/dist/shared/factory.d.ts.map +1 -1
  30. package/dist/shared/providers/anthropic.d.ts.map +1 -1
  31. package/dist/shared/providers/bedrock.d.ts.map +1 -1
  32. package/dist/shared/providers/bifrost.d.ts.map +1 -1
  33. package/dist/shared/providers/gemini.d.ts +0 -5
  34. package/dist/shared/providers/gemini.d.ts.map +1 -1
  35. package/dist/shared/providers/huggingface.d.ts.map +1 -1
  36. package/dist/shared/providers/litellm.d.ts.map +1 -1
  37. package/dist/shared/providers/ollama.d.ts +0 -1
  38. package/dist/shared/providers/ollama.d.ts.map +1 -1
  39. package/dist/shared/providers/openai.d.ts +2 -2
  40. package/dist/shared/providers/openai.d.ts.map +1 -1
  41. package/dist/shared/safety.d.ts +55 -0
  42. package/dist/shared/safety.d.ts.map +1 -0
  43. package/dist/shared/types.d.ts +74 -6
  44. package/dist/shared/types.d.ts.map +1 -1
  45. package/package.json +2 -2
  46. package/dist/chunks/anthropic-BRwbhwIl.js.map +0 -1
  47. package/dist/chunks/bedrock-Cf1xUerN.js.map +0 -1
  48. package/dist/chunks/bifrost-3mXtQsTj.js.map +0 -1
  49. package/dist/chunks/gemini-BfpHXDIQ.js.map +0 -1
  50. package/dist/chunks/huggingface-280qv9iv.js.map +0 -1
  51. package/dist/chunks/index-BT4thAvS.js.map +0 -1
  52. package/dist/chunks/litellm-DhPKa_Jz.js.map +0 -1
  53. package/dist/chunks/ollama-Di1ldur0.js.map +0 -1
  54. package/dist/chunks/openai-5snI2diE.js.map +0 -1
package/README.md CHANGED
@@ -146,6 +146,64 @@ console.log(key.key);
146
146
 
147
147
  LiteLLM uses the same SDK surface, mapping projects to LiteLLM teams and virtual keys to `/key/generate`.
148
148
 
149
+ ## Generation Safety
150
+
151
+ Every generative provider constructor applies the same safe defaults, including
152
+ instances created directly instead of through `getAI()`:
153
+
154
+ - 4,096 output tokens per request
155
+ - 1,024 reasoning tokens per request
156
+ - one generated image per request
157
+ - a 120-second provider timeout
158
+ - zero provider retries (one total upstream attempt)
159
+ - local rejection with `AI_LIMIT_EXCEEDED` before transport when a ceiling is exceeded
160
+
161
+ Reasoning is opt-in. The 1,024-token default is a ceiling for explicitly
162
+ requested reasoning, not an automatically enabled thinking budget.
163
+
164
+ An approved workload can raise a client-level ceiling explicitly. Prefer a
165
+ workload-specific client so the wider limit is not shared accidentally.
166
+
167
+ ```typescript
168
+ const ai = await getAI({
169
+ type: 'bifrost',
170
+ apiKey: process.env.BIFROST_API_KEY!,
171
+ baseUrl: process.env.BIFROST_BASE_URL!,
172
+ defaultModel: 'gemini-2.5-flash',
173
+ timeout: 105_000,
174
+ maxRetries: 0,
175
+ generationLimits: {
176
+ maxOutputTokens: 8192,
177
+ maxReasoningTokens: 1024,
178
+ },
179
+ usageTags: {
180
+ app: 'writer',
181
+ environment: 'production',
182
+ feature: 'long-form',
183
+ },
184
+ onRequest: (event) => telemetry.record(event),
185
+ });
186
+
187
+ const controller = new AbortController();
188
+ const result = await ai.message('Write the approved long-form response', {
189
+ maxTokens: 8192,
190
+ timeout: 105_000,
191
+ signal: controller.signal,
192
+ reasoning: { effort: 'low', maxTokens: 1024 },
193
+ });
194
+ ```
195
+
196
+ `signal` and the SDK timeout are composed and propagated to the provider. A
197
+ client abort is useful for correctness, but it does not guarantee that a remote
198
+ provider stops work or billing. Token ceilings and single attempts are the
199
+ primary cost controls.
200
+
201
+ `onRequest` receives one prompt-free terminal event for success, failure,
202
+ timeout, caller abort, or local rejection. Events include requested and
203
+ effective token ceilings plus sanitized `usageTags`; prompts, responses, and
204
+ credentials are never included. Legacy `thinkingLevel` options remain available
205
+ as deprecated aliases and are normalized through the reasoning ceiling.
206
+
149
207
  ## Opt-In Rate-Limit Pacing
150
208
 
151
209
  Use `rateLimit` when multiple calls share the same provider budget and you want
@@ -166,7 +224,7 @@ const ai = await getAI({
166
224
  key: 'gemini:shared-batch-key',
167
225
  cooldownMs: 2000,
168
226
  initialDelayMs: 15000,
169
- maxAttempts: 3,
227
+ maxAttempts: 2,
170
228
  },
171
229
  });
172
230
  ```
@@ -176,8 +234,8 @@ const ai = await getAI({
176
234
  - `initialDelayMs` is the fallback retry delay when the provider omits `Retry-After`
177
235
  - `maxAttempts` counts the first call plus any rate-limit retries
178
236
 
179
- When `rateLimit` is omitted, or `enabled: false` is set explicitly, `getAI()`
180
- behaves exactly as it did before.
237
+ When `rateLimit` is omitted, or `enabled: false` is set explicitly, no
238
+ in-process retry wrapper is applied. Provider retries still default to zero.
181
239
 
182
240
  ### `rateLimit` Options
183
241
 
@@ -187,7 +245,7 @@ behaves exactly as it did before.
187
245
  | `key` | `string` | derived | Shared budget key; clients with the same key coordinate with each other |
188
246
  | `cooldownMs` | `number` | `0` | Minimum delay after a successful call before the next call with the same key |
189
247
  | `initialDelayMs` | `number` | `5000` | Fallback retry delay when the provider does not return `Retry-After` |
190
- | `maxAttempts` | `number` | `3` | Total attempts, including the initial call |
248
+ | `maxAttempts` | `number` | `1` | Total attempts, including the initial call; increase explicitly only for an approved workload |
191
249
  | `requestsPerMinute` | `number` | provider-specific | Used by `qwen3-tts` local token-bucket limiting |
192
250
  | `maxConcurrent` | `number` | provider-specific | Used by `qwen3-tts` local concurrency limiting |
193
251
 
@@ -208,7 +266,7 @@ const ai = await getAI({
208
266
  key: 'praeco:multi-site-analysis',
209
267
  cooldownMs: 2000,
210
268
  initialDelayMs: 15000,
211
- maxAttempts: 3,
269
+ maxAttempts: 2,
212
270
  },
213
271
  });
214
272
 
@@ -1,4 +1,4 @@
1
- import { A as AIError, c as extractTextContent, a as ContextLengthError, M as ModelNotFoundError, R as RateLimitError, e as extractRetryAfterSeconds, b as AuthenticationError } from "./index-BT4thAvS.js";
1
+ import { b as normalizeBaseAIOptions, A as AIError, n as normalizeChatOptions, p as prepareRequestControls, f as extractTextContent, c as ContextLengthError, M as ModelNotFoundError, R as RateLimitError, e as extractRetryAfterSeconds, d as AuthenticationError } from "./index-DCXO0nZA.js";
2
2
  import { e as emitUsage } from "./usage-DMWiJ2oB.js";
3
3
  class AnthropicProvider {
4
4
  options;
@@ -9,11 +9,11 @@ class AnthropicProvider {
9
9
  * @param options - Configuration options for the Anthropic provider
10
10
  */
11
11
  constructor(options) {
12
- this.options = {
12
+ this.options = normalizeBaseAIOptions({
13
13
  defaultModel: "claude-3-5-sonnet-20241022",
14
14
  anthropicVersion: "2023-06-01",
15
15
  ...options
16
- };
16
+ });
17
17
  this.initializeClientSync();
18
18
  }
19
19
  initializeClientSync() {
@@ -82,14 +82,17 @@ class AnthropicProvider {
82
82
  */
83
83
  async chat(messages, options = {}) {
84
84
  const startTime = Date.now();
85
+ let controls;
85
86
  try {
86
87
  await this.ensureClient();
87
88
  const { system, anthropicMessages } = this.mapMessagesToAnthropic(messages);
88
89
  const model = options.model || this.options.defaultModel;
90
+ options = normalizeChatOptions(this.options, options, "anthropic", model);
91
+ controls = prepareRequestControls(this.options, options);
89
92
  const requestParams = {
90
93
  model,
91
94
  messages: anthropicMessages,
92
- max_tokens: options.maxTokens || 4096,
95
+ max_tokens: options.maxTokens,
93
96
  temperature: options.temperature,
94
97
  top_p: options.topP,
95
98
  stop_sequences: Array.isArray(options.stop) ? options.stop : options.stop ? [options.stop] : void 0,
@@ -102,11 +105,20 @@ class AnthropicProvider {
102
105
  tool_choice: this.mapToolChoice(options.toolChoice),
103
106
  stream: false
104
107
  };
108
+ if ((options.reasoning?.maxTokens || 0) > 0) {
109
+ requestParams.thinking = {
110
+ type: "enabled",
111
+ budget_tokens: options.reasoning?.maxTokens
112
+ };
113
+ }
105
114
  if (options.responseFormat?.type === "json_object") {
106
115
  const jsonInstruction = "\n\nIMPORTANT: You must respond with valid JSON only. Do not include any explanatory text outside the JSON object.";
107
116
  requestParams.system = requestParams.system ? requestParams.system + jsonInstruction : jsonInstruction.trim();
108
117
  }
109
- const response = await this.client.messages.create(requestParams);
118
+ const response = await this.client.messages.create(requestParams, {
119
+ signal: controls.signal,
120
+ timeout: controls.timeout
121
+ });
110
122
  const textContent = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
111
123
  const toolCalls = response.content.filter((block) => block.type === "tool_use").map((block) => ({
112
124
  id: block.id,
@@ -138,7 +150,25 @@ class AnthropicProvider {
138
150
  toolCalls: toolCalls.length > 0 ? toolCalls : void 0
139
151
  };
140
152
  } catch (error) {
153
+ if (controls?.didTimeout()) {
154
+ throw new AIError(
155
+ `AI request timed out after ${controls.timeout}ms`,
156
+ "AI_TIMEOUT",
157
+ "anthropic",
158
+ options.model
159
+ );
160
+ }
161
+ if (options.signal?.aborted) {
162
+ throw new AIError(
163
+ "AI request aborted by caller",
164
+ "AI_ABORTED",
165
+ "anthropic",
166
+ options.model
167
+ );
168
+ }
141
169
  throw this.mapError(error);
170
+ } finally {
171
+ controls?.cleanup();
142
172
  }
143
173
  }
144
174
  async complete(prompt, options = {}) {
@@ -151,6 +181,9 @@ class AnthropicProvider {
151
181
  stop: options.stop,
152
182
  stream: options.stream,
153
183
  onProgress: options.onProgress,
184
+ signal: options.signal,
185
+ timeout: options.timeout,
186
+ reasoning: options.reasoning,
154
187
  usageTags: options.usageTags
155
188
  });
156
189
  }
@@ -194,6 +227,9 @@ class AnthropicProvider {
194
227
  tools: options.tools,
195
228
  toolChoice: options.toolChoice,
196
229
  onProgress: options.onProgress,
230
+ signal: options.signal,
231
+ timeout: options.timeout,
232
+ reasoning: options.reasoning,
197
233
  usageTags: options.usageTags
198
234
  });
199
235
  return response.content;
@@ -228,19 +264,32 @@ class AnthropicProvider {
228
264
  }
229
265
  async *stream(messages, options = {}) {
230
266
  const startTime = Date.now();
267
+ let controls;
231
268
  try {
232
269
  await this.ensureClient();
233
270
  const { system, anthropicMessages } = this.mapMessagesToAnthropic(messages);
234
271
  const model = options.model || this.options.defaultModel;
235
- const stream = await this.client.messages.create({
272
+ options = normalizeChatOptions(this.options, options, "anthropic", model);
273
+ controls = prepareRequestControls(this.options, options);
274
+ const requestParams = {
236
275
  model,
237
276
  messages: anthropicMessages,
238
- max_tokens: options.maxTokens || 4096,
277
+ max_tokens: options.maxTokens,
239
278
  temperature: options.temperature,
240
279
  top_p: options.topP,
241
280
  stop_sequences: Array.isArray(options.stop) ? options.stop : options.stop ? [options.stop] : void 0,
242
281
  system: system || void 0,
243
282
  stream: true
283
+ };
284
+ if ((options.reasoning?.maxTokens || 0) > 0) {
285
+ requestParams.thinking = {
286
+ type: "enabled",
287
+ budget_tokens: options.reasoning?.maxTokens
288
+ };
289
+ }
290
+ const stream = await this.client.messages.create(requestParams, {
291
+ signal: controls.signal,
292
+ timeout: controls.timeout
244
293
  });
245
294
  for await (const chunk of stream) {
246
295
  if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
@@ -260,7 +309,25 @@ class AnthropicProvider {
260
309
  options.usageTags
261
310
  );
262
311
  } catch (error) {
312
+ if (controls?.didTimeout()) {
313
+ throw new AIError(
314
+ `AI request timed out after ${controls.timeout}ms`,
315
+ "AI_TIMEOUT",
316
+ "anthropic",
317
+ options.model
318
+ );
319
+ }
320
+ if (options.signal?.aborted) {
321
+ throw new AIError(
322
+ "AI request aborted by caller",
323
+ "AI_ABORTED",
324
+ "anthropic",
325
+ options.model
326
+ );
327
+ }
263
328
  throw this.mapError(error);
329
+ } finally {
330
+ controls?.cleanup();
264
331
  }
265
332
  }
266
333
  async countTokens(text) {
@@ -460,4 +527,4 @@ ${textContent}` : textContent;
460
527
  export {
461
528
  AnthropicProvider
462
529
  };
463
- //# sourceMappingURL=anthropic-BRwbhwIl.js.map
530
+ //# sourceMappingURL=anthropic-2z-82zgr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-2z-82zgr.js","sources":["../../src/shared/providers/anthropic.ts"],"sourcesContent":["/**\n * Anthropic Claude provider implementation\n *\n * Provides a standardized interface for interacting with Anthropic's Claude models,\n * including chat completions, streaming responses, and vision capabilities.\n * Note: Claude models do not support embeddings - use OpenAI or another provider for that.\n */\n\nimport { extractRetryAfterSeconds } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n AnthropicOptions,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n RateLimitError,\n} from '../types';\nimport { emitUsage } from './usage';\n\n// Note: This implementation will require @anthropic-ai/sdk package\n// For now, this is a placeholder that defines the interface\n\n/**\n * Anthropic Claude provider implementation that handles all interactions with Anthropic's API.\n * Supports Claude models, streaming, vision capabilities, and function calling.\n * Does not support embeddings (use OpenAI or another provider for embeddings).\n */\nexport class AnthropicProvider implements AIInterface {\n private options: AnthropicOptions;\n private client: any; // Will be Anthropic instance from @anthropic-ai/sdk\n\n /**\n * Creates a new Anthropic provider instance\n * @param options - Configuration options for the Anthropic provider\n */\n constructor(options: AnthropicOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: 'claude-3-5-sonnet-20241022',\n anthropicVersion: '2023-06-01',\n ...options,\n });\n\n // Initialize Anthropic client\n this.initializeClientSync();\n }\n\n private initializeClientSync() {\n try {\n // Dynamic import in constructor - this will work if the package is installed\n import('@anthropic-ai/sdk')\n .then(({ Anthropic }) => {\n this.client = new Anthropic({\n apiKey: this.options.apiKey,\n baseURL: this.options.baseUrl,\n timeout: this.options.timeout,\n maxRetries: this.options.maxRetries,\n defaultHeaders: {\n 'anthropic-version': this.options.anthropicVersion,\n ...this.options.headers,\n },\n });\n })\n .catch(() => {\n // Client will be null and we'll handle it in methods\n });\n } catch (_error) {\n // Client will be null and we'll handle it in methods\n }\n }\n\n /**\n * Ensures the Anthropic client is initialized by dynamically importing the SDK\n * @throws {AIError} When the Anthropic SDK cannot be loaded\n * @private\n */\n private async ensureClient() {\n if (!this.client) {\n try {\n const { Anthropic } = await import('@anthropic-ai/sdk');\n this.client = new Anthropic({\n apiKey: this.options.apiKey,\n baseURL: this.options.baseUrl,\n timeout: this.options.timeout,\n maxRetries: this.options.maxRetries,\n defaultHeaders: {\n 'anthropic-version': this.options.anthropicVersion,\n ...this.options.headers,\n },\n });\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Anthropic client. Make sure @anthropic-ai/sdk is installed.',\n 'INITIALIZATION_ERROR',\n 'anthropic',\n );\n }\n }\n }\n\n /**\n * Generate a chat completion using Claude models\n * @param messages - Array of conversation messages\n * @param options - Optional configuration for the chat completion\n * @returns Promise resolving to the AI response with content and metadata\n * @throws {AIError} When the API request fails or SDK is not available\n *\n * @example\n * ```typescript\n * const response = await provider.chat([\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'Explain quantum computing' }\n * ], {\n * model: 'claude-3-5-sonnet-20241022',\n * maxTokens: 1000\n * });\n * ```\n */\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const { system, anthropicMessages } =\n this.mapMessagesToAnthropic(messages);\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'anthropic', model);\n controls = prepareRequestControls(this.options, options);\n\n // Build request parameters\n const requestParams: Record<string, any> = {\n model,\n messages: anthropicMessages,\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n system: system || undefined,\n tools:\n options.tools && options.tools.length > 0\n ? options.tools.map((tool) => ({\n name: tool.function.name,\n description: tool.function.description || '',\n input_schema: tool.function.parameters || { type: 'object' },\n }))\n : undefined,\n tool_choice: this.mapToolChoice(options.toolChoice),\n stream: false,\n };\n if ((options.reasoning?.maxTokens || 0) > 0) {\n requestParams.thinking = {\n type: 'enabled',\n budget_tokens: options.reasoning?.maxTokens,\n };\n }\n\n // Add response format if specified\n if (options.responseFormat?.type === 'json_object') {\n const jsonInstruction =\n '\\n\\nIMPORTANT: You must respond with valid JSON only. Do not include any explanatory text outside the JSON object.';\n requestParams.system = requestParams.system\n ? requestParams.system + jsonInstruction\n : jsonInstruction.trim();\n }\n\n const response = await this.client.messages.create(requestParams, {\n signal: controls.signal,\n timeout: controls.timeout,\n });\n\n // Extract text content and tool calls from response\n const textContent = response.content\n .filter((block: any) => block.type === 'text')\n .map((block: any) => block.text)\n .join('');\n\n const toolCalls = response.content\n .filter((block: any) => block.type === 'tool_use')\n .map((block: any) => ({\n id: block.id,\n type: 'function' as const,\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input),\n },\n }));\n\n const usage: TokenUsage = {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n };\n emitUsage(\n this.options,\n 'anthropic',\n 'chat',\n response.model || model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n content: textContent,\n model: response.model,\n finishReason: this.mapFinishReason(response.stop_reason),\n usage,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'anthropic',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'anthropic',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n n: options.n,\n stop: options.stop,\n stream: options.stream,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n });\n }\n\n /**\n * Simple message interface for single-turn interactions with optional history\n *\n * @param text - The message text to send\n * @param options - Configuration options including history, model, etc.\n * @returns Promise resolving to the response content string\n *\n * @example\n * ```typescript\n * // Simple usage\n * const response = await provider.message('Hello!');\n *\n * // With history\n * const response = await provider.message('What was my question?', {\n * history: [\n * { role: 'user', content: 'What is 2+2?' },\n * { role: 'assistant', content: '4' }\n * ]\n * });\n * ```\n */\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n // Build messages array from history + current message\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n });\n\n return response.content;\n }\n\n async embed(\n _text: string | string[],\n _options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n // Anthropic Claude doesn't provide embeddings API\n throw new AIError(\n 'Anthropic Claude does not support embeddings. Use OpenAI or another provider for embeddings.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async embedImage(\n _image: string | Buffer,\n _options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Anthropic Claude does not support image embeddings. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async describeImage(\n _image: string | Buffer,\n _prompt?: string,\n _options: ImageDescriptionOptions = {},\n ): Promise<string> {\n // Note: Claude does support vision, but we're keeping this as a stub for now\n // A full implementation could use the chat API with image content\n throw new AIError(\n 'Image description is not yet implemented for Anthropic. Use OpenAI or Gemini.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async generateImage(\n _prompt: string,\n _options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n throw new AIError(\n 'Anthropic Claude does not support image generation. Use OpenAI or Gemini.',\n 'NOT_SUPPORTED',\n 'anthropic',\n );\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const { system, anthropicMessages } =\n this.mapMessagesToAnthropic(messages);\n\n const model = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'anthropic', model);\n controls = prepareRequestControls(this.options, options);\n\n const requestParams: Record<string, any> = {\n model,\n messages: anthropicMessages,\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n system: system || undefined,\n stream: true,\n };\n if ((options.reasoning?.maxTokens || 0) > 0) {\n requestParams.thinking = {\n type: 'enabled',\n budget_tokens: options.reasoning?.maxTokens,\n };\n }\n const stream = await this.client.messages.create(requestParams, {\n signal: controls.signal,\n timeout: controls.timeout,\n });\n\n for await (const chunk of stream) {\n if (\n chunk.type === 'content_block_delta' &&\n chunk.delta.type === 'text_delta'\n ) {\n if (options.onProgress) {\n options.onProgress(chunk.delta.text);\n }\n yield chunk.delta.text;\n }\n }\n\n emitUsage(\n this.options,\n 'anthropic',\n 'stream',\n model!,\n undefined,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'anthropic',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'anthropic',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n // Anthropic doesn't provide a direct token counting API\n // This is an approximation - Claude uses a different tokenizer than OpenAI\n return Math.ceil(text.length / 3.5); // Slightly different ratio for Claude\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return static list of known Claude models\n return [\n {\n id: 'claude-3-5-sonnet-20241022',\n name: 'Claude 3.5 Sonnet',\n description: 'Most intelligent Claude model with balanced performance',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-5-haiku-20241022',\n name: 'Claude 3.5 Haiku',\n description: 'Fastest Claude model for simple tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-opus-20240229',\n name: 'Claude 3 Opus',\n description: 'Most powerful Claude model for complex tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-sonnet-20240229',\n name: 'Claude 3 Sonnet',\n description: 'Balanced Claude model for most tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'claude-3-haiku-20240307',\n name: 'Claude 3 Haiku',\n description: 'Fast Claude model for simple tasks',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: false,\n supportsVision: true,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: true,\n completion: true,\n embeddings: false, // Claude doesn't support embeddings\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 200000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'streaming',\n 'functions',\n 'vision',\n ],\n };\n }\n\n // ============================================================================\n // TTS Methods (Not supported - use Qwen3-TTS provider)\n // ============================================================================\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Anthropic provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'anthropic',\n );\n }\n\n private mapMessagesToAnthropic(messages: AIMessage[]): {\n system?: string;\n anthropicMessages: Array<{ role: 'user' | 'assistant'; content: string }>;\n } {\n // Anthropic handles system messages separately\n let system: string | undefined;\n const anthropicMessages: Array<{\n role: 'user' | 'assistant';\n content: string;\n }> = [];\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n if (message.role === 'system') {\n // Combine multiple system messages\n system = system ? `${system}\\n\\n${textContent}` : textContent;\n } else {\n anthropicMessages.push({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content: textContent,\n });\n }\n }\n\n return { system, anthropicMessages };\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): any {\n if (!toolChoice || toolChoice === 'auto') {\n return { type: 'auto' };\n }\n\n if (toolChoice === 'none') {\n return undefined; // Anthropic doesn't have explicit 'none', just omit tools\n }\n\n if (typeof toolChoice === 'object' && toolChoice.type === 'function') {\n return {\n type: 'tool',\n name: toolChoice.function.name,\n };\n }\n\n return { type: 'auto' };\n }\n\n private mapFinishReason(reason: string | null): AIResponse['finishReason'] {\n switch (reason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool_calls';\n default:\n return 'stop';\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common HTTP status codes from Anthropic API\n if (typeof error === 'object' && error !== null && 'status' in error) {\n const apiError = error as { status: number; message?: string };\n switch (apiError.status) {\n case 401:\n return new AuthenticationError('anthropic');\n case 429:\n return new RateLimitError(\n 'anthropic',\n extractRetryAfterSeconds(error),\n );\n case 404:\n return new ModelNotFoundError(\n apiError.message || 'Model not found',\n 'anthropic',\n );\n case 413:\n return new ContextLengthError('anthropic');\n }\n }\n\n const errorMessage =\n error instanceof Error\n ? error.message\n : 'Unknown Anthropic error occurred';\n return new AIError(errorMessage, 'UNKNOWN_ERROR', 'anthropic');\n }\n}\n"],"names":[],"mappings":"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"}