@providerprotocol/ai 0.0.12 → 0.0.14

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 (44) hide show
  1. package/dist/anthropic/index.d.ts +51 -15
  2. package/dist/anthropic/index.js +80 -29
  3. package/dist/anthropic/index.js.map +1 -1
  4. package/dist/{chunk-SUNYWHTH.js → chunk-MOU4U3PO.js} +55 -3
  5. package/dist/chunk-MOU4U3PO.js.map +1 -0
  6. package/dist/{chunk-Y6Q7JCNP.js → chunk-MSR5P65T.js} +1 -1
  7. package/dist/chunk-MSR5P65T.js.map +1 -0
  8. package/dist/{chunk-W4BB4BG2.js → chunk-SVYROCLD.js} +31 -11
  9. package/dist/chunk-SVYROCLD.js.map +1 -0
  10. package/dist/chunk-U4JJC2YX.js +234 -0
  11. package/dist/chunk-U4JJC2YX.js.map +1 -0
  12. package/dist/{chunk-X5G4EHL7.js → chunk-Z7RBRCRN.js} +1 -1
  13. package/dist/chunk-Z7RBRCRN.js.map +1 -0
  14. package/dist/google/index.d.ts +376 -7
  15. package/dist/google/index.js +149 -21
  16. package/dist/google/index.js.map +1 -1
  17. package/dist/http/index.d.ts +222 -25
  18. package/dist/http/index.js +3 -3
  19. package/dist/index.d.ts +1484 -198
  20. package/dist/index.js +233 -47
  21. package/dist/index.js.map +1 -1
  22. package/dist/ollama/index.d.ts +92 -20
  23. package/dist/ollama/index.js +31 -7
  24. package/dist/ollama/index.js.map +1 -1
  25. package/dist/openai/index.d.ts +340 -61
  26. package/dist/openai/index.js +105 -31
  27. package/dist/openai/index.js.map +1 -1
  28. package/dist/openrouter/index.d.ts +107 -51
  29. package/dist/openrouter/index.js +84 -24
  30. package/dist/openrouter/index.js.map +1 -1
  31. package/dist/provider-Bi0nyNhA.d.ts +505 -0
  32. package/dist/retry-BatS2hjD.d.ts +508 -0
  33. package/dist/xai/index.d.ts +97 -22
  34. package/dist/xai/index.js +129 -45
  35. package/dist/xai/index.js.map +1 -1
  36. package/package.json +8 -3
  37. package/dist/chunk-CUCRF5W6.js +0 -136
  38. package/dist/chunk-CUCRF5W6.js.map +0 -1
  39. package/dist/chunk-SUNYWHTH.js.map +0 -1
  40. package/dist/chunk-W4BB4BG2.js.map +0 -1
  41. package/dist/chunk-X5G4EHL7.js.map +0 -1
  42. package/dist/chunk-Y6Q7JCNP.js.map +0 -1
  43. package/dist/provider-CUJWjgNl.d.ts +0 -192
  44. package/dist/retry-I2661_rv.d.ts +0 -118
@@ -1,40 +1,76 @@
1
- import { b as Provider } from '../provider-CUJWjgNl.js';
1
+ import { b as Provider } from '../provider-Bi0nyNhA.js';
2
2
 
3
3
  /**
4
- * Anthropic-specific LLM parameters
5
- * These are passed through to the Anthropic Messages API
4
+ * @fileoverview Anthropic API type definitions.
5
+ *
6
+ * Contains TypeScript interfaces for Anthropic's Messages API request/response
7
+ * structures, streaming events, and provider-specific parameters.
8
+ */
9
+ /**
10
+ * Provider-specific parameters for Anthropic Claude models.
11
+ *
12
+ * These parameters are passed through to the Anthropic Messages API and
13
+ * control model behavior such as sampling, token limits, and extended thinking.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const params: AnthropicLLMParams = {
18
+ * max_tokens: 4096,
19
+ * temperature: 0.7,
20
+ * thinking: { type: 'enabled', budget_tokens: 10000 },
21
+ * };
22
+ * ```
6
23
  */
7
24
  interface AnthropicLLMParams {
8
- /** Maximum number of tokens to generate (required by Anthropic API) */
25
+ /** Maximum number of tokens to generate. Defaults to model maximum if not specified. */
9
26
  max_tokens?: number;
10
- /** Temperature for randomness (0.0 - 1.0) */
27
+ /** Sampling temperature from 0.0 (deterministic) to 1.0 (maximum randomness). */
11
28
  temperature?: number;
12
- /** Top-p (nucleus) sampling */
29
+ /** Nucleus sampling threshold. Only tokens with cumulative probability <= top_p are considered. */
13
30
  top_p?: number;
14
- /** Top-k sampling */
31
+ /** Top-k sampling. Only the k most likely tokens are considered at each step. */
15
32
  top_k?: number;
16
- /** Custom stop sequences */
33
+ /** Custom sequences that will cause the model to stop generating. */
17
34
  stop_sequences?: string[];
18
- /** Metadata for the request */
35
+ /** Request metadata for tracking and analytics. */
19
36
  metadata?: {
37
+ /** Unique identifier for the end user making the request. */
20
38
  user_id?: string;
21
39
  };
22
- /** Extended thinking configuration */
40
+ /** Extended thinking configuration for complex reasoning tasks. */
23
41
  thinking?: {
42
+ /** Must be 'enabled' to activate extended thinking. */
24
43
  type: 'enabled';
44
+ /** Token budget for the thinking process. */
25
45
  budget_tokens: number;
26
46
  };
27
47
  /**
28
- * Service tier for priority/standard capacity
29
- * - "auto": Automatically select based on availability (default)
30
- * - "standard_only": Only use standard capacity
48
+ * Service tier selection for capacity routing.
49
+ * - `auto`: Automatically select based on availability (default)
50
+ * - `standard_only`: Only use standard capacity, never priority
31
51
  */
32
52
  service_tier?: 'auto' | 'standard_only';
33
53
  }
