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