@core-ai/anthropic 0.5.1 → 0.6.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
@@ -1,7 +1,8 @@
1
1
  import Anthropic from '@anthropic-ai/sdk';
2
2
  import { ChatModel } from '@core-ai/core-ai';
3
+ import { z } from 'zod';
3
4
 
4
- type AnthropicProviderOptions = {
5
+ type AnthropicProviderOptions$1 = {
5
6
  apiKey?: string;
6
7
  baseURL?: string;
7
8
  client?: Anthropic;
@@ -10,6 +11,51 @@ type AnthropicProviderOptions = {
10
11
  type AnthropicProvider = {
11
12
  chatModel(modelId: string): ChatModel;
12
13
  };
13
- declare function createAnthropic(options?: AnthropicProviderOptions): AnthropicProvider;
14
+ declare function createAnthropic(options?: AnthropicProviderOptions$1): AnthropicProvider;
14
15
 
15
- export { type AnthropicProvider, type AnthropicProviderOptions, createAnthropic };
16
+ type AnthropicReasoningMetadata = {
17
+ signature?: string;
18
+ redactedData?: string;
19
+ };
20
+
21
+ declare const anthropicGenerateProviderOptionsSchema: z.ZodObject<{
22
+ topK: z.ZodOptional<z.ZodNumber>;
23
+ stopSequences: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
24
+ betas: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
25
+ outputConfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
26
+ }, "strict", z.ZodTypeAny, {
27
+ topK?: number | undefined;
28
+ stopSequences?: string[] | undefined;
29
+ betas?: string[] | undefined;
30
+ outputConfig?: Record<string, unknown> | undefined;
31
+ }, {
32
+ topK?: number | undefined;
33
+ stopSequences?: string[] | undefined;
34
+ betas?: string[] | undefined;
35
+ outputConfig?: Record<string, unknown> | undefined;
36
+ }>;
37
+ type AnthropicGenerateProviderOptions = z.infer<typeof anthropicGenerateProviderOptionsSchema>;
38
+ declare module '@core-ai/core-ai' {
39
+ interface GenerateProviderOptions {
40
+ anthropic?: AnthropicGenerateProviderOptions;
41
+ }
42
+ }
43
+ declare const anthropicProviderOptionsSchema: z.ZodObject<{
44
+ topK: z.ZodOptional<z.ZodNumber>;
45
+ stopSequences: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
46
+ betas: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
47
+ outputConfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
48
+ }, "strict", z.ZodTypeAny, {
49
+ topK?: number | undefined;
50
+ stopSequences?: string[] | undefined;
51
+ betas?: string[] | undefined;
52
+ outputConfig?: Record<string, unknown> | undefined;
53
+ }, {
54
+ topK?: number | undefined;
55
+ stopSequences?: string[] | undefined;
56
+ betas?: string[] | undefined;
57
+ outputConfig?: Record<string, unknown> | undefined;
58
+ }>;
59
+ type AnthropicProviderOptions = AnthropicGenerateProviderOptions;
60
+
61
+ export { type AnthropicGenerateProviderOptions, type AnthropicProviderOptions as AnthropicModelProviderOptions, type AnthropicProvider, type AnthropicProviderOptions$1 as AnthropicProviderOptions, type AnthropicReasoningMetadata, anthropicGenerateProviderOptionsSchema, anthropicProviderOptionsSchema, createAnthropic };
package/dist/index.js CHANGED
@@ -6,14 +6,14 @@ import {
6
6
  StructuredOutputNoObjectGeneratedError,
7
7
  StructuredOutputParseError,
8
8
  StructuredOutputValidationError,
9
- createObjectStreamResult,
10
- createStreamResult
9
+ createObjectStream,
10
+ createChatStream
11
11
  } from "@core-ai/core-ai";
12
12
 
13
13
  // src/chat-adapter.ts
14
14
  import { APIError } from "@anthropic-ai/sdk";
15
15
  import { zodToJsonSchema } from "zod-to-json-schema";
16
- import { ProviderError } from "@core-ai/core-ai";
16
+ import { ProviderError, getProviderMetadata } from "@core-ai/core-ai";
17
17
 
18
18
  // src/model-capabilities.ts
19
19
  var DEFAULT_CAPABILITIES = {
@@ -110,6 +110,23 @@ function toAnthropicManualBudget(effort) {
110
110
  return 65536;
111
111
  }
112
112
 
113
+ // src/provider-options.ts
114
+ import { z } from "zod";
115
+ var anthropicGenerateProviderOptionsSchema = z.object({
116
+ topK: z.number().int().optional(),
117
+ stopSequences: z.array(z.string()).optional(),
118
+ betas: z.array(z.string()).optional(),
119
+ outputConfig: z.record(z.string(), z.unknown()).optional()
120
+ }).strict();
121
+ function parseAnthropicGenerateProviderOptions(providerOptions) {
122
+ const rawOptions = providerOptions?.anthropic;
123
+ if (rawOptions === void 0) {
124
+ return void 0;
125
+ }
126
+ return anthropicGenerateProviderOptionsSchema.parse(rawOptions);
127
+ }
128
+ var anthropicProviderOptionsSchema = anthropicGenerateProviderOptionsSchema;
129
+
113
130
  // src/chat-adapter.ts
114
131
  var UNSUPPORTED_ANTHROPIC_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
115
132
  "minimum",
@@ -158,8 +175,20 @@ function convertMessages(messages) {
158
175
  });
159
176
  continue;
160
177
  }
161
- const signature = part.providerMetadata?.["signature"];
162
- const redactedData = part.providerMetadata?.["redactedData"];
178
+ const anthropicMeta = getProviderMetadata(
179
+ part.providerMetadata,
180
+ "anthropic"
181
+ );
182
+ if (anthropicMeta == null) {
183
+ if (part.text.length > 0) {
184
+ contentBlocks.push({
185
+ type: "text",
186
+ text: `<thinking>${part.text}</thinking>`
187
+ });
188
+ }
189
+ continue;
190
+ }
191
+ const { signature, redactedData } = anthropicMeta;
163
192
  if (typeof redactedData === "string") {
164
193
  contentBlocks.push({
165
194
  type: "redacted_thinking",
@@ -167,14 +196,18 @@ function convertMessages(messages) {
167
196
  });
168
197
  continue;
169
198
  }
170
- const thinkingBlock = {
171
- type: "thinking",
172
- thinking: part.text
173
- };
174
- if (typeof signature === "string") {
175
- thinkingBlock["signature"] = signature;
199
+ if (part.text.length === 0) {
200
+ continue;
201
+ }
202
+ if (typeof signature !== "string") {
203
+ contentBlocks.push({ type: "text", text: part.text });
204
+ continue;
176
205
  }
177
- contentBlocks.push(thinkingBlock);
206
+ contentBlocks.push({
207
+ type: "thinking",
208
+ thinking: part.text,
209
+ signature
210
+ });
178
211
  }
179
212
  convertedMessages.push({
180
213
  role: "assistant",
@@ -282,13 +315,18 @@ function createStructuredOutputOptions(options) {
282
315
  return {
283
316
  messages: options.messages,
284
317
  reasoning: options.reasoning,
285
- config: options.config,
318
+ temperature: options.temperature,
319
+ maxTokens: options.maxTokens,
320
+ topP: options.topP,
286
321
  providerOptions: {
287
322
  ...options.providerOptions ?? {},
288
- output_config: {
289
- format: {
290
- type: "json_schema",
291
- schema
323
+ anthropic: {
324
+ ...options.providerOptions?.anthropic ?? {},
325
+ outputConfig: {
326
+ format: {
327
+ type: "json_schema",
328
+ schema
329
+ }
292
330
  }
293
331
  }
294
332
  },
@@ -329,49 +367,64 @@ function isJsonObject(value) {
329
367
  return value !== null && typeof value === "object" && !Array.isArray(value);
330
368
  }
331
369
  function createGenerateRequest(modelId, defaultMaxTokens, options) {
332
- const baseRequest = createRequestBase(modelId, defaultMaxTokens, options);
333
- return mergeProviderOptions(baseRequest, options.providerOptions);
370
+ const anthropicOptions = parseAnthropicGenerateProviderOptions(
371
+ options.providerOptions
372
+ );
373
+ const baseRequest = createRequestBase(
374
+ modelId,
375
+ defaultMaxTokens,
376
+ options,
377
+ anthropicOptions
378
+ );
379
+ return mapAnthropicProviderOptionsToRequest(baseRequest, anthropicOptions);
334
380
  }
335
381
  function createStreamRequest(modelId, defaultMaxTokens, options) {
382
+ const anthropicOptions = parseAnthropicGenerateProviderOptions(
383
+ options.providerOptions
384
+ );
336
385
  const baseRequest = {
337
- ...createRequestBase(modelId, defaultMaxTokens, options),
386
+ ...createRequestBase(
387
+ modelId,
388
+ defaultMaxTokens,
389
+ options,
390
+ anthropicOptions
391
+ ),
338
392
  stream: true
339
393
  };
340
- return mergeProviderOptions(baseRequest, options.providerOptions);
394
+ return mapAnthropicProviderOptionsToRequest(baseRequest, anthropicOptions);
341
395
  }
342
- function createRequestBase(modelId, defaultMaxTokens, options) {
343
- validateAnthropicReasoningConfig(modelId, options);
396
+ function createRequestBase(modelId, defaultMaxTokens, options, anthropicOptions) {
397
+ validateAnthropicReasoningConfig(modelId, options, anthropicOptions);
344
398
  const converted = convertMessages(options.messages);
345
399
  const reasoningFields = mapReasoningToRequestFields(modelId, options);
346
400
  return {
347
401
  model: modelId,
348
402
  messages: converted.messages,
349
- max_tokens: options.config?.maxTokens ?? defaultMaxTokens,
403
+ max_tokens: options.maxTokens ?? defaultMaxTokens,
350
404
  ...converted.system ? { system: converted.system } : {},
351
405
  ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertTools(options.tools) } : {},
352
406
  ...options.toolChoice ? { tool_choice: convertToolChoice(options.toolChoice) } : {},
353
407
  ...reasoningFields,
354
- ...mapConfigToRequestFields(options.config)
408
+ ...mapSamplingToRequestFields(options)
355
409
  };
356
410
  }
357
- function mapConfigToRequestFields(config) {
411
+ function mapSamplingToRequestFields(options) {
358
412
  return {
359
- ...config?.temperature !== void 0 ? { temperature: config.temperature } : {},
360
- ...config?.topP !== void 0 ? { top_p: config.topP } : {},
361
- ...config?.stopSequences ? { stop_sequences: config.stopSequences } : {}
413
+ ...options.temperature !== void 0 ? { temperature: options.temperature } : {},
414
+ ...options.topP !== void 0 ? { top_p: options.topP } : {}
362
415
  };
363
416
  }
364
- function validateAnthropicReasoningConfig(modelId, options) {
417
+ function validateAnthropicReasoningConfig(modelId, options, anthropicOptions) {
365
418
  if (!options.reasoning) {
366
419
  return;
367
420
  }
368
- if (options.config?.temperature !== void 0) {
421
+ if (options.temperature !== void 0) {
369
422
  throw new ProviderError(
370
423
  `Anthropic model "${modelId}" does not support temperature when reasoning is enabled`,
371
424
  "anthropic"
372
425
  );
373
426
  }
374
- if (options.config?.topP !== void 0 && (options.config.topP < 0.95 || options.config.topP > 1)) {
427
+ if (options.topP !== void 0 && (options.topP < 0.95 || options.topP > 1)) {
375
428
  throw new ProviderError(
376
429
  `Anthropic model "${modelId}" requires topP between 0.95 and 1 when reasoning is enabled`,
377
430
  "anthropic"
@@ -383,8 +436,7 @@ function validateAnthropicReasoningConfig(modelId, options) {
383
436
  "anthropic"
384
437
  );
385
438
  }
386
- const providerOptions = asObject(options.providerOptions);
387
- if (providerOptions["top_k"] !== void 0) {
439
+ if (anthropicOptions?.topK !== void 0) {
388
440
  throw new ProviderError(
389
441
  `Anthropic model "${modelId}" does not support top_k when reasoning is enabled`,
390
442
  "anthropic"
@@ -416,25 +468,25 @@ function mapReasoningToRequestFields(modelId, options) {
416
468
  };
417
469
  return baseFields;
418
470
  }
419
- function mergeProviderOptions(baseRequest, providerOptions) {
471
+ function mapAnthropicProviderOptionsToRequest(baseRequest, providerOptions) {
420
472
  if (!providerOptions) {
421
473
  return baseRequest;
422
474
  }
423
475
  const baseOutputConfig = asObject(
424
476
  baseRequest.output_config
425
477
  );
426
- const providerOutputConfig = asObject(providerOptions["output_config"]);
427
478
  const mergedOutputConfig = {
428
479
  ...baseOutputConfig,
429
- ...providerOutputConfig
480
+ ...providerOptions.outputConfig ?? {}
430
481
  };
431
482
  const mergedBetas = [
432
483
  ...asStringArray(baseRequest.betas),
433
- ...asStringArray(providerOptions["betas"])
484
+ ...providerOptions.betas ?? []
434
485
  ];
435
486
  const mergedRequest = {
436
487
  ...baseRequest,
437
- ...providerOptions,
488
+ ...providerOptions.topK !== void 0 ? { top_k: providerOptions.topK } : {},
489
+ ...providerOptions.stopSequences ? { stop_sequences: providerOptions.stopSequences } : {},
438
490
  ...Object.keys(mergedOutputConfig).length > 0 ? { output_config: mergedOutputConfig } : {},
439
491
  ...mergedBetas.length > 0 ? { betas: uniqueStrings(mergedBetas) } : {}
440
492
  };
@@ -467,11 +519,9 @@ function mapGenerateResponse(response) {
467
519
  parts.push({
468
520
  type: "reasoning",
469
521
  text: thinkingText,
470
- ...signature ? {
471
- providerMetadata: {
472
- signature
473
- }
474
- } : {}
522
+ providerMetadata: {
523
+ anthropic: { ...signature ? { signature } : {} }
524
+ }
475
525
  });
476
526
  continue;
477
527
  }
@@ -480,11 +530,9 @@ function mapGenerateResponse(response) {
480
530
  parts.push({
481
531
  type: "reasoning",
482
532
  text: "",
483
- ...redactedData ? {
484
- providerMetadata: {
485
- redactedData
486
- }
487
- } : {}
533
+ providerMetadata: {
534
+ anthropic: { ...redactedData ? { redactedData } : {} }
535
+ }
488
536
  });
489
537
  }
490
538
  }
@@ -527,6 +575,7 @@ async function* transformStream(stream) {
527
575
  const toolBuffers = /* @__PURE__ */ new Map();
528
576
  const emittedToolCalls = /* @__PURE__ */ new Set();
529
577
  const contentBlockTypeByIndex = /* @__PURE__ */ new Map();
578
+ const reasoningSignatureByIndex = /* @__PURE__ */ new Map();
530
579
  for await (const event of stream) {
531
580
  if (event.type === "message_start") {
532
581
  const cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;
@@ -586,6 +635,13 @@ async function* transformStream(stream) {
586
635
  }
587
636
  continue;
588
637
  }
638
+ if (event.delta.type === "signature_delta") {
639
+ reasoningSignatureByIndex.set(
640
+ event.index,
641
+ event.delta.signature
642
+ );
643
+ continue;
644
+ }
589
645
  if (event.delta.type === "input_json_delta") {
590
646
  const current = toolBuffers.get(event.index);
591
647
  if (!current) {
@@ -602,11 +658,18 @@ async function* transformStream(stream) {
602
658
  }
603
659
  if (event.type === "content_block_stop") {
604
660
  if (contentBlockTypeByIndex.get(event.index) === "thinking") {
661
+ const signature = reasoningSignatureByIndex.get(event.index);
662
+ reasoningSignatureByIndex.delete(event.index);
663
+ contentBlockTypeByIndex.delete(event.index);
605
664
  yield {
606
- type: "reasoning-end"
665
+ type: "reasoning-end",
666
+ providerMetadata: {
667
+ anthropic: { ...signature ? { signature } : {} }
668
+ }
607
669
  };
608
670
  continue;
609
671
  }
672
+ contentBlockTypeByIndex.delete(event.index);
610
673
  const current = toolBuffers.get(event.index);
611
674
  if (!current || emittedToolCalls.has(event.index)) {
612
675
  continue;
@@ -718,22 +781,32 @@ function wrapError(error) {
718
781
  // src/chat-model.ts
719
782
  function createAnthropicChatModel(client, modelId, defaultMaxTokens) {
720
783
  const provider = "anthropic";
721
- async function callAnthropicMessagesApi(request) {
784
+ async function callAnthropicMessagesApi(request, signal) {
722
785
  try {
723
- return await client.messages.create(request);
786
+ return await client.messages.create(request, {
787
+ signal
788
+ });
724
789
  } catch (error) {
725
790
  throw wrapError(error);
726
791
  }
727
792
  }
728
793
  async function generateChat(options) {
729
- const request = createGenerateRequest(modelId, defaultMaxTokens, options);
730
- const response = await callAnthropicMessagesApi(request);
794
+ const request = createGenerateRequest(
795
+ modelId,
796
+ defaultMaxTokens,
797
+ options
798
+ );
799
+ const response = await callAnthropicMessagesApi(request, options.signal);
731
800
  return mapGenerateResponse(response);
732
801
  }
733
802
  async function streamChat(options) {
734
803
  const request = createStreamRequest(modelId, defaultMaxTokens, options);
735
- const stream = await callAnthropicMessagesApi(request);
736
- return createStreamResult(transformStream(stream));
804
+ return createChatStream(
805
+ async () => transformStream(
806
+ await callAnthropicMessagesApi(request, options.signal)
807
+ ),
808
+ { signal: options.signal }
809
+ );
737
810
  }
738
811
  return {
739
812
  provider,
@@ -743,7 +816,11 @@ function createAnthropicChatModel(client, modelId, defaultMaxTokens) {
743
816
  async generateObject(options) {
744
817
  const structuredOptions = createStructuredOutputOptions(options);
745
818
  const result = await generateChat(structuredOptions);
746
- const object = extractStructuredObject(result, options.schema, provider);
819
+ const object = extractStructuredObject(
820
+ result,
821
+ options.schema,
822
+ provider
823
+ );
747
824
  return {
748
825
  object,
749
826
  finishReason: result.finishReason,
@@ -753,12 +830,15 @@ function createAnthropicChatModel(client, modelId, defaultMaxTokens) {
753
830
  async streamObject(options) {
754
831
  const structuredOptions = createStructuredOutputOptions(options);
755
832
  const stream = await streamChat(structuredOptions);
756
- return createObjectStreamResult(
833
+ return createObjectStream(
757
834
  transformStructuredOutputStream(
758
835
  stream,
759
836
  options.schema,
760
837
  provider
761
- )
838
+ ),
839
+ {
840
+ signal: options.signal
841
+ }
762
842
  );
763
843
  }
764
844
  };
@@ -835,7 +915,10 @@ function requireStructuredOutputPayload(finishReason, rawOutput, provider, noPay
835
915
  );
836
916
  }
837
917
  if (!rawOutput || rawOutput.length === 0) {
838
- throw new StructuredOutputNoObjectGeneratedError(noPayloadMessage, provider);
918
+ throw new StructuredOutputNoObjectGeneratedError(
919
+ noPayloadMessage,
920
+ provider
921
+ );
839
922
  }
840
923
  return rawOutput;
841
924
  }
@@ -890,5 +973,7 @@ function createAnthropic(options = {}) {
890
973
  };
891
974
  }
892
975
  export {
976
+ anthropicGenerateProviderOptionsSchema,
977
+ anthropicProviderOptionsSchema,
893
978
  createAnthropic
894
979
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/anthropic",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Anthropic provider package for @core-ai/core-ai",
5
5
  "license": "MIT",
6
6
  "author": "Omnifact (https://omnifact.ai)",
@@ -42,7 +42,7 @@
42
42
  "test:watch": "vitest"
43
43
  },
44
44
  "dependencies": {
45
- "@core-ai/core-ai": "^0.5.1",
45
+ "@core-ai/core-ai": "^0.6.0",
46
46
  "@anthropic-ai/sdk": "^0.78.0",
47
47
  "zod-to-json-schema": "^3.25.1"
48
48
  },
@@ -50,8 +50,9 @@
50
50
  "zod": "^3.25.0 || ^4.0.0"
51
51
  },
52
52
  "devDependencies": {
53
- "@core-ai/eslint-config": "^0.0.0",
54
- "@core-ai/typescript-config": "^0.0.0",
53
+ "@core-ai/eslint-config": "*",
54
+ "@core-ai/testing": "*",
55
+ "@core-ai/typescript-config": "*",
55
56
  "typescript": "^5.7.3",
56
57
  "vitest": "^3.2.4"
57
58
  }