@core-ai/anthropic 0.16.0 → 0.18.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.
Files changed (2) hide show
  1. package/dist/index.js +176 -22
  2. 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
- supported: true,
200
+ mode: "optional",
38
201
  supportedEfforts,
39
- restrictsSamplingParams: true
202
+ restrictsSamplingParams: true,
203
+ supportedToolChoices: ["auto", "none"]
40
204
  }
41
205
  };
42
206
  }
@@ -46,6 +210,7 @@ var ADAPTIVE_MAX_EFFORT_MODELS = /* @__PURE__ */ new Set([
46
210
  "claude-fable-5",
47
211
  "claude-mythos-5",
48
212
  "claude-mythos-preview",
213
+ "claude-opus-5",
49
214
  "claude-opus-4-8",
50
215
  "claude-opus-4-7",
51
216
  "claude-opus-4-6",
@@ -72,6 +237,7 @@ var ALWAYS_RESTRICTED_SAMPLING_MODELS = /* @__PURE__ */ new Set([
72
237
  "claude-fable-5",
73
238
  "claude-mythos-5",
74
239
  "claude-mythos-preview",
240
+ "claude-opus-5",
75
241
  "claude-opus-4-8",
76
242
  "claude-opus-4-7",
77
243
  "claude-sonnet-5"
@@ -477,6 +643,7 @@ function validateAnthropicReasoningConfig(modelId, maxTokens, options, anthropic
477
643
  provider
478
644
  );
479
645
  }
646
+ const capabilities = getAnthropicModelCapabilities(modelId);
480
647
  if (options.temperature !== void 0 && (!alwaysRestrictsSampling || options.temperature !== 1)) {
481
648
  throw new ValidationError(
482
649
  `Anthropic model "${modelId}" does not support temperature when reasoning is enabled`,
@@ -491,9 +658,10 @@ function validateAnthropicReasoningConfig(modelId, maxTokens, options, anthropic
491
658
  provider
492
659
  );
493
660
  }
494
- if (options.toolChoice && options.toolChoice !== "auto" && options.toolChoice !== "none") {
661
+ const toolChoiceMode = typeof options.toolChoice === "object" ? options.toolChoice.type : options.toolChoice;
662
+ if (toolChoiceMode !== void 0 && !capabilities.reasoning.supportedToolChoices.includes(toolChoiceMode)) {
495
663
  throw new ValidationError(
496
- `Anthropic model "${modelId}" only supports toolChoice "auto" or "none" when reasoning is enabled`,
664
+ `Anthropic model "${modelId}" does not support toolChoice "${toolChoiceMode}" when reasoning is enabled`,
497
665
  void 0,
498
666
  provider
499
667
  );
@@ -840,20 +1008,6 @@ function extractThinkingText(value) {
840
1008
  return typeof text === "string" ? [text] : [];
841
1009
  }).join("");
842
1010
  }
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
1011
 
858
1012
  // src/chat-model.ts
859
1013
  import {
@@ -878,7 +1032,7 @@ function createAnthropicChatModel(client, modelId, modelOptions = {}) {
878
1032
  signal
879
1033
  });
880
1034
  } catch (error) {
881
- throw wrapError(error, provider);
1035
+ throw wrapAnthropicError(error, provider);
882
1036
  }
883
1037
  }
884
1038
  async function generateChat(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/anthropic",
3
- "version": "0.16.0",
3
+ "version": "0.18.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.16.0"
48
+ "@core-ai/core-ai": "^0.18.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "zod": "^4.0.0"