@jaypie/llm 1.2.4 → 1.2.6
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/cjs/Llm.d.ts +15 -3
- package/dist/cjs/index.cjs +106 -23
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/types/LlmProvider.interface.d.ts +21 -0
- package/dist/esm/Llm.d.ts +15 -3
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +91 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/LlmProvider.interface.d.ts +21 -0
- package/package.json +1 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { default as Llm } from "./Llm.js";
|
|
2
2
|
export * as LLM from "./constants.js";
|
|
3
|
-
export type { LlmHistory, LlmInputContent, LlmInputContentFile, LlmInputContentImage, LlmInputContentText, LlmInputMessage, LlmMessageOptions, LlmOperateInput, LlmOperateInputContent, LlmOperateInputFile, LlmOperateInputImage, LlmOperateOptions, LlmOperateResponse, LlmOptions, LlmProvider, } from "./types/LlmProvider.interface.js";
|
|
3
|
+
export type { LlmFallbackConfig, LlmHistory, LlmInputContent, LlmInputContentFile, LlmInputContentImage, LlmInputContentText, LlmInputMessage, LlmMessageOptions, LlmOperateInput, LlmOperateInputContent, LlmOperateInputFile, LlmOperateInputImage, LlmOperateOptions, LlmOperateResponse, LlmOptions, LlmProvider, } from "./types/LlmProvider.interface.js";
|
|
4
4
|
export { LlmMessageRole, LlmMessageType, } from "./types/LlmProvider.interface.js";
|
|
5
5
|
export { isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, } from "./types/LlmOperateInput.guards.js";
|
|
6
6
|
export type { LlmTool } from "./types/LlmTool.interface.js";
|
|
@@ -144,6 +144,18 @@ interface LlmItemReference {
|
|
|
144
144
|
}
|
|
145
145
|
export type LlmHistoryItem = LlmInputMessage | LlmItemReference | LlmOutputItem | LlmToolResult;
|
|
146
146
|
export type LlmHistory = LlmHistoryItem[];
|
|
147
|
+
/**
|
|
148
|
+
* Configuration for a fallback provider.
|
|
149
|
+
* Used when the primary provider fails with an unrecoverable error.
|
|
150
|
+
*/
|
|
151
|
+
export interface LlmFallbackConfig {
|
|
152
|
+
/** Provider name (e.g., "openai", "anthropic", "gemini") */
|
|
153
|
+
provider: string;
|
|
154
|
+
/** Model to use with this provider (optional, uses provider default if not specified) */
|
|
155
|
+
model?: string;
|
|
156
|
+
/** API key for this provider (optional, uses environment variable if not specified) */
|
|
157
|
+
apiKey?: string;
|
|
158
|
+
}
|
|
147
159
|
export interface LlmMessageOptions {
|
|
148
160
|
data?: NaturalMap;
|
|
149
161
|
model?: string;
|
|
@@ -157,6 +169,8 @@ export interface LlmMessageOptions {
|
|
|
157
169
|
export interface LlmOperateOptions {
|
|
158
170
|
data?: NaturalMap;
|
|
159
171
|
explain?: boolean;
|
|
172
|
+
/** Chain of fallback providers to try if primary fails. Set to false to disable instance-level fallback. */
|
|
173
|
+
fallback?: LlmFallbackConfig[] | false;
|
|
160
174
|
format?: JsonObject | NaturalSchema | z.ZodType;
|
|
161
175
|
history?: LlmHistory;
|
|
162
176
|
hooks?: {
|
|
@@ -215,6 +229,8 @@ export interface LlmOperateOptions {
|
|
|
215
229
|
}
|
|
216
230
|
export interface LlmOptions {
|
|
217
231
|
apiKey?: string;
|
|
232
|
+
/** Chain of fallback providers to try if primary fails */
|
|
233
|
+
fallback?: LlmFallbackConfig[];
|
|
218
234
|
model?: string;
|
|
219
235
|
}
|
|
220
236
|
export interface LlmUsageItem {
|
|
@@ -229,9 +245,14 @@ export type LlmUsage = LlmUsageItem[];
|
|
|
229
245
|
export interface LlmOperateResponse {
|
|
230
246
|
content?: string | JsonObject;
|
|
231
247
|
error?: LlmError;
|
|
248
|
+
/** Number of providers attempted (1 = primary only, >1 = fallback(s) used) */
|
|
249
|
+
fallbackAttempts?: number;
|
|
250
|
+
/** Whether a fallback provider was used instead of the primary */
|
|
251
|
+
fallbackUsed?: boolean;
|
|
232
252
|
history: LlmHistory;
|
|
233
253
|
model?: string;
|
|
234
254
|
output: LlmOutput;
|
|
255
|
+
/** Which provider actually handled the request */
|
|
235
256
|
provider?: string;
|
|
236
257
|
reasoning: string[];
|
|
237
258
|
responses: JsonReturn[];
|
package/dist/esm/Llm.d.ts
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { JsonObject } from "@jaypie/types";
|
|
2
2
|
import { LlmProviderName } from "./constants.js";
|
|
3
|
-
import { LlmHistory, LlmInputMessage, LlmMessageOptions, LlmOperateInput, LlmOperateOptions, LlmOperateResponse, LlmOptions, LlmProvider } from "./types/LlmProvider.interface.js";
|
|
3
|
+
import { LlmFallbackConfig, LlmHistory, LlmInputMessage, LlmMessageOptions, LlmOperateInput, LlmOperateOptions, LlmOperateResponse, LlmOptions, LlmProvider } from "./types/LlmProvider.interface.js";
|
|
4
4
|
import { LlmStreamChunk } from "./types/LlmStreamChunk.interface.js";
|
|
5
5
|
declare class Llm implements LlmProvider {
|
|
6
|
-
private
|
|
6
|
+
private _fallbackConfig?;
|
|
7
7
|
private _llm;
|
|
8
8
|
private _options;
|
|
9
|
+
private _provider;
|
|
9
10
|
constructor(providerName?: LlmProviderName | string, options?: LlmOptions);
|
|
10
11
|
private createProvider;
|
|
11
12
|
send(message: string, options?: LlmMessageOptions): Promise<string | JsonObject>;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the fallback chain from instance config and per-call options.
|
|
15
|
+
* Per-call options take precedence over instance config.
|
|
16
|
+
* Returns empty array if fallback is disabled.
|
|
17
|
+
*/
|
|
18
|
+
private resolveFallbackChain;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a fallback Llm instance lazily when needed.
|
|
21
|
+
*/
|
|
22
|
+
private createFallbackInstance;
|
|
12
23
|
operate(input: string | LlmHistory | LlmInputMessage | LlmOperateInput, options?: LlmOperateOptions): Promise<LlmOperateResponse>;
|
|
13
24
|
stream(input: string | LlmHistory | LlmInputMessage | LlmOperateInput, options?: LlmOperateOptions): AsyncIterable<LlmStreamChunk>;
|
|
14
25
|
static send(message: string, options?: LlmMessageOptions & {
|
|
@@ -17,8 +28,9 @@ declare class Llm implements LlmProvider {
|
|
|
17
28
|
model?: string;
|
|
18
29
|
}): Promise<string | JsonObject>;
|
|
19
30
|
static operate(input: string | LlmHistory | LlmInputMessage | LlmOperateInput, options?: LlmOperateOptions & {
|
|
20
|
-
llm?: LlmProviderName;
|
|
21
31
|
apiKey?: string;
|
|
32
|
+
fallback?: LlmFallbackConfig[] | false;
|
|
33
|
+
llm?: LlmProviderName;
|
|
22
34
|
model?: string;
|
|
23
35
|
}): Promise<LlmOperateResponse>;
|
|
24
36
|
static stream(input: string | LlmHistory | LlmInputMessage | LlmOperateInput, options?: LlmOperateOptions & {
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { default as Llm } from "./Llm.js";
|
|
2
2
|
export * as LLM from "./constants.js";
|
|
3
|
-
export type { LlmHistory, LlmInputContent, LlmInputContentFile, LlmInputContentImage, LlmInputContentText, LlmInputMessage, LlmMessageOptions, LlmOperateInput, LlmOperateInputContent, LlmOperateInputFile, LlmOperateInputImage, LlmOperateOptions, LlmOperateResponse, LlmOptions, LlmProvider, } from "./types/LlmProvider.interface.js";
|
|
3
|
+
export type { LlmFallbackConfig, LlmHistory, LlmInputContent, LlmInputContentFile, LlmInputContentImage, LlmInputContentText, LlmInputMessage, LlmMessageOptions, LlmOperateInput, LlmOperateInputContent, LlmOperateInputFile, LlmOperateInputImage, LlmOperateOptions, LlmOperateResponse, LlmOptions, LlmProvider, } from "./types/LlmProvider.interface.js";
|
|
4
4
|
export { LlmMessageRole, LlmMessageType, } from "./types/LlmProvider.interface.js";
|
|
5
5
|
export { isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, } from "./types/LlmOperateInput.guards.js";
|
|
6
6
|
export type { LlmTool } from "./types/LlmTool.interface.js";
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConfigurationError, BadGatewayError, TooManyRequestsError, NotImplementedError } from '@jaypie/errors';
|
|
2
|
+
import log$3, { log as log$2 } from '@jaypie/logger';
|
|
2
3
|
import { z } from 'zod/v4';
|
|
3
4
|
import { placeholders, JAYPIE, resolveValue, sleep } from '@jaypie/kit';
|
|
4
|
-
import { log as log$2 } from '@jaypie/logger';
|
|
5
5
|
import RandomLib from 'random';
|
|
6
6
|
import { RateLimitError, APIConnectionError, APIConnectionTimeoutError, InternalServerError, APIUserAbortError, AuthenticationError, BadRequestError, ConflictError, NotFoundError, PermissionDeniedError, UnprocessableEntityError, OpenAI } from 'openai';
|
|
7
7
|
import { zodResponseFormat } from 'openai/helpers/zod';
|
|
@@ -3714,7 +3714,8 @@ class RetryExecutor {
|
|
|
3714
3714
|
providerRequest: options.context.providerRequest,
|
|
3715
3715
|
error,
|
|
3716
3716
|
});
|
|
3717
|
-
|
|
3717
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3718
|
+
throw new BadGatewayError(errorMessage);
|
|
3718
3719
|
}
|
|
3719
3720
|
// Check if error is not retryable
|
|
3720
3721
|
if (!this.errorClassifier.isRetryable(error)) {
|
|
@@ -3726,7 +3727,8 @@ class RetryExecutor {
|
|
|
3726
3727
|
providerRequest: options.context.providerRequest,
|
|
3727
3728
|
error,
|
|
3728
3729
|
});
|
|
3729
|
-
|
|
3730
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3731
|
+
throw new BadGatewayError(errorMessage);
|
|
3730
3732
|
}
|
|
3731
3733
|
// Warn if this is an unknown error type
|
|
3732
3734
|
if (!this.errorClassifier.isKnownError(error)) {
|
|
@@ -5181,7 +5183,7 @@ class OpenRouterProvider {
|
|
|
5181
5183
|
|
|
5182
5184
|
class Llm {
|
|
5183
5185
|
constructor(providerName = DEFAULT.PROVIDER.NAME, options = {}) {
|
|
5184
|
-
const { model } = options;
|
|
5186
|
+
const { fallback, model } = options;
|
|
5185
5187
|
let finalProvider = providerName;
|
|
5186
5188
|
let finalModel = model;
|
|
5187
5189
|
if (model) {
|
|
@@ -5210,6 +5212,7 @@ class Llm {
|
|
|
5210
5212
|
finalModel = undefined;
|
|
5211
5213
|
}
|
|
5212
5214
|
}
|
|
5215
|
+
this._fallbackConfig = fallback;
|
|
5213
5216
|
this._provider = finalProvider;
|
|
5214
5217
|
this._options = { ...options, model: finalModel };
|
|
5215
5218
|
this._llm = this.createProvider(finalProvider, this._options);
|
|
@@ -5238,11 +5241,81 @@ class Llm {
|
|
|
5238
5241
|
async send(message, options) {
|
|
5239
5242
|
return this._llm.send(message, options);
|
|
5240
5243
|
}
|
|
5244
|
+
/**
|
|
5245
|
+
* Resolves the fallback chain from instance config and per-call options.
|
|
5246
|
+
* Per-call options take precedence over instance config.
|
|
5247
|
+
* Returns empty array if fallback is disabled.
|
|
5248
|
+
*/
|
|
5249
|
+
resolveFallbackChain(options) {
|
|
5250
|
+
// Per-call `fallback: false` disables fallback entirely
|
|
5251
|
+
if (options.fallback === false) {
|
|
5252
|
+
return [];
|
|
5253
|
+
}
|
|
5254
|
+
// Per-call fallback array overrides instance config
|
|
5255
|
+
if (Array.isArray(options.fallback)) {
|
|
5256
|
+
return options.fallback;
|
|
5257
|
+
}
|
|
5258
|
+
// Use instance config if available
|
|
5259
|
+
return this._fallbackConfig || [];
|
|
5260
|
+
}
|
|
5261
|
+
/**
|
|
5262
|
+
* Creates a fallback Llm instance lazily when needed.
|
|
5263
|
+
*/
|
|
5264
|
+
createFallbackInstance(config) {
|
|
5265
|
+
return new Llm(config.provider, {
|
|
5266
|
+
apiKey: config.apiKey,
|
|
5267
|
+
model: config.model,
|
|
5268
|
+
});
|
|
5269
|
+
}
|
|
5241
5270
|
async operate(input, options = {}) {
|
|
5242
5271
|
if (!this._llm.operate) {
|
|
5243
5272
|
throw new NotImplementedError(`Provider ${this._provider} does not support operate method`);
|
|
5244
5273
|
}
|
|
5245
|
-
|
|
5274
|
+
const fallbackChain = this.resolveFallbackChain(options);
|
|
5275
|
+
const optionsWithoutFallback = { ...options, fallback: false };
|
|
5276
|
+
let lastError;
|
|
5277
|
+
let attempts = 0;
|
|
5278
|
+
// Try primary provider first
|
|
5279
|
+
attempts++;
|
|
5280
|
+
try {
|
|
5281
|
+
const response = await this._llm.operate(input, optionsWithoutFallback);
|
|
5282
|
+
return {
|
|
5283
|
+
...response,
|
|
5284
|
+
fallbackAttempts: attempts,
|
|
5285
|
+
fallbackUsed: false,
|
|
5286
|
+
provider: response.provider || this._provider,
|
|
5287
|
+
};
|
|
5288
|
+
}
|
|
5289
|
+
catch (error) {
|
|
5290
|
+
lastError = error;
|
|
5291
|
+
log$3.warn(`Provider ${this._provider} failed`, {
|
|
5292
|
+
error: lastError.message,
|
|
5293
|
+
fallbacksRemaining: fallbackChain.length,
|
|
5294
|
+
});
|
|
5295
|
+
}
|
|
5296
|
+
// Try fallback providers
|
|
5297
|
+
for (const fallbackConfig of fallbackChain) {
|
|
5298
|
+
attempts++;
|
|
5299
|
+
try {
|
|
5300
|
+
const fallbackInstance = this.createFallbackInstance(fallbackConfig);
|
|
5301
|
+
const response = await fallbackInstance.operate(input, optionsWithoutFallback);
|
|
5302
|
+
return {
|
|
5303
|
+
...response,
|
|
5304
|
+
fallbackAttempts: attempts,
|
|
5305
|
+
fallbackUsed: true,
|
|
5306
|
+
provider: response.provider || fallbackConfig.provider,
|
|
5307
|
+
};
|
|
5308
|
+
}
|
|
5309
|
+
catch (error) {
|
|
5310
|
+
lastError = error;
|
|
5311
|
+
log$3.warn(`Fallback provider ${fallbackConfig.provider} failed`, {
|
|
5312
|
+
error: lastError.message,
|
|
5313
|
+
fallbacksRemaining: fallbackChain.length - attempts + 1,
|
|
5314
|
+
});
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
// All providers failed, throw the last error
|
|
5318
|
+
throw lastError;
|
|
5246
5319
|
}
|
|
5247
5320
|
async *stream(input, options = {}) {
|
|
5248
5321
|
if (!this._llm.stream) {
|
|
@@ -5256,7 +5329,7 @@ class Llm {
|
|
|
5256
5329
|
return instance.send(message, messageOptions);
|
|
5257
5330
|
}
|
|
5258
5331
|
static async operate(input, options) {
|
|
5259
|
-
const {
|
|
5332
|
+
const { apiKey, fallback, llm, model, ...operateOptions } = options || {};
|
|
5260
5333
|
let finalLlm = llm;
|
|
5261
5334
|
let finalModel = model;
|
|
5262
5335
|
if (!llm && model) {
|
|
@@ -5273,8 +5346,18 @@ class Llm {
|
|
|
5273
5346
|
finalModel = undefined;
|
|
5274
5347
|
}
|
|
5275
5348
|
}
|
|
5276
|
-
|
|
5277
|
-
|
|
5349
|
+
// Resolve fallback for static method: pass to instance if array, pass to operate options if false
|
|
5350
|
+
const instanceFallback = Array.isArray(fallback) ? fallback : undefined;
|
|
5351
|
+
const operateFallback = fallback === false ? false : undefined;
|
|
5352
|
+
const instance = new Llm(finalLlm, {
|
|
5353
|
+
apiKey,
|
|
5354
|
+
fallback: instanceFallback,
|
|
5355
|
+
model: finalModel,
|
|
5356
|
+
});
|
|
5357
|
+
return instance.operate(input, {
|
|
5358
|
+
...operateOptions,
|
|
5359
|
+
...(operateFallback !== undefined && { fallback: operateFallback }),
|
|
5360
|
+
});
|
|
5278
5361
|
}
|
|
5279
5362
|
static stream(input, options) {
|
|
5280
5363
|
const { llm, apiKey, model, ...streamOptions } = options || {};
|