@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/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/cjs/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var errors = require('@jaypie/errors');
|
|
4
|
+
var log$2 = require('@jaypie/logger');
|
|
4
5
|
var v4 = require('zod/v4');
|
|
5
6
|
var kit = require('@jaypie/kit');
|
|
6
|
-
var logger = require('@jaypie/logger');
|
|
7
7
|
var RandomLib = require('random');
|
|
8
8
|
var openai = require('openai');
|
|
9
9
|
var zod = require('openai/helpers/zod');
|
|
@@ -481,7 +481,7 @@ function formatOperateInput(input, options) {
|
|
|
481
481
|
return [input];
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
const getLogger$4 = () =>
|
|
484
|
+
const getLogger$4 = () => log$2.log.lib({ lib: kit.JAYPIE.LIB.LLM });
|
|
485
485
|
const log$1 = getLogger$4();
|
|
486
486
|
|
|
487
487
|
// Turn policy constants
|
|
@@ -2368,16 +2368,16 @@ function convertContentToOpenRouter(content) {
|
|
|
2368
2368
|
}
|
|
2369
2369
|
// Image content - warn and discard
|
|
2370
2370
|
if (item.type === exports.LlmMessageType.InputImage) {
|
|
2371
|
-
|
|
2371
|
+
log$2.log.warn("OpenRouter does not support image uploads; image discarded");
|
|
2372
2372
|
continue;
|
|
2373
2373
|
}
|
|
2374
2374
|
// File/Document content - warn and discard
|
|
2375
2375
|
if (item.type === exports.LlmMessageType.InputFile) {
|
|
2376
|
-
|
|
2376
|
+
log$2.log.warn({ filename: item.filename }, "OpenRouter does not support file uploads; file discarded");
|
|
2377
2377
|
continue;
|
|
2378
2378
|
}
|
|
2379
2379
|
// Unknown type - warn and skip
|
|
2380
|
-
|
|
2380
|
+
log$2.log.warn({ item }, "Unknown content type for OpenRouter; discarded");
|
|
2381
2381
|
}
|
|
2382
2382
|
// If no text parts remain, return empty string to avoid empty array
|
|
2383
2383
|
if (parts.length === 0) {
|
|
@@ -2893,7 +2893,7 @@ class OpenRouterAdapter extends BaseProviderAdapter {
|
|
|
2893
2893
|
const openRouterAdapter = new OpenRouterAdapter();
|
|
2894
2894
|
|
|
2895
2895
|
const DEFAULT_TOOL_TYPE = "function";
|
|
2896
|
-
const log =
|
|
2896
|
+
const log = log$2.log.lib({ lib: kit.JAYPIE.LIB.LLM });
|
|
2897
2897
|
function logToolMessage(message, context) {
|
|
2898
2898
|
log.trace.var({ [context.name]: message });
|
|
2899
2899
|
}
|
|
@@ -3716,7 +3716,8 @@ class RetryExecutor {
|
|
|
3716
3716
|
providerRequest: options.context.providerRequest,
|
|
3717
3717
|
error,
|
|
3718
3718
|
});
|
|
3719
|
-
|
|
3719
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3720
|
+
throw new errors.BadGatewayError(errorMessage);
|
|
3720
3721
|
}
|
|
3721
3722
|
// Check if error is not retryable
|
|
3722
3723
|
if (!this.errorClassifier.isRetryable(error)) {
|
|
@@ -3728,7 +3729,8 @@ class RetryExecutor {
|
|
|
3728
3729
|
providerRequest: options.context.providerRequest,
|
|
3729
3730
|
error,
|
|
3730
3731
|
});
|
|
3731
|
-
|
|
3732
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3733
|
+
throw new errors.BadGatewayError(errorMessage);
|
|
3732
3734
|
}
|
|
3733
3735
|
// Warn if this is an unknown error type
|
|
3734
3736
|
if (!this.errorClassifier.isKnownError(error)) {
|
|
@@ -4493,7 +4495,7 @@ async function loadSdk$2() {
|
|
|
4493
4495
|
}
|
|
4494
4496
|
}
|
|
4495
4497
|
// Logger
|
|
4496
|
-
const getLogger$3 = () =>
|
|
4498
|
+
const getLogger$3 = () => log$2.log.lib({ lib: kit.JAYPIE.LIB.LLM });
|
|
4497
4499
|
// Client initialization
|
|
4498
4500
|
async function initializeClient$3({ apiKey, } = {}) {
|
|
4499
4501
|
const logger = getLogger$3();
|
|
@@ -4532,7 +4534,7 @@ function prepareMessages$3(message, { data, placeholders } = {}) {
|
|
|
4532
4534
|
}
|
|
4533
4535
|
// Basic text completion
|
|
4534
4536
|
async function createTextCompletion$1(client, messages, model, systemMessage) {
|
|
4535
|
-
|
|
4537
|
+
log$2.log.trace("Using text output (unstructured)");
|
|
4536
4538
|
const params = {
|
|
4537
4539
|
model,
|
|
4538
4540
|
messages,
|
|
@@ -4541,17 +4543,17 @@ async function createTextCompletion$1(client, messages, model, systemMessage) {
|
|
|
4541
4543
|
// Add system instruction if provided
|
|
4542
4544
|
if (systemMessage) {
|
|
4543
4545
|
params.system = systemMessage;
|
|
4544
|
-
|
|
4546
|
+
log$2.log.trace(`System message: ${systemMessage.length} characters`);
|
|
4545
4547
|
}
|
|
4546
4548
|
const response = await client.messages.create(params);
|
|
4547
4549
|
const firstContent = response.content[0];
|
|
4548
4550
|
const text = firstContent && "text" in firstContent ? firstContent.text : "";
|
|
4549
|
-
|
|
4551
|
+
log$2.log.trace(`Assistant reply: ${text.length} characters`);
|
|
4550
4552
|
return text;
|
|
4551
4553
|
}
|
|
4552
4554
|
// Structured output completion
|
|
4553
4555
|
async function createStructuredCompletion$1(client, messages, model, responseSchema, systemMessage) {
|
|
4554
|
-
|
|
4556
|
+
log$2.log.trace("Using structured output");
|
|
4555
4557
|
// Get the JSON schema for the response
|
|
4556
4558
|
const schema = responseSchema instanceof v4.z.ZodType
|
|
4557
4559
|
? responseSchema
|
|
@@ -4584,7 +4586,7 @@ async function createStructuredCompletion$1(client, messages, model, responseSch
|
|
|
4584
4586
|
if (!schema.parse(result)) {
|
|
4585
4587
|
throw new Error(`JSON response from Anthropic does not match schema: ${responseText}`);
|
|
4586
4588
|
}
|
|
4587
|
-
|
|
4589
|
+
log$2.log.trace("Received structured response", { result });
|
|
4588
4590
|
return result;
|
|
4589
4591
|
}
|
|
4590
4592
|
catch {
|
|
@@ -4595,7 +4597,7 @@ async function createStructuredCompletion$1(client, messages, model, responseSch
|
|
|
4595
4597
|
throw new Error("Failed to parse structured response from Anthropic");
|
|
4596
4598
|
}
|
|
4597
4599
|
catch (error) {
|
|
4598
|
-
|
|
4600
|
+
log$2.log.error("Error creating structured completion", { error });
|
|
4599
4601
|
throw error;
|
|
4600
4602
|
}
|
|
4601
4603
|
}
|
|
@@ -4709,7 +4711,7 @@ async function loadSdk$1() {
|
|
|
4709
4711
|
}
|
|
4710
4712
|
}
|
|
4711
4713
|
// Logger
|
|
4712
|
-
const getLogger$2 = () =>
|
|
4714
|
+
const getLogger$2 = () => log$2.log.lib({ lib: kit.JAYPIE.LIB.LLM });
|
|
4713
4715
|
// Client initialization
|
|
4714
4716
|
async function initializeClient$2({ apiKey, } = {}) {
|
|
4715
4717
|
const logger = getLogger$2();
|
|
@@ -4849,7 +4851,7 @@ class GeminiProvider {
|
|
|
4849
4851
|
}
|
|
4850
4852
|
|
|
4851
4853
|
// Logger
|
|
4852
|
-
const getLogger$1 = () =>
|
|
4854
|
+
const getLogger$1 = () => log$2.log.lib({ lib: kit.JAYPIE.LIB.LLM });
|
|
4853
4855
|
// Client initialization
|
|
4854
4856
|
async function initializeClient$1({ apiKey, } = {}) {
|
|
4855
4857
|
const logger = getLogger$1();
|
|
@@ -5033,7 +5035,7 @@ async function loadSdk() {
|
|
|
5033
5035
|
}
|
|
5034
5036
|
}
|
|
5035
5037
|
// Logger
|
|
5036
|
-
const getLogger = () =>
|
|
5038
|
+
const getLogger = () => log$2.log.lib({ lib: kit.JAYPIE.LIB.LLM });
|
|
5037
5039
|
// Client initialization
|
|
5038
5040
|
async function initializeClient({ apiKey, } = {}) {
|
|
5039
5041
|
const logger = getLogger();
|
|
@@ -5183,7 +5185,7 @@ class OpenRouterProvider {
|
|
|
5183
5185
|
|
|
5184
5186
|
class Llm {
|
|
5185
5187
|
constructor(providerName = DEFAULT.PROVIDER.NAME, options = {}) {
|
|
5186
|
-
const { model } = options;
|
|
5188
|
+
const { fallback, model } = options;
|
|
5187
5189
|
let finalProvider = providerName;
|
|
5188
5190
|
let finalModel = model;
|
|
5189
5191
|
if (model) {
|
|
@@ -5212,6 +5214,7 @@ class Llm {
|
|
|
5212
5214
|
finalModel = undefined;
|
|
5213
5215
|
}
|
|
5214
5216
|
}
|
|
5217
|
+
this._fallbackConfig = fallback;
|
|
5215
5218
|
this._provider = finalProvider;
|
|
5216
5219
|
this._options = { ...options, model: finalModel };
|
|
5217
5220
|
this._llm = this.createProvider(finalProvider, this._options);
|
|
@@ -5240,11 +5243,81 @@ class Llm {
|
|
|
5240
5243
|
async send(message, options) {
|
|
5241
5244
|
return this._llm.send(message, options);
|
|
5242
5245
|
}
|
|
5246
|
+
/**
|
|
5247
|
+
* Resolves the fallback chain from instance config and per-call options.
|
|
5248
|
+
* Per-call options take precedence over instance config.
|
|
5249
|
+
* Returns empty array if fallback is disabled.
|
|
5250
|
+
*/
|
|
5251
|
+
resolveFallbackChain(options) {
|
|
5252
|
+
// Per-call `fallback: false` disables fallback entirely
|
|
5253
|
+
if (options.fallback === false) {
|
|
5254
|
+
return [];
|
|
5255
|
+
}
|
|
5256
|
+
// Per-call fallback array overrides instance config
|
|
5257
|
+
if (Array.isArray(options.fallback)) {
|
|
5258
|
+
return options.fallback;
|
|
5259
|
+
}
|
|
5260
|
+
// Use instance config if available
|
|
5261
|
+
return this._fallbackConfig || [];
|
|
5262
|
+
}
|
|
5263
|
+
/**
|
|
5264
|
+
* Creates a fallback Llm instance lazily when needed.
|
|
5265
|
+
*/
|
|
5266
|
+
createFallbackInstance(config) {
|
|
5267
|
+
return new Llm(config.provider, {
|
|
5268
|
+
apiKey: config.apiKey,
|
|
5269
|
+
model: config.model,
|
|
5270
|
+
});
|
|
5271
|
+
}
|
|
5243
5272
|
async operate(input, options = {}) {
|
|
5244
5273
|
if (!this._llm.operate) {
|
|
5245
5274
|
throw new errors.NotImplementedError(`Provider ${this._provider} does not support operate method`);
|
|
5246
5275
|
}
|
|
5247
|
-
|
|
5276
|
+
const fallbackChain = this.resolveFallbackChain(options);
|
|
5277
|
+
const optionsWithoutFallback = { ...options, fallback: false };
|
|
5278
|
+
let lastError;
|
|
5279
|
+
let attempts = 0;
|
|
5280
|
+
// Try primary provider first
|
|
5281
|
+
attempts++;
|
|
5282
|
+
try {
|
|
5283
|
+
const response = await this._llm.operate(input, optionsWithoutFallback);
|
|
5284
|
+
return {
|
|
5285
|
+
...response,
|
|
5286
|
+
fallbackAttempts: attempts,
|
|
5287
|
+
fallbackUsed: false,
|
|
5288
|
+
provider: response.provider || this._provider,
|
|
5289
|
+
};
|
|
5290
|
+
}
|
|
5291
|
+
catch (error) {
|
|
5292
|
+
lastError = error;
|
|
5293
|
+
log$2.warn(`Provider ${this._provider} failed`, {
|
|
5294
|
+
error: lastError.message,
|
|
5295
|
+
fallbacksRemaining: fallbackChain.length,
|
|
5296
|
+
});
|
|
5297
|
+
}
|
|
5298
|
+
// Try fallback providers
|
|
5299
|
+
for (const fallbackConfig of fallbackChain) {
|
|
5300
|
+
attempts++;
|
|
5301
|
+
try {
|
|
5302
|
+
const fallbackInstance = this.createFallbackInstance(fallbackConfig);
|
|
5303
|
+
const response = await fallbackInstance.operate(input, optionsWithoutFallback);
|
|
5304
|
+
return {
|
|
5305
|
+
...response,
|
|
5306
|
+
fallbackAttempts: attempts,
|
|
5307
|
+
fallbackUsed: true,
|
|
5308
|
+
provider: response.provider || fallbackConfig.provider,
|
|
5309
|
+
};
|
|
5310
|
+
}
|
|
5311
|
+
catch (error) {
|
|
5312
|
+
lastError = error;
|
|
5313
|
+
log$2.warn(`Fallback provider ${fallbackConfig.provider} failed`, {
|
|
5314
|
+
error: lastError.message,
|
|
5315
|
+
fallbacksRemaining: fallbackChain.length - attempts + 1,
|
|
5316
|
+
});
|
|
5317
|
+
}
|
|
5318
|
+
}
|
|
5319
|
+
// All providers failed, throw the last error
|
|
5320
|
+
throw lastError;
|
|
5248
5321
|
}
|
|
5249
5322
|
async *stream(input, options = {}) {
|
|
5250
5323
|
if (!this._llm.stream) {
|
|
@@ -5258,7 +5331,7 @@ class Llm {
|
|
|
5258
5331
|
return instance.send(message, messageOptions);
|
|
5259
5332
|
}
|
|
5260
5333
|
static async operate(input, options) {
|
|
5261
|
-
const {
|
|
5334
|
+
const { apiKey, fallback, llm, model, ...operateOptions } = options || {};
|
|
5262
5335
|
let finalLlm = llm;
|
|
5263
5336
|
let finalModel = model;
|
|
5264
5337
|
if (!llm && model) {
|
|
@@ -5275,8 +5348,18 @@ class Llm {
|
|
|
5275
5348
|
finalModel = undefined;
|
|
5276
5349
|
}
|
|
5277
5350
|
}
|
|
5278
|
-
|
|
5279
|
-
|
|
5351
|
+
// Resolve fallback for static method: pass to instance if array, pass to operate options if false
|
|
5352
|
+
const instanceFallback = Array.isArray(fallback) ? fallback : undefined;
|
|
5353
|
+
const operateFallback = fallback === false ? false : undefined;
|
|
5354
|
+
const instance = new Llm(finalLlm, {
|
|
5355
|
+
apiKey,
|
|
5356
|
+
fallback: instanceFallback,
|
|
5357
|
+
model: finalModel,
|
|
5358
|
+
});
|
|
5359
|
+
return instance.operate(input, {
|
|
5360
|
+
...operateOptions,
|
|
5361
|
+
...(operateFallback !== undefined && { fallback: operateFallback }),
|
|
5362
|
+
});
|
|
5280
5363
|
}
|
|
5281
5364
|
static stream(input, options) {
|
|
5282
5365
|
const { llm, apiKey, model, ...streamOptions } = options || {};
|