@jaypie/llm 1.2.15 → 1.2.17

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.
@@ -10,3 +10,4 @@ export { JaypieToolkit, toolkit, Toolkit, tools } from "./tools/index.js";
10
10
  export { extractReasoning } from "./util/extractReasoning.js";
11
11
  export { GeminiProvider } from "./providers/gemini/index.js";
12
12
  export { OpenRouterProvider } from "./providers/openrouter/index.js";
13
+ export { XaiProvider } from "./providers/xai/index.js";
@@ -0,0 +1,11 @@
1
+ import { OpenAiAdapter } from "./OpenAiAdapter.js";
2
+ /**
3
+ * XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
4
+ * Only the name and default model are overridden; all request building, response parsing,
5
+ * error classification, tool handling, and streaming are inherited.
6
+ */
7
+ export declare class XaiAdapter extends OpenAiAdapter {
8
+ readonly name: "xai";
9
+ readonly defaultModel: "grok-4-1-fast-reasoning";
10
+ }
11
+ export declare const xaiAdapter: XaiAdapter;
@@ -4,3 +4,4 @@ export { AnthropicAdapter, anthropicAdapter } from "./AnthropicAdapter.js";
4
4
  export { GeminiAdapter, geminiAdapter } from "./GeminiAdapter.js";
5
5
  export { OpenAiAdapter, openAiAdapter } from "./OpenAiAdapter.js";
6
6
  export { OpenRouterAdapter, openRouterAdapter } from "./OpenRouterAdapter.js";
7
+ export { XaiAdapter, xaiAdapter } from "./XaiAdapter.js";
@@ -1,4 +1,4 @@
1
- export { AnthropicAdapter, anthropicAdapter, BaseProviderAdapter, GeminiAdapter, geminiAdapter, OpenAiAdapter, openAiAdapter, OpenRouterAdapter, openRouterAdapter, } from "./adapters/index.js";
1
+ export { AnthropicAdapter, anthropicAdapter, BaseProviderAdapter, GeminiAdapter, geminiAdapter, OpenAiAdapter, openAiAdapter, OpenRouterAdapter, openRouterAdapter, XaiAdapter, xaiAdapter, } from "./adapters/index.js";
2
2
  export type { ProviderAdapter } from "./adapters/index.js";
3
3
  export { createOperateLoop, OperateLoop } from "./OperateLoop.js";
4
4
  export type { OperateLoopConfig } from "./OperateLoop.js";
@@ -0,0 +1,21 @@
1
+ import { JsonObject } from "@jaypie/types";
2
+ import { LlmHistory, LlmInputMessage, LlmMessageOptions, LlmOperateOptions, LlmOperateResponse, LlmProvider } from "../../types/LlmProvider.interface.js";
3
+ import { LlmStreamChunk } from "../../types/LlmStreamChunk.interface.js";
4
+ export declare class XaiProvider implements LlmProvider {
5
+ private model;
6
+ private _client?;
7
+ private _operateLoop?;
8
+ private _streamLoop?;
9
+ private apiKey?;
10
+ private log;
11
+ private conversationHistory;
12
+ constructor(model?: string, { apiKey }?: {
13
+ apiKey?: string;
14
+ });
15
+ private getClient;
16
+ private getOperateLoop;
17
+ private getStreamLoop;
18
+ send(message: string, options?: LlmMessageOptions): Promise<string | JsonObject>;
19
+ operate(input: string | LlmHistory | LlmInputMessage, options?: LlmOperateOptions): Promise<LlmOperateResponse>;
20
+ stream(input: string | LlmHistory | LlmInputMessage, options?: LlmOperateOptions): AsyncIterable<LlmStreamChunk>;
21
+ }
@@ -0,0 +1 @@
1
+ export { XaiProvider } from "./XaiProvider.class.js";
@@ -0,0 +1,5 @@
1
+ import { OpenAI } from "openai";
2
+ export declare const getLogger: () => any;
3
+ export declare function initializeClient({ apiKey, }?: {
4
+ apiKey?: string;
5
+ }): Promise<OpenAI>;
@@ -16,6 +16,8 @@ export interface LlmStreamChunkToolCall {
16
16
  id: string;
17
17
  name: string;
18
18
  arguments: string;
19
+ /** Provider-specific metadata preserved through tool-call roundtrip */
20
+ metadata?: Record<string, unknown>;
19
21
  };
