@ai-sdk/anthropic 4.0.89 → 4.0.90
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.
- package/CHANGELOG.md +9 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -16
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +15 -13
- package/dist/internal/index.js.map +1 -1
- package/docs/05-anthropic.mdx +74 -2
- package/package.json +2 -2
- package/src/anthropic-files.ts +4 -2
- package/src/anthropic-language-model.ts +23 -8
- package/src/anthropic-provider.ts +7 -4
- package/src/skills/anthropic-skills.ts +2 -7
package/docs/05-anthropic.mdx
CHANGED
|
@@ -97,10 +97,12 @@ You can use the following optional settings to customize the Anthropic provider
|
|
|
97
97
|
It defaults to the `ANTHROPIC_API_KEY` environment variable.
|
|
98
98
|
Only one of `apiKey` or `authToken` is required.
|
|
99
99
|
|
|
100
|
-
- **authToken**
|
|
100
|
+
- **authToken** _string | PromiseLike<string> | (() => string | PromiseLike<string>)_
|
|
101
101
|
|
|
102
102
|
Auth token that is being sent using the `Authorization: Bearer` header.
|
|
103
|
-
|
|
103
|
+
Pass a function to resolve a token for each request, including short-lived
|
|
104
|
+
tokens managed by an external credential provider. This setting does not
|
|
105
|
+
enable OAuth beta headers; configure any required headers explicitly.
|
|
104
106
|
Only one of `apiKey` or `authToken` is required.
|
|
105
107
|
|
|
106
108
|
- **headers** _Record<string,string>_
|
|
@@ -114,6 +116,76 @@ You can use the following optional settings to customize the Anthropic provider
|
|
|
114
116
|
You can use it as a middleware to intercept requests,
|
|
115
117
|
or to provide a custom fetch implementation for e.g. testing.
|
|
116
118
|
|
|
119
|
+
### Workload identity federation
|
|
120
|
+
|
|
121
|
+
Use an `authToken` callback to connect the Anthropic SDK's token exchange and
|
|
122
|
+
cache helpers to the AI SDK. Configure your service account and federation rule
|
|
123
|
+
first, as described in [Anthropic's workload identity federation guide](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation).
|
|
124
|
+
|
|
125
|
+
The following example uses the credential helpers from `@anthropic-ai/sdk@0.129.0`:
|
|
126
|
+
|
|
127
|
+
<InstallPackages packages="ai @ai-sdk/anthropic @anthropic-ai/sdk@0.129.0" />
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
131
|
+
import { identityTokenFromFile } from '@anthropic-ai/sdk/lib/credentials/identity-token';
|
|
132
|
+
import { oidcFederationProvider } from '@anthropic-ai/sdk/lib/credentials/oidc-federation';
|
|
133
|
+
import { TokenCache } from '@anthropic-ai/sdk/lib/credentials/token-cache';
|
|
134
|
+
import { generateText } from 'ai';
|
|
135
|
+
|
|
136
|
+
// Create the cache and provider once, then reuse them across requests.
|
|
137
|
+
const tokenCache = new TokenCache(
|
|
138
|
+
oidcFederationProvider({
|
|
139
|
+
identityTokenProvider: identityTokenFromFile(
|
|
140
|
+
'/var/run/secrets/anthropic.com/token',
|
|
141
|
+
),
|
|
142
|
+
federationRuleId: process.env.ANTHROPIC_FEDERATION_RULE_ID!,
|
|
143
|
+
organizationId: process.env.ANTHROPIC_ORGANIZATION_ID!,
|
|
144
|
+
serviceAccountId: process.env.ANTHROPIC_SERVICE_ACCOUNT_ID!,
|
|
145
|
+
// Set this when your rule requires a workspace or to select a specific one.
|
|
146
|
+
workspaceId: process.env.ANTHROPIC_WORKSPACE_ID,
|
|
147
|
+
baseURL: 'https://api.anthropic.com',
|
|
148
|
+
fetch: globalThis.fetch,
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const anthropic = createAnthropic({
|
|
153
|
+
authToken: () => tokenCache.getToken(),
|
|
154
|
+
headers: { 'anthropic-beta': 'oauth-2025-04-20' },
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const { text } = await generateText({
|
|
158
|
+
model: anthropic('claude-opus-5-5'),
|
|
159
|
+
prompt: 'Explain workload identity federation in one sentence.',
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The AI SDK resolves `authToken` before each request and sends the returned token
|
|
164
|
+
as a bearer credential. The Anthropic SDK helpers perform the OIDC exchange,
|
|
165
|
+
cache the access token, and renew it as needed.
|
|
166
|
+
|
|
167
|
+
Set the `oauth-2025-04-20` beta explicitly for these federated OAuth tokens,
|
|
168
|
+
matching Anthropic's SDK. A bearer token or token callback alone does not imply
|
|
169
|
+
workload identity federation. The exchange helper supplies its own token-endpoint
|
|
170
|
+
headers. This example covers Messages API inference; it does not add WIF support
|
|
171
|
+
to the Files, Skills, or Batch APIs, which have separate beta-header handling.
|
|
172
|
+
|
|
173
|
+
Refresh is demand-driven: in the helper version above, `getToken()` starts a
|
|
174
|
+
background exchange when the cached token has at most two minutes remaining,
|
|
175
|
+
and waits for an exchange when at most 30 seconds remain. Concurrent requests
|
|
176
|
+
share the pending exchange. Federation renews access by exchanging another
|
|
177
|
+
identity token; it does not use a refresh token.
|
|
178
|
+
|
|
179
|
+
Your workload's identity provider must supply fresh identity tokens. The file
|
|
180
|
+
helper rereads the file on each exchange but does not rotate its contents.
|
|
181
|
+
Anthropic rejects reuse of assertions with a `jti` by default, so arrange for a
|
|
182
|
+
fresh assertion for each exchange. See the [WIF reference](https://platform.claude.com/docs/en/manage-claude/wif-reference)
|
|
183
|
+
for token lifetimes and replay protection.
|
|
184
|
+
|
|
185
|
+
This setup explicitly configures credentials; it does not enable the Anthropic
|
|
186
|
+
client's automatic credential discovery or its invalidate-and-retry behavior on
|
|
187
|
+
HTTP 401. Keep the helper version pinned and verify the integration when upgrading.
|
|
188
|
+
|
|
117
189
|
## Language Models
|
|
118
190
|
|
|
119
191
|
You can create models that call the [Anthropic Messages API](https://docs.anthropic.com/claude/reference/messages_post) using the provider instance.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/anthropic",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.90",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ai-sdk/provider": "4.0.34",
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.70"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
package/src/anthropic-files.ts
CHANGED
|
@@ -9,8 +9,10 @@ import {
|
|
|
9
9
|
createJsonResponseHandler,
|
|
10
10
|
lazySchema,
|
|
11
11
|
postFormDataToApi,
|
|
12
|
+
resolve,
|
|
12
13
|
zodSchema,
|
|
13
14
|
type FetchFunction,
|
|
15
|
+
type Resolvable,
|
|
14
16
|
} from '@ai-sdk/provider-utils';
|
|
15
17
|
import { z } from 'zod/v4';
|
|
16
18
|
import { anthropicFailedResponseHandler } from './anthropic-error';
|
|
@@ -32,7 +34,7 @@ const anthropicUploadFileResponseSchema = lazySchema(() =>
|
|
|
32
34
|
interface AnthropicFilesConfig {
|
|
33
35
|
provider: string;
|
|
34
36
|
baseURL: string;
|
|
35
|
-
headers:
|
|
37
|
+
headers: Resolvable<Record<string, string | undefined>>;
|
|
36
38
|
fetch?: FetchFunction;
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -68,7 +70,7 @@ export class AnthropicFiles implements FilesV4 {
|
|
|
68
70
|
const { value: response } = await postFormDataToApi({
|
|
69
71
|
url: `${this.config.baseURL}/files`,
|
|
70
72
|
headers: combineHeaders(
|
|
71
|
-
this.config.headers
|
|
73
|
+
await resolve(this.config.headers),
|
|
72
74
|
{ 'anthropic-beta': 'files-api-2025-04-14' },
|
|
73
75
|
headers,
|
|
74
76
|
),
|
|
@@ -1151,15 +1151,17 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1151
1151
|
|
|
1152
1152
|
private async getHeaders({
|
|
1153
1153
|
betas,
|
|
1154
|
+
configHeaders,
|
|
1154
1155
|
headers,
|
|
1155
1156
|
providerOptions,
|
|
1156
1157
|
}: {
|
|
1157
1158
|
betas: Set<string>;
|
|
1159
|
+
configHeaders: Record<string, string | undefined> | undefined;
|
|
1158
1160
|
headers: Record<string, string | undefined> | undefined;
|
|
1159
1161
|
providerOptions: LanguageModelV4CallOptions['providerOptions'];
|
|
1160
1162
|
}) {
|
|
1161
1163
|
const combinedHeaders = combineHeaders(
|
|
1162
|
-
|
|
1164
|
+
configHeaders,
|
|
1163
1165
|
headers,
|
|
1164
1166
|
betas.size > 0 ? { 'anthropic-beta': Array.from(betas).join(',') } : {},
|
|
1165
1167
|
);
|
|
@@ -1169,13 +1171,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1169
1171
|
: combinedHeaders;
|
|
1170
1172
|
}
|
|
1171
1173
|
|
|
1172
|
-
private
|
|
1174
|
+
private getBetasFromHeaders(
|
|
1175
|
+
configHeaders: Record<string, string | undefined> | undefined,
|
|
1173
1176
|
requestHeaders: Record<string, string | undefined> | undefined,
|
|
1174
1177
|
) {
|
|
1175
|
-
const configHeaders = this.config.headers
|
|
1176
|
-
? await resolve(this.config.headers)
|
|
1177
|
-
: undefined;
|
|
1178
|
-
|
|
1179
1178
|
const configBetaHeader = configHeaders?.['anthropic-beta'] ?? '';
|
|
1180
1179
|
const requestBetaHeader = requestHeaders?.['anthropic-beta'] ?? '';
|
|
1181
1180
|
|
|
@@ -1249,6 +1248,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1249
1248
|
async doGenerate(
|
|
1250
1249
|
options: LanguageModelV4CallOptions,
|
|
1251
1250
|
): Promise<LanguageModelV4GenerateResult> {
|
|
1251
|
+
const configHeaders = this.config.headers
|
|
1252
|
+
? await resolve(this.config.headers)
|
|
1253
|
+
: undefined;
|
|
1254
|
+
|
|
1252
1255
|
const {
|
|
1253
1256
|
args,
|
|
1254
1257
|
warnings,
|
|
@@ -1260,7 +1263,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1260
1263
|
} = await this.getArgs({
|
|
1261
1264
|
...options,
|
|
1262
1265
|
stream: false,
|
|
1263
|
-
userSuppliedBetas:
|
|
1266
|
+
userSuppliedBetas: this.getBetasFromHeaders(
|
|
1267
|
+
configHeaders,
|
|
1268
|
+
options.headers,
|
|
1269
|
+
),
|
|
1264
1270
|
});
|
|
1265
1271
|
|
|
1266
1272
|
// Extract citation documents for response processing
|
|
@@ -1279,6 +1285,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1279
1285
|
url: this.buildRequestUrl(false),
|
|
1280
1286
|
headers: await this.getHeaders({
|
|
1281
1287
|
betas,
|
|
1288
|
+
configHeaders,
|
|
1282
1289
|
headers: options.headers,
|
|
1283
1290
|
providerOptions: options.providerOptions,
|
|
1284
1291
|
}),
|
|
@@ -1896,6 +1903,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1896
1903
|
): Promise<LanguageModelV4StreamResult> {
|
|
1897
1904
|
'use step';
|
|
1898
1905
|
|
|
1906
|
+
const configHeaders = this.config.headers
|
|
1907
|
+
? await resolve(this.config.headers)
|
|
1908
|
+
: undefined;
|
|
1909
|
+
|
|
1899
1910
|
const {
|
|
1900
1911
|
args: body,
|
|
1901
1912
|
warnings,
|
|
@@ -1907,7 +1918,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1907
1918
|
} = await this.getArgs({
|
|
1908
1919
|
...options,
|
|
1909
1920
|
stream: true,
|
|
1910
|
-
userSuppliedBetas:
|
|
1921
|
+
userSuppliedBetas: this.getBetasFromHeaders(
|
|
1922
|
+
configHeaders,
|
|
1923
|
+
options.headers,
|
|
1924
|
+
),
|
|
1911
1925
|
});
|
|
1912
1926
|
|
|
1913
1927
|
// Extract citation documents for response processing
|
|
@@ -1923,6 +1937,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
|
|
|
1923
1937
|
url,
|
|
1924
1938
|
headers: await this.getHeaders({
|
|
1925
1939
|
betas,
|
|
1940
|
+
configHeaders,
|
|
1926
1941
|
headers: options.headers,
|
|
1927
1942
|
providerOptions: options.providerOptions,
|
|
1928
1943
|
}),
|
|
@@ -12,10 +12,12 @@ import {
|
|
|
12
12
|
generateId,
|
|
13
13
|
loadApiKey,
|
|
14
14
|
loadOptionalSetting,
|
|
15
|
+
resolve,
|
|
15
16
|
validateBaseURL,
|
|
16
17
|
withoutTrailingSlash,
|
|
17
18
|
withUserAgentSuffix,
|
|
18
19
|
type FetchFunction,
|
|
20
|
+
type Resolvable,
|
|
19
21
|
} from '@ai-sdk/provider-utils';
|
|
20
22
|
import { Experimental_DecisionLanguageModel as DecisionLanguageModel } from '@ai-sdk/provider-utils/experimental-decision';
|
|
21
23
|
import { AnthropicFiles } from './anthropic-files';
|
|
@@ -103,10 +105,11 @@ export interface AnthropicProviderSettings {
|
|
|
103
105
|
|
|
104
106
|
/**
|
|
105
107
|
* Auth token that is being sent using the `Authorization: Bearer` header.
|
|
106
|
-
*
|
|
108
|
+
* Can be a string, a promise, or a function returning either. Functions are
|
|
109
|
+
* called before each request to support short-lived tokens and token refresh.
|
|
107
110
|
* Only one of `apiKey` or `authToken` is required.
|
|
108
111
|
*/
|
|
109
|
-
authToken?: string
|
|
112
|
+
authToken?: Resolvable<string>;
|
|
110
113
|
|
|
111
114
|
/**
|
|
112
115
|
* Custom headers to include in the requests.
|
|
@@ -157,9 +160,9 @@ export function createAnthropic(
|
|
|
157
160
|
});
|
|
158
161
|
}
|
|
159
162
|
|
|
160
|
-
const getHeaders = () => {
|
|
163
|
+
const getHeaders = async () => {
|
|
161
164
|
const authHeaders: Record<string, string> = options.authToken
|
|
162
|
-
? { Authorization: `Bearer ${options.authToken}` }
|
|
165
|
+
? { Authorization: `Bearer ${await resolve(options.authToken)}` }
|
|
163
166
|
: {
|
|
164
167
|
'x-api-key': loadApiKey({
|
|
165
168
|
apiKey: options.apiKey,
|
|
@@ -41,16 +41,14 @@ export class AnthropicSkills implements SkillsV4 {
|
|
|
41
41
|
private async fetchVersionMetadata({
|
|
42
42
|
skillId,
|
|
43
43
|
version,
|
|
44
|
-
headers,
|
|
45
44
|
}: {
|
|
46
45
|
skillId: string;
|
|
47
46
|
version: string;
|
|
48
|
-
headers: Record<string, string | undefined>;
|
|
49
47
|
}): Promise<{ name?: string; description?: string }> {
|
|
50
48
|
const { value: versionResponse } = await getFromApi({
|
|
51
49
|
url: `${this.config.baseURL}/skills/${encodePathSegment(skillId)}/versions/${encodePathSegment(version)}`,
|
|
52
50
|
validateUrl: false,
|
|
53
|
-
headers,
|
|
51
|
+
headers: await this.getHeaders(),
|
|
54
52
|
failedResponseHandler: anthropicFailedResponseHandler,
|
|
55
53
|
successfulResponseHandler: createJsonResponseHandler(
|
|
56
54
|
anthropicSkillVersionResponseSchema,
|
|
@@ -86,11 +84,9 @@ export class AnthropicSkills implements SkillsV4 {
|
|
|
86
84
|
);
|
|
87
85
|
}
|
|
88
86
|
|
|
89
|
-
const headers = await this.getHeaders();
|
|
90
|
-
|
|
91
87
|
const { value: response } = await postFormDataToApi({
|
|
92
88
|
url: `${this.config.baseURL}/skills`,
|
|
93
|
-
headers,
|
|
89
|
+
headers: await this.getHeaders(),
|
|
94
90
|
formData,
|
|
95
91
|
failedResponseHandler: anthropicFailedResponseHandler,
|
|
96
92
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -104,7 +100,6 @@ export class AnthropicSkills implements SkillsV4 {
|
|
|
104
100
|
? await this.fetchVersionMetadata({
|
|
105
101
|
skillId: response.id,
|
|
106
102
|
version: response.latest_version,
|
|
107
|
-
headers,
|
|
108
103
|
})
|
|
109
104
|
: {};
|
|
110
105
|
|