@providerprotocol/ai 0.0.18 → 0.0.20

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 (39) hide show
  1. package/README.md +364 -111
  2. package/dist/anthropic/index.d.ts +1 -1
  3. package/dist/anthropic/index.js +6 -6
  4. package/dist/chunk-P5IRTEM5.js +120 -0
  5. package/dist/chunk-P5IRTEM5.js.map +1 -0
  6. package/dist/{chunk-5FEAOEXV.js → chunk-U3FZWV4U.js} +53 -102
  7. package/dist/chunk-U3FZWV4U.js.map +1 -0
  8. package/dist/chunk-WAKD3OO5.js +224 -0
  9. package/dist/chunk-WAKD3OO5.js.map +1 -0
  10. package/dist/content-DEl3z_W2.d.ts +276 -0
  11. package/dist/google/index.d.ts +3 -1
  12. package/dist/google/index.js +123 -7
  13. package/dist/google/index.js.map +1 -1
  14. package/dist/http/index.d.ts +2 -2
  15. package/dist/http/index.js +4 -3
  16. package/dist/image-Dhq-Yuq4.d.ts +456 -0
  17. package/dist/index.d.ts +55 -163
  18. package/dist/index.js +81 -213
  19. package/dist/index.js.map +1 -1
  20. package/dist/ollama/index.d.ts +1 -1
  21. package/dist/ollama/index.js +6 -6
  22. package/dist/openai/index.d.ts +47 -20
  23. package/dist/openai/index.js +310 -7
  24. package/dist/openai/index.js.map +1 -1
  25. package/dist/openrouter/index.d.ts +1 -1
  26. package/dist/openrouter/index.js +6 -6
  27. package/dist/{provider-D5MO3-pS.d.ts → provider-BBMBZuGn.d.ts} +11 -11
  28. package/dist/proxy/index.d.ts +310 -86
  29. package/dist/proxy/index.js +33 -59
  30. package/dist/proxy/index.js.map +1 -1
  31. package/dist/{retry-DZ4Sqmxp.d.ts → retry-DR7YRJDz.d.ts} +1 -1
  32. package/dist/{stream-BjyVzBxV.d.ts → stream-DRHy6q1a.d.ts} +2 -275
  33. package/dist/xai/index.d.ts +29 -1
  34. package/dist/xai/index.js +119 -7
  35. package/dist/xai/index.js.map +1 -1
  36. package/package.json +1 -1
  37. package/dist/chunk-5FEAOEXV.js.map +0 -1
  38. package/dist/chunk-DZQHVGNV.js +0 -71
  39. package/dist/chunk-DZQHVGNV.js.map +0 -1
package/README.md CHANGED
@@ -1,117 +1,130 @@
1
1
  # @providerprotocol/ai
2
2
 
3
- Unified Provider Protocol (UPP-1.2) implementation for AI inference across multiple providers.
4
-
5
- ## Install
3
+ A unified TypeScript SDK for AI inference across multiple providers. One API for LLMs, embeddings, and image generation.
6
4
 
7
5
  ```bash
8
6
  bun add @providerprotocol/ai
9
7
  ```
10
8
 
11
- ## Usage
9
+ ## Quick Start
12
10
 
13
11
  ```typescript
14
12
  import { llm } from '@providerprotocol/ai';
15
13
  import { anthropic } from '@providerprotocol/ai/anthropic';
16
- import { openai } from '@providerprotocol/ai/openai';
17
- import { google } from '@providerprotocol/ai/google';
18
- import { ollama } from '@providerprotocol/ai/ollama';
19
- import { openrouter } from '@providerprotocol/ai/openrouter';
20
- import { xai } from '@providerprotocol/ai/xai';
21
14
 
22
- // Simple generation
23
15
  const claude = llm({ model: anthropic('claude-sonnet-4-20250514') });
24
16
  const turn = await claude.generate('Hello!');
25
17
  console.log(turn.response.text);
18
+ ```
19
+
20
+ ## Providers
26
21
 
