@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/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$4 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
509
- const log$1 = getLogger$4();
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
- while (true) {
3959
- const controller = new AbortController();
3960
- try {
3961
- const result = await operation(controller.signal);
3962
- if (attempt > 0) {
3963
- log$1.debug(`API call succeeded after ${attempt} retries`);
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
- return result;
4038
+ };
4039
+ process.on("unhandledRejection", staleGuard);
4040
+ };
4041
+ const removeGuard = () => {
4042
+ if (staleGuard) {
4043
+ process.removeListener("unhandledRejection", staleGuard);
4044
+ staleGuard = undefined;
3966
4045
  }
3967
- catch (error) {
3968
- // Abort the previous request to kill lingering socket callbacks
3969
- controller.abort("retry");
3970
- // Check if we've exhausted retries
3971
- if (!this.policy.shouldRetry(attempt)) {
3972
- log$1.error(`API call failed after ${this.policy.maxRetries} retries`);
3973
- log$1.var({ error });
3974
- await this.hookRunner.runOnUnrecoverableError(options.hooks, {
3975
- input: options.context.input,
3976
- options: options.context.options,
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
- // Check if error is not retryable
3984
- if (!this.errorClassifier.isRetryable(error)) {
3985
- log$1.error("API call failed with non-retryable error");
3986
- log$1.var({ error });
3987
- await this.hookRunner.runOnUnrecoverableError(options.hooks, {
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
- while (true) {
4599
- const controller = new AbortController();
4600
- try {
4601
- // Execute streaming request
4602
- const streamGenerator = this.adapter.executeStreamRequest(this.client, providerRequest, controller.signal);
4603
- for await (const chunk of streamGenerator) {
4604
- // Pass through text chunks
4605
- if (chunk.type === LlmStreamChunkType.Text) {
4606
- chunksYielded = true;
4607
- yield chunk;
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
- // Collect tool calls
4610
- if (chunk.type === LlmStreamChunkType.ToolCall) {
4611
- chunksYielded = true;
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
- // Track usage from done chunk (but don't yield it yet - we'll emit our own)
4621
- if (chunk.type === LlmStreamChunkType.Done && chunk.usage) {
4622
- state.usageItems.push(...chunk.usage);
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
- // Pass through error chunks
4625
- if (chunk.type === LlmStreamChunkType.Error) {
4626
- chunksYielded = true;
4627
- yield chunk;
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
- // Stream completed successfully
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$3 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
4936
+ const getLogger$4 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
4837
4937
  // Client initialization
4838
- async function initializeClient$3({ apiKey, } = {}) {
4839
- const logger = getLogger$3();
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$3();
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$3();
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$3({ apiKey: this.apiKey });
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$2 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5152
+ const getLogger$3 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5053
5153
  // Client initialization
5054
- async function initializeClient$2({ apiKey, } = {}) {
5055
- const logger = getLogger$2();
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$2();
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$2();
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$2({ apiKey: this.apiKey });
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$1 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5303
+ const getLogger$2 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5204
5304
  // Client initialization
5205
- async function initializeClient$1({ apiKey, } = {}) {
5206
- const logger = getLogger$1();
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$1();
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$1();
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$1();
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$1();
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$1({ apiKey: this.apiKey });
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