20
22
  }
21
23
  export interface LlmStreamChunkToolResult {
@@ -64,8 +64,20 @@ export declare const PROVIDER: {
64
64
  readonly USER: "user";
65
65
  };
66
66
  };
67
+ readonly XAI: {
68
+ readonly API_KEY: "XAI_API_KEY";
69
+ readonly BASE_URL: "https://api.x.ai/v1";
70
+ readonly MODEL: {
71
+ readonly DEFAULT: "grok-4-1-fast-reasoning";
72
+ readonly LARGE: "grok-4-1-fast-reasoning";
73
+ readonly SMALL: "grok-3";
74
+ readonly TINY: "grok-3-mini";
75
+ };
76
+ readonly MODEL_MATCH_WORDS: readonly ["grok", "xai"];
77
+ readonly NAME: "xai";
78
+ };
67
79
  };
68
- export type LlmProviderName = typeof PROVIDER.ANTHROPIC.NAME | typeof PROVIDER.GEMINI.NAME | typeof PROVIDER.OPENAI.NAME | typeof PROVIDER.OPENROUTER.NAME;
80
+ export type LlmProviderName = typeof PROVIDER.ANTHROPIC.NAME | typeof PROVIDER.GEMINI.NAME | typeof PROVIDER.OPENAI.NAME | typeof PROVIDER.OPENROUTER.NAME | typeof PROVIDER.XAI.NAME;
69
81
  export declare const DEFAULT: {
70
82
  readonly MODEL: {
71
83
  readonly BASE: "gpt-5.2";
@@ -85,9 +97,9 @@ export declare const DEFAULT: {
85
97
  };
86
98
  };
87
99
  export declare const ALL: {
88
- readonly BASE: readonly ["claude-sonnet-4-5", "gemini-3-pro-preview", "gpt-5.2"];
89
- readonly COMBINED: readonly ["claude-sonnet-4-5", "claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5", "gemini-3-pro-preview", "gemini-3-pro-preview", "gemini-3-flash-preview", "gemini-3-flash-preview", "gpt-5.2", "gpt-5.2-pro", "gpt-5-mini", "gpt-5-nano"];
90
- readonly LARGE: readonly ["claude-opus-4-5", "gemini-3-pro-preview", "gpt-5.2-pro"];
91
- readonly SMALL: readonly ["claude-sonnet-4-5", "gemini-3-flash-preview", "gpt-5-mini"];
92
- readonly TINY: readonly ["claude-haiku-4-5", "gemini-3-flash-preview", "gpt-5-nano"];
100
+ readonly BASE: readonly ["claude-sonnet-4-5", "gemini-3-pro-preview", "gpt-5.2", "grok-4-1-fast-reasoning"];
101
+ readonly COMBINED: readonly ["claude-sonnet-4-5", "claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5", "gemini-3-pro-preview", "gemini-3-pro-preview", "gemini-3-flash-preview", "gemini-3-flash-preview", "gpt-5.2", "gpt-5.2-pro", "gpt-5-mini", "gpt-5-nano", "grok-4-1-fast-reasoning", "grok-4-1-fast-reasoning", "grok-3", "grok-3-mini"];
102
+ readonly LARGE: readonly ["claude-opus-4-5", "gemini-3-pro-preview", "gpt-5.2-pro", "grok-4-1-fast-reasoning"];
103
+ readonly SMALL: readonly ["claude-sonnet-4-5", "gemini-3-flash-preview", "gpt-5-mini", "grok-3"];
104
+ readonly TINY: readonly ["claude-haiku-4-5", "gemini-3-flash-preview", "gpt-5-nano", "grok-3-mini"];
93
105
  };
@@ -10,3 +10,4 @@ export { JaypieToolkit, toolkit, Toolkit, tools } from "./tools/index.js";
10
10
  export { extractReasoning } from "./util/extractReasoning.js";
11
11
  export { GeminiProvider } from "./providers/gemini/index.js";
12
12
  export { OpenRouterProvider } from "./providers/openrouter/index.js";
13
+ export { XaiProvider } from "./providers/xai/index.js";
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;
@@ -1628,6 +1679,11 @@ class GeminiAdapter extends BaseProviderAdapter {
1628
1679
  name: functionCall.name || "",
1629
1680
  arguments: functionCall.args || {},
1630
1681
  };
1682
+ // Preserve thoughtSignature for Gemini 3 models
1683
+ // Required to maintain tool call context between turns
1684
+ const metadata = part.thoughtSignature
1685
+ ? { thoughtSignature: part.thoughtSignature }
1686
+ : undefined;
1631
1687
  // Emit the function call immediately
1632
1688
  yield {
1633
1689
  type: LlmStreamChunkType.ToolCall,
@@ -1635,6 +1691,7 @@ class GeminiAdapter extends BaseProviderAdapter {
1635
1691
  id: currentFunctionCall.id,
1636
1692
  name: currentFunctionCall.name,
1637
1693
  arguments: JSON.stringify(currentFunctionCall.arguments),
1694
+ metadata,
1638
1695
  },
1639
1696
  };
1640
1697
  currentFunctionCall = null;
@@ -2321,6 +2378,9 @@ class OpenAiAdapter extends BaseProviderAdapter {
2321
2378
  id: currentFunctionCall.callId,
2322
2379
  name: currentFunctionCall.name,
2323
2380
  arguments: currentFunctionCall.arguments,
2381
+ // Preserve the item ID (fc_...) separately from call_id (call_...)
2382
+ // OpenAI Responses API requires both with correct prefixes
2383
+ metadata: { itemId: currentFunctionCall.id },
2324
2384
  },
2325
2385
  };
