@core-ai/anthropic 0.23.0 → 0.25.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.d.ts CHANGED
@@ -16,12 +16,10 @@ type AnthropicChatProviderOptions = {
16
16
  };
17
17
  /**
18
18
  * Factory options for sibling packages that compose Anthropic chat.
19
- * Not part of {@link createAnthropic} / {@link AnthropicProviderOptions}
20
- * first-party Anthropic always uses strict tool schemas.
19
+ * Not part of {@link createAnthropic} / {@link AnthropicProviderOptions}.
21
20
  */
22
21
  type AnthropicChatProviderFactoryOptions = {
23
22
  providerId?: string;
24
- useStrictToolSchemas?: boolean;
25
23
  };
26
24
  type AnthropicChatProvider = {
27
25
  chatModel(modelId: string): ChatModel;
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  ValidationError,
10
10
  safeParseJsonObject,
11
11
  validateInputModalities,
12
+ validateToolSchemaStrictness,
12
13
  zodSchemaToJsonSchema
13
14
  } from "@core-ai/core-ai";
14
15
 
@@ -19,6 +20,7 @@ import {
19
20
  ContextLengthExceededError,
20
21
  ModelOverloadedError,
21
22
  ProviderError,
23
+ ProviderQuotaExceededError,
22
24
  RateLimitError,
23
25
  ServiceUnavailableError,
24
26
  asRecord,
@@ -56,6 +58,9 @@ function wrapAnthropicError(error, provider = "anthropic") {
56
58
  if (isAnthropicOverloaded(errorType, providerMessage, message, statusCode)) {
57
59
  return new ModelOverloadedError(message, provider, options);
58
60
  }
61
+ if (isAnthropicQuotaExceeded(errorType, statusCode)) {
62
+ return new ProviderQuotaExceededError(message, provider, options);
63
+ }
59
64
  if (isAnthropicRateLimit(error, statusCode, errorType)) {
60
65
  return new RateLimitError(message, provider, {
61
66
  ...options,
@@ -79,6 +84,9 @@ function isAnthropicOverloaded(errorType, providerMessage, message, statusCode)
79
84
  statusCode
80
85
  );
81
86
  }
87
+ function isAnthropicQuotaExceeded(errorType, statusCode) {
88
+ return statusCode === 402 || errorType === "billing_error";
89
+ }
82
90
  function indicatesAnthropicOverload(text, statusCode) {
83
91
  if (statusCode !== void 0 && !OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES.has(statusCode)) {
84
92
  return false;
@@ -184,6 +192,8 @@ function getAnthropicErrorType(error) {
184
192
  // src/model-capabilities.ts
185
193
  import {
186
194
  MULTIMODAL_INPUT_MODALITIES,
195
+ SUPPORTED_TOOL_SCHEMA_STRICTNESS,
196
+ UNSUPPORTED_TOOL_SCHEMA_STRICTNESS,
187
197
  stripModelDateSuffix
188
198
  } from "@core-ai/core-ai";
189
199
  var STANDARD_EFFORTS = [
@@ -199,7 +209,7 @@ var MAX_EFFORTS = [
199
209
  "high",
200
210
  "max"
201
211
  ];
202
- function createCapabilities(supportedEfforts) {
212
+ function createCapabilities(supportedEfforts, supportsStrictToolSchemas) {
203
213
  return {
204
214
  reasoning: {
205
215
  mode: "optional",
@@ -207,11 +217,19 @@ function createCapabilities(supportedEfforts) {
207
217
  restrictsSamplingParams: true,
208
218
  supportedToolChoices: ["auto", "none"]
209
219
  },
210
- modalities: MULTIMODAL_INPUT_MODALITIES
220
+ modalities: MULTIMODAL_INPUT_MODALITIES,
221
+ tools: {
222
+ // The cap is enforced by the API but absent from Anthropic's docs
223
+ // pages; the rejection reads: 'Too many strict tools (22). The
224
+ // maximum number of strict tools supported is 20. Try reducing
225
+ // the number of tools marked as strict.'
226
+ strictSchemas: supportsStrictToolSchemas ? {
227
+ ...SUPPORTED_TOOL_SCHEMA_STRICTNESS,
228
+ maxStrictTools: 20
229
+ } : UNSUPPORTED_TOOL_SCHEMA_STRICTNESS
230
+ }
211
231
  };
212
232
  }
213
- var STANDARD_CAPABILITIES = createCapabilities(STANDARD_EFFORTS);
214
- var MAX_EFFORT_CAPABILITIES = createCapabilities(MAX_EFFORTS);
215
233
  var ADAPTIVE_MAX_EFFORT_MODELS = /* @__PURE__ */ new Set([
216
234
  "claude-fable-5",
217
235
  "claude-mythos-5",
@@ -223,6 +241,23 @@ var ADAPTIVE_MAX_EFFORT_MODELS = /* @__PURE__ */ new Set([
223
241
  "claude-sonnet-5",
224
242
  "claude-sonnet-4-6"
225
243
  ]);
244
+ var NON_STRICT_TOOL_SCHEMA_MODELS = /* @__PURE__ */ new Set([
245
+ "claude-opus-4-1",
246
+ "claude-opus-4",
247
+ "claude-sonnet-4",
248
+ "claude-sonnet-3-7",
249
+ "claude-3-7-sonnet",
250
+ "claude-3-5-sonnet",
251
+ "claude-3-5-haiku",
252
+ "claude-3-opus",
253
+ "claude-3-sonnet",
254
+ "claude-3-haiku",
255
+ "claude-2.1",
256
+ "claude-2.0",
257
+ "claude-2",
258
+ "claude-instant-1.2",
259
+ "claude-instant-1"
260
+ ]);
226
261
  var MANUAL_THINKING_MODELS = /* @__PURE__ */ new Set([
227
262
  "claude-opus-4-5",
228
263
  "claude-sonnet-4-5",
@@ -262,10 +297,11 @@ var ANTHROPIC_MANUAL_BUDGET_MAP = {
262
297
  max: 65536
263
298
  };
264
299
  function getAnthropicModelCapabilities(modelId) {
265
- if (supportsAnthropicMaxEffort(modelId) || getAnthropicThinkingMode(modelId) === "manual") {
266
- return MAX_EFFORT_CAPABILITIES;
267
- }
268
- return STANDARD_CAPABILITIES;
300
+ const supportedEfforts = supportsAnthropicMaxEffort(modelId) || getAnthropicThinkingMode(modelId) === "manual" ? MAX_EFFORTS : STANDARD_EFFORTS;
301
+ return createCapabilities(
302
+ supportedEfforts,
303
+ supportsAnthropicStrictToolSchemas(modelId)
304
+ );
269
305
  }
270
306
  function normalizeModelId(modelId) {
271
307
  return stripModelDateSuffix(modelId);
@@ -276,6 +312,9 @@ function getAnthropicThinkingMode(modelId) {
276
312
  function supportsAnthropicMaxEffort(modelId) {
277
313
  return ADAPTIVE_MAX_EFFORT_MODELS.has(normalizeModelId(modelId));
278
314
  }
315
+ function supportsAnthropicStrictToolSchemas(modelId) {
316
+ return !NON_STRICT_TOOL_SCHEMA_MODELS.has(normalizeModelId(modelId));
317
+ }
279
318
  function requiresAnthropicInterleavedThinkingBeta(modelId) {
280
319
  return MANUAL_INTERLEAVED_THINKING_MODELS.has(normalizeModelId(modelId));
281
320
  }
@@ -471,14 +510,15 @@ function convertUserContentPart(part) {
471
510
  }
472
511
  };
473
512
  }
474
- function convertTools(tools, useStrictToolSchemas = true) {
513
+ function convertTools(tools) {
475
514
  return Object.values(tools).map((tool) => {
476
- const schema = toAnthropicJsonSchema(tool.parameters);
515
+ const strict = tool.strict === true;
516
+ const schema = strict ? toAnthropicJsonSchema(tool.parameters) : zodSchemaToJsonSchema(tool.parameters);
477
517
  return {
478
518
  name: tool.name,
479
519
  description: tool.description,
480
520
  input_schema: schema,
481
- ...useStrictToolSchemas ? { strict: true } : {}
521
+ ...strict ? { strict: true } : {}
482
522
  };
483
523
  });
484
524
  }
@@ -545,6 +585,10 @@ function normalizeAnthropicJsonValue(value) {
545
585
  }
546
586
  normalized[key] = normalizeAnthropicJsonValue(child);
547
587
  }
588
+ if (Array.isArray(normalized.oneOf) && normalized.anyOf === void 0) {
589
+ normalized.anyOf = normalized.oneOf;
590
+ delete normalized.oneOf;
591
+ }
548
592
  if (isObjectSchema(normalized)) {
549
593
  normalized.additionalProperties = false;
550
594
  }
@@ -556,7 +600,7 @@ function isObjectSchema(value) {
556
600
  function isJsonObject(value) {
557
601
  return value !== null && typeof value === "object" && !Array.isArray(value);
558
602
  }
559
- function createGenerateRequest(modelId, defaultMaxTokens, options, provider = DEFAULT_PROVIDER_ID, useStrictToolSchemas = true, adapterOptions = {}) {
603
+ function createGenerateRequest(modelId, defaultMaxTokens, options, provider = DEFAULT_PROVIDER_ID, adapterOptions = {}) {
560
604
  const anthropicOptions = parseAnthropicGenerateProviderOptions(
561
605
  options.providerOptions
562
606
  );
@@ -566,12 +610,11 @@ function createGenerateRequest(modelId, defaultMaxTokens, options, provider = DE
566
610
  options,
567
611
  anthropicOptions,
568
612
  provider,
569
- useStrictToolSchemas,
570
613
  adapterOptions
571
614
  );
572
615
  return mapAnthropicProviderOptionsToRequest(baseRequest, anthropicOptions);
573
616
  }
574
- function createStreamRequest(modelId, defaultMaxTokens, options, provider = DEFAULT_PROVIDER_ID, useStrictToolSchemas = true, adapterOptions = {}) {
617
+ function createStreamRequest(modelId, defaultMaxTokens, options, provider = DEFAULT_PROVIDER_ID, adapterOptions = {}) {
575
618
  const anthropicOptions = parseAnthropicGenerateProviderOptions(
576
619
  options.providerOptions
577
620
  );
@@ -582,14 +625,13 @@ function createStreamRequest(modelId, defaultMaxTokens, options, provider = DEFA
582
625
  options,
583
626
  anthropicOptions,
584
627
  provider,
585
- useStrictToolSchemas,
586
628
  adapterOptions
587
629
  ),
588
630
  stream: true
589
631
  };
590
632
  return mapAnthropicProviderOptionsToRequest(baseRequest, anthropicOptions);
591
633
  }
592
- function createRequestBase(modelId, defaultMaxTokens, options, anthropicOptions, provider, useStrictToolSchemas, adapterOptions) {
634
+ function createRequestBase(modelId, defaultMaxTokens, options, anthropicOptions, provider, adapterOptions) {
593
635
  const maxTokens = options.maxTokens ?? defaultMaxTokens;
594
636
  const capabilities = adapterOptions.capabilities ?? getAnthropicModelCapabilities(modelId);
595
637
  validateAnthropicReasoningConfig(
@@ -613,12 +655,20 @@ function createRequestBase(modelId, defaultMaxTokens, options, anthropicOptions,
613
655
  options,
614
656
  capabilities
615
657
  );
658
+ if (options.tools) {
659
+ validateToolSchemaStrictness({
660
+ tools: options.tools,
661
+ capabilities,
662
+ providerId: provider,
663
+ modelId
664
+ });
665
+ }
616
666
  return {
617
667
  model: modelId,
618
668
  messages: converted.messages,
619
669
  max_tokens: maxTokens,
620
670
  ...converted.system ? { system: converted.system } : {},
621
- ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertTools(options.tools, useStrictToolSchemas) } : {},
671
+ ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertTools(options.tools) } : {},
622
672
  ...options.toolChoice ? { tool_choice: convertToolChoice(options.toolChoice) } : {},
623
673
  ...reasoningFields,
624
674
  ...mapSamplingToRequestFields(options)
@@ -1038,7 +1088,6 @@ import {
1038
1088
  function createAnthropicChatModel(client, modelId, modelOptions = {}) {
1039
1089
  const defaultMaxTokens = modelOptions.defaultMaxTokens ?? 4096;
1040
1090
  const provider = modelOptions.providerId ?? DEFAULT_PROVIDER_ID;
1041
- const useStrictToolSchemas = modelOptions.useStrictToolSchemas ?? true;
1042
1091
  const capabilities = getAnthropicModelCapabilities(modelId);
1043
1092
  const adapterOptions = { capabilities };
1044
1093
  async function callAnthropicMessagesApi(request, betas, signal) {
@@ -1061,7 +1110,6 @@ function createAnthropicChatModel(client, modelId, modelOptions = {}) {
1061
1110
  defaultMaxTokens,
1062
1111
  options,
1063
1112
  provider,
1064
- useStrictToolSchemas,
1065
1113
  adapterOptions
1066
1114
  );
1067
1115
  const response = await callAnthropicMessagesApi(request, getAnthropicRequestBetas(modelId, options), options.signal);
@@ -1073,7 +1121,6 @@ function createAnthropicChatModel(client, modelId, modelOptions = {}) {
1073
1121
  defaultMaxTokens,
1074
1122
  options,
1075
1123
  provider,
1076
- useStrictToolSchemas,
1077
1124
  adapterOptions
1078
1125
  );
1079
1126
  return createChatStream(
@@ -1252,12 +1299,10 @@ function createAnthropicChatProvider(options = {}, factoryOptions = {}) {
1252
1299
  });
1253
1300
  const defaultMaxTokens = options.defaultMaxTokens ?? 4096;
1254
1301
  const providerId = factoryOptions.providerId ?? DEFAULT_PROVIDER_ID;
1255
- const useStrictToolSchemas = factoryOptions.useStrictToolSchemas ?? true;
1256
1302
  return {
1257
1303
  chatModel: (modelId) => createAnthropicChatModel(client, modelId, {
1258
1304
  defaultMaxTokens,
1259
- providerId,
1260
- useStrictToolSchemas
1305
+ providerId
1261
1306
  })
1262
1307
  };
1263
1308
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/anthropic",
3
- "version": "0.23.0",
3
+ "version": "0.25.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.23.0"
48
+ "@core-ai/core-ai": "^0.25.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "zod": "^4.0.0"