@jaypie/llm 1.2.14 → 1.2.16
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/constants.d.ts +18 -6
- package/dist/cjs/index.cjs +363 -157
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/operate/adapters/XaiAdapter.d.ts +11 -0
- package/dist/cjs/operate/adapters/index.d.ts +1 -0
- package/dist/cjs/operate/index.d.ts +1 -1
- package/dist/cjs/providers/xai/XaiProvider.class.d.ts +21 -0
- package/dist/cjs/providers/xai/index.d.ts +1 -0
- package/dist/cjs/providers/xai/utils.d.ts +5 -0
- package/dist/esm/constants.d.ts +18 -6
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +363 -158
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/operate/adapters/XaiAdapter.d.ts +11 -0
- package/dist/esm/operate/adapters/index.d.ts +1 -0
- package/dist/esm/operate/index.d.ts +1 -1
- package/dist/esm/providers/xai/XaiProvider.class.d.ts +21 -0
- package/dist/esm/providers/xai/index.d.ts +1 -0
- package/dist/esm/providers/xai/utils.d.ts +5 -0
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -36,6 +36,12 @@ const FIRST_CLASS_PROVIDER = {
|
|
|
36
36
|
SMALL: "z-ai/glm-4.7",
|
|
37
37
|
TINY: "z-ai/glm-4.7",
|
|
38
38
|
},
|
|
39
|
+
XAI: {
|
|
40
|
+
DEFAULT: "grok-4-1-fast-reasoning",
|
|
41
|
+
LARGE: "grok-4-1-fast-reasoning",
|
|
42
|
+
SMALL: "grok-3",
|
|
43
|
+
TINY: "grok-3-mini",
|
|
44
|
+
},
|
|
39
45
|
};
|
|
40
46
|
const PROVIDER = {
|
|
41
47
|
ANTHROPIC: {
|
|
@@ -116,6 +122,19 @@ const PROVIDER = {
|
|
|
116
122
|
USER: "user",
|
|
117
123
|
},
|
|
118
124
|
},
|
|
125
|
+
XAI: {
|
|
126
|
+
// https://docs.x.ai/docs/models
|
|
127
|
+
API_KEY: "XAI_API_KEY",
|
|
128
|
+
BASE_URL: "https://api.x.ai/v1",
|
|
129
|
+
MODEL: {
|
|
130
|
+
DEFAULT: FIRST_CLASS_PROVIDER.XAI.DEFAULT,
|
|
131
|
+
LARGE: FIRST_CLASS_PROVIDER.XAI.LARGE,
|
|
132
|
+
SMALL: FIRST_CLASS_PROVIDER.XAI.SMALL,
|
|
133
|
+
TINY: FIRST_CLASS_PROVIDER.XAI.TINY,
|
|
134
|
+
},
|
|
135
|
+
MODEL_MATCH_WORDS: ["grok", "xai"],
|
|
136
|
+
NAME: "xai",
|
|
137
|
+
},
|
|
119
138
|
};
|
|
120
139
|
// Last: Defaults
|
|
121
140
|
const DEFAULT = {
|
|
@@ -133,6 +152,7 @@ const ALL = {
|
|
|
133
152
|
PROVIDER.ANTHROPIC.MODEL.DEFAULT,
|
|
134
153
|
PROVIDER.GEMINI.MODEL.DEFAULT,
|
|
135
154
|
PROVIDER.OPENAI.MODEL.DEFAULT,
|
|
155
|
+
PROVIDER.XAI.MODEL.DEFAULT,
|
|
136
156
|
],
|
|
137
157
|
COMBINED: [
|
|
138
158
|
PROVIDER.ANTHROPIC.MODEL.DEFAULT,
|
|
@@ -147,21 +167,28 @@ const ALL = {
|
|
|
147
167
|
PROVIDER.OPENAI.MODEL.LARGE,
|
|
148
168
|
PROVIDER.OPENAI.MODEL.SMALL,
|
|
149
169
|
PROVIDER.OPENAI.MODEL.TINY,
|
|
170
|
+
PROVIDER.XAI.MODEL.DEFAULT,
|
|
171
|
+
PROVIDER.XAI.MODEL.LARGE,
|
|
172
|
+
PROVIDER.XAI.MODEL.SMALL,
|
|
173
|
+
PROVIDER.XAI.MODEL.TINY,
|
|
150
174
|
],
|
|
151
175
|
LARGE: [
|
|
152
176
|
PROVIDER.ANTHROPIC.MODEL.LARGE,
|
|
153
177
|
PROVIDER.GEMINI.MODEL.LARGE,
|
|
154
178
|
PROVIDER.OPENAI.MODEL.LARGE,
|
|
179
|
+
PROVIDER.XAI.MODEL.LARGE,
|
|
155
180
|
],
|
|
156
181
|
SMALL: [
|
|
157
182
|
PROVIDER.ANTHROPIC.MODEL.SMALL,
|
|
158
183
|
PROVIDER.GEMINI.MODEL.SMALL,
|
|
159
184
|
PROVIDER.OPENAI.MODEL.SMALL,
|
|
185
|
+
PROVIDER.XAI.MODEL.SMALL,
|
|
160
186
|
],
|
|
161
187
|
TINY: [
|
|
162
188
|
PROVIDER.ANTHROPIC.MODEL.TINY,
|
|
163
189
|
PROVIDER.GEMINI.MODEL.TINY,
|
|
164
190
|
PROVIDER.OPENAI.MODEL.TINY,
|
|
191
|
+
PROVIDER.XAI.MODEL.TINY,
|
|
165
192
|
],
|
|
166
193
|
};
|
|
167
194
|
|
|
@@ -212,6 +239,12 @@ function determineModelProvider(input) {
|
|
|
212
239
|
provider: PROVIDER.OPENROUTER.NAME,
|
|
213
240
|
};
|
|
214
241
|
}
|
|
242
|
+
if (input === PROVIDER.XAI.NAME) {
|
|
243
|
+
return {
|
|
244
|
+
model: PROVIDER.XAI.MODEL.DEFAULT,
|
|
245
|
+
provider: PROVIDER.XAI.NAME,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
215
248
|
// Check if input matches an Anthropic model exactly
|
|
216
249
|
for (const [, modelValue] of Object.entries(PROVIDER.ANTHROPIC.MODEL)) {
|
|
217
250
|
if (input === modelValue) {
|
|
@@ -248,6 +281,15 @@ function determineModelProvider(input) {
|
|
|
248
281
|
};
|
|
249
282
|
}
|
|
250
283
|
}
|
|
284
|
+
// Check if input matches an xAI model exactly
|
|
285
|
+
for (const [, modelValue] of Object.entries(PROVIDER.XAI.MODEL)) {
|
|
286
|
+
if (input === modelValue) {
|
|
287
|
+
return {
|
|
288
|
+
model: input,
|
|
289
|
+
provider: PROVIDER.XAI.NAME,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
251
293
|
// Assume OpenRouter for models containing "/" (e.g., "openai/gpt-4", "anthropic/claude-3-opus")
|
|
252
294
|
// This check must come before match words so that "openai/gpt-4" is not matched by "openai" keyword
|
|
253
295
|
if (input.includes("/")) {
|
|
@@ -294,6 +336,15 @@ function determineModelProvider(input) {
|
|
|
294
336
|
}
|
|
295
337
|
}
|
|
296
338
|
}
|
|
339
|
+
// Check xAI match words
|
|
340
|
+
for (const matchWord of PROVIDER.XAI.MODEL_MATCH_WORDS) {
|
|
341
|
+
if (lowerInput.includes(matchWord)) {
|
|
342
|
+
return {
|
|
343
|
+
model: input,
|
|
344
|
+
provider: PROVIDER.XAI.NAME,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
}
|
|
297
348
|
// Check OpenRouter match words
|
|
298
349
|
for (const matchWord of PROVIDER.OPENROUTER.MODEL_MATCH_WORDS) {
|
|
299
350
|
if (lowerInput.includes(matchWord)) {
|
|
@@ -505,8 +556,8 @@ function formatOperateInput(input, options) {
|
|
|
505
556
|
return [input];
|
|
506
557
|
}
|
|
507
558
|
|
|
508
|
-
const getLogger$
|
|
509
|
-
const log$1 = getLogger$
|
|
559
|
+
const getLogger$5 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
560
|
+
const log$1 = getLogger$5();
|
|
510
561
|
|
|
511
562
|
// Turn policy constants
|
|
512
563
|
const MAX_TURNS_ABSOLUTE_LIMIT = 72;
|
|
@@ -3147,6 +3198,23 @@ class OpenRouterAdapter extends BaseProviderAdapter {
|
|
|
3147
3198
|
// Export singleton instance
|
|
3148
3199
|
const openRouterAdapter = new OpenRouterAdapter();
|
|
3149
3200
|
|
|
3201
|
+
/**
|
|
3202
|
+
* XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
|
|
3203
|
+
* Only the name and default model are overridden; all request building, response parsing,
|
|
3204
|
+
* error classification, tool handling, and streaming are inherited.
|
|
3205
|
+
*/
|
|
3206
|
+
class XaiAdapter extends OpenAiAdapter {
|
|
3207
|
+
constructor() {
|
|
3208
|
+
super(...arguments);
|
|
3209
|
+
// @ts-expect-error Narrowing override: xAI name differs from parent's literal "openai"
|
|
3210
|
+
this.name = PROVIDER.XAI.NAME;
|
|
3211
|
+
// @ts-expect-error Narrowing override: xAI default model differs from parent's literal
|
|
3212
|
+
this.defaultModel = PROVIDER.XAI.MODEL.DEFAULT;
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
// Export singleton instance
|
|
3216
|
+
const xaiAdapter = new XaiAdapter();
|
|
3217
|
+
|
|
3150
3218
|
const DEFAULT_TOOL_TYPE = "function";
|
|
3151
3219
|
const log = log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
3152
3220
|
function logToolMessage(message, context) {
|
|
@@ -3955,73 +4023,91 @@ class RetryExecutor {
|
|
|
3955
4023
|
*/
|
|
3956
4024
|
async execute(operation, options) {
|
|
3957
4025
|
let attempt = 0;
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
4026
|
+
// Persistent guard against stale socket errors (TypeError: terminated).
|
|
4027
|
+
// Installed after the first abort and kept alive through subsequent attempts
|
|
4028
|
+
// so that asynchronous undici socket teardown errors that fire between
|
|
4029
|
+
// sleep completion and the next operation's await are caught.
|
|
4030
|
+
let staleGuard;
|
|
4031
|
+
const installGuard = () => {
|
|
4032
|
+
if (staleGuard)
|
|
4033
|
+
return;
|
|
4034
|
+
staleGuard = (reason) => {
|
|
4035
|
+
if (isTransientNetworkError(reason)) {
|
|
4036
|
+
log$1.trace("Suppressed stale socket error during retry");
|
|
3964
4037
|
}
|
|
3965
|
-
|
|
4038
|
+
};
|
|
4039
|
+
process.on("unhandledRejection", staleGuard);
|
|
4040
|
+
};
|
|
4041
|
+
const removeGuard = () => {
|
|
4042
|
+
if (staleGuard) {
|
|
4043
|
+
process.removeListener("unhandledRejection", staleGuard);
|
|
4044
|
+
staleGuard = undefined;
|
|
3966
4045
|
}
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
providerRequest: options.context.providerRequest,
|
|
3978
|
-
error,
|
|
3979
|
-
});
|
|
3980
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3981
|
-
throw new BadGatewayError(errorMessage);
|
|
4046
|
+
};
|
|
4047
|
+
try {
|
|
4048
|
+
while (true) {
|
|
4049
|
+
const controller = new AbortController();
|
|
4050
|
+
try {
|
|
4051
|
+
const result = await operation(controller.signal);
|
|
4052
|
+
if (attempt > 0) {
|
|
4053
|
+
log$1.debug(`API call succeeded after ${attempt} retries`);
|
|
4054
|
+
}
|
|
4055
|
+
return result;
|
|
3982
4056
|
}
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
4057
|
+
catch (error) {
|
|
4058
|
+
// Abort the previous request to kill lingering socket callbacks
|
|
4059
|
+
controller.abort("retry");
|
|
4060
|
+
// Install the guard immediately after abort — stale socket errors
|
|
4061
|
+
// can fire on any subsequent microtask boundary (during hook calls,
|
|
4062
|
+
// sleep, or the next operation attempt)
|
|
4063
|
+
installGuard();
|
|
4064
|
+
// Check if we've exhausted retries
|
|
4065
|
+
if (!this.policy.shouldRetry(attempt)) {
|
|
4066
|
+
log$1.error(`API call failed after ${this.policy.maxRetries} retries`);
|
|
4067
|
+
log$1.var({ error });
|
|
4068
|
+
await this.hookRunner.runOnUnrecoverableError(options.hooks, {
|
|
4069
|
+
input: options.context.input,
|
|
4070
|
+
options: options.context.options,
|
|
4071
|
+
providerRequest: options.context.providerRequest,
|
|
4072
|
+
error,
|
|
4073
|
+
});
|
|
4074
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4075
|
+
throw new BadGatewayError(errorMessage);
|
|
4076
|
+
}
|
|
4077
|
+
// Check if error is not retryable
|
|
4078
|
+
if (!this.errorClassifier.isRetryable(error)) {
|
|
4079
|
+
log$1.error("API call failed with non-retryable error");
|
|
4080
|
+
log$1.var({ error });
|
|
4081
|
+
await this.hookRunner.runOnUnrecoverableError(options.hooks, {
|
|
4082
|
+
input: options.context.input,
|
|
4083
|
+
options: options.context.options,
|
|
4084
|
+
providerRequest: options.context.providerRequest,
|
|
4085
|
+
error,
|
|
4086
|
+
});
|
|
4087
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4088
|
+
throw new BadGatewayError(errorMessage);
|
|
4089
|
+
}
|
|
4090
|
+
// Warn if this is an unknown error type
|
|
4091
|
+
if (!this.errorClassifier.isKnownError(error)) {
|
|
4092
|
+
log$1.warn("API returned unknown error type, will retry");
|
|
4093
|
+
log$1.var({ error });
|
|
4094
|
+
}
|
|
4095
|
+
const delay = this.policy.getDelayForAttempt(attempt);
|
|
4096
|
+
log$1.warn(`API call failed. Retrying in ${delay}ms...`);
|
|
4097
|
+
await this.hookRunner.runOnRetryableError(options.hooks, {
|
|
3988
4098
|
input: options.context.input,
|
|
3989
4099
|
options: options.context.options,
|
|
3990
4100
|
providerRequest: options.context.providerRequest,
|
|
3991
4101
|
error,
|
|
3992
4102
|
});
|
|
3993
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3994
|
-
throw new BadGatewayError(errorMessage);
|
|
3995
|
-
}
|
|
3996
|
-
// Warn if this is an unknown error type
|
|
3997
|
-
if (!this.errorClassifier.isKnownError(error)) {
|
|
3998
|
-
log$1.warn("API returned unknown error type, will retry");
|
|
3999
|
-
log$1.var({ error });
|
|
4000
|
-
}
|
|
4001
|
-
const delay = this.policy.getDelayForAttempt(attempt);
|
|
4002
|
-
log$1.warn(`API call failed. Retrying in ${delay}ms...`);
|
|
4003
|
-
await this.hookRunner.runOnRetryableError(options.hooks, {
|
|
4004
|
-
input: options.context.input,
|
|
4005
|
-
options: options.context.options,
|
|
4006
|
-
providerRequest: options.context.providerRequest,
|
|
4007
|
-
error,
|
|
4008
|
-
});
|
|
4009
|
-
// Guard against stale socket errors that fire during sleep
|
|
4010
|
-
const staleHandler = (reason) => {
|
|
4011
|
-
if (isTransientNetworkError(reason)) {
|
|
4012
|
-
log$1.trace("Suppressed stale socket error during retry sleep");
|
|
4013
|
-
}
|
|
4014
|
-
};
|
|
4015
|
-
process.on("unhandledRejection", staleHandler);
|
|
4016
|
-
try {
|
|
4017
4103
|
await sleep(delay);
|
|
4104
|
+
attempt++;
|
|
4018
4105
|
}
|
|
4019
|
-
finally {
|
|
4020
|
-
process.removeListener("unhandledRejection", staleHandler);
|
|
4021
|
-
}
|
|
4022
|
-
attempt++;
|
|
4023
4106
|
}
|
|
4024
4107
|
}
|
|
4108
|
+
finally {
|
|
4109
|
+
removeGuard();
|
|
4110
|
+
}
|
|
4025
4111
|
}
|
|
4026
4112
|
}
|
|
4027
4113
|
|
|
@@ -4595,89 +4681,103 @@ class StreamLoop {
|
|
|
4595
4681
|
// Retry loop for connection-level failures
|
|
4596
4682
|
let attempt = 0;
|
|
4597
4683
|
let chunksYielded = false;
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4684
|
+
// Persistent guard against stale socket errors (TypeError: terminated).
|
|
4685
|
+
// Installed after the first abort and kept alive through subsequent attempts.
|
|
4686
|
+
let staleGuard;
|
|
4687
|
+
const installGuard = () => {
|
|
4688
|
+
if (staleGuard)
|
|
4689
|
+
return;
|
|
4690
|
+
staleGuard = (reason) => {
|
|
4691
|
+
if (isTransientNetworkError(reason)) {
|
|
4692
|
+
log$1.trace("Suppressed stale socket error during retry");
|
|
4693
|
+
}
|
|
4694
|
+
};
|
|
4695
|
+
process.on("unhandledRejection", staleGuard);
|
|
4696
|
+
};
|
|
4697
|
+
const removeGuard = () => {
|
|
4698
|
+
if (staleGuard) {
|
|
4699
|
+
process.removeListener("unhandledRejection", staleGuard);
|
|
4700
|
+
staleGuard = undefined;
|
|
4701
|
+
}
|
|
4702
|
+
};
|
|
4703
|
+
try {
|
|
4704
|
+
while (true) {
|
|
4705
|
+
const controller = new AbortController();
|
|
4706
|
+
try {
|
|
4707
|
+
// Execute streaming request
|
|
4708
|
+
const streamGenerator = this.adapter.executeStreamRequest(this.client, providerRequest, controller.signal);
|
|
4709
|
+
for await (const chunk of streamGenerator) {
|
|
4710
|
+
// Pass through text chunks
|
|
4711
|
+
if (chunk.type === LlmStreamChunkType.Text) {
|
|
4712
|
+
chunksYielded = true;
|
|
4713
|
+
yield chunk;
|
|
4714
|
+
}
|
|
4715
|
+
// Collect tool calls
|
|
4716
|
+
if (chunk.type === LlmStreamChunkType.ToolCall) {
|
|
4717
|
+
chunksYielded = true;
|
|
4718
|
+
collectedToolCalls.push({
|
|
4719
|
+
callId: chunk.toolCall.id,
|
|
4720
|
+
name: chunk.toolCall.name,
|
|
4721
|
+
arguments: chunk.toolCall.arguments,
|
|
4722
|
+
raw: chunk.toolCall,
|
|
4723
|
+
});
|
|
4724
|
+
yield chunk;
|
|
4725
|
+
}
|
|
4726
|
+
// Track usage from done chunk (but don't yield it yet - we'll emit our own)
|
|
4727
|
+
if (chunk.type === LlmStreamChunkType.Done && chunk.usage) {
|
|
4728
|
+
state.usageItems.push(...chunk.usage);
|
|
4729
|
+
}
|
|
4730
|
+
// Pass through error chunks
|
|
4731
|
+
if (chunk.type === LlmStreamChunkType.Error) {
|
|
4732
|
+
chunksYielded = true;
|
|
4733
|
+
yield chunk;
|
|
4734
|
+
}
|
|
4608
4735
|
}
|
|
4609
|
-
//
|
|
4610
|
-
if (
|
|
4611
|
-
|
|
4612
|
-
collectedToolCalls.push({
|
|
4613
|
-
callId: chunk.toolCall.id,
|
|
4614
|
-
name: chunk.toolCall.name,
|
|
4615
|
-
arguments: chunk.toolCall.arguments,
|
|
4616
|
-
raw: chunk.toolCall,
|
|
4617
|
-
});
|
|
4618
|
-
yield chunk;
|
|
4736
|
+
// Stream completed successfully
|
|
4737
|
+
if (attempt > 0) {
|
|
4738
|
+
log$1.debug(`Stream request succeeded after ${attempt} retries`);
|
|
4619
4739
|
}
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4740
|
+
break;
|
|
4741
|
+
}
|
|
4742
|
+
catch (error) {
|
|
4743
|
+
// Abort the previous request to kill lingering socket callbacks
|
|
4744
|
+
controller.abort("retry");
|
|
4745
|
+
// Install the guard immediately after abort
|
|
4746
|
+
installGuard();
|
|
4747
|
+
// If chunks were already yielded, we can't transparently retry
|
|
4748
|
+
if (chunksYielded) {
|
|
4749
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4750
|
+
log$1.error("Stream failed after partial data was delivered");
|
|
4751
|
+
log$1.var({ error });
|
|
4752
|
+
yield {
|
|
4753
|
+
type: LlmStreamChunkType.Error,
|
|
4754
|
+
error: {
|
|
4755
|
+
detail: errorMessage,
|
|
4756
|
+
status: 502,
|
|
4757
|
+
title: "Stream Error",
|
|
4758
|
+
},
|
|
4759
|
+
};
|
|
4760
|
+
return { shouldContinue: false };
|
|
4623
4761
|
}
|
|
4624
|
-
//
|
|
4625
|
-
if (
|
|
4626
|
-
|
|
4627
|
-
|
|
4762
|
+
// Check if we've exhausted retries or error is not retryable
|
|
4763
|
+
if (!this.retryPolicy.shouldRetry(attempt) ||
|
|
4764
|
+
!this.adapter.isRetryableError(error)) {
|
|
4765
|
+
log$1.error(`Stream request failed after ${this.retryPolicy.maxRetries} retries`);
|
|
4766
|
+
log$1.var({ error });
|
|
4767
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4768
|
+
throw new BadGatewayError(errorMessage);
|
|
4628
4769
|
}
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
if (attempt > 0) {
|
|
4632
|
-
log$1.debug(`Stream request succeeded after ${attempt} retries`);
|
|
4633
|
-
}
|
|
4634
|
-
break;
|
|
4635
|
-
}
|
|
4636
|
-
catch (error) {
|
|
4637
|
-
// Abort the previous request to kill lingering socket callbacks
|
|
4638
|
-
controller.abort("retry");
|
|
4639
|
-
// If chunks were already yielded, we can't transparently retry
|
|
4640
|
-
if (chunksYielded) {
|
|
4641
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4642
|
-
log$1.error("Stream failed after partial data was delivered");
|
|
4643
|
-
log$1.var({ error });
|
|
4644
|
-
yield {
|
|
4645
|
-
type: LlmStreamChunkType.Error,
|
|
4646
|
-
error: {
|
|
4647
|
-
detail: errorMessage,
|
|
4648
|
-
status: 502,
|
|
4649
|
-
title: "Stream Error",
|
|
4650
|
-
},
|
|
4651
|
-
};
|
|
4652
|
-
return { shouldContinue: false };
|
|
4653
|
-
}
|
|
4654
|
-
// Check if we've exhausted retries or error is not retryable
|
|
4655
|
-
if (!this.retryPolicy.shouldRetry(attempt) ||
|
|
4656
|
-
!this.adapter.isRetryableError(error)) {
|
|
4657
|
-
log$1.error(`Stream request failed after ${this.retryPolicy.maxRetries} retries`);
|
|
4770
|
+
const delay = this.retryPolicy.getDelayForAttempt(attempt);
|
|
4771
|
+
log$1.warn(`Stream request failed. Retrying in ${delay}ms...`);
|
|
4658
4772
|
log$1.var({ error });
|
|
4659
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4660
|
-
throw new BadGatewayError(errorMessage);
|
|
4661
|
-
}
|
|
4662
|
-
const delay = this.retryPolicy.getDelayForAttempt(attempt);
|
|
4663
|
-
log$1.warn(`Stream request failed. Retrying in ${delay}ms...`);
|
|
4664
|
-
log$1.var({ error });
|
|
4665
|
-
// Guard against stale socket errors that fire during sleep
|
|
4666
|
-
const staleHandler = (reason) => {
|
|
4667
|
-
if (isTransientNetworkError(reason)) {
|
|
4668
|
-
log$1.trace("Suppressed stale socket error during retry sleep");
|
|
4669
|
-
}
|
|
4670
|
-
};
|
|
4671
|
-
process.on("unhandledRejection", staleHandler);
|
|
4672
|
-
try {
|
|
4673
4773
|
await sleep(delay);
|
|
4774
|
+
attempt++;
|
|
4674
4775
|
}
|
|
4675
|
-
finally {
|
|
4676
|
-
process.removeListener("unhandledRejection", staleHandler);
|
|
4677
|
-
}
|
|
4678
|
-
attempt++;
|
|
4679
4776
|
}
|
|
4680
4777
|
}
|
|
4778
|
+
finally {
|
|
4779
|
+
removeGuard();
|
|
4780
|
+
}
|
|
4681
4781
|
// Execute afterEachModelResponse hook
|
|
4682
4782
|
await this.hookRunnerInstance.runAfterModelResponse(context.hooks, {
|
|
4683
4783
|
content: "",
|
|
@@ -4833,10 +4933,10 @@ async function loadSdk$2() {
|
|
|
4833
4933
|
}
|
|
4834
4934
|
}
|
|
4835
4935
|
// Logger
|
|
4836
|
-
const getLogger$
|
|
4936
|
+
const getLogger$4 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
4837
4937
|
// Client initialization
|
|
4838
|
-
async function initializeClient$
|
|
4839
|
-
const logger = getLogger$
|
|
4938
|
+
async function initializeClient$4({ apiKey, } = {}) {
|
|
4939
|
+
const logger = getLogger$4();
|
|
4840
4940
|
const resolvedApiKey = apiKey || (await getEnvSecret("ANTHROPIC_API_KEY"));
|
|
4841
4941
|
if (!resolvedApiKey) {
|
|
4842
4942
|
throw new ConfigurationError("The application could not resolve the required API key: ANTHROPIC_API_KEY");
|
|
@@ -4862,7 +4962,7 @@ function formatUserMessage$3(message, { data, placeholders: placeholders$1 } = {
|
|
|
4862
4962
|
};
|
|
4863
4963
|
}
|
|
4864
4964
|
function prepareMessages$3(message, { data, placeholders } = {}) {
|
|
4865
|
-
const logger = getLogger$
|
|
4965
|
+
const logger = getLogger$4();
|
|
4866
4966
|
const messages = [];
|
|
4867
4967
|
// Add user message (necessary for all requests)
|
|
4868
4968
|
const userMessage = formatUserMessage$3(message, { data, placeholders });
|
|
@@ -4951,7 +5051,7 @@ async function createStructuredCompletion$1(client, messages, model, responseSch
|
|
|
4951
5051
|
// Main class implementation
|
|
4952
5052
|
class AnthropicProvider {
|
|
4953
5053
|
constructor(model = PROVIDER.ANTHROPIC.MODEL.DEFAULT, { apiKey } = {}) {
|
|
4954
|
-
this.log = getLogger$
|
|
5054
|
+
this.log = getLogger$4();
|
|
4955
5055
|
this.conversationHistory = [];
|
|
4956
5056
|
this.model = model;
|
|
4957
5057
|
this.apiKey = apiKey;
|
|
@@ -4960,7 +5060,7 @@ class AnthropicProvider {
|
|
|
4960
5060
|
if (this._client) {
|
|
4961
5061
|
return this._client;
|
|
4962
5062
|
}
|
|
4963
|
-
this._client = await initializeClient$
|
|
5063
|
+
this._client = await initializeClient$4({ apiKey: this.apiKey });
|
|
4964
5064
|
return this._client;
|
|
4965
5065
|
}
|
|
4966
5066
|
async getOperateLoop() {
|
|
@@ -5049,10 +5149,10 @@ async function loadSdk$1() {
|
|
|
5049
5149
|
}
|
|
5050
5150
|
}
|
|
5051
5151
|
// Logger
|
|
5052
|
-
const getLogger$
|
|
5152
|
+
const getLogger$3 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
5053
5153
|
// Client initialization
|
|
5054
|
-
async function initializeClient$
|
|
5055
|
-
const logger = getLogger$
|
|
5154
|
+
async function initializeClient$3({ apiKey, } = {}) {
|
|
5155
|
+
const logger = getLogger$3();
|
|
5056
5156
|
const resolvedApiKey = apiKey || (await getEnvSecret("GEMINI_API_KEY"));
|
|
5057
5157
|
if (!resolvedApiKey) {
|
|
5058
5158
|
throw new ConfigurationError("The application could not resolve the requested keys");
|
|
@@ -5072,7 +5172,7 @@ function formatUserMessage$2(message, { data, placeholders: placeholders$1 } = {
|
|
|
5072
5172
|
};
|
|
5073
5173
|
}
|
|
5074
5174
|
function prepareMessages$2(message, { data, placeholders } = {}) {
|
|
5075
|
-
const logger = getLogger$
|
|
5175
|
+
const logger = getLogger$3();
|
|
5076
5176
|
const messages = [];
|
|
5077
5177
|
let systemInstruction;
|
|
5078
5178
|
// Note: Gemini handles system prompts differently via systemInstruction config
|
|
@@ -5086,7 +5186,7 @@ function prepareMessages$2(message, { data, placeholders } = {}) {
|
|
|
5086
5186
|
|
|
5087
5187
|
class GeminiProvider {
|
|
5088
5188
|
constructor(model = PROVIDER.GEMINI.MODEL.DEFAULT, { apiKey } = {}) {
|
|
5089
|
-
this.log = getLogger$
|
|
5189
|
+
this.log = getLogger$3();
|
|
5090
5190
|
this.conversationHistory = [];
|
|
5091
5191
|
this.model = model;
|
|
5092
5192
|
this.apiKey = apiKey;
|
|
@@ -5095,7 +5195,7 @@ class GeminiProvider {
|
|
|
5095
5195
|
if (this._client) {
|
|
5096
5196
|
return this._client;
|
|
5097
5197
|
}
|
|
5098
|
-
this._client = await initializeClient$
|
|
5198
|
+
this._client = await initializeClient$3({ apiKey: this.apiKey });
|
|
5099
5199
|
return this._client;
|
|
5100
5200
|
}
|
|
5101
5201
|
async getOperateLoop() {
|
|
@@ -5200,10 +5300,10 @@ class GeminiProvider {
|
|
|
5200
5300
|
}
|
|
5201
5301
|
|
|
5202
5302
|
// Logger
|
|
5203
|
-
const getLogger$
|
|
5303
|
+
const getLogger$2 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
5204
5304
|
// Client initialization
|
|
5205
|
-
async function initializeClient$
|
|
5206
|
-
const logger = getLogger$
|
|
5305
|
+
async function initializeClient$2({ apiKey, } = {}) {
|
|
5306
|
+
const logger = getLogger$2();
|
|
5207
5307
|
const resolvedApiKey = apiKey || (await getEnvSecret("OPENAI_API_KEY"));
|
|
5208
5308
|
if (!resolvedApiKey) {
|
|
5209
5309
|
throw new ConfigurationError("The application could not resolve the requested keys");
|
|
@@ -5231,7 +5331,7 @@ function formatUserMessage$1(message, { data, placeholders: placeholders$1 } = {
|
|
|
5231
5331
|
};
|
|
5232
5332
|
}
|
|
5233
5333
|
function prepareMessages$1(message, { system, data, placeholders } = {}) {
|
|
5234
|
-
const logger = getLogger$
|
|
5334
|
+
const logger = getLogger$2();
|
|
5235
5335
|
const messages = [];
|
|
5236
5336
|
if (system) {
|
|
5237
5337
|
const systemMessage = formatSystemMessage$1(system, { data, placeholders });
|
|
@@ -5245,7 +5345,7 @@ function prepareMessages$1(message, { system, data, placeholders } = {}) {
|
|
|
5245
5345
|
}
|
|
5246
5346
|
// Completion requests
|
|
5247
5347
|
async function createStructuredCompletion(client, { messages, responseSchema, model, }) {
|
|
5248
|
-
const logger = getLogger$
|
|
5348
|
+
const logger = getLogger$2();
|
|
5249
5349
|
logger.trace("Using structured output");
|
|
5250
5350
|
const zodSchema = responseSchema instanceof z.ZodType
|
|
5251
5351
|
? responseSchema
|
|
@@ -5276,7 +5376,7 @@ async function createStructuredCompletion(client, { messages, responseSchema, mo
|
|
|
5276
5376
|
return completion.choices[0].message.parsed;
|
|
5277
5377
|
}
|
|
5278
5378
|
async function createTextCompletion(client, { messages, model, }) {
|
|
5279
|
-
const logger = getLogger$
|
|
5379
|
+
const logger = getLogger$2();
|
|
5280
5380
|
logger.trace("Using text output (unstructured)");
|
|
5281
5381
|
const completion = await client.chat.completions.create({
|
|
5282
5382
|
messages,
|
|
@@ -5288,7 +5388,7 @@ async function createTextCompletion(client, { messages, model, }) {
|
|
|
5288
5388
|
|
|
5289
5389
|
class OpenAiProvider {
|
|
5290
5390
|
constructor(model = PROVIDER.OPENAI.MODEL.DEFAULT, { apiKey } = {}) {
|
|
5291
|
-
this.log = getLogger$
|
|
5391
|
+
this.log = getLogger$2();
|
|
5292
5392
|
this.conversationHistory = [];
|
|
5293
5393
|
this.model = model;
|
|
5294
5394
|
this.apiKey = apiKey;
|
|
@@ -5297,7 +5397,7 @@ class OpenAiProvider {
|
|
|
5297
5397
|
if (this._client) {
|
|
5298
5398
|
return this._client;
|
|
5299
5399
|
}
|
|
5300
|
-
this._client = await initializeClient$
|
|
5400
|
+
this._client = await initializeClient$2({ apiKey: this.apiKey });
|
|
5301
5401
|
return this._client;
|
|
5302
5402
|
}
|
|
5303
5403
|
async getOperateLoop() {
|
|
@@ -5384,10 +5484,10 @@ async function loadSdk() {
|
|
|
5384
5484
|
}
|
|
5385
5485
|
}
|
|
5386
5486
|
// Logger
|
|
5387
|
-
const getLogger = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
5487
|
+
const getLogger$1 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
5388
5488
|
// Client initialization
|
|
5389
|
-
async function initializeClient({ apiKey, } = {}) {
|
|
5390
|
-
const logger = getLogger();
|
|
5489
|
+
async function initializeClient$1({ apiKey, } = {}) {
|
|
5490
|
+
const logger = getLogger$1();
|
|
5391
5491
|
const resolvedApiKey = apiKey || (await getEnvSecret("OPENROUTER_API_KEY"));
|
|
5392
5492
|
if (!resolvedApiKey) {
|
|
5393
5493
|
throw new ConfigurationError("The application could not resolve the requested keys");
|
|
@@ -5420,7 +5520,7 @@ function formatUserMessage(message, { data, placeholders: placeholders$1 } = {})
|
|
|
5420
5520
|
};
|
|
5421
5521
|
}
|
|
5422
5522
|
function prepareMessages(message, { system, data, placeholders } = {}) {
|
|
5423
|
-
const logger = getLogger();
|
|
5523
|
+
const logger = getLogger$1();
|
|
5424
5524
|
const messages = [];
|
|
5425
5525
|
if (system) {
|
|
5426
5526
|
const systemMessage = formatSystemMessage(system, { data, placeholders });
|
|
@@ -5435,7 +5535,7 @@ function prepareMessages(message, { system, data, placeholders } = {}) {
|
|
|
5435
5535
|
|
|
5436
5536
|
class OpenRouterProvider {
|
|
5437
5537
|
constructor(model = getDefaultModel(), { apiKey } = {}) {
|
|
5438
|
-
this.log = getLogger();
|
|
5538
|
+
this.log = getLogger$1();
|
|
5439
5539
|
this.conversationHistory = [];
|
|
5440
5540
|
this.model = model;
|
|
5441
5541
|
this.apiKey = apiKey;
|
|
@@ -5444,7 +5544,7 @@ class OpenRouterProvider {
|
|
|
5444
5544
|
if (this._client) {
|
|
5445
5545
|
return this._client;
|
|
5446
5546
|
}
|
|
5447
|
-
this._client = await initializeClient({ apiKey: this.apiKey });
|
|
5547
|
+
this._client = await initializeClient$1({ apiKey: this.apiKey });
|
|
5448
5548
|
return this._client;
|
|
5449
5549
|
}
|
|
5450
5550
|
async getOperateLoop() {
|
|
@@ -5532,6 +5632,107 @@ class OpenRouterProvider {
|
|
|
5532
5632
|
}
|
|
5533
5633
|
}
|
|
5534
5634
|
|
|
5635
|
+
// Logger
|
|
5636
|
+
const getLogger = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
|
|
5637
|
+
// Client initialization
|
|
5638
|
+
async function initializeClient({ apiKey, } = {}) {
|
|
5639
|
+
const logger = getLogger();
|
|
5640
|
+
const resolvedApiKey = apiKey || (await getEnvSecret(PROVIDER.XAI.API_KEY));
|
|
5641
|
+
if (!resolvedApiKey) {
|
|
5642
|
+
throw new ConfigurationError("The application could not resolve the requested keys");
|
|
5643
|
+
}
|
|
5644
|
+
const client = new OpenAI({
|
|
5645
|
+
apiKey: resolvedApiKey,
|
|
5646
|
+
baseURL: PROVIDER.XAI.BASE_URL,
|
|
5647
|
+
});
|
|
5648
|
+
logger.trace("Initialized xAI client");
|
|
5649
|
+
return client;
|
|
5650
|
+
}
|
|
5651
|
+
|
|
5652
|
+
class XaiProvider {
|
|
5653
|
+
constructor(model = PROVIDER.XAI.MODEL.DEFAULT, { apiKey } = {}) {
|
|
5654
|
+
this.log = getLogger$2();
|
|
5655
|
+
this.conversationHistory = [];
|
|
5656
|
+
this.model = model;
|
|
5657
|
+
this.apiKey = apiKey;
|
|
5658
|
+
}
|
|
5659
|
+
async getClient() {
|
|
5660
|
+
if (this._client) {
|
|
5661
|
+
return this._client;
|
|
5662
|
+
}
|
|
5663
|
+
this._client = await initializeClient({ apiKey: this.apiKey });
|
|
5664
|
+
return this._client;
|
|
5665
|
+
}
|
|
5666
|
+
async getOperateLoop() {
|
|
5667
|
+
if (this._operateLoop) {
|
|
5668
|
+
return this._operateLoop;
|
|
5669
|
+
}
|
|
5670
|
+
const client = await this.getClient();
|
|
5671
|
+
this._operateLoop = createOperateLoop({
|
|
5672
|
+
adapter: xaiAdapter,
|
|
5673
|
+
client,
|
|
5674
|
+
});
|
|
5675
|
+
return this._operateLoop;
|
|
5676
|
+
}
|
|
5677
|
+
async getStreamLoop() {
|
|
5678
|
+
if (this._streamLoop) {
|
|
5679
|
+
return this._streamLoop;
|
|
5680
|
+
}
|
|
5681
|
+
const client = await this.getClient();
|
|
5682
|
+
this._streamLoop = createStreamLoop({
|
|
5683
|
+
adapter: xaiAdapter,
|
|
5684
|
+
client,
|
|
5685
|
+
});
|
|
5686
|
+
return this._streamLoop;
|
|
5687
|
+
}
|
|
5688
|
+
async send(message, options) {
|
|
5689
|
+
const client = await this.getClient();
|
|
5690
|
+
const messages = prepareMessages$1(message, options || {});
|
|
5691
|
+
const modelToUse = options?.model || this.model;
|
|
5692
|
+
if (options?.response) {
|
|
5693
|
+
return createStructuredCompletion(client, {
|
|
5694
|
+
messages,
|
|
5695
|
+
responseSchema: options.response,
|
|
5696
|
+
model: modelToUse,
|
|
5697
|
+
});
|
|
5698
|
+
}
|
|
5699
|
+
return createTextCompletion(client, {
|
|
5700
|
+
messages,
|
|
5701
|
+
model: modelToUse,
|
|
5702
|
+
});
|
|
5703
|
+
}
|
|
5704
|
+
async operate(input, options = {}) {
|
|
5705
|
+
const operateLoop = await this.getOperateLoop();
|
|
5706
|
+
const mergedOptions = { ...options, model: options.model ?? this.model };
|
|
5707
|
+
// Create a merged history including both the tracked history and any explicitly provided history
|
|
5708
|
+
if (this.conversationHistory.length > 0) {
|
|
5709
|
+
// If options.history exists, merge with instance history, otherwise use instance history
|
|
5710
|
+
mergedOptions.history = options.history
|
|
5711
|
+
? [...this.conversationHistory, ...options.history]
|
|
5712
|
+
: [...this.conversationHistory];
|
|
5713
|
+
}
|
|
5714
|
+
// Execute operate loop
|
|
5715
|
+
const response = await operateLoop.execute(input, mergedOptions);
|
|
5716
|
+
// Update conversation history with the new history from the response
|
|
5717
|
+
if (response.history && response.history.length > 0) {
|
|
5718
|
+
this.conversationHistory = response.history;
|
|
5719
|
+
}
|
|
5720
|
+
return response;
|
|
5721
|
+
}
|
|
5722
|
+
async *stream(input, options = {}) {
|
|
5723
|
+
const streamLoop = await this.getStreamLoop();
|
|
5724
|
+
const mergedOptions = { ...options, model: options.model ?? this.model };
|
|
5725
|
+
// Create a merged history including both the tracked history and any explicitly provided history
|
|
5726
|
+
if (this.conversationHistory.length > 0) {
|
|
5727
|
+
mergedOptions.history = options.history
|
|
5728
|
+
? [...this.conversationHistory, ...options.history]
|
|
5729
|
+
: [...this.conversationHistory];
|
|
5730
|
+
}
|
|
5731
|
+
// Execute stream loop
|
|
5732
|
+
yield* streamLoop.execute(input, mergedOptions);
|
|
5733
|
+
}
|
|
5734
|
+
}
|
|
5735
|
+
|
|
5535
5736
|
class Llm {
|
|
5536
5737
|
constructor(providerName = DEFAULT.PROVIDER.NAME, options = {}) {
|
|
5537
5738
|
const { fallback, model } = options;
|
|
@@ -5593,6 +5794,10 @@ class Llm {
|
|
|
5593
5794
|
return new OpenRouterProvider(model || PROVIDER.OPENROUTER.MODEL.DEFAULT, {
|
|
5594
5795
|
apiKey,
|
|
5595
5796
|
});
|
|
5797
|
+
case PROVIDER.XAI.NAME:
|
|
5798
|
+
return new XaiProvider(model || PROVIDER.XAI.MODEL.DEFAULT, {
|
|
5799
|
+
apiKey,
|
|
5800
|
+
});
|
|
5596
5801
|
default:
|
|
5597
5802
|
throw new ConfigurationError(`Unsupported provider: ${providerName}`);
|
|
5598
5803
|
}
|
|
@@ -6031,5 +6236,5 @@ const toolkit = new JaypieToolkit(tools);
|
|
|
6031
6236
|
[LlmMessageRole.Developer]: "user",
|
|
6032
6237
|
});
|
|
6033
6238
|
|
|
6034
|
-
export { GeminiProvider, JaypieToolkit, constants as LLM, Llm, LlmMessageRole, LlmMessageType, LlmStreamChunkType, OpenRouterProvider, Toolkit, extractReasoning, isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, toolkit, tools };
|
|
6239
|
+
export { GeminiProvider, JaypieToolkit, constants as LLM, Llm, LlmMessageRole, LlmMessageType, LlmStreamChunkType, OpenRouterProvider, Toolkit, XaiProvider, extractReasoning, isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, toolkit, tools };
|
|
6035
6240
|
//# sourceMappingURL=index.js.map
|