@core-ai/core-ai 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.
package/dist/index.d.ts CHANGED
@@ -110,15 +110,17 @@ type ToolChoice = 'auto' | 'none' | 'required' | {
110
110
  type: 'tool';
111
111
  toolName: string;
112
112
  };
113
+ type ToolChoiceMode = 'auto' | 'none' | 'required' | 'tool';
113
114
  type ModelCapabilities = {
114
115
  reasoning: {
115
- supported: boolean;
116
+ mode: 'unsupported' | 'optional' | 'always-on';
116
117
  supportedEfforts: readonly ReasoningEffort[];
117
118
  /**
118
- * When true, sampling parameters such as `temperature` and `topP`
119
- * must not be set alongside `reasoning`.
119
+ * Whether reasoning changes which sampling parameters or values the
120
+ * provider accepts.
120
121
  */
121
122
  restrictsSamplingParams: boolean;
123
+ supportedToolChoices: readonly ToolChoiceMode[];
122
124
  };
123
125
  };
124
126
  type ChatModel = {
@@ -377,9 +379,50 @@ declare class AbortedError extends CoreAIError {
377
379
  declare class StreamAbortedError extends AbortedError {
378
380
  constructor(cause?: unknown, provider?: string);
379
381
  }
382
+ type ProviderErrorOptions = {
383
+ statusCode?: number;
384
+ cause?: unknown;
385
+ };
380
386
  declare class ProviderError extends CoreAIError {
381
387
  readonly statusCode?: number;
382
- constructor(message: string, provider: string, statusCode?: number, cause?: unknown);
388
+ /**
389
+ * @param message Human-readable error message (may include provider text).
390
+ * @param provider Provider id (e.g. `'openai'`, `'anthropic'`).
391
+ * @param options Optional HTTP status and underlying cause.
392
+ */
393
+ constructor(message: string, provider: string, options?: ProviderErrorOptions);
394
+ }
395
+ /**
396
+ * Base class for transient provider failures that are safe to retry
397
+ * (rate limits, overload, temporary unavailability).
398
+ * Discriminate with `instanceof RetryableProviderError`.
399
+ */
400
+ declare class RetryableProviderError extends ProviderError {
401
+ constructor(message: string, provider: string, options?: ProviderErrorOptions);
402
+ }
403
+ type ContextLengthExceededErrorOptions = ProviderErrorOptions & {
404
+ maxTokens?: number;
405
+ actualTokens?: number;
406
+ };
407
+ declare class ContextLengthExceededError extends ProviderError {
408
+ readonly maxTokens?: number;
409
+ readonly actualTokens?: number;
410
+ constructor(message: string, provider: string, options?: ContextLengthExceededErrorOptions);
411
+ }
412
+ type RateLimitErrorOptions = ProviderErrorOptions & {
413
+ retryAfterSeconds?: number;
414
+ };
415
+ declare class RateLimitError extends RetryableProviderError {
416
+ readonly retryAfterSeconds?: number;
417
+ constructor(message: string, provider: string, options?: RateLimitErrorOptions);
418
+ }
419
+ type ModelOverloadedErrorOptions = ProviderErrorOptions;
420
+ declare class ModelOverloadedError extends RetryableProviderError {
421
+ constructor(message: string, provider: string, options?: ModelOverloadedErrorOptions);
422
+ }
423
+ type ServiceUnavailableErrorOptions = ProviderErrorOptions;
424
+ declare class ServiceUnavailableError extends RetryableProviderError {
425
+ constructor(message: string, provider: string, options?: ServiceUnavailableErrorOptions);
383
426
  }
384
427
  type StructuredOutputErrorOptions = {
385
428
  statusCode?: number;
@@ -402,6 +445,32 @@ declare class StructuredOutputValidationError extends StructuredOutputError {
402
445
  constructor(message: string, provider: string, issues: string[], options?: StructuredOutputErrorOptions);
403
446
  }
404
447
 
448
+ /**
449
+ * Shared helpers for provider error wrappers.
450
+ * Providers decide which error subclass to throw; these utilities only
451
+ * extract common SDK shapes and thin HTTP status conventions.
452
+ * Provider-specific message heuristics stay in each wrap*Error.
453
+ */
454
+ declare function isRateLimitStatus(statusCode: number | undefined): boolean;
455
+ declare function isTransientUnavailableStatus(statusCode: number | undefined): boolean;
456
+ declare function getErrorMessage(error: unknown): string;
457
+ declare function asRecord(value: unknown): Record<string, unknown> | undefined;
458
+ declare function getString(source: Record<string, unknown> | undefined, key: string): string | undefined;
459
+ /**
460
+ * Reads a finite numeric HTTP status from common SDK error shapes
461
+ * (`status` and/or `statusCode`).
462
+ */
463
+ declare function getHttpStatusCode(error: unknown, keys?: readonly ('status' | 'statusCode')[]): number | undefined;
464
+ declare function isAbortErrorByName(error: unknown): boolean;
465
+ /**
466
+ * Parses retry delay from a `Headers` instance or plain header map.
467
+ * Prefers Azure `retry-after-ms` (ceil ms → seconds), then `Retry-After`
468
+ * as integer seconds or HTTP-date.
469
+ */
470
+ declare function parseRetryAfterSeconds(headers: Headers | Record<string, string> | undefined): number | undefined;
471
+ /** Reads `Retry-After` from common SDK error shapes that expose `headers`. */
472
+ declare function getRetryAfterSecondsFromError(error: unknown): number | undefined;
473
+
405
474
  declare function defineTool(options: ToolDefinition): ToolDefinition;
406
475
 
407
476
  /**
@@ -414,6 +483,12 @@ declare function stripModelDateSuffix(modelId: string): string;
414
483
 
415
484
  declare function clampReasoningEffort(effort: ReasoningEffort, supportedEfforts: readonly ReasoningEffort[]): ReasoningEffort;
416
485
 
486
+ declare const UNKNOWN_MODEL: unique symbol;
487
+ type ModelCapabilitiesRegistry<TCapabilities extends ModelCapabilities = ModelCapabilities> = Record<string, TCapabilities> & {
488
+ [UNKNOWN_MODEL]?: TCapabilities;
489
+ };
490
+ declare function getRegisteredModelCapabilities<TCapabilities extends ModelCapabilities>(registry: ModelCapabilitiesRegistry<TCapabilities> | undefined, modelId: string): TCapabilities | undefined;
491
+
417
492
  declare function asObject(value: unknown): Record<string, unknown>;
418
493
  declare function safeParseJsonObject(json: string): Record<string, unknown>;
419
494
 
@@ -477,4 +552,4 @@ type GenerateImageParams = ImageGenerateOptions & {
477
552
  };
478
553
  declare function generateImage(params: GenerateImageParams): Promise<ImageGenerateResult>;
479
554
 
480
- export { AbortedError, type AssistantContentPart, type AssistantMessage, type AssistantTextPart, type BaseGenerateOptions, type ChatInputTokenDetails, type ChatModel, type ChatModelMiddleware, type ChatOutputTokenDetails, type ChatStream, type ChatUsage, CoreAIError, type EmbedOptions, type EmbedProviderOptions, type EmbedResult, type EmbeddingModel, type EmbeddingModelMiddleware, type EmbeddingUsage, type FilePart, type FinishReason, type GenerateObjectOptions, type GenerateObjectResult, type GenerateOptions, type GenerateProviderOptions, type GenerateResult, type GeneratedImage, type ImageGenerateOptions, type ImageGenerateResult, type ImageModel, type ImageModelMiddleware, type ImagePart, type ImageProviderOptions, type Message, type ModelCapabilities, type ObjectStream, type ObjectStreamEvent, ProviderError, type ReasoningConfig, type ReasoningEffort, type ReasoningPart, StreamAbortedError, type StreamEvent, type StreamObjectOptions, StructuredOutputError, StructuredOutputNoObjectGeneratedError, StructuredOutputParseError, StructuredOutputValidationError, type SystemMessage, type TextPart, type ToolCall, type ToolCallPart, type ToolChoice, type ToolDefinition, type ToolResultMessage, type ToolSet, type UserContentPart, type UserMessage, ValidationError, asObject, assistantMessage, clampReasoningEffort, createChatStream, createObjectStream, defineTool, embed, generate, generateImage, generateObject, getProviderMetadata, resultToMessage, safeParseJsonObject, stream, streamObject, stripModelDateSuffix, wrapChatModel, wrapEmbeddingModel, wrapImageModel, zodSchemaToJsonSchema };
555
+ export { AbortedError, type AssistantContentPart, type AssistantMessage, type AssistantTextPart, type BaseGenerateOptions, type ChatInputTokenDetails, type ChatModel, type ChatModelMiddleware, type ChatOutputTokenDetails, type ChatStream, type ChatUsage, ContextLengthExceededError, type ContextLengthExceededErrorOptions, CoreAIError, type EmbedOptions, type EmbedProviderOptions, type EmbedResult, type EmbeddingModel, type EmbeddingModelMiddleware, type EmbeddingUsage, type FilePart, type FinishReason, type GenerateObjectOptions, type GenerateObjectResult, type GenerateOptions, type GenerateProviderOptions, type GenerateResult, type GeneratedImage, type ImageGenerateOptions, type ImageGenerateResult, type ImageModel, type ImageModelMiddleware, type ImagePart, type ImageProviderOptions, type Message, type ModelCapabilities, type ModelCapabilitiesRegistry, ModelOverloadedError, type ModelOverloadedErrorOptions, type ObjectStream, type ObjectStreamEvent, ProviderError, type ProviderErrorOptions, RateLimitError, type RateLimitErrorOptions, type ReasoningConfig, type ReasoningEffort, type ReasoningPart, RetryableProviderError, ServiceUnavailableError, type ServiceUnavailableErrorOptions, StreamAbortedError, type StreamEvent, type StreamObjectOptions, StructuredOutputError, StructuredOutputNoObjectGeneratedError, StructuredOutputParseError, StructuredOutputValidationError, type SystemMessage, type TextPart, type ToolCall, type ToolCallPart, type ToolChoice, type ToolDefinition, type ToolResultMessage, type ToolSet, UNKNOWN_MODEL, type UserContentPart, type UserMessage, ValidationError, asObject, asRecord, assistantMessage, clampReasoningEffort, createChatStream, createObjectStream, defineTool, embed, generate, generateImage, generateObject, getErrorMessage, getHttpStatusCode, getProviderMetadata, getRegisteredModelCapabilities, getRetryAfterSecondsFromError, getString, isAbortErrorByName, isRateLimitStatus, isTransientUnavailableStatus, parseRetryAfterSeconds, resultToMessage, safeParseJsonObject, stream, streamObject, stripModelDateSuffix, wrapChatModel, wrapEmbeddingModel, wrapImageModel, zodSchemaToJsonSchema };
package/dist/index.js CHANGED
@@ -30,10 +30,57 @@ var StreamAbortedError = class extends AbortedError {
30
30
  };
31
31
  var ProviderError = class extends CoreAIError {
32
32
  statusCode;
33
- constructor(message, provider, statusCode, cause) {
34
- super(message, cause, provider);
33
+ /**
34
+ * @param message Human-readable error message (may include provider text).
35
+ * @param provider Provider id (e.g. `'openai'`, `'anthropic'`).
36
+ * @param options Optional HTTP status and underlying cause.
37
+ */
38
+ constructor(message, provider, options = {}) {
39
+ super(message, options.cause, provider);
35
40
  this.name = "ProviderError";
36
- this.statusCode = statusCode;
41
+ this.statusCode = options.statusCode;
42
+ }
43
+ };
44
+ var RetryableProviderError = class extends ProviderError {
45
+ constructor(message, provider, options = {}) {
46
+ super(message, provider, options);
47
+ this.name = "RetryableProviderError";
48
+ }
49
+ };
50
+ var ContextLengthExceededError = class extends ProviderError {
51
+ maxTokens;
52
+ actualTokens;
53
+ constructor(message, provider, options = {}) {
54
+ super(message, provider, {
55
+ statusCode: options.statusCode,
56
+ cause: options.cause
57
+ });
58
+ this.name = "ContextLengthExceededError";
59
+ this.maxTokens = options.maxTokens;
60
+ this.actualTokens = options.actualTokens;
61
+ }
62
+ };
63
+ var RateLimitError = class extends RetryableProviderError {
64
+ retryAfterSeconds;
65
+ constructor(message, provider, options = {}) {
66
+ super(message, provider, {
67
+ statusCode: options.statusCode ?? 429,
68
+ cause: options.cause
69
+ });
70
+ this.name = "RateLimitError";
71
+ this.retryAfterSeconds = options.retryAfterSeconds;
72
+ }
73
+ };
74
+ var ModelOverloadedError = class extends RetryableProviderError {
75
+ constructor(message, provider, options = {}) {
76
+ super(message, provider, options);
77
+ this.name = "ModelOverloadedError";
78
+ }
79
+ };
80
+ var ServiceUnavailableError = class extends RetryableProviderError {
81
+ constructor(message, provider, options = {}) {
82
+ super(message, provider, options);
83
+ this.name = "ServiceUnavailableError";
37
84
  }
38
85
  };
39
86
  var StructuredOutputError = class extends CoreAIError {
@@ -67,6 +114,107 @@ var StructuredOutputValidationError = class extends StructuredOutputError {
67
114
  }
68
115
  };
69
116
 
117
+ // src/provider-error-utils.ts
118
+ var TRANSIENT_UNAVAILABLE_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
119
+ function isRateLimitStatus(statusCode) {
120
+ return statusCode === 429;
121
+ }
122
+ function isTransientUnavailableStatus(statusCode) {
123
+ return statusCode !== void 0 && TRANSIENT_UNAVAILABLE_STATUS_CODES.has(statusCode);
124
+ }
125
+ function getErrorMessage(error) {
126
+ if (error instanceof Error) {
127
+ return error.message;
128
+ }
129
+ const record = asRecord(error);
130
+ const message = getString(record, "message");
131
+ if (message) {
132
+ return message;
133
+ }
134
+ return String(error);
135
+ }
136
+ function asRecord(value) {
137
+ if (value && typeof value === "object" && !Array.isArray(value)) {
138
+ return value;
139
+ }
140
+ return void 0;
141
+ }
142
+ function getString(source, key) {
143
+ if (!source) {
144
+ return void 0;
145
+ }
146
+ const value = source[key];
147
+ return typeof value === "string" ? value : void 0;
148
+ }
149
+ function getHttpStatusCode(error, keys = ["status", "statusCode"]) {
150
+ const record = asRecord(error);
151
+ if (!record) {
152
+ return void 0;
153
+ }
154
+ for (const key of keys) {
155
+ const value = record[key];
156
+ if (typeof value === "number" && Number.isFinite(value)) {
157
+ return value;
158
+ }
159
+ }
160
+ return void 0;
161
+ }
162
+ function isAbortErrorByName(error) {
163
+ return error instanceof Error && error.name === "AbortError";
164
+ }
165
+ function parseRetryAfterSeconds(headers) {
166
+ if (!headers) {
167
+ return void 0;
168
+ }
169
+ const retryAfterMs = getHeaderValue(headers, "retry-after-ms");
170
+ if (retryAfterMs !== void 0) {
171
+ const ms = Number(retryAfterMs);
172
+ if (Number.isFinite(ms) && ms >= 0) {
173
+ return Math.ceil(ms / 1e3);
174
+ }
175
+ }
176
+ const retryAfter = getHeaderValue(headers, "retry-after");
177
+ if (retryAfter === void 0) {
178
+ return void 0;
179
+ }
180
+ const asSeconds = Number(retryAfter);
181
+ if (Number.isFinite(asSeconds) && /^\d+$/.test(retryAfter.trim())) {
182
+ return asSeconds;
183
+ }
184
+ const when = Date.parse(retryAfter);
185
+ if (!Number.isFinite(when)) {
186
+ return void 0;
187
+ }
188
+ const seconds = Math.ceil((when - Date.now()) / 1e3);
189
+ return seconds >= 0 ? seconds : void 0;
190
+ }
191
+ function getHeaderValue(headers, name) {
192
+ if (typeof headers.get === "function") {
193
+ return headers.get(name) ?? void 0;
194
+ }
195
+ const record = headers;
196
+ const direct = record[name];
197
+ if (typeof direct === "string") {
198
+ return direct;
199
+ }
200
+ const lower = name.toLowerCase();
201
+ for (const [key, value] of Object.entries(record)) {
202
+ if (key.toLowerCase() === lower && typeof value === "string") {
203
+ return value;
204
+ }
205
+ }
206
+ return void 0;
207
+ }
208
+ function getRetryAfterSecondsFromError(error) {
209
+ const record = asRecord(error);
210
+ if (!record?.headers || typeof record.headers !== "object") {
211
+ return void 0;
212
+ }
213
+ return parseRetryAfterSeconds(
214
+ record.headers
215
+ );
216
+ }
217
+
70
218
  // src/tool.ts
71
219
  function defineTool(options) {
72
220
  return options;
@@ -115,6 +263,15 @@ function clampReasoningEffort(effort, supportedEfforts) {
115
263
  return best;
116
264
  }
117
265
 
266
+ // src/model-capabilities-registry.ts
267
+ var UNKNOWN_MODEL = /* @__PURE__ */ Symbol("unknown-model");
268
+ function getRegisteredModelCapabilities(registry, modelId) {
269
+ if (!registry) {
270
+ return void 0;
271
+ }
272
+ return registry[modelId] ?? registry[stripModelDateSuffix(modelId)] ?? registry[UNKNOWN_MODEL];
273
+ }
274
+
118
275
  // src/provider-utils.ts
119
276
  function asObject(value) {
120
277
  if (value && typeof value === "object" && !Array.isArray(value)) {
@@ -730,15 +887,22 @@ async function generateImage(params) {
730
887
  }
731
888
  export {
732
889
  AbortedError,
890
+ ContextLengthExceededError,
733
891
  CoreAIError,
892
+ ModelOverloadedError,
734
893
  ProviderError,
894
+ RateLimitError,
895
+ RetryableProviderError,
896
+ ServiceUnavailableError,
735
897
  StreamAbortedError,
736
898
  StructuredOutputError,
737
899
  StructuredOutputNoObjectGeneratedError,
738
900
  StructuredOutputParseError,
739
901
  StructuredOutputValidationError,
902
+ UNKNOWN_MODEL,
740
903
  ValidationError,
741
904
  asObject,
905
+ asRecord,
742
906
  assistantMessage,
743
907
  clampReasoningEffort,
744
908
  createChatStream,
@@ -748,7 +912,16 @@ export {
748
912
  generate,
749
913
  generateImage,
750
914
  generateObject,
915
+ getErrorMessage,
916
+ getHttpStatusCode,
751
917
  getProviderMetadata,
918
+ getRegisteredModelCapabilities,
919
+ getRetryAfterSecondsFromError,
920
+ getString,
921
+ isAbortErrorByName,
922
+ isRateLimitStatus,
923
+ isTransientUnavailableStatus,
924
+ parseRetryAfterSeconds,
752
925
  resultToMessage,
753
926
  safeParseJsonObject,
754
927
  stream,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/core-ai",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Type-safe LLM abstraction layer over native provider SDKs",
5
5
  "license": "MIT",
6
6
  "author": "Omnifact (https://omnifact.ai)",