27
- // Streaming
22
+ | Provider | Import | LLM | Embedding | Image |
23
+ |----------|--------|:---:|:---------:|:-----:|
24
+ | Anthropic | `@providerprotocol/ai/anthropic` | ✓ | | |
25
+ | OpenAI | `@providerprotocol/ai/openai` | ✓ | ✓ | ✓ |
26
+ | Google | `@providerprotocol/ai/google` | ✓ | ✓ | ✓ |
27
+ | xAI | `@providerprotocol/ai/xai` | ✓ | | ✓ |
28
+ | Ollama | `@providerprotocol/ai/ollama` | ✓ | ✓ | |
29
+ | OpenRouter | `@providerprotocol/ai/openrouter` | ✓ | ✓ | |
30
+
31
+ API keys are loaded automatically from environment variables (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, etc.).
32
+
33
+ ## LLM
34
+
35
+ ### Streaming
36
+
37
+ ```typescript
28
38
  const stream = claude.stream('Count to 5');
29
39
  for await (const event of stream) {
30
- if (event.type === 'text_delta') process.stdout.write(event.delta.text);
40
+ if (event.type === 'text_delta') {
41
+ process.stdout.write(event.delta.text);
42
+ }
31
43
  }
44
+ const turn = await stream.turn;
45
+ ```
46
+
47
+ ### Multi-turn Conversations
48
+
49
+ ```typescript
50
+ const history: Message[] = [];
32
51
 
33
- // Multi-turn
34
- const history = [];
35
52
  const t1 = await claude.generate(history, 'My name is Alice');
36
53
  history.push(...t1.messages);
54
+
37
55
  const t2 = await claude.generate(history, 'What is my name?');
56
+ // Response: "Your name is Alice"
57
+ ```
58
+
59
+ ### Tools
38
60
 
39
- // Tools
61
+ ```typescript
40
62
  const turn = await claude.generate({
41
63
  tools: [{
42
64
  name: 'getWeather',
43
65
  description: 'Get weather for a location',
44
- parameters: { type: 'object', properties: { location: { type: 'string' } } },
45
- run: async ({ location }) => `Sunny in ${location}`,
66
+ parameters: {
67
+ type: 'object',
68
+ properties: { location: { type: 'string' } },
69
+ required: ['location'],
70
+ },
71
+ run: async ({ location }) => ({ temp: 72, conditions: 'sunny' }),
46
72
  }],
47
- }, 'Weather in Tokyo?');
73
+ }, 'What is the weather in Tokyo?');
74
+ ```
75
+
76
+ ### Structured Output
48
77
 
