@tanstack/ai-anthropic 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ import { BaseSummarizeAdapter } from '@tanstack/ai/adapters';
2
+ import { ANTHROPIC_MODELS } from '../model-meta.js';
3
+ import { StreamChunk, SummarizationOptions, SummarizationResult } from '@tanstack/ai';
4
+ import { AnthropicClientConfig } from '../utils.js';
5
+ /**
6
+ * Configuration for Anthropic summarize adapter
7
+ */
8
+ export interface AnthropicSummarizeConfig extends AnthropicClientConfig {
9
+ }
10
+ /**
11
+ * Anthropic-specific provider options for summarization
12
+ */
13
+ export interface AnthropicSummarizeProviderOptions {
14
+ /** Temperature for response generation (0-1) */
15
+ temperature?: number;
16
+ /** Maximum tokens in the response */
17
+ maxTokens?: number;
18
+ }
19
+ /** Model type for Anthropic summarization */
20
+ export type AnthropicSummarizeModel = (typeof ANTHROPIC_MODELS)[number];
21
+ /**
22
+ * Anthropic Summarize Adapter
23
+ *
24
+ * Tree-shakeable adapter for Anthropic summarization functionality.
25
+ * Import only what you need for smaller bundle sizes.
26
+ */
27
+ export declare class AnthropicSummarizeAdapter<TModel extends AnthropicSummarizeModel> extends BaseSummarizeAdapter<TModel, AnthropicSummarizeProviderOptions> {
28
+ readonly kind: "summarize";
29
+ readonly name: "anthropic";
30
+ private client;
31
+ constructor(config: AnthropicSummarizeConfig, model: TModel);
32
+ summarize(options: SummarizationOptions): Promise<SummarizationResult>;
33
+ summarizeStream(options: SummarizationOptions): AsyncIterable<StreamChunk>;
34
+ private buildSummarizationPrompt;
35
+ }
36
+ /**
37
+ * Creates an Anthropic summarize adapter with explicit API key.
38
+ * Type resolution happens here at the call site.
39
+ *
40
+ * @param model - The model name (e.g., 'claude-sonnet-4-5', 'claude-3-5-haiku-latest')
41
+ * @param apiKey - Your Anthropic API key
42
+ * @param config - Optional additional configuration
43
+ * @returns Configured Anthropic summarize adapter instance with resolved types
44
+ */
45
+ export declare function createAnthropicSummarize<TModel extends AnthropicSummarizeModel>(model: TModel, apiKey: string, config?: Omit<AnthropicSummarizeConfig, 'apiKey'>): AnthropicSummarizeAdapter<TModel>;
46
+ /**
47
+ * Creates an Anthropic summarize adapter with automatic API key detection.
48
+ * Type resolution happens here at the call site.
49
+ *
50
+ * @param model - The model name (e.g., 'claude-sonnet-4-5', 'claude-3-5-haiku-latest')
51
+ * @param config - Optional configuration (excluding apiKey which is auto-detected)
52
+ * @returns Configured Anthropic summarize adapter instance with resolved types
53
+ */
54
+ export declare function anthropicSummarize<TModel extends AnthropicSummarizeModel>(model: TModel, config?: Omit<AnthropicSummarizeConfig, 'apiKey'>): AnthropicSummarizeAdapter<TModel>;
@@ -0,0 +1,117 @@
1
+ import { BaseSummarizeAdapter } from "@tanstack/ai/adapters";
2
+ import { createAnthropicClient, generateId, getAnthropicApiKeyFromEnv } from "../utils/client.js";
3
+ class AnthropicSummarizeAdapter extends BaseSummarizeAdapter {
4
+ constructor(config, model) {
5
+ super({}, model);
6
+ this.kind = "summarize";
7
+ this.name = "anthropic";
8
+ this.client = createAnthropicClient(config);
9
+ }
10
+ async summarize(options) {
11
+ const systemPrompt = this.buildSummarizationPrompt(options);
12
+ const response = await this.client.messages.create({
13
+ model: options.model,
14
+ messages: [{ role: "user", content: options.text }],
15
+ system: systemPrompt,
16
+ max_tokens: options.maxLength || 500,
17
+ temperature: 0.3,
18
+ stream: false
19
+ });
20
+ const content = response.content.map((c) => c.type === "text" ? c.text : "").join("");
21
+ return {
22
+ id: response.id,
23
+ model: response.model,
24
+ summary: content,
25
+ usage: {
26
+ promptTokens: response.usage.input_tokens,
27
+ completionTokens: response.usage.output_tokens,
28
+ totalTokens: response.usage.input_tokens + response.usage.output_tokens
29
+ }
30
+ };
31
+ }
32
+ async *summarizeStream(options) {
33
+ const systemPrompt = this.buildSummarizationPrompt(options);
34
+ const id = generateId(this.name);
35
+ const model = options.model;
36
+ let accumulatedContent = "";
37
+ let inputTokens = 0;
38
+ let outputTokens = 0;
39
+ const stream = await this.client.messages.create({
40
+ model: options.model,
41
+ messages: [{ role: "user", content: options.text }],
42
+ system: systemPrompt,
43
+ max_tokens: options.maxLength || 500,
44
+ temperature: 0.3,
45
+ stream: true
46
+ });
47
+ for await (const event of stream) {
48
+ if (event.type === "message_start") {
49
+ inputTokens = event.message.usage.input_tokens;
50
+ } else if (event.type === "content_block_delta") {
51
+ if (event.delta.type === "text_delta") {
52
+ const delta = event.delta.text;
53
+ accumulatedContent += delta;
54
+ yield {
55
+ type: "content",
56
+ id,
57
+ model,
58
+ timestamp: Date.now(),
59
+ delta,
60
+ content: accumulatedContent,
61
+ role: "assistant"
62
+ };
63
+ }
64
+ } else if (event.type === "message_delta") {
65
+ outputTokens = event.usage.output_tokens;
66
+ yield {
67
+ type: "done",
68
+ id,
69
+ model,
70
+ timestamp: Date.now(),
71
+ finishReason: event.delta.stop_reason,
72
+ usage: {
73
+ promptTokens: inputTokens,
74
+ completionTokens: outputTokens,
75
+ totalTokens: inputTokens + outputTokens
76
+ }
77
+ };
78
+ }
79
+ }
80
+ }
81
+ buildSummarizationPrompt(options) {
82
+ let prompt = "You are a professional summarizer. ";
83
+ switch (options.style) {
84
+ case "bullet-points":
85
+ prompt += "Provide a summary in bullet point format. ";
86
+ break;
87
+ case "paragraph":
88
+ prompt += "Provide a summary in paragraph format. ";
89
+ break;
90
+ case "concise":
91
+ prompt += "Provide a very concise summary in 1-2 sentences. ";
92
+ break;
93
+ default:
94
+ prompt += "Provide a clear and concise summary. ";
95
+ }
96
+ if (options.focus && options.focus.length > 0) {
97
+ prompt += `Focus on the following aspects: ${options.focus.join(", ")}. `;
98
+ }
99
+ if (options.maxLength) {
100
+ prompt += `Keep the summary under ${options.maxLength} tokens. `;
101
+ }
102
+ return prompt;
103
+ }
104
+ }
105
+ function createAnthropicSummarize(model, apiKey, config) {
106
+ return new AnthropicSummarizeAdapter({ apiKey, ...config }, model);
107
+ }
108
+ function anthropicSummarize(model, config) {
109
+ const apiKey = getAnthropicApiKeyFromEnv();
110
+ return createAnthropicSummarize(model, apiKey, config);
111
+ }
112
+ export {
113
+ AnthropicSummarizeAdapter,
114
+ anthropicSummarize,
115
+ createAnthropicSummarize
116
+ };
117
+ //# sourceMappingURL=summarize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.js","sources":["../../../src/adapters/summarize.ts"],"sourcesContent":["import { BaseSummarizeAdapter } from '@tanstack/ai/adapters'\nimport {\n createAnthropicClient,\n generateId,\n getAnthropicApiKeyFromEnv,\n} from '../utils'\nimport type { ANTHROPIC_MODELS } from '../model-meta'\nimport type {\n StreamChunk,\n SummarizationOptions,\n SummarizationResult,\n} from '@tanstack/ai'\nimport type { AnthropicClientConfig } from '../utils'\n\n/**\n * Configuration for Anthropic summarize adapter\n */\nexport interface AnthropicSummarizeConfig extends AnthropicClientConfig {}\n\n/**\n * Anthropic-specific provider options for summarization\n */\nexport interface AnthropicSummarizeProviderOptions {\n /** Temperature for response generation (0-1) */\n temperature?: number\n /** Maximum tokens in the response */\n maxTokens?: number\n}\n\n/** Model type for Anthropic summarization */\nexport type AnthropicSummarizeModel = (typeof ANTHROPIC_MODELS)[number]\n\n/**\n * Anthropic Summarize Adapter\n *\n * Tree-shakeable adapter for Anthropic summarization functionality.\n * Import only what you need for smaller bundle sizes.\n */\nexport class AnthropicSummarizeAdapter<\n TModel extends AnthropicSummarizeModel,\n> extends BaseSummarizeAdapter<TModel, AnthropicSummarizeProviderOptions> {\n readonly kind = 'summarize' as const\n readonly name = 'anthropic' as const\n\n private client: ReturnType<typeof createAnthropicClient>\n\n constructor(config: AnthropicSummarizeConfig, model: TModel) {\n super({}, model)\n this.client = createAnthropicClient(config)\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 async *summarizeStream(\n options: SummarizationOptions,\n ): AsyncIterable<StreamChunk> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n const id = generateId(this.name)\n const model = options.model\n let accumulatedContent = ''\n let inputTokens = 0\n let outputTokens = 0\n\n const stream = 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: true,\n })\n\n for await (const event of stream) {\n if (event.type === 'message_start') {\n inputTokens = event.message.usage.input_tokens\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,\n model,\n timestamp: Date.now(),\n delta,\n content: accumulatedContent,\n role: 'assistant',\n }\n }\n } else if (event.type === 'message_delta') {\n outputTokens = event.usage.output_tokens\n yield {\n type: 'done',\n id,\n model,\n timestamp: Date.now(),\n finishReason: event.delta.stop_reason as\n | 'stop'\n | 'length'\n | 'content_filter'\n | null,\n usage: {\n promptTokens: inputTokens,\n completionTokens: outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n }\n }\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/**\n * Creates an Anthropic summarize adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'claude-sonnet-4-5', 'claude-3-5-haiku-latest')\n * @param apiKey - Your Anthropic API key\n * @param config - Optional additional configuration\n * @returns Configured Anthropic summarize adapter instance with resolved types\n */\nexport function createAnthropicSummarize<\n TModel extends AnthropicSummarizeModel,\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<AnthropicSummarizeConfig, 'apiKey'>,\n): AnthropicSummarizeAdapter<TModel> {\n return new AnthropicSummarizeAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates an Anthropic summarize adapter with automatic API key detection.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'claude-sonnet-4-5', 'claude-3-5-haiku-latest')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Anthropic summarize adapter instance with resolved types\n */\nexport function anthropicSummarize<TModel extends AnthropicSummarizeModel>(\n model: TModel,\n config?: Omit<AnthropicSummarizeConfig, 'apiKey'>,\n): AnthropicSummarizeAdapter<TModel> {\n const apiKey = getAnthropicApiKeyFromEnv()\n return createAnthropicSummarize(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { BaseTextAdapter, StructuredOutputOptions, StructuredOutputResult } from '@tanstack/ai/adapters';
2
+ import { ANTHROPIC_MODELS, AnthropicChatModelProviderOptionsByName, AnthropicModelInputModalitiesByName } from '../model-meta.js';
3
+ import { Modality, StreamChunk, TextOptions } from '@tanstack/ai';
4
+ import { ExternalTextProviderOptions } from '../text/text-provider-options.js';
5
+ import { AnthropicMessageMetadataByModality } from '../message-types.js';
6
+ import { AnthropicClientConfig } from '../utils.js';
7
+ /**
8
+ * Configuration for Anthropic text adapter
9
+ */
10
+ export interface AnthropicTextConfig extends AnthropicClientConfig {
11
+ }
12
+ /**
13
+ * Anthropic-specific provider options for text/chat
14
+ */
15
+ export type AnthropicTextProviderOptions = ExternalTextProviderOptions;
16
+ /**
17
+ * Resolve provider options for a specific model.
18
+ * If the model has explicit options in the map, use those; otherwise use base options.
19
+ */
20
+ type ResolveProviderOptions<TModel extends string> = TModel extends keyof AnthropicChatModelProviderOptionsByName ? AnthropicChatModelProviderOptionsByName[TModel] : AnthropicTextProviderOptions;
21
+ /**
22
+ * Resolve input modalities for a specific model.
23
+ * If the model has explicit modalities in the map, use those; otherwise use default.
24
+ */
25
+ type ResolveInputModalities<TModel extends string> = TModel extends keyof AnthropicModelInputModalitiesByName ? AnthropicModelInputModalitiesByName[TModel] : readonly ['text', 'image', 'document'];
26
+ /**
27
+ * Anthropic Text (Chat) Adapter
28
+ *
29
+ * Tree-shakeable adapter for Anthropic chat/text completion functionality.
30
+ * Import only what you need for smaller bundle sizes.
31
+ */
32
+ export declare class AnthropicTextAdapter<TModel extends (typeof ANTHROPIC_MODELS)[number], TProviderOptions extends object = ResolveProviderOptions<TModel>, TInputModalities extends ReadonlyArray<Modality> = ResolveInputModalities<TModel>> extends BaseTextAdapter<TModel, TProviderOptions, TInputModalities, AnthropicMessageMetadataByModality> {
33
+ readonly kind: "text";
34
+ readonly name: "anthropic";
35
+ private client;
36
+ constructor(config: AnthropicTextConfig, model: TModel);
37
+ chatStream(options: TextOptions<AnthropicTextProviderOptions>): AsyncIterable<StreamChunk>;
38
+ /**
39
+ * Generate structured output using Anthropic's tool-based approach.
40
+ * Anthropic doesn't have native structured output, so we use a tool with the schema
41
+ * and force the model to call it.
42
+ * The outputSchema is already JSON Schema (converted in the ai layer).
43
+ */
44
+ structuredOutput(options: StructuredOutputOptions<AnthropicTextProviderOptions>): Promise<StructuredOutputResult<unknown>>;
45
+ private mapCommonOptionsToAnthropic;
46
+ private convertContentPartToAnthropic;
47
+ private formatMessages;
48
+ private processAnthropicStream;
49
+ }
50
+ /**
51
+ * Creates an Anthropic chat adapter with explicit API key.
52
+ * Type resolution happens here at the call site.
53
+ */
54
+ export declare function createAnthropicChat<TModel extends (typeof ANTHROPIC_MODELS)[number]>(model: TModel, apiKey: string, config?: Omit<AnthropicTextConfig, 'apiKey'>): AnthropicTextAdapter<TModel, ResolveProviderOptions<TModel>, ResolveInputModalities<TModel>>;
55
+ /**
56
+ * Creates an Anthropic text adapter with automatic API key detection.
57
+ * Type resolution happens here at the call site.
58
+ */
59
+ export declare function anthropicText<TModel extends (typeof ANTHROPIC_MODELS)[number]>(model: TModel, config?: Omit<AnthropicTextConfig, 'apiKey'>): AnthropicTextAdapter<TModel, ResolveProviderOptions<TModel>, ResolveInputModalities<TModel>>;
60
+ export {};
@@ -1,16 +1,13 @@
1
- import Anthropic_SDK from "@anthropic-ai/sdk";
2
- import { BaseAdapter } from "@tanstack/ai";
3
- import { ANTHROPIC_MODELS } from "./model-meta.js";
4
- import { convertToolsToProviderFormat } from "./tools/tool-converter.js";
5
- import { validateTextProviderOptions } from "./text/text-provider-options.js";
6
- class Anthropic extends BaseAdapter {
7
- constructor(config) {
8
- super({});
1
+ import { BaseTextAdapter } from "@tanstack/ai/adapters";
2
+ import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
3
+ import { validateTextProviderOptions } from "../text/text-provider-options.js";
4
+ import { createAnthropicClient, generateId, getAnthropicApiKeyFromEnv } from "../utils/client.js";
5
+ class AnthropicTextAdapter extends BaseTextAdapter {
6
+ constructor(config, model) {
7
+ super({}, model);
8
+ this.kind = "text";
9
9
  this.name = "anthropic";
10
- this.models = ANTHROPIC_MODELS;
11
- this.client = new Anthropic_SDK({
12
- apiKey: config.apiKey
13
- });
10
+ this.client = createAnthropicClient(config);
14
11
  }
15
12
  async *chatStream(options) {
16
13
  try {
@@ -25,90 +22,94 @@ class Anthropic extends BaseAdapter {
25
22
  yield* this.processAnthropicStream(
26
23
  stream,
27
24
  options.model,
28
- () => this.generateId()
25
+ () => generateId(this.name)
29
26
  );
30
27
  } catch (error) {
31
- console.error("[Anthropic Adapter] Error in chatStream:", {
32
- message: error?.message,
33
- status: error?.status,
34
- statusText: error?.statusText,
35
- code: error?.code,
36
- type: error?.type,
37
- error,
38
- stack: error?.stack
39
- });
28
+ const err = error;
40
29
  yield {
41
30
  type: "error",
42
- id: this.generateId(),
31
+ id: generateId(this.name),
43
32
  model: options.model,
44
33
  timestamp: Date.now(),
45
34
  error: {
46
- message: error?.message || "Unknown error occurred",
47
- code: error?.code || error?.status
35
+ message: err.message || "Unknown error occurred",
36
+ code: err.code || String(err.status)
48
37
  }
49
38
  };
50
39
  }
51
40
  }
52
- async summarize(options) {
53
- const systemPrompt = this.buildSummarizationPrompt(options);
54
- const response = await this.client.messages.create({
55
- model: options.model,
56
- messages: [{ role: "user", content: options.text }],
57
- system: systemPrompt,
58
- max_tokens: options.maxLength || 500,
59
- temperature: 0.3,
60
- stream: false
61
- });
62
- const content = response.content.map((c) => c.type === "text" ? c.text : "").join("");
63
- return {
64
- id: response.id,
65
- model: response.model,
66
- summary: content,
67
- usage: {
68
- promptTokens: response.usage.input_tokens,
69
- completionTokens: response.usage.output_tokens,
70
- totalTokens: response.usage.input_tokens + response.usage.output_tokens
41
+ /**
42
+ * Generate structured output using Anthropic's tool-based approach.
43
+ * Anthropic doesn't have native structured output, so we use a tool with the schema
44
+ * and force the model to call it.
45
+ * The outputSchema is already JSON Schema (converted in the ai layer).
46
+ */
47
+ async structuredOutput(options) {
48
+ const { chatOptions, outputSchema } = options;
49
+ const requestParams = this.mapCommonOptionsToAnthropic(chatOptions);
50
+ const structuredOutputTool = {
51
+ name: "structured_output",
52
+ description: "Use this tool to provide your response in the required structured format.",
53
+ input_schema: {
54
+ type: "object",
55
+ properties: outputSchema.properties ?? {},
56
+ required: outputSchema.required ?? []
71
57
  }
72
58
  };
73
- }
74
- createEmbeddings(_options) {
75
- throw new Error(
76
- "Embeddings are not natively supported by Anthropic. Consider using OpenAI or another provider for embeddings."
77
- );
78
- }
79
- buildSummarizationPrompt(options) {
80
- let prompt = "You are a professional summarizer. ";
81
- switch (options.style) {
82
- case "bullet-points":
83
- prompt += "Provide a summary in bullet point format. ";
84
- break;
85
- case "paragraph":
86
- prompt += "Provide a summary in paragraph format. ";
87
- break;
88
- case "concise":
89
- prompt += "Provide a very concise summary in 1-2 sentences. ";
90
- break;
91
- default:
92
- prompt += "Provide a clear and concise summary. ";
93
- }
94
- if (options.focus && options.focus.length > 0) {
95
- prompt += `Focus on the following aspects: ${options.focus.join(", ")}. `;
96
- }
97
- if (options.maxLength) {
98
- prompt += `Keep the summary under ${options.maxLength} tokens. `;
59
+ try {
60
+ const response = await this.client.messages.create(
61
+ {
62
+ ...requestParams,
63
+ stream: false,
64
+ tools: [structuredOutputTool],
65
+ tool_choice: { type: "tool", name: "structured_output" }
66
+ },
67
+ {
68
+ signal: chatOptions.request?.signal,
69
+ headers: chatOptions.request?.headers
70
+ }
71
+ );
72
+ let parsed = null;
73
+ let rawText = "";
74
+ for (const block of response.content) {
75
+ if (block.type === "tool_use" && block.name === "structured_output") {
76
+ parsed = block.input;
77
+ rawText = JSON.stringify(block.input);
78
+ break;
79
+ }
80
+ }
81
+ if (parsed === null) {
82
+ rawText = response.content.map((b) => {
83
+ if (b.type === "text") {
84
+ return b.text;
85
+ }
86
+ return "";
87
+ }).join("");
88
+ try {
89
+ parsed = JSON.parse(rawText);
90
+ } catch {
91
+ throw new Error(
92
+ `Failed to extract structured output from response. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? "..." : ""}`
93
+ );
94
+ }
95
+ }
96
+ return {
97
+ data: parsed,
98
+ rawText
99
+ };
100
+ } catch (error) {
101
+ const err = error;
102
+ throw new Error(
103
+ `Structured output generation failed: ${err.message || "Unknown error occurred"}`
104
+ );
99
105
  }
100
- return prompt;
101
106
  }
102
- /**
103
- * Maps common options to Anthropic-specific format
104
- * Handles translation of normalized options to Anthropic's API format
105
- */
106
107
  mapCommonOptionsToAnthropic(options) {
107
- const providerOptions = options.providerOptions;
108
+ const modelOptions = options.modelOptions;
108
109
  const formattedMessages = this.formatMessages(options.messages);
109
110
  const tools = options.tools ? convertToolsToProviderFormat(options.tools) : void 0;
110
111
  const validProviderOptions = {};
111
- if (providerOptions) {
112
+ if (modelOptions) {
112
113
  const validKeys = [
113
114
  "container",
114
115
  "context_management",
@@ -121,10 +122,12 @@ class Anthropic extends BaseAdapter {
121
122
  "top_k"
122
123
  ];
123
124
  for (const key of validKeys) {
124
- if (key in providerOptions) {
125
- const value = providerOptions[key];
125
+ if (key in modelOptions) {
126
+ const value = modelOptions[key];
126
127
  if (key === "tool_choice" && typeof value === "string") {
127
- validProviderOptions[key] = { type: value };
128
+ validProviderOptions[key] = {
129
+ type: value
130
+ };
128
131
  } else {
129
132
  validProviderOptions[key] = value;
130
133
  }
@@ -132,13 +135,13 @@ class Anthropic extends BaseAdapter {
132
135
  }
133
136
  }
134
137
  const thinkingBudget = validProviderOptions.thinking?.type === "enabled" ? validProviderOptions.thinking.budget_tokens : void 0;
135
- const defaultMaxTokens = options.options?.maxTokens || 1024;
138
+ const defaultMaxTokens = options.maxTokens || 1024;
136
139
  const maxTokens = thinkingBudget && thinkingBudget >= defaultMaxTokens ? thinkingBudget + 1 : defaultMaxTokens;
137
140
  const requestParams = {
138
141
  model: options.model,
139
142
  max_tokens: maxTokens,
140
- temperature: options.options?.temperature,
141
- top_p: options.options?.topP,
143
+ temperature: options.temperature,
144
+ top_p: options.topP,
142
145
  messages: formattedMessages,
143
146
  system: options.systemPrompts?.join("\n"),
144
147
  tools,
@@ -167,7 +170,7 @@ class Anthropic extends BaseAdapter {
167
170
  type: "url",
168
171
  url: part.source.value
169
172
  };
170
- const { mediaType, ...meta } = metadata || {};
173
+ const { mediaType: _mediaType, ...meta } = metadata || {};
171
174
  return {
172
175
  type: "image",
173
176
  source: imageSource,
@@ -270,7 +273,7 @@ class Anthropic extends BaseAdapter {
270
273
  }
271
274
  return formattedMessages;
272
275
  }
273
- async *processAnthropicStream(stream, model, generateId) {
276
+ async *processAnthropicStream(stream, model, genId) {
274
277
  let accumulatedContent = "";
275
278
  let accumulatedThinking = "";
276
279
  const timestamp = Date.now();
@@ -295,7 +298,7 @@ class Anthropic extends BaseAdapter {
295
298
  accumulatedContent += delta;
296
299
  yield {
297
300
  type: "content",
298
- id: generateId(),
301
+ id: genId(),
299
302
  model,
300
303
  timestamp,
301
304
  delta,
@@ -307,7 +310,7 @@ class Anthropic extends BaseAdapter {
307
310
  accumulatedThinking += delta;
308
311
  yield {
309
312
  type: "thinking",
310
- id: generateId(),
313
+ id: genId(),
311
314
  model,
312
315
  timestamp,
313
316
  delta,
@@ -319,7 +322,7 @@ class Anthropic extends BaseAdapter {
319
322
  existing.input += event.delta.partial_json;
320
323
  yield {
321
324
  type: "tool_call",
322
- id: generateId(),
325
+ id: genId(),
323
326
  model,
324
327
  timestamp,
325
328
  toolCall: {
@@ -339,7 +342,7 @@ class Anthropic extends BaseAdapter {
339
342
  if (existing && existing.input === "") {
340
343
  yield {
341
344
  type: "tool_call",
342
- id: generateId(),
345
+ id: genId(),
343
346
  model,
344
347
  timestamp,
345
348
  toolCall: {
@@ -356,7 +359,7 @@ class Anthropic extends BaseAdapter {
356
359
  } else if (event.type === "message_stop") {
357
360
  yield {
358
361
  type: "done",
359
- id: generateId(),
362
+ id: genId(),
360
363
  model,
361
364
  timestamp,
362
365
  finishReason: "stop"
@@ -367,7 +370,7 @@ class Anthropic extends BaseAdapter {
367
370
  case "tool_use": {
368
371
  yield {
369
372
  type: "done",
370
- id: generateId(),
373
+ id: genId(),
371
374
  model,
372
375
  timestamp,
373
376
  finishReason: "tool_calls",
@@ -382,7 +385,7 @@ class Anthropic extends BaseAdapter {
382
385
  case "max_tokens": {
383
386
  yield {
384
387
  type: "error",
385
- id: generateId(),
388
+ id: genId(),
386
389
  model,
387
390
  timestamp,
388
391
  error: {
@@ -392,36 +395,10 @@ class Anthropic extends BaseAdapter {
392
395
  };
393
396
  break;
394
397
  }
395
- case "model_context_window_exceeded": {
396
- yield {
397
- type: "error",
398
- id: generateId(),
399
- model,
400
- timestamp,
401
- error: {
402
- message: "The response was cut off because the model's context window was exceeded.",
403
- code: "context_window_exceeded"
404
- }
405
- };
406
- break;
407
- }
408
- case "refusal": {
409
- yield {
410
- type: "error",
411
- id: generateId(),
412
- model,
413
- timestamp,
414
- error: {
415
- message: "The model refused to complete the request.",
416
- code: "refusal"
417
- }
418
- };
419
- break;
420
- }
421
398
  default: {
422
399
  yield {
423
400
  type: "done",
424
- id: generateId(),
401
+ id: genId(),
425
402
  model,
426
403
  timestamp,
427
404
  finishReason: "stop",
@@ -437,44 +414,30 @@ class Anthropic extends BaseAdapter {
437
414
  }
438
415
  }
439
416
  } catch (error) {
440
- console.error("[Anthropic Adapter] Error in processAnthropicStream:", {
441
- message: error?.message,
442
- status: error?.status,
443
- statusText: error?.statusText,
444
- code: error?.code,
445
- type: error?.type,
446
- error,
447
- stack: error?.stack
448
- });
417
+ const err = error;
449
418
  yield {
450
419
  type: "error",
451
- id: generateId(),
420
+ id: genId(),
452
421
  model,
453
422
  timestamp,
454
423
  error: {
455
- message: error?.message || "Unknown error occurred",
456
- code: error?.code || error?.status
424
+ message: err.message || "Unknown error occurred",
425
+ code: err.code || String(err.status)
457
426
  }
458
427
  };
459
428
  }
460
429
  }
461
430
  }
462
- function createAnthropic(apiKey, config) {
463
- return new Anthropic({ apiKey, ...config });
431
+ function createAnthropicChat(model, apiKey, config) {
432
+ return new AnthropicTextAdapter({ apiKey, ...config }, model);
464
433
  }
465
- function anthropic(config) {
466
- const env = typeof globalThis !== "undefined" && globalThis.window?.env ? globalThis.window.env : typeof process !== "undefined" ? process.env : void 0;
467
- const key = env?.ANTHROPIC_API_KEY;
468
- if (!key) {
469
- throw new Error(
470
- "ANTHROPIC_API_KEY is required. Please set it in your environment variables or use createAnthropic(apiKey, config) instead."
471
- );
472
- }
473
- return createAnthropic(key, config);
434
+ function anthropicText(model, config) {
435
+ const apiKey = getAnthropicApiKeyFromEnv();
436
+ return createAnthropicChat(model, apiKey, config);
474
437
  }
475
438
  export {
476
- Anthropic,
477
- anthropic,
478
- createAnthropic
439
+ AnthropicTextAdapter,
440
+ anthropicText,
441
+ createAnthropicChat
479
442
  };
480
- //# sourceMappingURL=anthropic-adapter.js.map
443
+ //# sourceMappingURL=text.js.map