34
54
 
35
55
  /**
36
- * Anthropic provider
37
- * Supports LLM modality with Claude models
56
+ * Anthropic provider instance for the Universal Provider Protocol.
57
+ *
58
+ * Provides access to Claude language models through a unified interface.
59
+ * Currently supports the LLM modality with full streaming, tool use,
60
+ * structured output, and image input capabilities.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * import { anthropic } from './providers/anthropic';
65
+ *
66
+ * const claude = anthropic.llm.bind('claude-sonnet-4-20250514');
67
+ * const response = await claude.complete({
68
+ * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],
69
+ * config: { apiKey: 'sk-...' },
70
+ * });
71
+ * ```
72
+ *
73
+ * @see {@link AnthropicLLMParams} for provider-specific parameters
38
74
  */
39
75
  declare const anthropic: Provider<unknown>;
40
76
 
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  createProvider
3
- } from "../chunk-Y6Q7JCNP.js";
3
+ } from "../chunk-MSR5P65T.js";
4
4
  import {
5
5
  AssistantMessage,
6
6
  isAssistantMessage,
7
7
  isToolResultMessage,
8
8
  isUserMessage
9
- } from "../chunk-W4BB4BG2.js";
9
+ } from "../chunk-SVYROCLD.js";
10
10
  import {
11
11
  parseSSEStream
12
- } from "../chunk-X5G4EHL7.js";
12
+ } from "../chunk-Z7RBRCRN.js";
13
13
  import {
14
14
  UPPError,
15
15
  doFetch,
16
16
  doStreamFetch,
17
17
  normalizeHttpError,
18
18
  resolveApiKey
19
- } from "../chunk-SUNYWHTH.js";
19
+ } from "../chunk-MOU4U3PO.js";
20
20
 
21
21
  // src/providers/anthropic/transform.ts