49
- // Structured output
50
- const turn = await llm({
78
+ ```typescript
79
+ import { llm } from '@providerprotocol/ai';
80
+ import { openai } from '@providerprotocol/ai/openai';
81
+
82
+ const extractor = llm({
51
83
  model: openai('gpt-4o'),
52
84
  structure: {
53
85
  type: 'object',
54
- properties: { name: { type: 'string' }, age: { type: 'number' } },
86
+ properties: {
87
+ name: { type: 'string' },
88
+ age: { type: 'number' },
89
+ },
90
+ required: ['name', 'age'],
55
91
  },
56
- }).generate('Extract: John is 30 years old');
92
+ });
93
+
94
+ const turn = await extractor.generate('John is 30 years old');
57
95
  console.log(turn.data); // { name: 'John', age: 30 }
58
96
  ```
59
97
 
60
- ## Embeddings
98
+ ### Multimodal Input
99
+
100
+ ```typescript
101
+ import { Image } from '@providerprotocol/ai';
102
+
103
+ const img = await Image.fromPath('./photo.png');
104
+ const turn = await claude.generate([img, 'What is in this image?']);
105
+ ```
61
106
 
62
- Generate vector embeddings from text using the unified `embedding()` interface.
107
+ ## Embeddings
63
108
 
64
109
  ```typescript
65
110
  import { embedding } from '@providerprotocol/ai';
66
111
  import { openai } from '@providerprotocol/ai/openai';
67
- import { google } from '@providerprotocol/ai/google';
68
- import { ollama } from '@providerprotocol/ai/ollama';
69
- import { openrouter } from '@providerprotocol/ai/openrouter';
70
112
 
71
- // Single text embedding
72
113
  const embedder = embedding({ model: openai('text-embedding-3-small') });
73
- const result = await embedder.embed('Hello world');
74
- console.log(result.embeddings[0].vector); // [0.123, -0.456, ...]
75
- console.log(result.embeddings[0].dimensions); // 1536
76
114
 
77
- // Batch embedding
115
+ // Single or batch
116
+ const result = await embedder.embed('Hello world');
78
117
  const batch = await embedder.embed(['doc1', 'doc2', 'doc3']);
79
- console.log(batch.embeddings.length); // 3
80
118
 
81
- // Custom dimensions (OpenAI text-embedding-3 models)
82
- const smallEmbed = embedding({
83
- model: openai('text-embedding-3-small'),
84
- params: { dimensions: 256 },
85
- });
86
-
87
- // Google with task type optimization
88
- const googleEmbed = embedding({
89
- model: google('text-embedding-004'),
90
- params: {
91
- taskType: 'RETRIEVAL_DOCUMENT',
92
- title: 'Important Document',
93
- },
94
- });
95
-
96
- // Ollama local embeddings
97
- const localEmbed = embedding({
98
- model: ollama('qwen3-embedding:4b'),
99
- });
100
-
101
- // OpenRouter (access multiple providers)
102
- const routerEmbed = embedding({
103
- model: openrouter('openai/text-embedding-3-small'),
104
- });
119
+ console.log(result.embeddings[0].vector); // [0.123, -0.456, ...]
120
+ console.log(result.embeddings[0].dimensions); // 1536
105
121
  ```
106
122
 
107
- ### Chunked Streaming
123
+ ### Chunked Processing
108
124
 
109
- For large document sets, use chunked mode for progress tracking:
125
+ For large datasets with progress tracking:
110
126
 
111
127
  ```typescript
112
- const embedder = embedding({ model: openai('text-embedding-3-small') });
113
- const documents = Array.from({ length: 1000 }, (_, i) => `Document ${i}`);
114
-
115
128
  const stream = embedder.embed(documents, {
116
129
  chunked: true,
117
130
  batchSize: 100,
@@ -120,89 +133,329 @@ const stream = embedder.embed(documents, {
120
133
 
121
134
  for await (const progress of stream) {
122
135
  console.log(`${progress.percent.toFixed(1)}% complete`);
123
- console.log(`Processed ${progress.completed} of ${progress.total}`);
124
136
  }
125
137
 
126
- const finalResult = await stream.result;
127
- console.log(`Total embeddings: ${finalResult.embeddings.length}`);
138
+ const result = await stream.result;
139
+ ```
140
+
141
+ ## Image Generation
142
+
143
+ ```typescript
144
+ import { image } from '@providerprotocol/ai';
145
+ import { openai } from '@providerprotocol/ai/openai';
146
+
147
+ const dalle = image({ model: openai('dall-e-3') });
148
+ const result = await dalle.generate('A sunset over mountains');
149
+
150
+ console.log(result.images[0].image.toBase64());
128
151
  ```
129
152
 
130
- ### Provider-Specific Parameters
153
+ ### With Parameters
154
+
155
+ ```typescript
156
+ const hd = image({
157
+ model: openai('dall-e-3'),
158
+ params: { size: '1792x1024', quality: 'hd', style: 'natural' },
159
+ });
160
+ ```
131
161
 
132
- Each provider supports its native parameters passed through unchanged:
162
+ ### Image Editing
133
163
 
134
164
  ```typescript
135
- // OpenAI: dimensions, encoding_format, user
136
- embedding({
137
- model: openai('text-embedding-3-large'),
138
- params: { dimensions: 1024, encoding_format: 'float' },
165
+ import { image, Image } from '@providerprotocol/ai';
166
+
167
+ const editor = image({ model: openai('dall-e-2') });
168
+
169
+ const source = await Image.fromPath('./photo.png');
170
+ const mask = await Image.fromPath('./mask.png');
171
+
172
+ const result = await editor.edit({
173
+ image: source,
174
+ mask,
175
+ prompt: 'Add a rainbow in the sky',
139
176
  });
177
+ ```
178
+
179
+ ## Configuration
180
+
181
+ ```typescript
182
+ import { llm } from '@providerprotocol/ai';
183
+ import { openai } from '@providerprotocol/ai/openai';
184
+ import { ExponentialBackoff, RoundRobinKeys } from '@providerprotocol/ai/http';
140
185
 
141
- // Google: taskType, title, outputDimensionality
142
- embedding({
143
- model: google('text-embedding-004'),
186
+ const instance = llm({
187
+ model: openai('gpt-4o'),
188
+ config: {
189
+ apiKey: new RoundRobinKeys(['sk-key1', 'sk-key2']),
190
+ timeout: 30000,
191
+ retryStrategy: new ExponentialBackoff({ maxAttempts: 3 }),
192
+ },
144
193
  params: {
145
- taskType: 'SEMANTIC_SIMILARITY',
146
- outputDimensionality: 256,
194
+ temperature: 0.7,
195
+ max_tokens: 1000,
147
196
  },
197
+ system: 'You are a helpful assistant.',
148
198
  });
199
+ ```
149
200
 
150
- // Ollama: truncate, keep_alive, options
151
- embedding({
152
- model: ollama('nomic-embed-text'),
153
- params: { truncate: true, keep_alive: '5m' },
154
- });
201
+ ### Key Strategies
155
202
 
156
- // OpenRouter: dimensions, encoding_format, input_type
157
- embedding({
158
- model: openrouter('openai/text-embedding-3-small'),
159
- params: { dimensions: 512 },
160
- });
203
+ ```typescript
204
+ import { RoundRobinKeys, WeightedKeys, DynamicKey } from '@providerprotocol/ai/http';
205
+
206
+ // Cycle through keys evenly
207
+ new RoundRobinKeys(['sk-1', 'sk-2', 'sk-3'])
208
+
209
+ // Weighted selection (70% key1, 30% key2)
210
+ new WeightedKeys([
211
+ { key: 'sk-1', weight: 70 },
212
+ { key: 'sk-2', weight: 30 },
213
+ ])
214
+
215
+ // Dynamic fetching (secrets manager, etc.)
216
+ new DynamicKey(async () => fetchKeyFromVault())
161
217
  ```
162
218
 
163
- ## Providers
219
+ ### Retry Strategies
220
+
221
+ ```typescript
222
+ import {
223
+ ExponentialBackoff,
224
+ LinearBackoff,
225
+ NoRetry,
226
+ TokenBucket,
227
+ RetryAfterStrategy,
228
+ } from '@providerprotocol/ai/http';
164
229
 
165
- | Provider | Import | LLM | Embedding |
166
- |----------|--------|-----|-----------|
167
- | Anthropic | `@providerprotocol/ai/anthropic` | Yes | - |
168
- | OpenAI | `@providerprotocol/ai/openai` | Yes | Yes |
169
- | Google | `@providerprotocol/ai/google` | Yes | Yes |
170
- | Ollama | `@providerprotocol/ai/ollama` | Yes | Yes |
171
- | OpenRouter | `@providerprotocol/ai/openrouter` | Yes | Yes |
172
- | xAI (Grok) | `@providerprotocol/ai/xai` | Yes | - |
230
+ // Exponential: 1s, 2s, 4s... (default)
231
+ new ExponentialBackoff({ maxAttempts: 5, baseDelay: 1000, maxDelay: 30000 })
173
232
 
174
- ### xAI API Modes
233
+ // Linear: 1s, 2s, 3s...
234
+ new LinearBackoff({ maxAttempts: 3, delay: 1000 })
175
235
 
176
- xAI supports three API modes:
236
+ // Rate limiting with token bucket
237
+ new TokenBucket({ maxTokens: 10, refillRate: 1 })
238
+
239
+ // Respect server Retry-After headers
240
+ new RetryAfterStrategy({ maxAttempts: 3, fallbackDelay: 5000 })
241
+
242
+ // No retries
243
+ new NoRetry()
244
+ ```
245
+
246
+ ## Tool Execution Control
177
247
 
178
248
  ```typescript
179
- import { xai } from '@providerprotocol/ai/xai';
249
+ const turn = await claude.generate({
250
+ tools: [weatherTool, searchTool],
251
+ toolStrategy: {
252
+ maxIterations: 5,
253
+ onBeforeCall: (tool, params) => {
254
+ if (tool.name === 'dangerousTool') return false; // Block execution
255
+ return true;
256
+ },
257
+ onAfterCall: (tool, params, result) => {
258
+ console.log(`${tool.name} returned:`, result);
259
+ },
260
+ onError: (tool, params, error) => {
261
+ console.error(`${tool.name} failed:`, error);
262
+ },
263
+ },
264
+ }, 'Search for recent news about AI');
265
+ ```
180
266
 
181
- // Chat Completions API (OpenAI-compatible, default)
182
- const grok = llm({ model: xai('grok-3-fast') });
267
+ ## Thread Management
183
268
 
184
- // Responses API (stateful, OpenAI Responses-compatible)
185
- const grok = llm({ model: xai('grok-3-fast', { api: 'responses' }) });
269
+ ```typescript
270
+ import { Thread } from '@providerprotocol/ai';
186
271
 
187
- // Messages API (Anthropic-compatible)
188
- const grok = llm({ model: xai('grok-3-fast', { api: 'messages' }) });
272
+ const thread = new Thread();
273
+
274
+ thread.user('Hello!');
275
+ const turn = await claude.generate(thread.toMessages(), 'How are you?');
276
+ thread.append(turn);
277
+
278
+ // Serialize for storage
279
+ const json = thread.toJSON();
280
+ localStorage.setItem('conversation', JSON.stringify(json));
281
+
282
+ // Restore later
283
+ const restored = Thread.fromJSON(JSON.parse(localStorage.getItem('conversation')));
189
284
  ```
190
285
 
191
- ## Configuration
286
+ ## Error Handling
287
+
288
+ All errors are normalized to `UPPError` with consistent error codes:
192
289
 
193
290
  ```typescript
291
+ import { UPPError } from '@providerprotocol/ai';
292
+
293
+ try {
294
+ await claude.generate('Hello');
295
+ } catch (error) {
296
+ if (error instanceof UPPError) {
297
+ switch (error.code) {
298
+ case 'RATE_LIMITED':
299
+ // Wait and retry
300
+ break;
301
+ case 'CONTEXT_LENGTH_EXCEEDED':
302
+ // Reduce input size
303
+ break;
304
+ case 'AUTHENTICATION_FAILED':
305
+ // Check API key
306
+ break;
307
+ case 'CONTENT_FILTERED':
308
+ // Content policy violation
309
+ break;
310
+ }
311
+ }
312
+ }
313
+ ```
314
+
315
+ **Error Codes:** `AUTHENTICATION_FAILED`, `RATE_LIMITED`, `CONTEXT_LENGTH_EXCEEDED`, `MODEL_NOT_FOUND`, `INVALID_REQUEST`, `INVALID_RESPONSE`, `CONTENT_FILTERED`, `QUOTA_EXCEEDED`, `PROVIDER_ERROR`, `NETWORK_ERROR`, `TIMEOUT`, `CANCELLED`
316
+
317
+ ## API Gateway / Proxy
318
+
319
+ Build AI API gateways with your own authentication. Users authenticate with your platform - AI provider keys stay hidden on the server.
320
+
321
+ > **Security Note:** The proxy works without any configuration, but this means **no authentication by default**. Always add your own auth layer in production - the examples below show how.
322
+
323
+ ### Server (Bun/Deno/Cloudflare Workers)
324
+
325
+ ```typescript
326
+ import { llm } from '@providerprotocol/ai';
327
+ import { anthropic } from '@providerprotocol/ai/anthropic';
194
328
  import { ExponentialBackoff, RoundRobinKeys } from '@providerprotocol/ai/http';
329
+ import { parseBody, toJSON, toSSE, toError } from '@providerprotocol/ai/proxy';
195
330
 
196
- const instance = llm({
197
- model: openai('gpt-4o'),
331
+ // Server manages AI provider keys - users never see them
332
+ const claude = llm({
333
+ model: anthropic('claude-sonnet-4-20250514'),
198
334
  config: {
199
- apiKey: 'sk-...',
200
- timeout: 30000,
335
+ apiKey: new RoundRobinKeys([process.env.ANTHROPIC_KEY_1!, process.env.ANTHROPIC_KEY_2!]),
336
+ retryStrategy: new ExponentialBackoff({ maxAttempts: 3 }),
337
+ },
338
+ });
339
+
340
+ Bun.serve({
341
+ port: 3000,
342
+ async fetch(req) {
343
+ // Authenticate with YOUR platform credentials
344
+ const token = req.headers.get('Authorization')?.replace('Bearer ', '');
345
+ const user = await validatePlatformToken(token ?? '');
346
+ if (!user) return toError('Unauthorized', 401);
347
+
348
+ // Rate limit, track usage, bill user, etc.
349
+ await trackUsage(user.id);
350
+
351
+ const { messages, system, params } = parseBody(await req.json());
352
+
353
+ if (params?.stream) {
354
+ return toSSE(claude.stream(messages, { system }));
355
+ }
356
+ return toJSON(await claude.generate(messages, { system }));
357
+ },
358
+ });
359
+ ```
360
+
361
+ ### Client
362
+
363
+ Clients authenticate with your platform token. They get automatic retry on network failures to your proxy.
364
+
365
+ ```typescript
366
+ import { llm } from '@providerprotocol/ai';
367
+ import { proxy } from '@providerprotocol/ai/proxy';
368
+ import { ExponentialBackoff } from '@providerprotocol/ai/http';
369
+
370
+ const claude = llm({
371
+ model: proxy('https://api.yourplatform.com/ai'),
372
+ config: {
373
+ headers: { 'Authorization': 'Bearer user-platform-token' },
201
374
  retryStrategy: new ExponentialBackoff({ maxAttempts: 3 }),
375
+ timeout: 30000,
202
376
  },
203
- params: { temperature: 0.7, max_tokens: 1000 },
204
- system: 'You are helpful.',
205
377
  });
378
+
379
+ const turn = await claude.generate('Hello!');
380
+ ```
381
+
382
+ ### Framework Adapters
383
+
384
+ Server adapters for Express, Fastify, and Nuxt/H3:
385
+
386
+ ```typescript
387
+ // Express
388
+ import { express as expressAdapter } from '@providerprotocol/ai/proxy/server';
389
+ app.post('/ai', authMiddleware, async (req, res) => {
390
+ const { messages, system, params } = parseBody(req.body);
391
+ if (params?.stream) {
392
+ expressAdapter.streamSSE(claude.stream(messages, { system }), res);
393
+ } else {
394
+ expressAdapter.sendJSON(await claude.generate(messages, { system }), res);
395
+ }
396
+ });
397
+
398
+ // Fastify
399
+ import { fastify as fastifyAdapter } from '@providerprotocol/ai/proxy/server';
400
+ app.post('/ai', async (request, reply) => {
401
+ const { messages, system, params } = parseBody(request.body);
402
+ if (params?.stream) {
403
+ return fastifyAdapter.streamSSE(claude.stream(messages, { system }), reply);
404
+ }
405
+ return fastifyAdapter.sendJSON(await claude.generate(messages, { system }), reply);
406
+ });
407
+
408
+ // Nuxt/H3 (server/api/ai.post.ts)
409
+ import { h3 as h3Adapter } from '@providerprotocol/ai/proxy/server';
410
+ export default defineEventHandler(async (event) => {
411
+ const { messages, system, params } = parseBody(await readBody(event));
412
+ if (params?.stream) {
413
+ return h3Adapter.streamSSE(claude.stream(messages, { system }), event);
414
+ }
415
+ return h3Adapter.sendJSON(await claude.generate(messages, { system }), event);
416
+ });
417
+ ```
418
+
419
+ **What this enables:**
420
+ - Users auth with your platform credentials (JWT, API keys, sessions)
421
+ - You manage/rotate AI provider keys centrally
422
+ - Per-user rate limiting, usage tracking, billing
423
+ - Model access control (different users get different models)
424
+ - Request/response logging, content filtering
425
+ - Double-layer retry: client retries to proxy, server retries to AI provider
426
+
427
+ ## xAI API Modes
428
+
429
+ xAI supports multiple API compatibility modes:
430
+
431
+ ```typescript
432
+ import { xai } from '@providerprotocol/ai/xai';
433
+
434
+ // Chat Completions (OpenAI-compatible, default)
435
+ xai('grok-3-fast')
436
+
437
+ // Responses API (stateful)
438
+ xai('grok-3-fast', { api: 'responses' })
439
+
440
+ // Messages API (Anthropic-compatible)
441
+ xai('grok-3-fast', { api: 'messages' })
442
+ ```
443
+
444
+ ## TypeScript
445
+
446
+ Full type safety with no `any` types. All provider parameters are typed:
447
+
448
+ ```typescript
449
+ import type {
450
+ Turn,
451
+ Message,
452
+ Tool,
453
+ UPPError,
454
+ TokenUsage,
455
+ StreamEvent,
456
+ EmbeddingResult,
457
+ ImageResult,
458
+ } from '@providerprotocol/ai';
206
459
  ```
207
460
 
208
461
  ## License
@@ -1,4 +1,4 @@
1
- import { d as Provider } from '../provider-D5MO3-pS.js';
1
+ import { d as Provider } from '../provider-BBMBZuGn.js';
2
2
 
3
3
  /**
4
4
  * @fileoverview Anthropic API type definitions.
@@ -11,14 +11,14 @@ import {
11
11
  parseSSEStream
12
12
  } from "../chunk-Z7RBRCRN.js";
13
13
  import {
14
- doFetch,
15
- doStreamFetch,
16
- normalizeHttpError,
17
14
  resolveApiKey
18
- } from "../chunk-5FEAOEXV.js";
15
+ } from "../chunk-P5IRTEM5.js";
19
16
  import {
20
- UPPError
21
- } from "../chunk-DZQHVGNV.js";
17
+ UPPError,
18
+ doFetch,
19
+ doStreamFetch,
20
+ normalizeHttpError
21
+ } from "../chunk-U3FZWV4U.js";
22
22
 
23
23
  // src/providers/anthropic/transform.ts
24
24
  function transformRequest(request, modelId) {