@core-ai/anthropic 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +174 -22
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,18 +2,181 @@
|
|
|
2
2
|
import Anthropic from "@anthropic-ai/sdk";
|
|
3
3
|
|
|
4
4
|
// src/chat-adapter.ts
|
|
5
|
-
import { APIError, APIUserAbortError } from "@anthropic-ai/sdk";
|
|
6
5
|
import {
|
|
7
|
-
AbortedError,
|
|
8
6
|
asObject,
|
|
9
7
|
clampReasoningEffort,
|
|
10
8
|
getProviderMetadata,
|
|
11
|
-
ProviderError,
|
|
12
9
|
ValidationError,
|
|
13
10
|
safeParseJsonObject,
|
|
14
11
|
zodSchemaToJsonSchema
|
|
15
12
|
} from "@core-ai/core-ai";
|
|
16
13
|
|
|
14
|
+
// src/anthropic-error.ts
|
|
15
|
+
import { APIError, APIUserAbortError } from "@anthropic-ai/sdk";
|
|
16
|
+
import {
|
|
17
|
+
AbortedError,
|
|
18
|
+
ContextLengthExceededError,
|
|
19
|
+
ModelOverloadedError,
|
|
20
|
+
ProviderError,
|
|
21
|
+
RateLimitError,
|
|
22
|
+
ServiceUnavailableError,
|
|
23
|
+
asRecord,
|
|
24
|
+
getErrorMessage,
|
|
25
|
+
getHttpStatusCode,
|
|
26
|
+
getRetryAfterSecondsFromError,
|
|
27
|
+
getString,
|
|
28
|
+
isAbortErrorByName,
|
|
29
|
+
isRateLimitStatus,
|
|
30
|
+
isTransientUnavailableStatus
|
|
31
|
+
} from "@core-ai/core-ai";
|
|
32
|
+
var OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES = /* @__PURE__ */ new Set([
|
|
33
|
+
500,
|
|
34
|
+
502,
|
|
35
|
+
503,
|
|
36
|
+
504,
|
|
37
|
+
529
|
|
38
|
+
]);
|
|
39
|
+
function wrapAnthropicError(error, provider = "anthropic") {
|
|
40
|
+
if (isAnthropicAbortError(error)) {
|
|
41
|
+
return new AbortedError(error, provider);
|
|
42
|
+
}
|
|
43
|
+
const message = getErrorMessage(error);
|
|
44
|
+
const statusCode = error instanceof APIError ? error.status : getHttpStatusCode(error, ["status"]);
|
|
45
|
+
const providerMessage = getAnthropicErrorMessage(error);
|
|
46
|
+
const errorType = getAnthropicErrorType(error);
|
|
47
|
+
const options = { statusCode, cause: error };
|
|
48
|
+
const contextLength = getContextLengthDetails(providerMessage, errorType);
|
|
49
|
+
if (contextLength) {
|
|
50
|
+
return new ContextLengthExceededError(message, provider, {
|
|
51
|
+
...options,
|
|
52
|
+
...contextLength
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (isAnthropicOverloaded(errorType, providerMessage, message, statusCode)) {
|
|
56
|
+
return new ModelOverloadedError(message, provider, options);
|
|
57
|
+
}
|
|
58
|
+
if (isAnthropicRateLimit(error, statusCode, errorType)) {
|
|
59
|
+
return new RateLimitError(message, provider, {
|
|
60
|
+
...options,
|
|
61
|
+
retryAfterSeconds: getRetryAfterSecondsFromError(error)
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (isUnavailableStatus(error) || isTransientUnavailableStatus(statusCode)) {
|
|
65
|
+
return new ServiceUnavailableError(message, provider, options);
|
|
66
|
+
}
|
|
67
|
+
return new ProviderError(message, provider, options);
|
|
68
|
+
}
|
|
69
|
+
function isAnthropicAbortError(error) {
|
|
70
|
+
return error instanceof APIUserAbortError || isAbortErrorByName(error);
|
|
71
|
+
}
|
|
72
|
+
function isAnthropicOverloaded(errorType, providerMessage, message, statusCode) {
|
|
73
|
+
return statusCode === 529 || errorType === "overloaded_error" || indicatesAnthropicOverload(
|
|
74
|
+
`${providerMessage ?? ""} ${message}`,
|
|
75
|
+
statusCode
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function indicatesAnthropicOverload(text, statusCode) {
|
|
79
|
+
if (statusCode !== void 0 && !OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES.has(statusCode)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return /\boverloaded\b/i.test(text);
|
|
83
|
+
}
|
|
84
|
+
function isAnthropicRateLimit(error, statusCode, errorType) {
|
|
85
|
+
return isRateLimitStatus(statusCode) || errorType === "rate_limit_error" || isResourceExhaustedError(error);
|
|
86
|
+
}
|
|
87
|
+
function getContextLengthDetails(providerMessage, errorType) {
|
|
88
|
+
if (errorType === "rate_limit_error" || !providerMessage) {
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
if (!/prompt is too long/i.test(providerMessage)) {
|
|
92
|
+
const inputTokensMatch = providerMessage.match(
|
|
93
|
+
/Input tokens exceed the context limit of (\d+)/i
|
|
94
|
+
);
|
|
95
|
+
if (inputTokensMatch?.[1]) {
|
|
96
|
+
return { maxTokens: parseInt(inputTokensMatch[1], 10) };
|
|
97
|
+
}
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
const withMaximum = providerMessage.match(
|
|
101
|
+
/prompt is too long: (\d+) tokens > (\d+) maximum/i
|
|
102
|
+
);
|
|
103
|
+
if (withMaximum) {
|
|
104
|
+
const actualTokens = withMaximum[1];
|
|
105
|
+
const maxTokens = withMaximum[2];
|
|
106
|
+
if (actualTokens !== void 0 && maxTokens !== void 0) {
|
|
107
|
+
return {
|
|
108
|
+
maxTokens: parseInt(maxTokens, 10),
|
|
109
|
+
actualTokens: parseInt(actualTokens, 10)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const withoutMaximum = providerMessage.match(
|
|
114
|
+
/prompt is too long: (\d+) tokens > (\d+)/i
|
|
115
|
+
);
|
|
116
|
+
if (withoutMaximum) {
|
|
117
|
+
const actualTokens = withoutMaximum[1];
|
|
118
|
+
const maxTokens = withoutMaximum[2];
|
|
119
|
+
if (actualTokens !== void 0 && maxTokens !== void 0) {
|
|
120
|
+
return {
|
|
121
|
+
maxTokens: parseInt(maxTokens, 10),
|
|
122
|
+
actualTokens: parseInt(actualTokens, 10)
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
function isResourceExhaustedError(error) {
|
|
129
|
+
const body = getNestedGoogleApiErrorBody(error);
|
|
130
|
+
if (!body) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
const code = typeof body.code === "number" ? body.code : Number(body.code);
|
|
134
|
+
return code === 429 || body.status?.toUpperCase() === "RESOURCE_EXHAUSTED";
|
|
135
|
+
}
|
|
136
|
+
function isUnavailableStatus(error) {
|
|
137
|
+
const body = getNestedGoogleApiErrorBody(error);
|
|
138
|
+
return body?.status?.toUpperCase() === "UNAVAILABLE";
|
|
139
|
+
}
|
|
140
|
+
function getNestedGoogleApiErrorBody(error) {
|
|
141
|
+
const record = asRecord(error);
|
|
142
|
+
const outer = asRecord(record?.error);
|
|
143
|
+
if (!outer) {
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
146
|
+
const inner = asRecord(outer.error);
|
|
147
|
+
if (inner && ("code" in inner || "status" in inner)) {
|
|
148
|
+
return inner;
|
|
149
|
+
}
|
|
150
|
+
if ("code" in outer || "status" in outer) {
|
|
151
|
+
return outer;
|
|
152
|
+
}
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
function getAnthropicErrorMessage(error) {
|
|
156
|
+
if (error instanceof APIError) {
|
|
157
|
+
const nested = asRecord(error.error);
|
|
158
|
+
return getString(nested, "message") ?? error.message;
|
|
159
|
+
}
|
|
160
|
+
const record = asRecord(error);
|
|
161
|
+
const outer = asRecord(record?.error);
|
|
162
|
+
const inner = asRecord(outer?.error);
|
|
163
|
+
return getString(inner, "message") ?? getString(outer, "message") ?? getString(record, "message");
|
|
164
|
+
}
|
|
165
|
+
function getAnthropicErrorType(error) {
|
|
166
|
+
if (error instanceof APIError) {
|
|
167
|
+
if (typeof error.type === "string") {
|
|
168
|
+
return error.type;
|
|
169
|
+
}
|
|
170
|
+
if (typeof error.error === "object" && error.error) {
|
|
171
|
+
return getString(asRecord(error.error), "type");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const record = asRecord(error);
|
|
175
|
+
const outer = asRecord(record?.error);
|
|
176
|
+
const inner = asRecord(outer?.error);
|
|
177
|
+
return getString(inner, "type") ?? getString(outer, "type");
|
|
178
|
+
}
|
|
179
|
+
|
|
17
180
|
// src/model-capabilities.ts
|
|
18
181
|
import {
|
|
19
182
|
stripModelDateSuffix
|
|
@@ -34,9 +197,10 @@ var MAX_EFFORTS = [
|
|
|
34
197
|
function createCapabilities(supportedEfforts) {
|
|
35
198
|
return {
|
|
36
199
|
reasoning: {
|
|
37
|
-
|
|
200
|
+
mode: "optional",
|
|
38
201
|
supportedEfforts,
|
|
39
|
-
restrictsSamplingParams: true
|
|
202
|
+
restrictsSamplingParams: true,
|
|
203
|
+
supportedToolChoices: ["auto", "none"]
|
|
40
204
|
}
|
|
41
205
|
};
|
|
42
206
|
}
|
|
@@ -477,6 +641,7 @@ function validateAnthropicReasoningConfig(modelId, maxTokens, options, anthropic
|
|
|
477
641
|
provider
|
|
478
642
|
);
|
|
479
643
|
}
|
|
644
|
+
const capabilities = getAnthropicModelCapabilities(modelId);
|
|
480
645
|
if (options.temperature !== void 0 && (!alwaysRestrictsSampling || options.temperature !== 1)) {
|
|
481
646
|
throw new ValidationError(
|
|
482
647
|
`Anthropic model "${modelId}" does not support temperature when reasoning is enabled`,
|
|
@@ -491,9 +656,10 @@ function validateAnthropicReasoningConfig(modelId, maxTokens, options, anthropic
|
|
|
491
656
|
provider
|
|
492
657
|
);
|
|
493
658
|
}
|
|
494
|
-
|
|
659
|
+
const toolChoiceMode = typeof options.toolChoice === "object" ? options.toolChoice.type : options.toolChoice;
|
|
660
|
+
if (toolChoiceMode !== void 0 && !capabilities.reasoning.supportedToolChoices.includes(toolChoiceMode)) {
|
|
495
661
|
throw new ValidationError(
|
|
496
|
-
`Anthropic model "${modelId}"
|
|
662
|
+
`Anthropic model "${modelId}" does not support toolChoice "${toolChoiceMode}" when reasoning is enabled`,
|
|
497
663
|
void 0,
|
|
498
664
|
provider
|
|
499
665
|
);
|
|
@@ -840,20 +1006,6 @@ function extractThinkingText(value) {
|
|
|
840
1006
|
return typeof text === "string" ? [text] : [];
|
|
841
1007
|
}).join("");
|
|
842
1008
|
}
|
|
843
|
-
function wrapError(error, provider = DEFAULT_PROVIDER_ID) {
|
|
844
|
-
if (error instanceof APIUserAbortError || error instanceof Error && error.name === "AbortError") {
|
|
845
|
-
return new AbortedError(error, provider);
|
|
846
|
-
}
|
|
847
|
-
if (error instanceof APIError) {
|
|
848
|
-
return new ProviderError(error.message, provider, error.status, error);
|
|
849
|
-
}
|
|
850
|
-
return new ProviderError(
|
|
851
|
-
error instanceof Error ? error.message : String(error),
|
|
852
|
-
provider,
|
|
853
|
-
void 0,
|
|
854
|
-
error
|
|
855
|
-
);
|
|
856
|
-
}
|
|
857
1009
|
|
|
858
1010
|
// src/chat-model.ts
|
|
859
1011
|
import {
|
|
@@ -878,7 +1030,7 @@ function createAnthropicChatModel(client, modelId, modelOptions = {}) {
|
|
|
878
1030
|
signal
|
|
879
1031
|
});
|
|
880
1032
|
} catch (error) {
|
|
881
|
-
throw
|
|
1033
|
+
throw wrapAnthropicError(error, provider);
|
|
882
1034
|
}
|
|
883
1035
|
}
|
|
884
1036
|
async function generateChat(options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@core-ai/anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Anthropic provider package for @core-ai/core-ai",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Omnifact (https://omnifact.ai)",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@anthropic-ai/sdk": "^0.110.0",
|
|
48
|
-
"@core-ai/core-ai": "^0.
|
|
48
|
+
"@core-ai/core-ai": "^0.17.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"zod": "^4.0.0"
|