2326
2386
  currentFunctionCall = null;
@@ -3147,6 +3207,23 @@ class OpenRouterAdapter extends BaseProviderAdapter {
3147
3207
  // Export singleton instance
3148
3208
  const openRouterAdapter = new OpenRouterAdapter();
3149
3209
 
3210
+ /**
3211
+ * XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
3212
+ * Only the name and default model are overridden; all request building, response parsing,
3213
+ * error classification, tool handling, and streaming are inherited.
3214
+ */
3215
+ class XaiAdapter extends OpenAiAdapter {
3216
+ constructor() {
3217
+ super(...arguments);
3218
+ // @ts-expect-error Narrowing override: xAI name differs from parent's literal "openai"
3219
+ this.name = PROVIDER.XAI.NAME;
3220
+ // @ts-expect-error Narrowing override: xAI default model differs from parent's literal
3221
+ this.defaultModel = PROVIDER.XAI.MODEL.DEFAULT;
3222
+ }
3223
+ }
3224
+ // Export singleton instance
3225
+ const xaiAdapter = new XaiAdapter();
3226
+
3150
3227
  const DEFAULT_TOOL_TYPE = "function";
3151
3228
  const log = log$2.lib({ lib: JAYPIE.LIB.LLM });
3152
3229
  function logToolMessage(message, context) {
@@ -4723,13 +4800,22 @@ class StreamLoop {
4723
4800
  if (collectedToolCalls.length > 0 && state.toolkit && state.maxTurns > 1) {
4724
4801
  // Add tool calls to history
4725
4802
  for (const toolCall of collectedToolCalls) {
4726
- state.currentInput.push({
4803
+ // Extract provider-specific metadata from the stream chunk
4804
+ const metadata = toolCall.raw?.metadata;
4805
+ const historyItem = {
4727
4806
  type: LlmMessageType.FunctionCall,
4728
4807
  name: toolCall.name,
4729
4808
  arguments: toolCall.arguments,
4730
4809
  call_id: toolCall.callId,
4731
- id: toolCall.callId,
4732
- });
4810
+ // Use provider item ID if available (e.g., OpenAI fc_... prefix),
4811
+ // otherwise fall back to callId
4812
+ id: metadata?.itemId || toolCall.callId,
4813
+ };
4814
+ // Preserve provider-specific fields (e.g., Gemini thoughtSignature)
4815
+ if (metadata?.thoughtSignature) {
4816
+ historyItem.thoughtSignature = metadata.thoughtSignature;
4817
+ }
4818
+ state.currentInput.push(historyItem);
4733
4819
  }
4734
4820
  return { shouldContinue: true, toolCalls: collectedToolCalls };
4735
4821
  }
@@ -4865,10 +4951,10 @@ async function loadSdk$2() {
4865
4951
  }
4866
4952
  }
4867
4953
  // Logger
4868
- const getLogger$3 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
4954
+ const getLogger$4 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
4869
4955
  // Client initialization
4870
- async function initializeClient$3({ apiKey, } = {}) {
4871
- const logger = getLogger$3();
4956
+ async function initializeClient$4({ apiKey, } = {}) {
4957
+ const logger = getLogger$4();
4872
4958
  const resolvedApiKey = apiKey || (await getEnvSecret("ANTHROPIC_API_KEY"));
4873
4959
  if (!resolvedApiKey) {
4874
4960
  throw new ConfigurationError("The application could not resolve the required API key: ANTHROPIC_API_KEY");
@@ -4894,7 +4980,7 @@ function formatUserMessage$3(message, { data, placeholders: placeholders$1 } = {
4894
4980
  };
4895
4981
  }
4896
4982
  function prepareMessages$3(message, { data, placeholders } = {}) {
4897
- const logger = getLogger$3();
4983
+ const logger = getLogger$4();
4898
4984
  const messages = [];
4899
4985
  // Add user message (necessary for all requests)
4900
4986
  const userMessage = formatUserMessage$3(message, { data, placeholders });
@@ -4983,7 +5069,7 @@ async function createStructuredCompletion$1(client, messages, model, responseSch
4983
5069
  // Main class implementation
4984
5070
  class AnthropicProvider {
4985
5071
  constructor(model = PROVIDER.ANTHROPIC.MODEL.DEFAULT, { apiKey } = {}) {
4986
- this.log = getLogger$3();
5072
+ this.log = getLogger$4();
4987
5073
  this.conversationHistory = [];
4988
5074
  this.model = model;
4989
5075
  this.apiKey = apiKey;
@@ -4992,7 +5078,7 @@ class AnthropicProvider {
4992
5078
  if (this._client) {
4993
5079
  return this._client;
4994
5080
  }
4995
- this._client = await initializeClient$3({ apiKey: this.apiKey });
5081
+ this._client = await initializeClient$4({ apiKey: this.apiKey });
4996
5082
  return this._client;
4997
5083
  }
4998
5084
  async getOperateLoop() {
@@ -5081,10 +5167,10 @@ async function loadSdk$1() {
5081
5167
  }
5082
5168
  }
5083
5169
  // Logger
5084
- const getLogger$2 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5170
+ const getLogger$3 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5085
5171
  // Client initialization
5086
- async function initializeClient$2({ apiKey, } = {}) {
5087
- const logger = getLogger$2();
5172
+ async function initializeClient$3({ apiKey, } = {}) {
5173
+ const logger = getLogger$3();
5088
5174
  const resolvedApiKey = apiKey || (await getEnvSecret("GEMINI_API_KEY"));
5089
5175
  if (!resolvedApiKey) {
5090
5176
  throw new ConfigurationError("The application could not resolve the requested keys");
@@ -5104,7 +5190,7 @@ function formatUserMessage$2(message, { data, placeholders: placeholders$1 } = {
5104
5190
  };
5105
5191
  }
5106
5192
  function prepareMessages$2(message, { data, placeholders } = {}) {
5107
- const logger = getLogger$2();
5193
+ const logger = getLogger$3();
5108
5194
  const messages = [];
5109
5195
  let systemInstruction;
5110
5196
  // Note: Gemini handles system prompts differently via systemInstruction config
@@ -5118,7 +5204,7 @@ function prepareMessages$2(message, { data, placeholders } = {}) {
5118
5204
 
5119
5205
  class GeminiProvider {
5120
5206
  constructor(model = PROVIDER.GEMINI.MODEL.DEFAULT, { apiKey } = {}) {
5121
- this.log = getLogger$2();
5207
+ this.log = getLogger$3();
5122
5208
  this.conversationHistory = [];
5123
5209
  this.model = model;
5124
5210
  this.apiKey = apiKey;
@@ -5127,7 +5213,7 @@ class GeminiProvider {
5127
5213
  if (this._client) {
5128
5214
  return this._client;
5129
5215
  }
5130
- this._client = await initializeClient$2({ apiKey: this.apiKey });
5216
+ this._client = await initializeClient$3({ apiKey: this.apiKey });
5131
5217
  return this._client;
5132
5218
  }
5133
5219
  async getOperateLoop() {
@@ -5232,10 +5318,10 @@ class GeminiProvider {
5232
5318
  }
5233
5319
 
5234
5320
  // Logger
5235
- const getLogger$1 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5321
+ const getLogger$2 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5236
5322
  // Client initialization
5237
- async function initializeClient$1({ apiKey, } = {}) {
5238
- const logger = getLogger$1();
5323
+ async function initializeClient$2({ apiKey, } = {}) {
5324
+ const logger = getLogger$2();
5239
5325
  const resolvedApiKey = apiKey || (await getEnvSecret("OPENAI_API_KEY"));
5240
5326
  if (!resolvedApiKey) {
5241
5327
  throw new ConfigurationError("The application could not resolve the requested keys");
@@ -5263,7 +5349,7 @@ function formatUserMessage$1(message, { data, placeholders: placeholders$1 } = {
5263
5349
  };
5264
5350
  }
5265
5351
  function prepareMessages$1(message, { system, data, placeholders } = {}) {
5266
- const logger = getLogger$1();
5352
+ const logger = getLogger$2();
5267
5353
  const messages = [];
5268
5354
  if (system) {
5269
5355
  const systemMessage = formatSystemMessage$1(system, { data, placeholders });
@@ -5277,7 +5363,7 @@ function prepareMessages$1(message, { system, data, placeholders } = {}) {
5277
5363
  }
5278
5364
  // Completion requests
5279
5365
  async function createStructuredCompletion(client, { messages, responseSchema, model, }) {
5280
- const logger = getLogger$1();
5366
+ const logger = getLogger$2();
5281
5367
  logger.trace("Using structured output");
5282
5368
  const zodSchema = responseSchema instanceof z.ZodType
5283
5369
  ? responseSchema
@@ -5308,7 +5394,7 @@ async function createStructuredCompletion(client, { messages, responseSchema, mo
5308
5394
  return completion.choices[0].message.parsed;
5309
5395
  }
5310
5396
  async function createTextCompletion(client, { messages, model, }) {
5311
- const logger = getLogger$1();
5397
+ const logger = getLogger$2();
5312
5398
  logger.trace("Using text output (unstructured)");
5313
5399
  const completion = await client.chat.completions.create({
5314
5400
  messages,
@@ -5320,7 +5406,7 @@ async function createTextCompletion(client, { messages, model, }) {
5320
5406
 
5321
5407
  class OpenAiProvider {
5322
5408
  constructor(model = PROVIDER.OPENAI.MODEL.DEFAULT, { apiKey } = {}) {
5323
- this.log = getLogger$1();
5409
+ this.log = getLogger$2();
5324
5410
  this.conversationHistory = [];
5325
5411
  this.model = model;
5326
5412
  this.apiKey = apiKey;
@@ -5329,7 +5415,7 @@ class OpenAiProvider {
5329
5415
  if (this._client) {
5330
5416
  return this._client;
5331
5417
  }
5332
- this._client = await initializeClient$1({ apiKey: this.apiKey });
5418
+ this._client = await initializeClient$2({ apiKey: this.apiKey });
5333
5419
  return this._client;
5334
5420
  }
5335
5421
  async getOperateLoop() {
@@ -5416,10 +5502,10 @@ async function loadSdk() {
5416
5502
  }
5417
5503
  }
5418
5504
  // Logger
5419
- const getLogger = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5505
+ const getLogger$1 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5420
5506
  // Client initialization
5421
- async function initializeClient({ apiKey, } = {}) {
5422
- const logger = getLogger();
5507
+ async function initializeClient$1({ apiKey, } = {}) {
5508
+ const logger = getLogger$1();
5423
5509
  const resolvedApiKey = apiKey || (await getEnvSecret("OPENROUTER_API_KEY"));
5424
5510
  if (!resolvedApiKey) {
5425
5511
  throw new ConfigurationError("The application could not resolve the requested keys");
@@ -5452,7 +5538,7 @@ function formatUserMessage(message, { data, placeholders: placeholders$1 } = {})
5452
5538
  };
5453
5539
  }
5454
5540
  function prepareMessages(message, { system, data, placeholders } = {}) {
5455
- const logger = getLogger();
5541
+ const logger = getLogger$1();
5456
5542
  const messages = [];
5457
5543
  if (system) {
5458
5544
  const systemMessage = formatSystemMessage(system, { data, placeholders });
@@ -5467,7 +5553,7 @@ function prepareMessages(message, { system, data, placeholders } = {}) {
5467
5553
 
5468
5554
  class OpenRouterProvider {
5469
5555
  constructor(model = getDefaultModel(), { apiKey } = {}) {
5470
- this.log = getLogger();
5556
+ this.log = getLogger$1();
5471
5557
  this.conversationHistory = [];
5472
5558
  this.model = model;
5473
5559
  this.apiKey = apiKey;
@@ -5476,7 +5562,7 @@ class OpenRouterProvider {
5476
5562
  if (this._client) {
5477
5563
  return this._client;
5478
5564
  }
5479
- this._client = await initializeClient({ apiKey: this.apiKey });
5565
+ this._client = await initializeClient$1({ apiKey: this.apiKey });
5480
5566
  return this._client;
5481
5567
  }
5482
5568
  async getOperateLoop() {
@@ -5564,6 +5650,107 @@ class OpenRouterProvider {
5564
5650
  }
5565
5651
  }
5566
5652
 
5653
+ // Logger
5654
+ const getLogger = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
5655
+ // Client initialization
5656
+ async function initializeClient({ apiKey, } = {}) {
5657
+ const logger = getLogger();
5658
+ const resolvedApiKey = apiKey || (await getEnvSecret(PROVIDER.XAI.API_KEY));
5659
+ if (!resolvedApiKey) {
5660
+ throw new ConfigurationError("The application could not resolve the requested keys");
5661
+ }
5662
+ const client = new OpenAI({
5663
+ apiKey: resolvedApiKey,
5664
+ baseURL: PROVIDER.XAI.BASE_URL,
5665
+ });
5666
+ logger.trace("Initialized xAI client");
5667
+ return client;
5668
+ }
5669
+
5670
+ class XaiProvider {
5671
+ constructor(model = PROVIDER.XAI.MODEL.DEFAULT, { apiKey } = {}) {
5672
+ this.log = getLogger$2();
5673
+ this.conversationHistory = [];
5674
+ this.model = model;
5675
+ this.apiKey = apiKey;
5676
+ }
5677
+ async getClient() {
5678
+ if (this._client) {
5679
+ return this._client;
5680
+ }
5681
+ this._client = await initializeClient({ apiKey: this.apiKey });
5682
+ return this._client;
5683
+ }
5684
+ async getOperateLoop() {
5685
+ if (this._operateLoop) {
5686
+ return this._operateLoop;
5687
+ }
5688
+ const client = await this.getClient();
5689
+ this._operateLoop = createOperateLoop({
5690
+ adapter: xaiAdapter,
5691
+ client,
5692
+ });
5693
+ return this._operateLoop;
5694
+ }
5695
+ async getStreamLoop() {
5696
+ if (this._streamLoop) {
5697
+ return this._streamLoop;
5698
+ }
5699
+ const client = await this.getClient();
5700
+ this._streamLoop = createStreamLoop({
5701
+ adapter: xaiAdapter,
5702
+ client,
5703
+ });
5704
+ return this._streamLoop;
5705
+ }
5706
+ async send(message, options) {
5707
+ const client = await this.getClient();
5708
+ const messages = prepareMessages$1(message, options || {});
5709
+ const modelToUse = options?.model || this.model;
5710
+ if (options?.response) {
5711
+ return createStructuredCompletion(client, {
5712
+ messages,
5713
+ responseSchema: options.response,
5714
+ model: modelToUse,
5715
+ });
5716
+ }
5717
+ return createTextCompletion(client, {
5718
+ messages,
5719
+ model: modelToUse,
5720
+ });
5721
+ }
5722
+ async operate(input, options = {}) {
5723
+ const operateLoop = await this.getOperateLoop();
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
+ // If options.history exists, merge with instance history, otherwise use instance history
5728
+ mergedOptions.history = options.history
5729
+ ? [...this.conversationHistory, ...options.history]
5730
+ : [...this.conversationHistory];
5731
+ }
5732
+ // Execute operate loop
5733
+ const response = await operateLoop.execute(input, mergedOptions);
5734
+ // Update conversation history with the new history from the response
5735
+ if (response.history && response.history.length > 0) {
5736
+ this.conversationHistory = response.history;
5737
+ }
5738
+ return response;
5739
+ }
5740
+ async *stream(input, options = {}) {
5741
+ const streamLoop = await this.getStreamLoop();
5742
+ const mergedOptions = { ...options, model: options.model ?? this.model };
5743
+ // Create a merged history including both the tracked history and any explicitly provided history
5744
+ if (this.conversationHistory.length > 0) {
5745
+ mergedOptions.history = options.history
5746
+ ? [...this.conversationHistory, ...options.history]
5747
+ : [...this.conversationHistory];
5748
+ }
5749
+ // Execute stream loop
5750
+ yield* streamLoop.execute(input, mergedOptions);
5751
+ }
5752
+ }
5753
+
5567
5754
  class Llm {
5568
5755
  constructor(providerName = DEFAULT.PROVIDER.NAME, options = {}) {
5569
5756
  const { fallback, model } = options;
@@ -5625,6 +5812,10 @@ class Llm {
5625
5812
  return new OpenRouterProvider(model || PROVIDER.OPENROUTER.MODEL.DEFAULT, {
5626
5813
  apiKey,
5627
5814
  });
5815
+ case PROVIDER.XAI.NAME:
5816
+ return new XaiProvider(model || PROVIDER.XAI.MODEL.DEFAULT, {
5817
+ apiKey,
5818
+ });
5628
5819
  default:
5629
5820
  throw new ConfigurationError(`Unsupported provider: ${providerName}`);
5630
5821
  }
@@ -6063,5 +6254,5 @@ const toolkit = new JaypieToolkit(tools);
6063
6254
  [LlmMessageRole.Developer]: "user",
6064
6255
  });
6065
6256
 
6066
- export { GeminiProvider, JaypieToolkit, constants as LLM, Llm, LlmMessageRole, LlmMessageType, LlmStreamChunkType, OpenRouterProvider, Toolkit, extractReasoning, isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, toolkit, tools };
6257
+ export { GeminiProvider, JaypieToolkit, constants as LLM, Llm, LlmMessageRole, LlmMessageType, LlmStreamChunkType, OpenRouterProvider, Toolkit, XaiProvider, extractReasoning, isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, toolkit, tools };
6067
6258
  //# sourceMappingURL=index.js.map