@ai-sdk/anthropic 4.0.50 → 4.0.52

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.
@@ -144,65 +144,16 @@ The following optional provider options are available for Anthropic models:
144
144
  Optional. Metadata to include with the request. See the [Anthropic API documentation](https://platform.claude.com/docs/en/api/messages/create) for details.
145
145
  - `userId` _string_ - An external identifier for the end-user. Should be a UUID, hash, or other opaque identifier. Must not contain PII.
146
146
 
147
- ### Text Batches
147
+ ### Batch
148
148
 
149
149
  <Note type="warning">
150
- Text batch support is experimental and the API may change in patch releases.
150
+ Batch support is experimental and the API may change in patch releases.
151
151
  </Note>
152
152
 
153
153
  Anthropic language models support asynchronous text generation through the
154
154
  [Message Batches API](https://platform.claude.com/docs/en/build-with-claude/batch-processing).
155
- Use the experimental text batch APIs to start a batch, poll its status, and
156
- stream its results:
157
-
158
- ```ts
159
- import { anthropic } from '@ai-sdk/anthropic';
160
- import {
161
- experimental_getBatchResults as getBatchResults,
162
- experimental_getBatchStatus as getBatchStatus,
163
- experimental_startBatch as startBatch,
164
- } from 'ai';
165
- import { setTimeout } from 'node:timers/promises';
166
-
167
- const model = 'claude-haiku-4-5';
168
-
169
- const batch = await startBatch({
170
- provider: anthropic,
171
- requests: [
172
- {
173
- id: 'capital-france',
174
- type: 'text',
175
- model,
176
- prompt: 'What is the capital of France?',
177
- },
178
- {
179
- id: 'capital-germany',
180
- type: 'text',
181
- model: 'claude-sonnet-4-5',
182
- prompt: 'What is the capital of Germany?',
183
- },
184
- ],
185
- });
186
-
187
- let status = batch.status;
188
- while (status === 'pending') {
189
- await setTimeout(60_000);
190
- ({ status } = await getBatchStatus({ provider: anthropic, batch }));
191
- }
192
-
193
- for await (const item of getBatchResults({ provider: anthropic, batch })) {
194
- if (item.status === 'succeeded') {
195
- console.log(item.id, item.text);
196
- } else {
197
- console.error(item.id, item.error);
198
- }
199
- }
200
- ```
201
-
202
- `startBatch` returns a serializable batch reference. Persist this reference
203
- to check the batch status or retrieve its results from another process. Results
204
- can arrive in a different order from the input requests, so match each result by
205
- its `id`.
155
+ Pass the Anthropic provider to the AI SDK's [Batch](/docs/ai-sdk-core/batch)
156
+ API for the complete workflow, including polling, persistence, and result handling.
206
157
 
207
158
  Each request specifies its `type` and `model`. Anthropic supports using
208
159
  different text models within the same batch.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/anthropic",
3
- "version": "4.0.50",
3
+ "version": "4.0.52",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -35,8 +35,8 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@ai-sdk/provider": "4.0.11",
39
- "@ai-sdk/provider-utils": "5.0.37"
38
+ "@ai-sdk/provider": "4.0.13",
39
+ "@ai-sdk/provider-utils": "5.0.39"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@ai-sdk/test-server": "2.0.1",
@@ -3,7 +3,10 @@ import {
3
3
  InvalidResponseDataError,
4
4
  UnsupportedFunctionalityError,
5
5
  type Experimental_BatchV4 as BatchV4,
6
+ type Experimental_BatchV4CancelResult as BatchV4CancelResult,
6
7
  type Experimental_BatchV4ItemResult as BatchV4ItemResult,
8
+ type Experimental_BatchV4ListOptions as BatchV4ListOptions,
9
+ type Experimental_BatchV4ListResult as BatchV4ListResult,
7
10
  type Experimental_BatchV4OperationOptions as BatchV4OperationOptions,
8
11
  type Experimental_BatchV4StartResult as BatchV4StartResult,
9
12
  type Experimental_BatchV4Status as BatchV4Status,
@@ -64,25 +67,36 @@ const anthropicBatchProviderOptionsSchema = anthropicLanguageModelOptions.pick({
64
67
 
65
68
  type AnthropicBatchRequest = TextBatchV4Request<AnthropicModelId>;
66
69
 
70
+ const anthropicBatchResponseZodSchema = () =>
71
+ z.object({
72
+ id: z.string(),
73
+ type: z.literal('message_batch'),
74
+ processing_status: z.string(),
75
+ request_counts: z.object({
76
+ processing: z.number(),
77
+ succeeded: z.number(),
78
+ errored: z.number(),
79
+ canceled: z.number(),
80
+ expired: z.number(),
81
+ }),
82
+ created_at: z.string(),
83
+ expires_at: z.string(),
84
+ archived_at: z.string().nullish(),
85
+ cancel_initiated_at: z.string().nullish(),
86
+ ended_at: z.string().nullish(),
87
+ results_url: z.string().nullish(),
88
+ });
89
+
67
90
  const anthropicBatchResponseSchema = lazySchema(() =>
91
+ zodSchema(anthropicBatchResponseZodSchema()),
92
+ );
93
+
94
+ const anthropicBatchListResponseSchema = lazySchema(() =>
68
95
  zodSchema(
69
96
  z.object({
70
- id: z.string(),
71
- type: z.literal('message_batch'),
72
- processing_status: z.string(),
73
- request_counts: z.object({
74
- processing: z.number(),
75
- succeeded: z.number(),
76
- errored: z.number(),
77
- canceled: z.number(),
78
- expired: z.number(),
79
- }),
80
- created_at: z.string(),
81
- expires_at: z.string(),
82
- archived_at: z.string().nullish(),
83
- cancel_initiated_at: z.string().nullish(),
84
- ended_at: z.string().nullish(),
85
- results_url: z.string().nullish(),
97
+ data: z.array(anthropicBatchResponseZodSchema()),
98
+ has_more: z.boolean(),
99
+ last_id: z.string().nullish(),
86
100
  }),
87
101
  ),
88
102
  );
@@ -295,6 +309,56 @@ export class AnthropicBatch implements BatchV4<{
295
309
  return convertAnthropicBatchStatus(await this.retrieveBatch(options));
296
310
  }
297
311
 
312
+ async doCancelBatch(
313
+ options: BatchV4OperationOptions,
314
+ ): Promise<BatchV4CancelResult> {
315
+ await postJsonToApi({
316
+ url: this.getBatchUrl(`/${encodeURIComponent(options.batchId)}/cancel`),
317
+ headers: await this.getBatchHeaders(options.headers),
318
+ body: {},
319
+ failedResponseHandler: anthropicFailedResponseHandler,
320
+ successfulResponseHandler: createJsonResponseHandler(
321
+ anthropicBatchResponseSchema,
322
+ ),
323
+ abortSignal: options.abortSignal,
324
+ fetch: this.options.config.fetch,
325
+ });
326
+
327
+ return {};
328
+ }
329
+
330
+ async doListBatches(options: BatchV4ListOptions): Promise<BatchV4ListResult> {
331
+ const url = new URL(this.getBatchUrl(''));
332
+ if (options.limit != null) {
333
+ url.searchParams.set('limit', String(options.limit));
334
+ }
335
+ if (options.cursor != null) {
336
+ url.searchParams.set('after_id', options.cursor);
337
+ }
338
+
339
+ const { value: page } = await getFromApi({
340
+ url: url.toString(),
341
+ validateUrl: false,
342
+ headers: await this.getBatchHeaders(options.headers),
343
+ failedResponseHandler: anthropicFailedResponseHandler,
344
+ successfulResponseHandler: createJsonResponseHandler(
345
+ anthropicBatchListResponseSchema,
346
+ ),
347
+ abortSignal: options.abortSignal,
348
+ fetch: this.options.config.fetch,
349
+ });
350
+
351
+ return {
352
+ batches: page.data.map(batch => ({
353
+ batchId: batch.id,
354
+ ...convertAnthropicBatchStatus(batch),
355
+ })),
356
+ ...(page.has_more && page.last_id != null
357
+ ? { nextCursor: page.last_id }
358
+ : {}),
359
+ };
360
+ }
361
+
298
362
  async doGetBatchResults(
299
363
  options: BatchV4OperationOptions,
300
364
  ): Promise<ReadableStream<BatchV4ItemResult>> {