@tanstack/ai-anthropic 0.0.1 → 0.0.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.
@@ -149,11 +149,14 @@ class Anthropic extends BaseAdapter {
149
149
  }
150
150
  convertContentPartToAnthropic(part) {
151
151
  switch (part.type) {
152
- case "text":
152
+ case "text": {
153
+ const metadata = part.metadata;
153
154
  return {
154
155
  type: "text",
155
- text: part.content
156
+ text: part.content,
157
+ ...metadata
156
158
  };
159
+ }
157
160
  case "image": {
158
161
  const metadata = part.metadata;
159
162
  const imageSource = part.source.type === "data" ? {
@@ -164,12 +167,15 @@ class Anthropic extends BaseAdapter {
164
167
  type: "url",
165
168
  url: part.source.value
166
169
  };
170
+ const { mediaType, ...meta } = metadata || {};
167
171
  return {
168
172
  type: "image",
169
- source: imageSource
173
+ source: imageSource,
174
+ ...meta
170
175
  };
171
176
  }
172
177
  case "document": {
178
+ const metadata = part.metadata;
173
179
  const docSource = part.source.type === "data" ? {
174
180
  type: "base64",
175
181
  data: part.source.value,
@@ -180,7 +186,8 @@ class Anthropic extends BaseAdapter {
180
186
  };
181
187
  return {
182
188
  type: "document",
183
- source: docSource
189
+ source: docSource,
190
+ ...metadata
184
191
  };
185
192
  }
186
193
  case "audio":
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-adapter.js","sources":["../../src/anthropic-adapter.ts"],"sourcesContent":["import Anthropic_SDK from '@anthropic-ai/sdk'\nimport { BaseAdapter } from '@tanstack/ai'\nimport { ANTHROPIC_MODELS } from './model-meta'\nimport { convertToolsToProviderFormat } from './tools/tool-converter'\nimport { validateTextProviderOptions } from './text/text-provider-options'\nimport type {\n AnthropicImageMetadata,\n AnthropicMessageMetadataByModality,\n} from './message-types'\nimport type {\n ChatOptions,\n ContentPart,\n EmbeddingOptions,\n EmbeddingResult,\n ModelMessage,\n StreamChunk,\n SummarizationOptions,\n SummarizationResult,\n} from '@tanstack/ai'\nimport type {\n AnthropicChatModelProviderOptionsByName,\n AnthropicModelInputModalitiesByName,\n} from './model-meta'\nimport type {\n ExternalTextProviderOptions,\n InternalTextProviderOptions,\n} from './text/text-provider-options'\nimport type {\n Base64ImageSource,\n Base64PDFSource,\n DocumentBlockParam,\n ImageBlockParam,\n MessageParam,\n TextBlockParam,\n URLImageSource,\n URLPDFSource,\n} from '@anthropic-ai/sdk/resources/messages'\n\nexport interface AnthropicConfig {\n apiKey: string\n}\n\n/**\n * Anthropic-specific provider options\n * @see https://ai-sdk.dev/providers/ai-sdk-providers/anthropic\n */\nexport type AnthropicProviderOptions = ExternalTextProviderOptions\n\ntype AnthropicContentBlocks =\n Extract<MessageParam['content'], Array<unknown>> extends Array<infer Block>\n ? Array<Block>\n : never\ntype AnthropicContentBlock =\n AnthropicContentBlocks extends Array<infer Block> ? Block : never\n\nexport class Anthropic extends BaseAdapter<\n typeof ANTHROPIC_MODELS,\n [],\n AnthropicProviderOptions,\n Record<string, any>,\n AnthropicChatModelProviderOptionsByName,\n AnthropicModelInputModalitiesByName,\n AnthropicMessageMetadataByModality\n> {\n name = 'anthropic' as const\n models = ANTHROPIC_MODELS\n\n declare _modelProviderOptionsByName: AnthropicChatModelProviderOptionsByName\n declare _modelInputModalitiesByName: AnthropicModelInputModalitiesByName\n declare _messageMetadataByModality: AnthropicMessageMetadataByModality\n\n private client: Anthropic_SDK\n\n constructor(config: AnthropicConfig) {\n super({})\n this.client = new Anthropic_SDK({\n apiKey: config.apiKey,\n })\n }\n\n async *chatStream(\n options: ChatOptions<string, AnthropicProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n try {\n // Map common options to Anthropic format using the centralized mapping function\n const requestParams = this.mapCommonOptionsToAnthropic(options)\n\n const stream = await this.client.beta.messages.create(\n { ...requestParams, stream: true },\n {\n signal: options.request?.signal,\n headers: options.request?.headers,\n },\n )\n\n yield* this.processAnthropicStream(stream, options.model, () =>\n this.generateId(),\n )\n } catch (error: any) {\n console.error('[Anthropic Adapter] Error in chatStream:', {\n message: error?.message,\n status: error?.status,\n statusText: error?.statusText,\n code: error?.code,\n type: error?.type,\n error: error,\n stack: error?.stack,\n })\n\n // Emit an error chunk\n yield {\n type: 'error',\n id: this.generateId(),\n model: options.model,\n timestamp: Date.now(),\n error: {\n message: error?.message || 'Unknown error occurred',\n code: error?.code || error?.status,\n },\n }\n }\n }\n\n async summarize(options: SummarizationOptions): Promise<SummarizationResult> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n const response = await this.client.messages.create({\n model: options.model,\n messages: [{ role: 'user', content: options.text }],\n system: systemPrompt,\n max_tokens: options.maxLength || 500,\n temperature: 0.3,\n stream: false,\n })\n\n const content = response.content\n .map((c) => (c.type === 'text' ? c.text : ''))\n .join('')\n\n return {\n id: response.id,\n model: response.model,\n summary: content,\n usage: {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n },\n }\n }\n\n createEmbeddings(_options: EmbeddingOptions): Promise<EmbeddingResult> {\n // Note: Anthropic doesn't have a native embeddings API\n // You would need to use a different service or implement a workaround\n throw new Error(\n 'Embeddings are not natively supported by Anthropic. Consider using OpenAI or another provider for embeddings.',\n )\n }\n\n private buildSummarizationPrompt(options: SummarizationOptions): string {\n let prompt = 'You are a professional summarizer. '\n\n switch (options.style) {\n case 'bullet-points':\n prompt += 'Provide a summary in bullet point format. '\n break\n case 'paragraph':\n prompt += 'Provide a summary in paragraph format. '\n break\n case 'concise':\n prompt += 'Provide a very concise summary in 1-2 sentences. '\n break\n default:\n prompt += 'Provide a clear and concise summary. '\n }\n\n if (options.focus && options.focus.length > 0) {\n prompt += `Focus on the following aspects: ${options.focus.join(', ')}. `\n }\n\n if (options.maxLength) {\n prompt += `Keep the summary under ${options.maxLength} tokens. `\n }\n\n return prompt\n }\n\n /**\n * Maps common options to Anthropic-specific format\n * Handles translation of normalized options to Anthropic's API format\n */\n private mapCommonOptionsToAnthropic(\n options: ChatOptions<string, AnthropicProviderOptions>,\n ) {\n const providerOptions = options.providerOptions as\n | InternalTextProviderOptions\n | undefined\n\n const formattedMessages = this.formatMessages(options.messages)\n const tools = options.tools\n ? convertToolsToProviderFormat(options.tools)\n : undefined\n\n // Filter out invalid fields from providerOptions (like 'store' which is OpenAI-specific)\n const validProviderOptions: Partial<InternalTextProviderOptions> = {}\n if (providerOptions) {\n const validKeys: Array<keyof InternalTextProviderOptions> = [\n 'container',\n 'context_management',\n 'mcp_servers',\n 'service_tier',\n 'stop_sequences',\n 'system',\n 'thinking',\n 'tool_choice',\n 'top_k',\n ]\n for (const key of validKeys) {\n if (key in providerOptions) {\n const value = providerOptions[key]\n // Anthropic expects tool_choice to be an object, not a string\n if (key === 'tool_choice' && typeof value === 'string') {\n ;(validProviderOptions as any)[key] = { type: value }\n } else {\n ;(validProviderOptions as any)[key] = value\n }\n }\n }\n }\n\n // Ensure max_tokens is greater than thinking.budget_tokens if thinking is enabled\n const thinkingBudget =\n validProviderOptions.thinking?.type === 'enabled'\n ? validProviderOptions.thinking.budget_tokens\n : undefined\n const defaultMaxTokens = options.options?.maxTokens || 1024\n const maxTokens =\n thinkingBudget && thinkingBudget >= defaultMaxTokens\n ? thinkingBudget + 1 // Ensure max_tokens is greater than budget_tokens\n : defaultMaxTokens\n\n const requestParams: InternalTextProviderOptions = {\n model: options.model,\n max_tokens: maxTokens,\n temperature: options.options?.temperature,\n top_p: options.options?.topP,\n messages: formattedMessages,\n system: options.systemPrompts?.join('\\n'),\n tools: tools,\n ...validProviderOptions,\n }\n validateTextProviderOptions(requestParams)\n return requestParams\n }\n\n private convertContentPartToAnthropic(\n part: ContentPart,\n ): TextBlockParam | ImageBlockParam | DocumentBlockParam {\n switch (part.type) {\n case 'text':\n return {\n type: 'text',\n text: part.content,\n }\n case 'image': {\n const metadata = part.metadata as any as\n | AnthropicImageMetadata\n | undefined\n const imageSource: Base64ImageSource | URLImageSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: metadata?.mediaType ?? 'image/jpeg',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'image',\n source: imageSource,\n }\n }\n case 'document': {\n const docSource: Base64PDFSource | URLPDFSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: 'application/pdf',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'document',\n source: docSource,\n }\n }\n case 'audio':\n case 'video':\n // Anthropic doesn't support audio/video directly, treat as text with a note\n throw new Error(\n `Anthropic does not support ${part.type} content directly`,\n )\n default: {\n // Exhaustive check - this should never happen with known types\n const _exhaustiveCheck: never = part\n throw new Error(\n `Unsupported content part type: ${(_exhaustiveCheck as ContentPart).type}`,\n )\n }\n }\n }\n\n private formatMessages(\n messages: Array<ModelMessage>,\n ): InternalTextProviderOptions['messages'] {\n const formattedMessages: InternalTextProviderOptions['messages'] = []\n\n for (const message of messages) {\n const role = message.role\n\n if (role === 'tool' && message.toolCallId) {\n formattedMessages.push({\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: message.toolCallId,\n content:\n typeof message.content === 'string' ? message.content : '',\n },\n ],\n })\n continue\n }\n\n if (role === 'assistant' && message.toolCalls?.length) {\n const contentBlocks: AnthropicContentBlocks = []\n\n if (message.content) {\n const content =\n typeof message.content === 'string' ? message.content : ''\n const textBlock: AnthropicContentBlock = {\n type: 'text',\n text: content,\n }\n contentBlocks.push(textBlock)\n }\n\n for (const toolCall of message.toolCalls) {\n let parsedInput: unknown = {}\n try {\n parsedInput = toolCall.function.arguments\n ? JSON.parse(toolCall.function.arguments)\n : {}\n } catch {\n parsedInput = toolCall.function.arguments\n }\n\n const toolUseBlock: AnthropicContentBlock = {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parsedInput,\n }\n contentBlocks.push(toolUseBlock)\n }\n\n formattedMessages.push({\n role: 'assistant',\n content: contentBlocks,\n })\n\n continue\n }\n\n // Handle user messages with multimodal content\n if (role === 'user' && Array.isArray(message.content)) {\n const contentBlocks = message.content.map((part) =>\n this.convertContentPartToAnthropic(part),\n )\n formattedMessages.push({\n role: 'user',\n content: contentBlocks,\n })\n continue\n }\n\n formattedMessages.push({\n role: role === 'assistant' ? 'assistant' : 'user',\n content:\n typeof message.content === 'string'\n ? message.content\n : message.content\n ? message.content.map((c) =>\n this.convertContentPartToAnthropic(c),\n )\n : '',\n })\n }\n\n return formattedMessages\n }\n\n private async *processAnthropicStream(\n stream: AsyncIterable<Anthropic_SDK.Beta.BetaRawMessageStreamEvent>,\n model: string,\n generateId: () => string,\n ): AsyncIterable<StreamChunk> {\n let accumulatedContent = ''\n let accumulatedThinking = ''\n const timestamp = Date.now()\n const toolCallsMap = new Map<\n number,\n { id: string; name: string; input: string }\n >()\n let currentToolIndex = -1\n\n try {\n for await (const event of stream) {\n if (event.type === 'content_block_start') {\n if (event.content_block.type === 'tool_use') {\n currentToolIndex++\n toolCallsMap.set(currentToolIndex, {\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n })\n } else if (event.content_block.type === 'thinking') {\n // Reset thinking content when a new thinking block starts\n accumulatedThinking = ''\n }\n } else if (event.type === 'content_block_delta') {\n if (event.delta.type === 'text_delta') {\n const delta = event.delta.text\n accumulatedContent += delta\n yield {\n type: 'content',\n id: generateId(),\n model: model,\n timestamp,\n delta,\n content: accumulatedContent,\n role: 'assistant',\n }\n } else if (event.delta.type === 'thinking_delta') {\n // Handle thinking content\n const delta = event.delta.thinking\n accumulatedThinking += delta\n yield {\n type: 'thinking',\n id: generateId(),\n model: model,\n timestamp,\n delta,\n content: accumulatedThinking,\n }\n } else if (event.delta.type === 'input_json_delta') {\n // Tool input is being streamed\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing) {\n // Accumulate the input for final processing\n existing.input += event.delta.partial_json\n\n // Yield the DELTA (partial_json), not the full accumulated input\n // The stream processor will concatenate these deltas\n yield {\n type: 'tool_call',\n id: generateId(),\n model: model,\n timestamp,\n toolCall: {\n id: existing.id,\n type: 'function',\n function: {\n name: existing.name,\n arguments: event.delta.partial_json,\n },\n },\n index: currentToolIndex,\n }\n }\n }\n } else if (event.type === 'content_block_stop') {\n // If this is a tool call and we haven't received any input deltas,\n // emit a tool_call chunk with empty arguments\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing && existing.input === '') {\n // No input_json_delta events received, emit empty arguments\n yield {\n type: 'tool_call',\n id: generateId(),\n model: model,\n timestamp,\n toolCall: {\n id: existing.id,\n type: 'function',\n function: {\n name: existing.name,\n arguments: '{}',\n },\n },\n index: currentToolIndex,\n }\n }\n } else if (event.type === 'message_stop') {\n yield {\n type: 'done',\n id: generateId(),\n model: model,\n timestamp,\n finishReason: 'stop',\n }\n } else if (event.type === 'message_delta') {\n if (event.delta.stop_reason) {\n switch (event.delta.stop_reason) {\n case 'tool_use': {\n yield {\n type: 'done',\n id: generateId(),\n model: model,\n timestamp,\n finishReason: 'tool_calls',\n\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n break\n }\n case 'max_tokens': {\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message:\n 'The response was cut off because the maximum token limit was reached.',\n code: 'max_tokens',\n },\n }\n break\n }\n case 'model_context_window_exceeded': {\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message:\n \"The response was cut off because the model's context window was exceeded.\",\n code: 'context_window_exceeded',\n },\n }\n break\n }\n case 'refusal': {\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message: 'The model refused to complete the request.',\n code: 'refusal',\n },\n }\n break\n }\n default: {\n yield {\n type: 'done',\n id: generateId(),\n model: model,\n timestamp,\n finishReason: 'stop',\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n }\n }\n }\n }\n }\n } catch (error: any) {\n console.error('[Anthropic Adapter] Error in processAnthropicStream:', {\n message: error?.message,\n status: error?.status,\n statusText: error?.statusText,\n code: error?.code,\n type: error?.type,\n error: error,\n stack: error?.stack,\n })\n\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message: error?.message || 'Unknown error occurred',\n code: error?.code || error?.status,\n },\n }\n }\n }\n}\n/**\n * Creates an Anthropic adapter with simplified configuration\n * @param apiKey - Your Anthropic API key\n * @returns A fully configured Anthropic adapter instance\n *\n * @example\n * ```typescript\n * const anthropic = createAnthropic(\"sk-ant-...\");\n *\n * const ai = new AI({\n * adapters: {\n * anthropic,\n * }\n * });\n * ```\n */\nexport function createAnthropic(\n apiKey: string,\n config?: Omit<AnthropicConfig, 'apiKey'>,\n): Anthropic {\n return new Anthropic({ apiKey, ...config })\n}\n\n/**\n * Create an Anthropic adapter with automatic API key detection from environment variables.\n *\n * Looks for `ANTHROPIC_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Anthropic adapter instance\n * @throws Error if ANTHROPIC_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses ANTHROPIC_API_KEY from environment\n * const aiInstance = ai(anthropic());\n * ```\n */\nexport function anthropic(config?: Omit<AnthropicConfig, 'apiKey'>): Anthropic {\n const env =\n typeof globalThis !== 'undefined' && (globalThis as any).window?.env\n ? (globalThis as any).window.env\n : typeof process !== 'undefined'\n ? process.env\n : undefined\n const key = env?.ANTHROPIC_API_KEY\n\n if (!key) {\n throw new Error(\n 'ANTHROPIC_API_KEY is required. Please set it in your environment variables or use createAnthropic(apiKey, config) instead.',\n )\n }\n\n return createAnthropic(key, config)\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"anthropic-adapter.js","sources":["../../src/anthropic-adapter.ts"],"sourcesContent":["import Anthropic_SDK from '@anthropic-ai/sdk'\nimport { BaseAdapter } from '@tanstack/ai'\nimport { ANTHROPIC_MODELS } from './model-meta'\nimport { convertToolsToProviderFormat } from './tools/tool-converter'\nimport { validateTextProviderOptions } from './text/text-provider-options'\nimport type {\n AnthropicDocumentMetadata,\n AnthropicImageMetadata,\n AnthropicMessageMetadataByModality,\n AnthropicTextMetadata,\n} from './message-types'\nimport type {\n ChatOptions,\n ContentPart,\n EmbeddingOptions,\n EmbeddingResult,\n ModelMessage,\n StreamChunk,\n SummarizationOptions,\n SummarizationResult,\n} from '@tanstack/ai'\nimport type {\n AnthropicChatModelProviderOptionsByName,\n AnthropicModelInputModalitiesByName,\n} from './model-meta'\nimport type {\n ExternalTextProviderOptions,\n InternalTextProviderOptions,\n} from './text/text-provider-options'\nimport type {\n Base64ImageSource,\n Base64PDFSource,\n DocumentBlockParam,\n ImageBlockParam,\n MessageParam,\n TextBlockParam,\n URLImageSource,\n URLPDFSource,\n} from '@anthropic-ai/sdk/resources/messages'\n\nexport interface AnthropicConfig {\n apiKey: string\n}\n\n/**\n * Anthropic-specific provider options\n * @see https://ai-sdk.dev/providers/ai-sdk-providers/anthropic\n */\nexport type AnthropicProviderOptions = ExternalTextProviderOptions\n\ntype AnthropicContentBlocks =\n Extract<MessageParam['content'], Array<unknown>> extends Array<infer Block>\n ? Array<Block>\n : never\ntype AnthropicContentBlock =\n AnthropicContentBlocks extends Array<infer Block> ? Block : never\n\nexport class Anthropic extends BaseAdapter<\n typeof ANTHROPIC_MODELS,\n [],\n AnthropicProviderOptions,\n Record<string, any>,\n AnthropicChatModelProviderOptionsByName,\n AnthropicModelInputModalitiesByName,\n AnthropicMessageMetadataByModality\n> {\n name = 'anthropic' as const\n models = ANTHROPIC_MODELS\n\n declare _modelProviderOptionsByName: AnthropicChatModelProviderOptionsByName\n declare _modelInputModalitiesByName: AnthropicModelInputModalitiesByName\n declare _messageMetadataByModality: AnthropicMessageMetadataByModality\n\n private client: Anthropic_SDK\n\n constructor(config: AnthropicConfig) {\n super({})\n this.client = new Anthropic_SDK({\n apiKey: config.apiKey,\n })\n }\n\n async *chatStream(\n options: ChatOptions<string, AnthropicProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n try {\n // Map common options to Anthropic format using the centralized mapping function\n const requestParams = this.mapCommonOptionsToAnthropic(options)\n\n const stream = await this.client.beta.messages.create(\n { ...requestParams, stream: true },\n {\n signal: options.request?.signal,\n headers: options.request?.headers,\n },\n )\n\n yield* this.processAnthropicStream(stream, options.model, () =>\n this.generateId(),\n )\n } catch (error: any) {\n console.error('[Anthropic Adapter] Error in chatStream:', {\n message: error?.message,\n status: error?.status,\n statusText: error?.statusText,\n code: error?.code,\n type: error?.type,\n error: error,\n stack: error?.stack,\n })\n\n // Emit an error chunk\n yield {\n type: 'error',\n id: this.generateId(),\n model: options.model,\n timestamp: Date.now(),\n error: {\n message: error?.message || 'Unknown error occurred',\n code: error?.code || error?.status,\n },\n }\n }\n }\n\n async summarize(options: SummarizationOptions): Promise<SummarizationResult> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n const response = await this.client.messages.create({\n model: options.model,\n messages: [{ role: 'user', content: options.text }],\n system: systemPrompt,\n max_tokens: options.maxLength || 500,\n temperature: 0.3,\n stream: false,\n })\n\n const content = response.content\n .map((c) => (c.type === 'text' ? c.text : ''))\n .join('')\n\n return {\n id: response.id,\n model: response.model,\n summary: content,\n usage: {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n },\n }\n }\n\n createEmbeddings(_options: EmbeddingOptions): Promise<EmbeddingResult> {\n // Note: Anthropic doesn't have a native embeddings API\n // You would need to use a different service or implement a workaround\n throw new Error(\n 'Embeddings are not natively supported by Anthropic. Consider using OpenAI or another provider for embeddings.',\n )\n }\n\n private buildSummarizationPrompt(options: SummarizationOptions): string {\n let prompt = 'You are a professional summarizer. '\n\n switch (options.style) {\n case 'bullet-points':\n prompt += 'Provide a summary in bullet point format. '\n break\n case 'paragraph':\n prompt += 'Provide a summary in paragraph format. '\n break\n case 'concise':\n prompt += 'Provide a very concise summary in 1-2 sentences. '\n break\n default:\n prompt += 'Provide a clear and concise summary. '\n }\n\n if (options.focus && options.focus.length > 0) {\n prompt += `Focus on the following aspects: ${options.focus.join(', ')}. `\n }\n\n if (options.maxLength) {\n prompt += `Keep the summary under ${options.maxLength} tokens. `\n }\n\n return prompt\n }\n\n /**\n * Maps common options to Anthropic-specific format\n * Handles translation of normalized options to Anthropic's API format\n */\n private mapCommonOptionsToAnthropic(\n options: ChatOptions<string, AnthropicProviderOptions>,\n ) {\n const providerOptions = options.providerOptions as\n | InternalTextProviderOptions\n | undefined\n\n const formattedMessages = this.formatMessages(options.messages)\n const tools = options.tools\n ? convertToolsToProviderFormat(options.tools)\n : undefined\n\n // Filter out invalid fields from providerOptions (like 'store' which is OpenAI-specific)\n const validProviderOptions: Partial<InternalTextProviderOptions> = {}\n if (providerOptions) {\n const validKeys: Array<keyof InternalTextProviderOptions> = [\n 'container',\n 'context_management',\n 'mcp_servers',\n 'service_tier',\n 'stop_sequences',\n 'system',\n 'thinking',\n 'tool_choice',\n 'top_k',\n ]\n for (const key of validKeys) {\n if (key in providerOptions) {\n const value = providerOptions[key]\n // Anthropic expects tool_choice to be an object, not a string\n if (key === 'tool_choice' && typeof value === 'string') {\n ;(validProviderOptions as any)[key] = { type: value }\n } else {\n ;(validProviderOptions as any)[key] = value\n }\n }\n }\n }\n\n // Ensure max_tokens is greater than thinking.budget_tokens if thinking is enabled\n const thinkingBudget =\n validProviderOptions.thinking?.type === 'enabled'\n ? validProviderOptions.thinking.budget_tokens\n : undefined\n const defaultMaxTokens = options.options?.maxTokens || 1024\n const maxTokens =\n thinkingBudget && thinkingBudget >= defaultMaxTokens\n ? thinkingBudget + 1 // Ensure max_tokens is greater than budget_tokens\n : defaultMaxTokens\n\n const requestParams: InternalTextProviderOptions = {\n model: options.model,\n max_tokens: maxTokens,\n temperature: options.options?.temperature,\n top_p: options.options?.topP,\n messages: formattedMessages,\n system: options.systemPrompts?.join('\\n'),\n tools: tools,\n ...validProviderOptions,\n }\n validateTextProviderOptions(requestParams)\n return requestParams\n }\n\n private convertContentPartToAnthropic(\n part: ContentPart,\n ): TextBlockParam | ImageBlockParam | DocumentBlockParam {\n switch (part.type) {\n case 'text': {\n const metadata = part.metadata as any as\n | AnthropicTextMetadata\n | undefined\n return {\n type: 'text',\n text: part.content,\n ...metadata,\n }\n }\n\n case 'image': {\n const metadata = part.metadata as any as\n | AnthropicImageMetadata\n | undefined\n const imageSource: Base64ImageSource | URLImageSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: metadata?.mediaType ?? 'image/jpeg',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n // exclude the media type\n const { mediaType, ...meta } = metadata || {}\n return {\n type: 'image',\n source: imageSource,\n ...meta,\n }\n }\n case 'document': {\n const metadata = part.metadata as any as\n | AnthropicDocumentMetadata\n | undefined\n const docSource: Base64PDFSource | URLPDFSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: 'application/pdf',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'document',\n source: docSource,\n ...metadata,\n }\n }\n case 'audio':\n case 'video':\n // Anthropic doesn't support audio/video directly, treat as text with a note\n throw new Error(\n `Anthropic does not support ${part.type} content directly`,\n )\n default: {\n // Exhaustive check - this should never happen with known types\n const _exhaustiveCheck: never = part\n throw new Error(\n `Unsupported content part type: ${(_exhaustiveCheck as ContentPart).type}`,\n )\n }\n }\n }\n\n private formatMessages(\n messages: Array<ModelMessage>,\n ): InternalTextProviderOptions['messages'] {\n const formattedMessages: InternalTextProviderOptions['messages'] = []\n\n for (const message of messages) {\n const role = message.role\n\n if (role === 'tool' && message.toolCallId) {\n formattedMessages.push({\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: message.toolCallId,\n content:\n typeof message.content === 'string' ? message.content : '',\n },\n ],\n })\n continue\n }\n\n if (role === 'assistant' && message.toolCalls?.length) {\n const contentBlocks: AnthropicContentBlocks = []\n\n if (message.content) {\n const content =\n typeof message.content === 'string' ? message.content : ''\n const textBlock: AnthropicContentBlock = {\n type: 'text',\n text: content,\n }\n contentBlocks.push(textBlock)\n }\n\n for (const toolCall of message.toolCalls) {\n let parsedInput: unknown = {}\n try {\n parsedInput = toolCall.function.arguments\n ? JSON.parse(toolCall.function.arguments)\n : {}\n } catch {\n parsedInput = toolCall.function.arguments\n }\n\n const toolUseBlock: AnthropicContentBlock = {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parsedInput,\n }\n contentBlocks.push(toolUseBlock)\n }\n\n formattedMessages.push({\n role: 'assistant',\n content: contentBlocks,\n })\n\n continue\n }\n\n // Handle user messages with multimodal content\n if (role === 'user' && Array.isArray(message.content)) {\n const contentBlocks = message.content.map((part) =>\n this.convertContentPartToAnthropic(part),\n )\n formattedMessages.push({\n role: 'user',\n content: contentBlocks,\n })\n continue\n }\n\n formattedMessages.push({\n role: role === 'assistant' ? 'assistant' : 'user',\n content:\n typeof message.content === 'string'\n ? message.content\n : message.content\n ? message.content.map((c) =>\n this.convertContentPartToAnthropic(c),\n )\n : '',\n })\n }\n\n return formattedMessages\n }\n\n private async *processAnthropicStream(\n stream: AsyncIterable<Anthropic_SDK.Beta.BetaRawMessageStreamEvent>,\n model: string,\n generateId: () => string,\n ): AsyncIterable<StreamChunk> {\n let accumulatedContent = ''\n let accumulatedThinking = ''\n const timestamp = Date.now()\n const toolCallsMap = new Map<\n number,\n { id: string; name: string; input: string }\n >()\n let currentToolIndex = -1\n\n try {\n for await (const event of stream) {\n if (event.type === 'content_block_start') {\n if (event.content_block.type === 'tool_use') {\n currentToolIndex++\n toolCallsMap.set(currentToolIndex, {\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n })\n } else if (event.content_block.type === 'thinking') {\n // Reset thinking content when a new thinking block starts\n accumulatedThinking = ''\n }\n } else if (event.type === 'content_block_delta') {\n if (event.delta.type === 'text_delta') {\n const delta = event.delta.text\n accumulatedContent += delta\n yield {\n type: 'content',\n id: generateId(),\n model: model,\n timestamp,\n delta,\n content: accumulatedContent,\n role: 'assistant',\n }\n } else if (event.delta.type === 'thinking_delta') {\n // Handle thinking content\n const delta = event.delta.thinking\n accumulatedThinking += delta\n yield {\n type: 'thinking',\n id: generateId(),\n model: model,\n timestamp,\n delta,\n content: accumulatedThinking,\n }\n } else if (event.delta.type === 'input_json_delta') {\n // Tool input is being streamed\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing) {\n // Accumulate the input for final processing\n existing.input += event.delta.partial_json\n\n // Yield the DELTA (partial_json), not the full accumulated input\n // The stream processor will concatenate these deltas\n yield {\n type: 'tool_call',\n id: generateId(),\n model: model,\n timestamp,\n toolCall: {\n id: existing.id,\n type: 'function',\n function: {\n name: existing.name,\n arguments: event.delta.partial_json,\n },\n },\n index: currentToolIndex,\n }\n }\n }\n } else if (event.type === 'content_block_stop') {\n // If this is a tool call and we haven't received any input deltas,\n // emit a tool_call chunk with empty arguments\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing && existing.input === '') {\n // No input_json_delta events received, emit empty arguments\n yield {\n type: 'tool_call',\n id: generateId(),\n model: model,\n timestamp,\n toolCall: {\n id: existing.id,\n type: 'function',\n function: {\n name: existing.name,\n arguments: '{}',\n },\n },\n index: currentToolIndex,\n }\n }\n } else if (event.type === 'message_stop') {\n yield {\n type: 'done',\n id: generateId(),\n model: model,\n timestamp,\n finishReason: 'stop',\n }\n } else if (event.type === 'message_delta') {\n if (event.delta.stop_reason) {\n switch (event.delta.stop_reason) {\n case 'tool_use': {\n yield {\n type: 'done',\n id: generateId(),\n model: model,\n timestamp,\n finishReason: 'tool_calls',\n\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n break\n }\n case 'max_tokens': {\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message:\n 'The response was cut off because the maximum token limit was reached.',\n code: 'max_tokens',\n },\n }\n break\n }\n case 'model_context_window_exceeded': {\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message:\n \"The response was cut off because the model's context window was exceeded.\",\n code: 'context_window_exceeded',\n },\n }\n break\n }\n case 'refusal': {\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message: 'The model refused to complete the request.',\n code: 'refusal',\n },\n }\n break\n }\n default: {\n yield {\n type: 'done',\n id: generateId(),\n model: model,\n timestamp,\n finishReason: 'stop',\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n }\n }\n }\n }\n }\n } catch (error: any) {\n console.error('[Anthropic Adapter] Error in processAnthropicStream:', {\n message: error?.message,\n status: error?.status,\n statusText: error?.statusText,\n code: error?.code,\n type: error?.type,\n error: error,\n stack: error?.stack,\n })\n\n yield {\n type: 'error',\n id: generateId(),\n model: model,\n timestamp,\n error: {\n message: error?.message || 'Unknown error occurred',\n code: error?.code || error?.status,\n },\n }\n }\n }\n}\n/**\n * Creates an Anthropic adapter with simplified configuration\n * @param apiKey - Your Anthropic API key\n * @returns A fully configured Anthropic adapter instance\n *\n * @example\n * ```typescript\n * const anthropic = createAnthropic(\"sk-ant-...\");\n *\n * const ai = new AI({\n * adapters: {\n * anthropic,\n * }\n * });\n * ```\n */\nexport function createAnthropic(\n apiKey: string,\n config?: Omit<AnthropicConfig, 'apiKey'>,\n): Anthropic {\n return new Anthropic({ apiKey, ...config })\n}\n\n/**\n * Create an Anthropic adapter with automatic API key detection from environment variables.\n *\n * Looks for `ANTHROPIC_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Anthropic adapter instance\n * @throws Error if ANTHROPIC_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses ANTHROPIC_API_KEY from environment\n * const aiInstance = ai(anthropic());\n * ```\n */\nexport function anthropic(config?: Omit<AnthropicConfig, 'apiKey'>): Anthropic {\n const env =\n typeof globalThis !== 'undefined' && (globalThis as any).window?.env\n ? (globalThis as any).window.env\n : typeof process !== 'undefined'\n ? process.env\n : undefined\n const key = env?.ANTHROPIC_API_KEY\n\n if (!key) {\n throw new Error(\n 'ANTHROPIC_API_KEY is required. Please set it in your environment variables or use createAnthropic(apiKey, config) instead.',\n )\n }\n\n return createAnthropic(key, config)\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export { Anthropic, createAnthropic, anthropic, type AnthropicConfig, } from './anthropic-adapter.js';
2
2
  export type { AnthropicChatModelProviderOptionsByName, AnthropicModelInputModalitiesByName, } from './model-meta.js';
3
- export type { AnthropicImageMetadata, AnthropicDocumentMetadata, AnthropicAudioMetadata, AnthropicVideoMetadata, AnthropicImageMediaType, AnthropicDocumentMediaType, AnthropicMessageMetadataByModality, } from './message-types.js';
3
+ export type { AnthropicTextMetadata, AnthropicImageMetadata, AnthropicDocumentMetadata, AnthropicAudioMetadata, AnthropicVideoMetadata, AnthropicImageMediaType, AnthropicDocumentMediaType, AnthropicMessageMetadataByModality, } from './message-types.js';
4
4
  export { convertToolsToProviderFormat } from './tools/tool-converter.js';
5
5
  export type { AnthropicTool, CustomTool } from './tools.js';
@@ -1,10 +1,4 @@
1
- /**
2
- * Anthropic-specific metadata types for multimodal content parts.
3
- * These types extend the base ContentPart metadata with Anthropic-specific options.
4
- *
5
- * @see https://docs.anthropic.com/claude/docs/vision
6
- * @see https://docs.anthropic.com/claude/docs/pdf-support
7
- */
1
+ import { CacheControlEphemeral, TextCitationParam } from '@anthropic-ai/sdk/resources';
8
2
  /**
9
3
  * Supported image media types for Anthropic.
10
4
  */
@@ -20,6 +14,20 @@ export interface AnthropicImageMetadata {
20
14
  * @see https://docs.anthropic.com/claude/docs/vision#supported-image-types
21
15
  */
22
16
  mediaType?: AnthropicImageMediaType;
17
+ /**
18
+ * Cache control settings for the image content.
19
+ */
20
+ cache_control?: CacheControlEphemeral;
21
+ }
22
+ export interface AnthropicTextMetadata {
23
+ /**
24
+ * Cache control settings for the text content.
25
+ */
26
+ cache_control?: CacheControlEphemeral;
27
+ /**
28
+ * Text citations to include with the text content.
29
+ */
30
+ citations?: Array<TextCitationParam>;
23
31
  }
24
32
  /**
25
33
  * Supported document media types for Anthropic.
@@ -36,6 +44,12 @@ export interface AnthropicDocumentMetadata {
36
44
  * @see https://docs.anthropic.com/claude/docs/pdf-support
37
45
  */
38
46
  mediaType?: AnthropicDocumentMediaType;
47
+ /**
48
+ * Cache control settings for the document.
49
+ */
50
+ cache_control?: CacheControlEphemeral;
51
+ context?: string;
52
+ title?: string;
39
53
  }
40
54
  /**
41
55
  * Metadata for Anthropic audio content parts.
@@ -62,6 +76,7 @@ export interface AnthropicVideoMetadata {
62
76
  * Used for type inference when constructing multimodal messages.
63
77
  */
64
78
  export interface AnthropicMessageMetadataByModality {
79
+ text: AnthropicTextMetadata;
65
80
  image: AnthropicImageMetadata;
66
81
  audio: AnthropicAudioMetadata;
67
82
  video: AnthropicVideoMetadata;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-anthropic",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Anthropic Claude adapter for TanStack AI",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -31,14 +31,14 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@anthropic-ai/sdk": "^0.71.0",
34
- "@tanstack/ai": "0.0.1"
34
+ "@tanstack/ai": "0.0.3"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@vitest/coverage-v8": "4.0.14",
38
38
  "zod": "^4.1.13"
39
39
  },
40
40
  "peerDependencies": {
41
- "@tanstack/ai": "0.0.1"
41
+ "@tanstack/ai": "0.0.3"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "vite build",
@@ -4,8 +4,10 @@ import { ANTHROPIC_MODELS } from './model-meta'
4
4
  import { convertToolsToProviderFormat } from './tools/tool-converter'
5
5
  import { validateTextProviderOptions } from './text/text-provider-options'
6
6
  import type {
7
+ AnthropicDocumentMetadata,
7
8
  AnthropicImageMetadata,
8
9
  AnthropicMessageMetadataByModality,
10
+ AnthropicTextMetadata,
9
11
  } from './message-types'
10
12
  import type {
11
13
  ChatOptions,
@@ -257,11 +259,17 @@ export class Anthropic extends BaseAdapter<
257
259
  part: ContentPart,
258
260
  ): TextBlockParam | ImageBlockParam | DocumentBlockParam {
259
261
  switch (part.type) {
260
- case 'text':
262
+ case 'text': {
263
+ const metadata = part.metadata as any as
264
+ | AnthropicTextMetadata
265
+ | undefined
261
266
  return {
262
267
  type: 'text',
263
268
  text: part.content,
269
+ ...metadata,
264
270
  }
271
+ }
272
+
265
273
  case 'image': {
266
274
  const metadata = part.metadata as any as
267
275
  | AnthropicImageMetadata
@@ -277,12 +285,18 @@ export class Anthropic extends BaseAdapter<
277
285
  type: 'url',
278
286
  url: part.source.value,
279
287
  }
288
+ // exclude the media type
289
+ const { mediaType, ...meta } = metadata || {}
280
290
  return {
281
291
  type: 'image',
282
292
  source: imageSource,
293
+ ...meta,
283
294
  }
284
295
  }
285
296
  case 'document': {
297
+ const metadata = part.metadata as any as
298
+ | AnthropicDocumentMetadata
299
+ | undefined
286
300
  const docSource: Base64PDFSource | URLPDFSource =
287
301
  part.source.type === 'data'
288
302
  ? {
@@ -297,6 +311,7 @@ export class Anthropic extends BaseAdapter<
297
311
  return {
298
312
  type: 'document',
299
313
  source: docSource,
314
+ ...metadata,
300
315
  }
301
316
  }
302
317
  case 'audio':
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export type {
9
9
  AnthropicModelInputModalitiesByName,
10
10
  } from './model-meta'
11
11
  export type {
12
+ AnthropicTextMetadata,
12
13
  AnthropicImageMetadata,
13
14
  AnthropicDocumentMetadata,
14
15
  AnthropicAudioMetadata,
@@ -6,6 +6,11 @@
6
6
  * @see https://docs.anthropic.com/claude/docs/pdf-support
7
7
  */
8
8
 
9
+ import type {
10
+ CacheControlEphemeral,
11
+ TextCitationParam,
12
+ } from '@anthropic-ai/sdk/resources'
13
+
9
14
  /**
10
15
  * Supported image media types for Anthropic.
11
16
  */
@@ -26,8 +31,22 @@ export interface AnthropicImageMetadata {
26
31
  * @see https://docs.anthropic.com/claude/docs/vision#supported-image-types
27
32
  */
28
33
  mediaType?: AnthropicImageMediaType
34
+ /**
35
+ * Cache control settings for the image content.
36
+ */
37
+ cache_control?: CacheControlEphemeral
29
38
  }
30
39
 
40
+ export interface AnthropicTextMetadata {
41
+ /**
42
+ * Cache control settings for the text content.
43
+ */
44
+ cache_control?: CacheControlEphemeral
45
+ /**
46
+ * Text citations to include with the text content.
47
+ */
48
+ citations?: Array<TextCitationParam>
49
+ }
31
50
  /**
32
51
  * Supported document media types for Anthropic.
33
52
  */
@@ -44,6 +63,14 @@ export interface AnthropicDocumentMetadata {
44
63
  * @see https://docs.anthropic.com/claude/docs/pdf-support
45
64
  */
46
65
  mediaType?: AnthropicDocumentMediaType
66
+ /**
67
+ * Cache control settings for the document.
68
+ */
69
+ cache_control?: CacheControlEphemeral
70
+
71
+ context?: string
72
+
73
+ title?: string
47
74
  }
48
75
 
49
76
  /**
@@ -78,6 +105,7 @@ export interface AnthropicVideoMetadata {
78
105
  * Used for type inference when constructing multimodal messages.
79
106
  */
80
107
  export interface AnthropicMessageMetadataByModality {
108
+ text: AnthropicTextMetadata
81
109
  image: AnthropicImageMetadata
82
110
  audio: AnthropicAudioMetadata
83
111
  video: AnthropicVideoMetadata