22
22
  function transformRequest(request, modelId) {
@@ -51,24 +51,37 @@ function transformRequest(request, modelId) {
51
51
  function filterValidContent(content) {
52
52
  return content.filter((c) => c && typeof c.type === "string");
53
53
  }
54
+ function extractCacheControl(message) {
55
+ const anthropicMeta = message.metadata?.anthropic;
56
+ return anthropicMeta?.cache_control;
57
+ }
54
58
  function transformMessage(message) {
59
+ const cacheControl = extractCacheControl(message);
55
60
  if (isUserMessage(message)) {
56
61
  const validContent = filterValidContent(message.content);
62
+ const contentBlocks = validContent.map(
63
+ (block, index, arr) => transformContentBlock(block, index === arr.length - 1 ? cacheControl : void 0)
64
+ );
57
65
  return {
58
66
  role: "user",
59
- content: validContent.map(transformContentBlock)
67
+ content: contentBlocks
60
68
  };
61
69
  }
62
70
  if (isAssistantMessage(message)) {
63
71
  const validContent = filterValidContent(message.content);
64
- const content = validContent.map(transformContentBlock);
72
+ const content = validContent.map(
73
+ (block, index, arr) => transformContentBlock(block, index === arr.length - 1 && !message.toolCalls?.length ? cacheControl : void 0)
74
+ );
65
75
  if (message.toolCalls) {
66
- for (const call of message.toolCalls) {
76
+ for (let i = 0; i < message.toolCalls.length; i++) {
77
+ const call = message.toolCalls[i];
78
+ const isLast = i === message.toolCalls.length - 1;
67
79
  content.push({
68
80
  type: "tool_use",
69
81
  id: call.toolCallId,
70
82
  name: call.toolName,
71
- input: call.arguments
83
+ input: call.arguments,
84
+ ...isLast && cacheControl ? { cache_control: cacheControl } : {}
72
85
  });
73
86
  }
74
87
  }
@@ -80,20 +93,25 @@ function transformMessage(message) {
80
93
  if (isToolResultMessage(message)) {
81
94
  return {
82
95
  role: "user",
83
- content: message.results.map((result) => ({
96
+ content: message.results.map((result, index, arr) => ({
84
97
  type: "tool_result",
85
98
  tool_use_id: result.toolCallId,
86
99
  content: typeof result.result === "string" ? result.result : JSON.stringify(result.result),
87
- is_error: result.isError
100
+ is_error: result.isError,
101
+ ...index === arr.length - 1 && cacheControl ? { cache_control: cacheControl } : {}
88
102
  }))
89
103
  };
90
104
  }
91
105
  throw new Error(`Unknown message type: ${message.type}`);
92
106
  }
93
- function transformContentBlock(block) {
107
+ function transformContentBlock(block, cacheControl) {
94
108
  switch (block.type) {
95
109
  case "text":
96
- return { type: "text", text: block.text };
110
+ return {
111
+ type: "text",
112
+ text: block.text,
113
+ ...cacheControl ? { cache_control: cacheControl } : {}
114
+ };
97
115
  case "image": {
98
116
  const imageBlock = block;
99
117
  if (imageBlock.source.type === "base64") {
@@ -103,7 +121,8 @@ function transformContentBlock(block) {
103
121
  type: "base64",
104
122
  media_type: imageBlock.mimeType,
105
123
  data: imageBlock.source.data
106
- }
124
+ },
125
+ ...cacheControl ? { cache_control: cacheControl } : {}
107
126
  };
108
127
  }
109
128
  if (imageBlock.source.type === "url") {
@@ -112,7 +131,8 @@ function transformContentBlock(block) {
112
131
  source: {
113
132
  type: "url",
114
133
  url: imageBlock.source.url
115
- }
134
+ },
135
+ ...cacheControl ? { cache_control: cacheControl } : {}
116
136
  };
117
137
  }
118
138
  if (imageBlock.source.type === "bytes") {
@@ -125,7 +145,8 @@ function transformContentBlock(block) {
125
145
  type: "base64",
126
146
  media_type: imageBlock.mimeType,
127
147
  data: base64
128
- }
148
+ },
149
+ ...cacheControl ? { cache_control: cacheControl } : {}
129
150
  };
130
151
  }
131
152
  throw new Error(`Unknown image source type`);
@@ -134,7 +155,12 @@ function transformContentBlock(block) {
134
155
  throw new Error(`Unsupported content type: ${block.type}`);
135
156
  }
136
157
  }
158
+ function extractToolCacheControl(tool) {
159
+ const anthropicMeta = tool.metadata?.anthropic;
160
+ return anthropicMeta?.cache_control;
161
+ }
137
162
  function transformTool(tool) {
163
+ const cacheControl = extractToolCacheControl(tool);
138
164
  return {
139
165
  name: tool.name,
140
166
  description: tool.description,
@@ -142,7 +168,8 @@ function transformTool(tool) {
142
168
  type: "object",
143
169
  properties: tool.parameters.properties,
144
170
  required: tool.parameters.required
145
- }
171
+ },
172
+ ...cacheControl ? { cache_control: cacheControl } : {}
146
173
  };
147
174
  }
148
175
  function transformResponse(data) {
@@ -180,7 +207,9 @@ function transformResponse(data) {
180
207
  const usage = {
181
208
  inputTokens: data.usage.input_tokens,
182
209
  outputTokens: data.usage.output_tokens,
183
- totalTokens: data.usage.input_tokens + data.usage.output_tokens
210
+ totalTokens: data.usage.input_tokens + data.usage.output_tokens,
211
+ cacheReadTokens: data.usage.cache_read_input_tokens ?? 0,
212
+ cacheWriteTokens: data.usage.cache_creation_input_tokens ?? 0
184
213
  };
185
214
  return {
186
215
  message,
@@ -196,7 +225,9 @@ function createStreamState() {
196
225
  content: [],
197
226
  stopReason: null,
198
227
  inputTokens: 0,
199
- outputTokens: 0
228
+ outputTokens: 0,
229
+ cacheReadTokens: 0,
230
+ cacheWriteTokens: 0
200
231
  };
201
232
  }
202
233
  function transformStreamEvent(event, state) {
@@ -205,6 +236,8 @@ function transformStreamEvent(event, state) {
205
236
  state.messageId = event.message.id;
206
237
  state.model = event.message.model;
207
238
  state.inputTokens = event.message.usage.input_tokens;
239
+ state.cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;
240
+ state.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;
208
241
  return { type: "message_start", index: 0, delta: {} };
209
242
  case "content_block_start":
210
243
  if (event.content_block.type === "text") {
@@ -309,7 +342,9 @@ function buildResponseFromState(state) {
309
342
  const usage = {
310
343
  inputTokens: state.inputTokens,
311
344
  outputTokens: state.outputTokens,
312
- totalTokens: state.inputTokens + state.outputTokens
345
+ totalTokens: state.inputTokens + state.outputTokens,
346
+ cacheReadTokens: state.cacheReadTokens,
347
+ cacheWriteTokens: state.cacheWriteTokens
313
348
  };
314
349
  return {
315
350
  message,
@@ -360,15 +395,23 @@ function createLLMHandler() {
360
395
  );
361
396
  const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;
362
397
  const body = transformRequest(request, modelId);
398
+ const headers = {
399
+ "Content-Type": "application/json",
400
+ "x-api-key": apiKey,
401
+ "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
402
+ };
403
+ if (request.config.headers) {
404
+ for (const [key, value] of Object.entries(request.config.headers)) {
405
+ if (value !== void 0) {
406
+ headers[key] = value;
407
+ }
408
+ }
409
+ }
363
410
  const response = await doFetch(
364
411
  baseUrl,
365
412
  {
366
413
  method: "POST",
367
- headers: {
368
- "Content-Type": "application/json",
369
- "x-api-key": apiKey,
370
- "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
371
- },
414
+ headers,
372
415
  body: JSON.stringify(body),
373
416
  signal: request.signal
374
417
  },
@@ -398,15 +441,23 @@ function createLLMHandler() {
398
441
  const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;
399
442
  const body = transformRequest(request, modelId);
400
443
  body.stream = true;
444
+ const headers = {
445
+ "Content-Type": "application/json",
446
+ "x-api-key": apiKey,
447
+ "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
448
+ };
449
+ if (request.config.headers) {
450
+ for (const [key, value] of Object.entries(request.config.headers)) {
451
+ if (value !== void 0) {
452
+ headers[key] = value;
453
+ }
454
+ }
455
+ }
401
456
  const response = await doStreamFetch(
402
457
  baseUrl,
403
458
  {
404
459
  method: "POST",
405
- headers: {
406
- "Content-Type": "application/json",
407
- "x-api-key": apiKey,
408
- "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
409
- },
460
+ headers,
410
461
  body: JSON.stringify(body),
411
462
  signal: request.signal
412
463
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/anthropic/transform.ts","../../src/providers/anthropic/llm.ts","../../src/providers/anthropic/index.ts"],"sourcesContent":["import type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n UserMessage,\n ToolResultMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n AnthropicLLMParams,\n AnthropicRequest,\n AnthropicMessage,\n AnthropicContent,\n AnthropicTool,\n AnthropicResponse,\n AnthropicStreamEvent,\n AnthropicContentBlockDeltaEvent,\n} from './types.ts';\n\n/**\n * Transform UPP request to Anthropic format\n *\n * Params are spread directly to allow pass-through of any Anthropic API fields,\n * even those not explicitly defined in our type. This enables developers to\n * use new API features without waiting for library updates.\n */\nexport function transformRequest<TParams extends AnthropicLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): AnthropicRequest {\n const params = (request.params ?? {}) as AnthropicLLMParams;\n\n // Spread params to pass through all fields, then set required fields\n const anthropicRequest: AnthropicRequest = {\n ...params,\n model: modelId,\n messages: request.messages.map(transformMessage),\n };\n\n // System prompt (top-level in Anthropic)\n if (request.system) {\n anthropicRequest.system = request.system;\n }\n\n // Tools come from request, not params\n if (request.tools && request.tools.length > 0) {\n anthropicRequest.tools = request.tools.map(transformTool);\n anthropicRequest.tool_choice = { type: 'auto' };\n }\n\n // Structured output via tool-based approach\n // Anthropic doesn't have native structured output, so we use a tool to enforce the schema\n if (request.structure) {\n const structuredTool: AnthropicTool = {\n name: 'json_response',\n description: 'Return the response in the specified JSON format. You MUST use this tool to provide your response.',\n input_schema: {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n },\n };\n\n // Add the structured output tool (may coexist with user tools)\n anthropicRequest.tools = [...(anthropicRequest.tools ?? []), structuredTool];\n // Force the model to use the json_response tool\n anthropicRequest.tool_choice = { type: 'tool', name: 'json_response' };\n }\n\n return anthropicRequest;\n}\n\n/**\n * Filter to only valid content blocks with a type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transform a UPP Message to Anthropic format\n */\nfunction transformMessage(message: Message): AnthropicMessage {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const content: AnthropicContent[] = validContent.map(transformContentBlock);\n\n // Add tool calls as tool_use content blocks\n if (message.toolCalls) {\n for (const call of message.toolCalls) {\n content.push({\n type: 'tool_use',\n id: call.toolCallId,\n name: call.toolName,\n input: call.arguments,\n });\n }\n }\n\n return {\n role: 'assistant',\n content,\n };\n }\n\n if (isToolResultMessage(message)) {\n // Tool results are sent as user messages with tool_result content\n return {\n role: 'user',\n content: message.results.map((result) => ({\n type: 'tool_result' as const,\n tool_use_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n is_error: result.isError,\n })),\n };\n }\n\n throw new Error(`Unknown message type: ${message.type}`);\n}\n\n/**\n * Transform a content block to Anthropic format\n */\nfunction transformContentBlock(block: ContentBlock): AnthropicContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: imageBlock.source.data,\n },\n };\n }\n if (imageBlock.source.type === 'url') {\n return {\n type: 'image',\n source: {\n type: 'url',\n url: imageBlock.source.url,\n },\n };\n }\n if (imageBlock.source.type === 'bytes') {\n // Convert bytes to base64\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: base64,\n },\n };\n }\n throw new Error(`Unknown image source type`);\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transform a UPP Tool to Anthropic format\n */\nfunction transformTool(tool: Tool): AnthropicTool {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n };\n}\n\n/**\n * Transform Anthropic response to UPP LLMResponse\n */\nexport function transformResponse(data: AnthropicResponse): LLMResponse {\n // Extract text content\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of data.content) {\n if (block.type === 'text') {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use') {\n // Check if this is the json_response tool (structured output)\n if (block.name === 'json_response') {\n // Extract structured data from tool arguments\n structuredData = block.input;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: block.input,\n });\n }\n // Skip thinking blocks for now\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n anthropic: {\n stop_reason: data.stop_reason,\n stop_sequence: data.stop_sequence,\n model: data.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n };\n\n return {\n message,\n usage,\n stopReason: data.stop_reason ?? 'end_turn',\n data: structuredData,\n };\n}\n\n/**\n * State for accumulating streaming response\n */\nexport interface StreamState {\n messageId: string;\n model: string;\n content: Array<{ type: string; text?: string; id?: string; name?: string; input?: string }>;\n stopReason: string | null;\n inputTokens: number;\n outputTokens: number;\n}\n\n/**\n * Create initial stream state\n */\nexport function createStreamState(): StreamState {\n return {\n messageId: '',\n model: '',\n content: [],\n stopReason: null,\n inputTokens: 0,\n outputTokens: 0,\n };\n}\n\n/**\n * Transform Anthropic stream event to UPP StreamEvent\n * Returns null for events that don't produce UPP events\n */\nexport function transformStreamEvent(\n event: AnthropicStreamEvent,\n state: StreamState\n): StreamEvent | null {\n switch (event.type) {\n case 'message_start':\n state.messageId = event.message.id;\n state.model = event.message.model;\n state.inputTokens = event.message.usage.input_tokens;\n return { type: 'message_start', index: 0, delta: {} };\n\n case 'content_block_start':\n // Initialize content block\n if (event.content_block.type === 'text') {\n state.content[event.index] = { type: 'text', text: '' };\n } else if (event.content_block.type === 'tool_use') {\n state.content[event.index] = {\n type: 'tool_use',\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n };\n }\n return { type: 'content_block_start', index: event.index, delta: {} };\n\n case 'content_block_delta': {\n const delta = event.delta;\n if (delta.type === 'text_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.text =\n (state.content[event.index]!.text ?? '') + delta.text;\n }\n return {\n type: 'text_delta',\n index: event.index,\n delta: { text: delta.text },\n };\n }\n if (delta.type === 'input_json_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.input =\n (state.content[event.index]!.input ?? '') + delta.partial_json;\n }\n return {\n type: 'tool_call_delta',\n index: event.index,\n delta: {\n argumentsJson: delta.partial_json,\n toolCallId: state.content[event.index]?.id,\n toolName: state.content[event.index]?.name,\n },\n };\n }\n if (delta.type === 'thinking_delta') {\n return {\n type: 'reasoning_delta',\n index: event.index,\n delta: { text: delta.thinking },\n };\n }\n return null;\n }\n\n case 'content_block_stop':\n return { type: 'content_block_stop', index: event.index, delta: {} };\n\n case 'message_delta':\n state.stopReason = event.delta.stop_reason;\n state.outputTokens = event.usage.output_tokens;\n return null;\n\n case 'message_stop':\n return { type: 'message_stop', index: 0, delta: {} };\n\n case 'ping':\n case 'error':\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Build LLMResponse from accumulated stream state\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of state.content) {\n if (block.type === 'text' && block.text) {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use' && block.id && block.name) {\n let args: Record<string, unknown> = {};\n if (block.input) {\n try {\n args = JSON.parse(block.input);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n // Check if this is the json_response tool (structured output)\n if (block.name === 'json_response') {\n structuredData = args;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.messageId,\n metadata: {\n anthropic: {\n stop_reason: state.stopReason,\n model: state.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n };\n\n return {\n message,\n usage,\n stopReason: state.stopReason ?? 'end_turn',\n data: structuredData,\n };\n}\n","import type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { AnthropicLLMParams, AnthropicResponse, AnthropicStreamEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\nconst ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';\nconst ANTHROPIC_VERSION = '2023-06-01';\n\n/**\n * Anthropic API capabilities\n */\nconst ANTHROPIC_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Create Anthropic LLM handler\n */\nexport function createLLMHandler(): LLMHandler<AnthropicLLMParams> {\n // Provider reference injected by createProvider() after construction\n let providerRef: LLMProvider<AnthropicLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<AnthropicLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<AnthropicLLMParams> {\n // Use the injected provider reference (set by createProvider)\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'anthropic',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<AnthropicLLMParams> = {\n modelId,\n capabilities: ANTHROPIC_CAPABILITIES,\n\n get provider(): LLMProvider<AnthropicLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<AnthropicLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n const data = (await response.json()) as AnthropicResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<AnthropicLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'anthropic', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Check for Anthropic error event\n if (typeof data === 'object' && data !== null && 'type' in data) {\n const event = data as AnthropicStreamEvent;\n\n if (event.type === 'error') {\n const error = new UPPError(\n event.error.message,\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvent = transformStreamEvent(event, state);\n if (uppEvent) {\n yield uppEvent;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Anthropic provider\n * Supports LLM modality with Claude models\n */\nexport const anthropic = createProvider({\n name: 'anthropic',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\n// Re-export types\nexport type { AnthropicLLMParams } from './types.ts';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/providers/anthropic/transform.ts","../../src/providers/anthropic/llm.ts","../../src/providers/anthropic/index.ts"],"sourcesContent":["/**\n * @fileoverview UPP to Anthropic message transformation utilities.\n *\n * This module handles bidirectional conversion between Universal Provider Protocol\n * message formats and Anthropic's native API structures. It supports:\n * - Request transformation (UPP -> Anthropic)\n * - Response transformation (Anthropic -> UPP)\n * - Stream event transformation for real-time responses\n * - Tool call and structured output handling\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n AnthropicLLMParams,\n AnthropicRequest,\n AnthropicMessage,\n AnthropicContent,\n AnthropicTool,\n AnthropicResponse,\n AnthropicStreamEvent,\n AnthropicCacheControl,\n AnthropicSystemContent,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request to Anthropic's native API format.\n *\n * Handles conversion of messages, system prompts, tools, and structured output\n * configuration. Parameters are spread directly to enable pass-through of any\n * Anthropic API fields, even those not explicitly defined in our types.\n *\n * @typeParam TParams - Anthropic-specific parameters extending AnthropicLLMParams\n * @param request - The UPP-formatted LLM request\n * @param modelId - The Anthropic model identifier (e.g., 'claude-sonnet-4-20250514')\n * @returns An AnthropicRequest ready for the Messages API\n *\n * @example\n * ```typescript\n * const anthropicRequest = transformRequest({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: 'sk-...' },\n * params: { max_tokens: 1024, temperature: 0.7 },\n * }, 'claude-sonnet-4-20250514');\n * ```\n *\n * @see {@link transformResponse} for the reverse transformation\n */\nexport function transformRequest<TParams extends AnthropicLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): AnthropicRequest {\n const params = (request.params ?? {}) as AnthropicLLMParams;\n\n const anthropicRequest: AnthropicRequest = {\n ...params,\n model: modelId,\n messages: request.messages.map(transformMessage),\n };\n\n if (request.system) {\n // Pass through directly - accepts string or array of AnthropicSystemContent\n // Array format enables cache_control: [{type: 'text', text: '...', cache_control: {...}}]\n anthropicRequest.system = request.system as string | AnthropicSystemContent[];\n }\n\n if (request.tools && request.tools.length > 0) {\n // For tool caching, use params.tools directly with native Anthropic format\n anthropicRequest.tools = request.tools.map(transformTool);\n anthropicRequest.tool_choice = { type: 'auto' };\n }\n\n if (request.structure) {\n const structuredTool: AnthropicTool = {\n name: 'json_response',\n description: 'Return the response in the specified JSON format. You MUST use this tool to provide your response.',\n input_schema: {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n },\n };\n\n anthropicRequest.tools = [...(anthropicRequest.tools ?? []), structuredTool];\n anthropicRequest.tool_choice = { type: 'tool', name: 'json_response' };\n }\n\n return anthropicRequest;\n}\n\n/**\n * Filters content blocks to include only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with a string type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Extracts cache control configuration from message metadata.\n *\n * @param message - The message to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractCacheControl(message: Message): AnthropicCacheControl | undefined {\n const anthropicMeta = message.metadata?.anthropic as\n | { cache_control?: AnthropicCacheControl }\n | undefined;\n return anthropicMeta?.cache_control;\n}\n\n/**\n * Transforms a UPP Message to Anthropic's message format.\n *\n * Handles three message types:\n * - UserMessage: Converted with content blocks\n * - AssistantMessage: Includes text and tool_use blocks\n * - ToolResultMessage: Converted to user role with tool_result content\n *\n * Cache control can be specified via message metadata:\n * ```typescript\n * new UserMessage(content, {\n * metadata: { anthropic: { cache_control: { type: \"ephemeral\" } } }\n * })\n * ```\n *\n * @param message - The UPP message to transform\n * @returns An AnthropicMessage with the appropriate role and content\n * @throws Error if the message type is unknown\n */\nfunction transformMessage(message: Message): AnthropicMessage {\n const cacheControl = extractCacheControl(message);\n\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n const contentBlocks = validContent.map((block, index, arr) =>\n transformContentBlock(block, index === arr.length - 1 ? cacheControl : undefined)\n );\n return {\n role: 'user',\n content: contentBlocks,\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const content: AnthropicContent[] = validContent.map((block, index, arr) =>\n transformContentBlock(block, index === arr.length - 1 && !message.toolCalls?.length ? cacheControl : undefined)\n );\n\n if (message.toolCalls) {\n for (let i = 0; i < message.toolCalls.length; i++) {\n const call = message.toolCalls[i]!;\n const isLast = i === message.toolCalls.length - 1;\n content.push({\n type: 'tool_use',\n id: call.toolCallId,\n name: call.toolName,\n input: call.arguments,\n ...(isLast && cacheControl ? { cache_control: cacheControl } : {}),\n });\n }\n }\n\n return {\n role: 'assistant',\n content,\n };\n }\n\n if (isToolResultMessage(message)) {\n return {\n role: 'user',\n content: message.results.map((result, index, arr) => ({\n type: 'tool_result' as const,\n tool_use_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n is_error: result.isError,\n ...(index === arr.length - 1 && cacheControl ? { cache_control: cacheControl } : {}),\n })),\n };\n }\n\n throw new Error(`Unknown message type: ${message.type}`);\n}\n\n/**\n * Transforms a UPP ContentBlock to Anthropic's content format.\n *\n * Supports text and image content types. Image blocks can be provided\n * as base64, URL, or raw bytes (which are converted to base64).\n *\n * @param block - The UPP content block to transform\n * @param cacheControl - Optional cache control to apply to the block\n * @returns An AnthropicContent object\n * @throws Error if the content type or image source type is unsupported\n */\nfunction transformContentBlock(\n block: ContentBlock,\n cacheControl?: AnthropicCacheControl\n): AnthropicContent {\n switch (block.type) {\n case 'text':\n return {\n type: 'text',\n text: block.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: imageBlock.source.data,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n if (imageBlock.source.type === 'url') {\n return {\n type: 'image',\n source: {\n type: 'url',\n url: imageBlock.source.url,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: base64,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n throw new Error(`Unknown image source type`);\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts cache control configuration from tool metadata.\n *\n * @param tool - The tool to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractToolCacheControl(tool: Tool): AnthropicCacheControl | undefined {\n const anthropicMeta = tool.metadata?.anthropic as\n | { cache_control?: AnthropicCacheControl }\n | undefined;\n return anthropicMeta?.cache_control;\n}\n\n/**\n * Transforms a UPP Tool definition to Anthropic's tool format.\n *\n * Cache control can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'search_docs',\n * description: 'Search documentation',\n * parameters: {...},\n * metadata: { anthropic: { cache_control: { type: 'ephemeral' } } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns An AnthropicTool with the appropriate input schema\n */\nfunction transformTool(tool: Tool): AnthropicTool {\n const cacheControl = extractToolCacheControl(tool);\n\n return {\n name: tool.name,\n description: tool.description,\n input_schema: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n}\n\n/**\n * Transforms an Anthropic API response to UPP's LLMResponse format.\n *\n * Extracts text content, tool calls, and structured output data from\n * Anthropic's response. The json_response tool is treated specially\n * for structured output extraction.\n *\n * @param data - The raw Anthropic API response\n * @returns A UPP LLMResponse with message, usage, and optional structured data\n *\n * @see {@link transformRequest} for the request transformation\n */\nexport function transformResponse(data: AnthropicResponse): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of data.content) {\n if (block.type === 'text') {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use') {\n if (block.name === 'json_response') {\n structuredData = block.input;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: block.input,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n anthropic: {\n stop_reason: data.stop_reason,\n stop_sequence: data.stop_sequence,\n model: data.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n cacheReadTokens: data.usage.cache_read_input_tokens ?? 0,\n cacheWriteTokens: data.usage.cache_creation_input_tokens ?? 0,\n };\n\n return {\n message,\n usage,\n stopReason: data.stop_reason ?? 'end_turn',\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating streamed response data.\n *\n * Used during streaming to collect content blocks, token counts, and\n * metadata as events arrive from the Anthropic API.\n */\nexport interface StreamState {\n /** Unique identifier for the message being streamed. */\n messageId: string;\n /** The model that generated this response. */\n model: string;\n /** Accumulated content blocks indexed by their stream position. */\n content: Array<{ type: string; text?: string; id?: string; name?: string; input?: string }>;\n /** The reason the response ended, if completed. */\n stopReason: string | null;\n /** Number of input tokens consumed. */\n inputTokens: number;\n /** Number of output tokens generated. */\n outputTokens: number;\n /** Number of tokens read from cache (cache hits). */\n cacheReadTokens: number;\n /** Number of tokens written to cache. */\n cacheWriteTokens: number;\n}\n\n/**\n * Creates an initialized StreamState for accumulating streaming responses.\n *\n * @returns A fresh StreamState with empty/default values\n */\nexport function createStreamState(): StreamState {\n return {\n messageId: '',\n model: '',\n content: [],\n stopReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n}\n\n/**\n * Transforms an Anthropic streaming event to a UPP StreamEvent.\n *\n * Updates the provided state object as a side effect to accumulate\n * response data across multiple events. Returns null for events that\n * don't produce corresponding UPP events (e.g., ping, message_delta).\n *\n * @param event - The Anthropic SSE event to transform\n * @param state - Mutable state object to update with accumulated data\n * @returns A UPP StreamEvent, or null if no event should be emitted\n *\n * @example\n * ```typescript\n * const state = createStreamState();\n * for await (const event of parseSSEStream(response.body)) {\n * const uppEvent = transformStreamEvent(event, state);\n * if (uppEvent) {\n * yield uppEvent;\n * }\n * }\n * const finalResponse = buildResponseFromState(state);\n * ```\n */\nexport function transformStreamEvent(\n event: AnthropicStreamEvent,\n state: StreamState\n): StreamEvent | null {\n switch (event.type) {\n case 'message_start':\n state.messageId = event.message.id;\n state.model = event.message.model;\n state.inputTokens = event.message.usage.input_tokens;\n state.cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;\n state.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;\n return { type: 'message_start', index: 0, delta: {} };\n\n case 'content_block_start':\n if (event.content_block.type === 'text') {\n state.content[event.index] = { type: 'text', text: '' };\n } else if (event.content_block.type === 'tool_use') {\n state.content[event.index] = {\n type: 'tool_use',\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n };\n }\n return { type: 'content_block_start', index: event.index, delta: {} };\n\n case 'content_block_delta': {\n const delta = event.delta;\n if (delta.type === 'text_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.text =\n (state.content[event.index]!.text ?? '') + delta.text;\n }\n return {\n type: 'text_delta',\n index: event.index,\n delta: { text: delta.text },\n };\n }\n if (delta.type === 'input_json_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.input =\n (state.content[event.index]!.input ?? '') + delta.partial_json;\n }\n return {\n type: 'tool_call_delta',\n index: event.index,\n delta: {\n argumentsJson: delta.partial_json,\n toolCallId: state.content[event.index]?.id,\n toolName: state.content[event.index]?.name,\n },\n };\n }\n if (delta.type === 'thinking_delta') {\n return {\n type: 'reasoning_delta',\n index: event.index,\n delta: { text: delta.thinking },\n };\n }\n return null;\n }\n\n case 'content_block_stop':\n return { type: 'content_block_stop', index: event.index, delta: {} };\n\n case 'message_delta':\n state.stopReason = event.delta.stop_reason;\n state.outputTokens = event.usage.output_tokens;\n return null;\n\n case 'message_stop':\n return { type: 'message_stop', index: 0, delta: {} };\n\n case 'ping':\n case 'error':\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Builds a complete LLMResponse from accumulated stream state.\n *\n * Call this after all stream events have been processed to construct\n * the final response. Parses accumulated JSON for tool call arguments\n * and extracts structured output data.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n *\n * @see {@link createStreamState} for initializing state\n * @see {@link transformStreamEvent} for populating state from events\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of state.content) {\n if (block.type === 'text' && block.text) {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use' && block.id && block.name) {\n let args: Record<string, unknown> = {};\n if (block.input) {\n try {\n args = JSON.parse(block.input);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n if (block.name === 'json_response') {\n structuredData = args;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.messageId,\n metadata: {\n anthropic: {\n stop_reason: state.stopReason,\n model: state.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: state.cacheWriteTokens,\n };\n\n return {\n message,\n usage,\n stopReason: state.stopReason ?? 'end_turn',\n data: structuredData,\n };\n}\n","/**\n * @fileoverview Anthropic LLM handler implementation.\n *\n * This module provides the core LLM handler for Anthropic's Claude models,\n * implementing both synchronous completion and streaming capabilities.\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { AnthropicLLMParams, AnthropicResponse, AnthropicStreamEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for the Anthropic Messages API. */\nconst ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';\n\n/** Default Anthropic API version header value. */\nconst ANTHROPIC_VERSION = '2023-06-01';\n\n/**\n * Capability flags for Anthropic Claude models.\n *\n * Defines what features are supported by the Anthropic provider:\n * - streaming: Real-time token generation via SSE\n * - tools: Function calling / tool use\n * - structuredOutput: JSON schema-constrained responses (via tool forcing)\n * - imageInput: Vision capabilities for image analysis\n */\nconst ANTHROPIC_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an Anthropic LLM handler for the Universal Provider Protocol.\n *\n * The handler provides methods to bind specific Claude models and make\n * completion requests. It handles API authentication, request transformation,\n * and response parsing.\n *\n * @returns An LLMHandler configured for Anthropic's Messages API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('claude-sonnet-4-20250514');\n *\n * const response = await model.complete({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: process.env.ANTHROPIC_API_KEY },\n * });\n * ```\n */\nexport function createLLMHandler(): LLMHandler<AnthropicLLMParams> {\n let providerRef: LLMProvider<AnthropicLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<AnthropicLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<AnthropicLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'anthropic',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<AnthropicLLMParams> = {\n modelId,\n capabilities: ANTHROPIC_CAPABILITIES,\n\n get provider(): LLMProvider<AnthropicLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<AnthropicLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n const data = (await response.json()) as AnthropicResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<AnthropicLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'anthropic', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (typeof data === 'object' && data !== null && 'type' in data) {\n const event = data as AnthropicStreamEvent;\n\n if (event.type === 'error') {\n const error = new UPPError(\n event.error.message,\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvent = transformStreamEvent(event, state);\n if (uppEvent) {\n yield uppEvent;\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Anthropic provider instance for the Universal Provider Protocol.\n *\n * Provides access to Claude language models through a unified interface.\n * Currently supports the LLM modality with full streaming, tool use,\n * structured output, and image input capabilities.\n *\n * @example\n * ```typescript\n * import { anthropic } from './providers/anthropic';\n *\n * const claude = anthropic.llm.bind('claude-sonnet-4-20250514');\n * const response = await claude.complete({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: 'sk-...' },\n * });\n * ```\n *\n * @see {@link AnthropicLLMParams} for provider-specific parameters\n */\nexport const anthropic = createProvider({\n name: 'anthropic',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\nexport type { AnthropicLLMParams, AnthropicHeaders } from './types.ts';\n"],"mappings":"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","names":[]}
@@ -1,11 +1,27 @@
1
1
  // src/types/errors.ts
2
2
  var UPPError = class _UPPError extends Error {
3
+ /** Normalized error code for programmatic handling */
3
4
  code;
5
+ /** Name of the provider that generated the error */
4
6
  provider;
7
+ /** The modality that was being used when the error occurred */
5
8
  modality;
9
+ /** HTTP status code from the provider's response, if available */
6
10
  statusCode;
11
+ /** The original error that caused this UPPError, if wrapping another error */
7
12
  cause;
13
+ /** Error class name, always 'UPPError' */
8
14
  name = "UPPError";
15
+ /**
16
+ * Creates a new UPPError instance.
17
+ *
18
+ * @param message - Human-readable error description
19
+ * @param code - Normalized error code for programmatic handling
20
+ * @param provider - Name of the provider that generated the error
21
+ * @param modality - The modality that was being used
22
+ * @param statusCode - HTTP status code from the provider's response
23
+ * @param cause - The original error being wrapped
24
+ */
9
25
  constructor(message, code, provider, modality, statusCode, cause) {
10
26
  super(message);
11
27
  this.code = code;
@@ -18,7 +34,9 @@ var UPPError = class _UPPError extends Error {
18
34
  }
19
35
  }
20
36
  /**
21
- * Create a string representation of the error
37
+ * Creates a string representation of the error.
38
+ *
39
+ * @returns Formatted error string including code, message, provider, and modality
22
40
  */
23
41
  toString() {
24
42
  let str = `UPPError [${this.code}]: ${this.message}`;
@@ -30,7 +48,9 @@ var UPPError = class _UPPError extends Error {
30
48
  return str;
31
49
  }
32
50
  /**
33
- * Convert to JSON for serialization
51
+ * Converts the error to a JSON-serializable object.
52
+ *
53
+ * @returns Plain object representation suitable for logging or transmission
34
54
  */
35
55
  toJSON() {
36
56
  return {
@@ -49,12 +69,23 @@ var UPPError = class _UPPError extends Error {
49
69
  var RoundRobinKeys = class {
50
70
  keys;
51
71
  index = 0;
72
+ /**
73
+ * Creates a new RoundRobinKeys instance.
74
+ *
75
+ * @param keys - Array of API keys to rotate through
76
+ * @throws {Error} When the keys array is empty
77
+ */
52
78
  constructor(keys) {
53
79
  if (keys.length === 0) {
54
80
  throw new Error("RoundRobinKeys requires at least one key");
55
81
  }
56
82
  this.keys = keys;
57
83
  }
84
+ /**
85
+ * Returns the next key in the rotation sequence.
86
+ *
87
+ * @returns The next API key in round-robin order
88
+ */
58
89
  getKey() {
59
90
  const key = this.keys[this.index];
60
91
  this.index = (this.index + 1) % this.keys.length;
@@ -64,6 +95,12 @@ var RoundRobinKeys = class {
64
95
  var WeightedKeys = class {
65
96
  entries;
66
97
  totalWeight;
98
+ /**
99
+ * Creates a new WeightedKeys instance.
100
+ *
101
+ * @param keys - Array of key-weight pairs defining selection probabilities
102
+ * @throws {Error} When the keys array is empty
103
+ */
67
104
  constructor(keys) {
68
105
  if (keys.length === 0) {
69
106
  throw new Error("WeightedKeys requires at least one key");
@@ -71,6 +108,11 @@ var WeightedKeys = class {
71
108
  this.entries = keys;
72
109
  this.totalWeight = keys.reduce((sum, k) => sum + k.weight, 0);
73
110
  }
111
+ /**
112
+ * Returns a randomly selected key based on configured weights.
113
+ *
114
+ * @returns An API key selected with probability proportional to its weight
115
+ */
74
116
  getKey() {
75
117
  const random = Math.random() * this.totalWeight;
76
118
  let cumulative = 0;
@@ -85,9 +127,19 @@ var WeightedKeys = class {
85
127
  };
86
128
  var DynamicKey = class {
87
129
  selector;
130
+ /**
131
+ * Creates a new DynamicKey instance.
132
+ *
133
+ * @param selector - Function that returns an API key (sync or async)
134
+ */
88
135
  constructor(selector) {
89
136
  this.selector = selector;
90
137
  }
138
+ /**
139
+ * Invokes the selector function to retrieve the current key.
140
+ *
141
+ * @returns Promise resolving to the selected API key
142
+ */
91
143
  async getKey() {
92
144
  return this.selector();
93
145
  }
@@ -334,4 +386,4 @@ export {
334
386
  doFetch,
335
387
  doStreamFetch
336
388
  };
337
- //# sourceMappingURL=chunk-SUNYWHTH.js.map
389
+ //# sourceMappingURL=chunk-MOU4U3PO.js.map